docs: def aperture_photometry(data, apertures, error=None, mask=None,
                          method='exact', subpixels=5, unit=None, wcs=None):
      """
      Perform aperture photometry on the input data by summing the flux
      within the given aperture(s).
  
      Parameters
      ----------
      data : array_like, `~astropy.units.Quantity`, `~astropy.io.fits.ImageHDU`, or `~astropy.io.fits.HDUList`
          The 2D array on which to perform photometry. ``data`` should be
          background-subtracted.  Units can be used during the photometry,
          either provided with the data (i.e. a `~astropy.units.Quantity`
          array) or the ``unit`` keyword.  If ``data`` is an
          `~astropy.io.fits.ImageHDU` or `~astropy.io.fits.HDUList`, the
          unit is determined from the ``'BUNIT'`` header keyword.
  
      apertures : `~photutils.Aperture`
          The aperture(s) to use for the photometry.
  
      error : array_like or `~astropy.units.Quantity`, optional
          The pixel-wise Gaussian 1-sigma errors of the input ``data``.
          ``error`` is assumed to include *all* sources of error,
          including the Poisson error of the sources (see
          `~photutils.utils.calc_total_error`) .  ``error`` must have the
          same shape as the input ``data``.
  
      mask : array_like (bool), optional
          A boolean mask with the same shape as ``data`` where a `True`
          value indicates the corresponding element of ``data`` is masked.
          Masked data are excluded from all calculations.
  
      method : {'exact', 'center', 'subpixel'}, optional
          The method used to determine the overlap of the aperture on the
          pixel grid.  Not all options are available for all aperture
          types.  Note that the more precise methods are generally slower.
          The following methods are available:
  
              * ``'exact'`` (default):
                  The the exact fractional overlap of the aperture and
                  each pixel is calculated.  The returned mask will
                  contain values between 0 and 1.
  
              * ``'center'``:
                  A pixel is considered to be entirely in or out of the
                  aperture depending on whether its center is in or out of
                  the aperture.  The returned mask will contain values
                  only of 0 (out) and 1 (in).
  
              * ``'subpixel'``:
                  A pixel is divided into subpixels (see the ``subpixels``
                  keyword), each of which are considered to be entirely in
                  or out of the aperture depending on whether its center
                  is in or out of the aperture.  If ``subpixels=1``, this
                  method is equivalent to ``'center'``.  The returned mask
                  will contain values between 0 and 1.
  
      subpixels : int, optional
          For the ``'subpixel'`` method, resample pixels by this factor in
          each dimension.  That is, each pixel is divided into ``subpixels
          ** 2`` subpixels.
  
      unit : `~astropy.units.UnitBase` object or str, optional
          An object that represents the unit associated with the input
          ``data`` and ``error`` arrays.  Must be a
          `~astropy.units.UnitBase` object or a string parseable by the
          :mod:`~astropy.units` package.  If ``data`` or ``error`` already
          have a different unit, the input ``unit`` will not be used and a
          warning will be raised.  If ``data`` is an
          `~astropy.io.fits.ImageHDU` or `~astropy.io.fits.HDUList`,
          ``unit`` will override the ``'BUNIT'`` header keyword.
  
      wcs : `~astropy.wcs.WCS`, optional
          The WCS transformation to use if the input ``apertures`` is a
          `SkyAperture` object.  If ``data`` is an
          `~astropy.io.fits.ImageHDU` or `~astropy.io.fits.HDUList`,
          ``wcs`` overrides any WCS transformation present in the header.
  
      Returns
      -------
      table : `~astropy.table.QTable`
          A table of the photometry with the following columns:
  
              * ``'id'``:
                The source ID.
  
              * ``'xcenter'``, ``'ycenter'``:
                The ``x`` and ``y`` pixel coordinates of the input
                aperture center(s).
  
              * ``'celestial_center'``:
                The celestial coordinates of the input aperture center(s).
                Returned only if the input ``apertures`` is a
                `SkyAperture` object.
  
              * ``'aperture_sum'``:
                The sum of the values within the aperture.
  
              * ``'aperture_sum_err'``:
                The corresponding uncertainty in the ``'aperture_sum'``
                values.  Returned only if the input ``error`` is not
                `None`.
  
          The table metadata includes the Astropy and Photutils version
          numbers and the `aperture_photometry` calling arguments.
  
      Notes
      -----
      This function is decorated with `~astropy.nddata.support_nddata` and
      thus supports `~astropy.nddata.NDData` objects as input.
      """
  
      data, error, mask, wcs = _prepare_photometry_input(data, error, mask,
                                                         wcs, unit)
  
      if method == 'subpixel':
          if (int(subpixels) != subpixels) or (subpixels <= 0):
              raise ValueError('subpixels must be a positive integer.')
  
      scalar_aperture = False
      if isinstance(apertures, Aperture):
          scalar_aperture = True
  
      apertures = np.atleast_1d(apertures)
  
      # convert sky to pixel apertures
      skyaper = False
      if isinstance(apertures[0], SkyAperture):
          if wcs is None:
              raise ValueError('A WCS transform must be defined by the input '
                               'data or the wcs keyword when using a '
                               'SkyAperture object.')
  
          skyaper = True
          skycoord_pos = apertures[0].positions
  
          pix_aper = [aper.to_pixel(wcs) for aper in apertures]
          apertures = pix_aper
  
      # do comparison in pixels to avoid comparing SkyCoord objects
      positions = apertures[0].positions
      for aper in apertures[1:]:
          if not np.array_equal(aper.positions, positions):
              raise ValueError('Input apertures must all have identical '
                               'positions.')
  
      meta = OrderedDict()
      meta['name'] = 'Aperture photometry results'
      meta['version'] = get_version_info()
      calling_args = ("method='{0}', subpixels={1}".format(method, subpixels))
      meta['aperture_photometry_args'] = calling_args
  
      tbl = QTable(meta=meta)
      tbl['id'] = np.arange(len(apertures[0]), dtype=int) + 1
  
      xypos_pixel = np.transpose(apertures[0].positions) * u.pixel
      tbl['xcenter'] = xypos_pixel[0]
      tbl['ycenter'] = xypos_pixel[1]
  
      if skyaper:
          if skycoord_pos.isscalar:
              tbl['celestial_center'] = (skycoord_pos,)
          else:
              tbl['celestial_center'] = skycoord_pos
  
      for i, aper in enumerate(apertures):
          aper_sum, aper_sum_err = aper.do_photometry(data, error=error,
                                                      mask=mask, method=method,
                                                      subpixels=subpixels)
  
          sum_key = 'aperture_sum'
          sum_err_key = 'aperture_sum_err'
          if not scalar_aperture:
              sum_key += '_{}'.format(i)
              sum_err_key += '_{}'.format(i)
  
          tbl[sum_key] = aper_sum
          if error is not None:
              tbl[sum_err_key] = aper_sum_err
  
      return tbl