docs: def chained_lsqfit(
          self, data=None, pdata=None, prior=None, p0=None, add_priornoise=None,
          **kargs
          ):
          """ Compute chained least-squares fit of models to data.
  
          In a chained fit to models ``[s1, s2, ...]``, the models are fit one
          at a time, with the fit output from one being fed into the prior for
          the next. This can be much faster than  fitting the models together,
          simultaneously. The final result comes from the last fit in the chain,
          and includes parameters from all of the models.
  
          The most general chain has the structure ``[s1, s2, s3 ...]``
          where each ``sn`` is one of:
  
              1) A model (derived from :class:`multifitter.MultiFitterModel`).
  
              2) A tuple ``(m1, m2, m3)`` of models, to be fit together in
                  a single fit (i.e., simultaneously). Simultaneous fits
                  are useful for closely related models.
  
              3) A list ``[p1, p2, p3 ...]`` where each ``pn`` is either
                  a model or a tuple of models (see #2). The ``pn`` are fit
                  separately: the fit output from one fit is *not* fed into the
                  prior of the next (i.e., the fits are effectively in
                  parallel). Results from the separate fits are averaged at the
                  end to provide a single composite result for the collection of
                  fits. Parallel fits are effective (and fast) when the
                  different fits have few or no fit parameters in common.
  
              4) A dictionary that (temporarily) resets default values for
                  fitter keywords. The new values, specified in the dictionary,
                  apply to subsequent fits in the chain. Any number of such
                  dictionaries can be included in the model chain.
  
  
          Fit results are returned in a :class:`lsqfit.MultiFitter.chained_fit`
          object ``fit``, which is very similar to a :class:`nonlinear_fit`
          object (see documentation for more information). Object ``fit`` has an
          extra attribute ``fit.chained_fits`` which is an ordered dictionary
          containing fit results for each link in the chain of fits, indexed by
          fit names built from the corresponding data tags.
  
          To list results from all of the fits in the chain, use ::
  
              print(fit.formatall())
  
          This method has optional keyword arguments ``maxline``,
          ``pstyle``, and ``nline``; see the documentation for
          :meth:`lsqfit.nonlinear_fit.format` for more
          information.
  
          To view plots of each fit use
  
              fit.show_plots()
  
          This method has optional keyword arguments ``save`` and ``view``;
          see documentation for :class:`lsqfit.MultiFitter.show_plots`
          for more information. Plotting requires module :mod:`matplotlib`.
  
          To bootstrap a fit, use ``fit.bootstrapped_fit_iter(...)``;
          see :meth:`lsqfit.nonlinear_fit.bootstrapped_fit_iter` for more
          information.
  
          Args:
              data: Input data. One of ``data`` or ``pdata`` must be
                  specified but not both. ``pdata`` is obtained from ``data``
                  by collecting the output from ``m.builddata(data)``
                  for each model ``m`` and storing it in a dictionary
                  with key ``m.datatag``.
              pdata: Input data that has been processed by the
                  models using :meth:`MultiFitter.process_data` or
                  :meth:`MultiFitter.process_dataset`. One of
                  ``data`` or ``pdata`` must be  specified but not both.
              prior: Bayesian prior for fit parameters used by the models.
              p0: Dictionary , indexed by parameter labels, containing
                  initial values for the parameters in the fit. Setting
                  ``p0=None`` implies that initial values are extracted from the
                  prior. Setting ``p0="filename"`` causes the fitter to look in
                  the file with name ``"filename"`` for initial values and to
                  write out best-fit parameter values after the fit (for the
                  next call to ``self.lsqfit()``).
              kargs: Arguments that override parameters specified when
                  the :class:`MultiFitter` was created. Can also include
                  additional arguments to be passed through to
                  the :mod:`lsqfit` fitter.
          """
          if prior is None:
              raise ValueError('no prior')
          if add_priornoise:
              # intercept at top level so same treatment for all fits
              prior = prior + (gvar.sample(prior) - gvar.mean(prior))
          kargs, oldargs = self.set(**kargs)
  
          # parameters for bootstrap (see below)
          fitter_args_kargs = (
              self.chained_lsqfit,
              dict(data=data, prior=prior, pdata=pdata, models=self.models),
              dict(kargs),
              )
  
          # local copy of prior
          if self.fast:
              prior = self.buildprior(prior)
          else:
              prior = gvar.BufferDict(prior)
  
          # execute tasks in self.tasklist
          chained_fits = collections.OrderedDict()
          all_fnames = []
          all_fitp = []
          for tasktype, taskdata in self.tasklist:
              if tasktype == 'fit':
                  fitter = self.__class__(models=taskdata, **kargs)
                  fit = fitter.lsqfit(
                      data=data, pdata=pdata, prior=prior, p0=p0
                      )
                  fname = list(fit.chained_fits.keys())[0]
                  if fname in chained_fits:
                      raise ValueError('duplicate fits in chain: ' + str(fname))
                  elif fname[:5] == 'wavg(' and fname[-1] == ')':
                      raise ValueError('bad fit name: ' + fname)
                  else:
                      all_fnames.append(fname)
                      chained_fits[fname] = fit
                      all_fitp.append(fit.p)
              elif tasktype == 'update-prior':
                  lastfit = chained_fits[all_fnames[-1]]
                  lastfit_p = lastfit.p
                  for k in lastfit_p:
                      idx = tuple(
                          slice(None, i) for i in numpy.shape(lastfit.p[k])
                          )
                      if idx != ():
                          prior[k][idx] = lastfit.p[k]
                      else:
                          prior[k] = lastfit.p[k]
              elif tasktype == 'wavg':
                      nlist = all_fnames[-taskdata:]
                      plist = [chained_fits[k].p for k in nlist]
                      fit = lsqfit.wavg(plist, **self.wavg_kargs).fit
                      fname = self.fitname('wavg({})'.format(','.join(nlist)))
                      all_fnames.append(fname)
                      chained_fits[fname] = fit
              elif tasktype == 'update-kargs':
                  kargs.update(taskdata)
              else:
                  raise RuntimeError('unknown task: ' + tasktype)
  
          if self.fast and self.wavg_all:
              fit = lsqfit.wavg(all_fitp, **self.wavg_kargs).fit
              fname = self.fitname('wavg(all)')
              chained_fits[fname] = fit
              prior = fit.p
  
          # build output class
          self.fit = chained_nonlinear_fit(
              p=prior, chained_fits=chained_fits,
              multifitter=self, prior=fitter_args_kargs[1]['prior'],
              )
  
          # add bootstrap method
          fitter_args_kargs[1]['p0'] = self.fit.pmean
          def _bstrap_iter(
              n=None, datalist=None, pdatalist=None, **kargs
              ):
              return MultiFitter._bootstrapped_fit_iter(
                  fitter_args_kargs,
                  n=n, datalist=datalist, pdatalist=pdatalist, **kargs
                  )
          self.fit.bootstrapped_fit_iter = _bstrap_iter
  
          # restore default keywords
          self.set(**oldargs)
          return self.fit