docs: def fit(self, conver=DEFAULT_CONVERGENCE, minit=DEFAULT_MINIT,
              maxit=DEFAULT_MAXIT, fflag=DEFAULT_FFLAG, maxgerr=DEFAULT_MAXGERR,
              going_inwards=False):
          """
          Fit an elliptical isophote.
  
          Parameters
          ----------
          conver : float, optional
              The main convergence criterion. Iterations stop when the
              largest harmonic amplitude becomes smaller (in absolute
              value) than ``conver`` times the harmonic fit rms.  The
              default is 0.05.
          minit : int, optional
              The minimum number of iterations to perform. A minimum of 10
              (the default) iterations guarantees that, on average, 2
              iterations will be available for fitting each independent
              parameter (the four harmonic amplitudes and the intensity
              level). For the first isophote, the minimum number of
              iterations is 2 * ``minit`` to ensure that, even departing
              from not-so-good initial values, the algorithm has a better
              chance to converge to a sensible solution.
          maxit : int, optional
              The maximum number of iterations to perform.  The default is
              50.
          fflag : float, optional
              The acceptable fraction of flagged data points in the
              sample.  If the actual fraction of valid data points is
              smaller than this, the iterations will stop and the current
              `~photutils.isophote.Isophote` will be returned.  Flagged
              data points are points that either lie outside the image
              frame, are masked, or were rejected by sigma-clipping.  The
              default is 0.7.
          maxgerr : float, optional
              The maximum acceptable relative error in the local radial
              intensity gradient. This is the main control for preventing
              ellipses to grow to regions of too low signal-to-noise
              ratio.  It specifies the maximum acceptable relative error
              in the local radial intensity gradient.  `Busko (1996; ASPC
              101, 139)
              <http://adsabs.harvard.edu/abs/1996ASPC..101..139B>`_ showed
              that the fitting precision relates to that relative error.
              The usual behavior of the gradient relative error is to
              increase with semimajor axis, being larger in outer, fainter
              regions of a galaxy image.  In the current implementation,
              the ``maxgerr`` criterion is triggered only when two
              consecutive isophotes exceed the value specified by the
              parameter. This prevents premature stopping caused by
              contamination such as stars and HII regions.
  
              A number of actions may happen when the gradient error
              exceeds ``maxgerr`` (or becomes non-significant and is set
              to `None`).  If the maximum semimajor axis specified by
              ``maxsma`` is set to `None`, semimajor axis growth is
              stopped and the algorithm proceeds inwards to the galaxy
              center. If ``maxsma`` is set to some finite value, and this
              value is larger than the current semimajor axis length, the
              algorithm enters non-iterative mode and proceeds outwards
              until reaching ``maxsma``.  The default is 0.5.
          going_inwards : bool, optional
              Parameter to define the sense of SMA growth. When fitting
              just one isophote, this parameter is used only by the code
              that defines the details of how elliptical arc segments
              ("sectors") are extracted from the image, when using area
              extraction modes (see the ``integrmode`` parameter in the
              `~photutils.isophote.EllipseSample` class).  The default is
              `False`.
  
          Returns
          -------
          result : `~photutils.isophote.Isophote` instance
              The fitted isophote, which also contains fit status
              information.
  
          Examples
          --------
          >>> from photutils.isophote import EllipseSample, EllipseFitter
          >>> sample = EllipseSample(data, sma=10.)
          >>> fitter = EllipseFitter(sample)
          >>> isophote = fitter.fit()
          """
  
          sample = self._sample
  
          # this flag signals that limiting gradient error (`maxgerr`)
          # wasn't exceeded yet.
          lexceed = False
  
          # here we keep track of the sample that caused the minimum harmonic
          # amplitude(in absolute value). This will eventually be used to
          # build the resulting Isophote in cases where iterations run to
          # the maximum allowed (maxit), or the maximum number of flagged
          # data points (fflag) is reached.
          minimum_amplitude_value = np.Inf
          minimum_amplitude_sample = None
  
          for iter in range(maxit):
              # Force the sample to compute its gradient and associated values.
              sample.update()
  
              # The extract() method returns sampled values as a 2-d numpy array
              # with the following structure:
              # values[0] = 1-d array with angles
              # values[1] = 1-d array with radii
              # values[2] = 1-d array with intensity
              values = sample.extract()
  
              # Fit harmonic coefficients. Failure in fitting is
              # a fatal error; terminate immediately with sample
              # marked as invalid.
              try:
                  coeffs = fit_first_and_second_harmonics(values[0], values[2])
              except Exception as e:
                  log.info(e)
                  return Isophote(sample, iter+1, False, 3)
  
              coeffs = coeffs[0]
  
              # largest harmonic in absolute value drives the correction.
              largest_harmonic_index = np.argmax(np.abs(coeffs[1:]))
              largest_harmonic = coeffs[1:][largest_harmonic_index]
  
              # see if the amplitude decreased; if yes, keep the
              # corresponding sample for eventual later use.
              if abs(largest_harmonic) < minimum_amplitude_value:
                  minimum_amplitude_value = abs(largest_harmonic)
                  minimum_amplitude_sample = sample
  
              # check if converged
              model = first_and_second_harmonic_function(values[0], coeffs)
              residual = values[2] - model
  
              if ((conver * sample.sector_area * np.std(residual))
                      > np.abs(largest_harmonic)):
                  # Got a valid solution. But before returning, ensure
                  # that a minimum of iterations has run.
                  if iter >= minit-1:
                      sample.update()
                      return Isophote(sample, iter+1, True, 0)
  
              # it may not have converged yet, but the sample contains too
              # many invalid data points: return.
              if sample.actual_points < (sample.total_points * fflag):
                  # when too many data points were flagged, return the
                  # best fit sample instead of the current one.
                  minimum_amplitude_sample.update()
                  return Isophote(minimum_amplitude_sample, iter+1, True, 1)
  
              # pick appropriate corrector code.
              corrector = _correctors[largest_harmonic_index]
  
              # generate *NEW* EllipseSample instance with corrected
              # parameter.  Note that this instance is still devoid of other
              # information besides its geometry.  It needs to be explicitly
              # updated for computations to proceed.  We have to build a new
              # EllipseSample instance every time because of the lazy
              # extraction process used by EllipseSample code. To minimize
              # the number of calls to the area integrators, we pay a
              # (hopefully smaller) price here, by having multiple calls to
              # the EllipseSample constructor.
              sample = corrector.correct(sample, largest_harmonic)
              sample.update()
  
              # see if any abnormal (or unusual) conditions warrant
              # the change to non-iterative mode, or go-inwards mode.
              proceed, lexceed = self._check_conditions(
                  sample, maxgerr, going_inwards, lexceed)
  
              if not proceed:
                  sample.update()
                  return Isophote(sample, iter+1, True, -1)
  
          # Got to the maximum number of iterations. Return with
          # code 2, and handle it as a valid isophote. Use the
          # best fit sample instead of the current one.
          minimum_amplitude_sample.update()
          return Isophote(minimum_amplitude_sample, maxit, True, 2)