docs: def simple_srcflux(env, infile=None, psfmethod='arfcorr', conf=0.68,
                     verbose=0, **kwargs):
      """Run the CIAO "srcflux" script and retrieve its results.
  
      *infile*
        The input events file; must be specified. The computation is done
        in a temporary directory, so this path — and all others passed in
        as arguments — **must be made absolute**.
      *psfmethod* = "arfcorr"
        The PSF modeling method to be used; see the "srcflux" documentation.
      *conf* = 0.68
        The confidence limit to detect. We default to 1 sigma, instead of
        the 90% mark, which is the srcflux default.
      *verbose* = 0
        The level of verbosity to be used by the tool.
      *kwargs*
        Remaining keyword arguments are passed to the tool as command-line
        keyword arguments, with values stringified.
      Returns:
        A :class:`pandas.DataFrame` extracted from the results table generated
        by the tool. There is one row for each source analyzed; in common usage,
        this means that there will be one row.
  
      """
      from ...io import Path
      import shutil, signal, tempfile
  
      if infile is None:
          raise ValueError('must specify infile')
  
      kwargs.update(dict(
          infile = infile,
          psfmethod = psfmethod,
          conf = conf,
          verbose = verbose,
          clobber = 'yes',
          outroot = 'sf',
      ))
  
      argv = ['srcflux'] + ['%s=%s' % t for t in kwargs.items()]
      argstr = ' '.join(argv)
      tempdir = None
  
      try:
          tempdir = tempfile.mkdtemp(prefix='srcflux')
  
          proc = env.launch(argv, cwd=tempdir, shell=False)
          retcode = proc.wait()
  
          if retcode > 0:
              raise RuntimeError('command "%s" failed with exit code %d' % (argstr, retcode))
          elif retcode == -signal.SIGINT:
              raise KeyboardInterrupt()
          elif retcode < 0:
              raise RuntimeError('command "%s" killed by signal %d' % (argstr, -retcode))
  
          tables = list(Path(tempdir).glob('*.flux'))
          if len(tables) != 1:
              raise RuntimeError('expected exactly one flux table from srcflux; got %d' % len(tables))
  
          return tables[0].read_fits_bintable(hdu=1)
      finally:
          if tempdir is not None:
              shutil.rmtree(tempdir, onerror=_rmtree_error)