lsst.fgcmcal  21.0.0-11-gd78879e+3b4b239aea
fgcmBuildStarsTable.py
Go to the documentation of this file.
1 # See COPYRIGHT file at the top of the source tree.
2 #
3 # This file is part of fgcmcal.
4 #
5 # Developed for the LSST Data Management System.
6 # This product includes software developed by the LSST Project
7 # (https://www.lsst.org).
8 # See the COPYRIGHT file at the top-level directory of this distribution
9 # for details of code ownership.
10 #
11 # This program is free software: you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation, either version 3 of the License, or
14 # (at your option) any later version.
15 #
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with this program. If not, see <https://www.gnu.org/licenses/>.
23 """Build star observations for input to FGCM using sourceTable_visit.
24 
25 This task finds all the visits and sourceTable_visits in a repository (or a
26 subset based on command line parameters) and extracts all the potential
27 calibration stars for input into fgcm. This task additionally uses fgcm to
28 match star observations into unique stars, and performs as much cleaning of the
29 input catalog as possible.
30 """
31 
32 import time
33 
34 import numpy as np
35 import collections
36 
37 import lsst.daf.persistence as dafPersist
38 import lsst.pex.config as pexConfig
39 import lsst.pipe.base as pipeBase
40 from lsst.pipe.base import connectionTypes
41 import lsst.afw.table as afwTable
42 from lsst.meas.algorithms import ReferenceObjectLoader
43 
44 from .fgcmBuildStarsBase import FgcmBuildStarsConfigBase, FgcmBuildStarsRunner, FgcmBuildStarsBaseTask
45 from .utilities import computeApproxPixelAreaFields, computeApertureRadiusFromDataRef
46 from .utilities import lookupStaticCalibrations
47 
48 __all__ = ['FgcmBuildStarsTableConfig', 'FgcmBuildStarsTableTask']
49 
50 
51 class FgcmBuildStarsTableConnections(pipeBase.PipelineTaskConnections,
52  dimensions=("instrument",),
53  defaultTemplates={}):
54  camera = connectionTypes.PrerequisiteInput(
55  doc="Camera instrument",
56  name="camera",
57  storageClass="Camera",
58  dimensions=("instrument",),
59  lookupFunction=lookupStaticCalibrations,
60  isCalibration=True,
61  )
62 
63  fgcmLookUpTable = connectionTypes.PrerequisiteInput(
64  doc=("Atmosphere + instrument look-up-table for FGCM throughput and "
65  "chromatic corrections."),
66  name="fgcmLookUpTable",
67  storageClass="Catalog",
68  dimensions=("instrument",),
69  deferLoad=True,
70  )
71 
72  sourceSchema = connectionTypes.PrerequisiteInput(
73  doc="Schema for source catalogs",
74  name="src_schema",
75  storageClass="SourceCatalog",
76  deferLoad=True,
77  )
78 
79  refCat = connectionTypes.PrerequisiteInput(
80  doc="Reference catalog to use for photometric calibration",
81  name="cal_ref_cat",
82  storageClass="SimpleCatalog",
83  dimensions=("skypix",),
84  deferLoad=True,
85  multiple=True,
86  )
87 
88  sourceTable_visit = connectionTypes.Input(
89  doc="Source table in parquet format, per visit",
90  name="sourceTable_visit",
91  storageClass="DataFrame",
92  dimensions=("instrument", "visit"),
93  deferLoad=True,
94  multiple=True,
95  )
96 
97  visitSummary = connectionTypes.Input(
98  doc=("Per-visit consolidated exposure metadata. These catalogs use "
99  "detector id for the id and must be sorted for fast lookups of a "
100  "detector."),
101  name="visitSummary",
102  storageClass="ExposureCatalog",
103  dimensions=("instrument", "visit"),
104  deferLoad=True,
105  multiple=True,
106  )
107 
108  background = connectionTypes.Input(
109  doc="Calexp background model",
110  name="calexpBackground",
111  storageClass="Background",
112  dimensions=("instrument", "visit", "detector"),
113  deferLoad=True,
114  multiple=True,
115  )
116 
117  fgcmVisitCatalog = connectionTypes.Output(
118  doc="Catalog of visit information for fgcm",
119  name="fgcmVisitCatalog",
120  storageClass="Catalog",
121  dimensions=("instrument",),
122  )
123 
124  fgcmStarObservations = connectionTypes.Output(
125  doc="Catalog of star observations for fgcm",
126  name="fgcmStarObservations",
127  storageClass="Catalog",
128  dimensions=("instrument",),
129  )
130 
131  fgcmStarIds = connectionTypes.Output(
132  doc="Catalog of fgcm calibration star IDs",
133  name="fgcmStarIds",
134  storageClass="Catalog",
135  dimensions=("instrument",),
136  )
137 
138  fgcmStarIndices = connectionTypes.Output(
139  doc="Catalog of fgcm calibration star indices",
140  name="fgcmStarIndices",
141  storageClass="Catalog",
142  dimensions=("instrument",),
143  )
144 
145  fgcmReferenceStars = connectionTypes.Output(
146  doc="Catalog of fgcm-matched reference stars",
147  name="fgcmReferenceStars",
148  storageClass="Catalog",
149  dimensions=("instrument",),
150  )
151 
152  def __init__(self, *, config=None):
153  super().__init__(config=config)
154 
155  if not config.doReferenceMatches:
156  self.prerequisiteInputs.remove("refCat")
157  self.prerequisiteInputs.remove("fgcmLookUpTable")
158 
159  if not config.doModelErrorsWithBackground:
160  self.inputs.remove("background")
161 
162  if not config.doReferenceMatches:
163  self.outputs.remove("fgcmReferenceStars")
164 
165 
166 class FgcmBuildStarsTableConfig(FgcmBuildStarsConfigBase, pipeBase.PipelineTaskConfig,
167  pipelineConnections=FgcmBuildStarsTableConnections):
168  """Config for FgcmBuildStarsTableTask"""
169 
170  referenceCCD = pexConfig.Field(
171  doc="Reference CCD for checking PSF and background",
172  dtype=int,
173  default=40,
174  )
175 
176  def setDefaults(self):
177  super().setDefaults()
178 
179  # The names here correspond to the post-transformed
180  # sourceTable_visit catalogs, which differ from the raw src
181  # catalogs. Therefore, all field and flag names cannot
182  # be derived from the base config class.
183  self.instFluxFieldinstFluxFieldinstFluxField = 'ApFlux_12_0_instFlux'
184  self.localBackgroundFluxFieldlocalBackgroundFluxFieldlocalBackgroundFluxField = 'LocalBackground_instFlux'
185  self.apertureInnerInstFluxFieldapertureInnerInstFluxFieldapertureInnerInstFluxField = 'ApFlux_12_0_instFlux'
186  self.apertureOuterInstFluxFieldapertureOuterInstFluxFieldapertureOuterInstFluxField = 'ApFlux_17_0_instFlux'
187  self.psfCandidateNamepsfCandidateNamepsfCandidateName = 'Calib_psf_candidate'
188 
189  sourceSelector = self.sourceSelectorsourceSelector["science"]
190 
191  fluxFlagName = self.instFluxFieldinstFluxFieldinstFluxField[0: -len('instFlux')] + 'flag'
192 
193  sourceSelector.flags.bad = ['PixelFlags_edge',
194  'PixelFlags_interpolatedCenter',
195  'PixelFlags_saturatedCenter',
196  'PixelFlags_crCenter',
197  'PixelFlags_bad',
198  'PixelFlags_interpolated',
199  'PixelFlags_saturated',
200  'Centroid_flag',
201  fluxFlagName]
202 
203  if self.doSubtractLocalBackgrounddoSubtractLocalBackground:
204  localBackgroundFlagName = self.localBackgroundFluxFieldlocalBackgroundFluxFieldlocalBackgroundFluxField[0: -len('instFlux')] + 'flag'
205  sourceSelector.flags.bad.append(localBackgroundFlagName)
206 
207  sourceSelector.signalToNoise.fluxField = self.instFluxFieldinstFluxFieldinstFluxField
208  sourceSelector.signalToNoise.errField = self.instFluxFieldinstFluxFieldinstFluxField + 'Err'
209 
210  sourceSelector.isolated.parentName = 'parentSourceId'
211  sourceSelector.isolated.nChildName = 'Deblend_nChild'
212 
213  sourceSelector.unresolved.name = 'extendedness'
214 
215 
217  """
218  Build stars for the FGCM global calibration, using sourceTable_visit catalogs.
219  """
220  ConfigClass = FgcmBuildStarsTableConfig
221  RunnerClass = FgcmBuildStarsRunner
222  _DefaultName = "fgcmBuildStarsTable"
223 
224  canMultiprocess = False
225 
226  def runQuantum(self, butlerQC, inputRefs, outputRefs):
227  inputRefDict = butlerQC.get(inputRefs)
228 
229  sourceTableRefs = inputRefDict['sourceTable_visit']
230 
231  self.log.info("Running with %d sourceTable_visit dataRefs",
232  len(sourceTableRefs))
233 
234  sourceTableDataRefDict = {sourceTableRef.dataId['visit']: sourceTableRef for
235  sourceTableRef in sourceTableRefs}
236 
237  if self.config.doReferenceMatches:
238  # Get the LUT dataRef
239  lutDataRef = inputRefDict['fgcmLookUpTable']
240 
241  # Prepare the refCat loader
242  refConfig = self.config.fgcmLoadReferenceCatalog.refObjLoader
243  refObjLoader = ReferenceObjectLoader(dataIds=[ref.datasetRef.dataId
244  for ref in inputRefs.refCat],
245  refCats=butlerQC.get(inputRefs.refCat),
246  config=refConfig,
247  log=self.log)
248  self.makeSubtask('fgcmLoadReferenceCatalog', refObjLoader=refObjLoader)
249  else:
250  lutDataRef = None
251 
252  # Compute aperture radius if necessary. This is useful to do now before
253  # any heave lifting has happened (fail early).
254  calibFluxApertureRadius = None
255  if self.config.doSubtractLocalBackground:
256  try:
257  calibFluxApertureRadius = computeApertureRadiusFromDataRef(sourceTableRefs[0],
258  self.config.instFluxField)
259  except RuntimeError as e:
260  raise RuntimeError("Could not determine aperture radius from %s. "
261  "Cannot use doSubtractLocalBackground." %
262  (self.config.instFluxField)) from e
263 
264  visitSummaryRefs = inputRefDict['visitSummary']
265  visitSummaryDataRefDict = {visitSummaryRef.dataId['visit']: visitSummaryRef for
266  visitSummaryRef in visitSummaryRefs}
267 
268  camera = inputRefDict['camera']
269  groupedDataRefs = self._groupDataRefs_groupDataRefs(sourceTableDataRefDict,
270  visitSummaryDataRefDict)
271 
272  if self.config.doModelErrorsWithBackground:
273  bkgRefs = inputRefDict['background']
274  bkgDataRefDict = {(bkgRef.dataId.byName()['visit'],
275  bkgRef.dataId.byName()['detector']): bkgRef for
276  bkgRef in bkgRefs}
277  else:
278  bkgDataRefDict = None
279 
280  # Gen3 does not currently allow "checkpoint" saving of datasets,
281  # so we need to have this all in one go.
282  visitCat = self.fgcmMakeVisitCatalogfgcmMakeVisitCatalog(camera, groupedDataRefs,
283  bkgDataRefDict=bkgDataRefDict,
284  visitCatDataRef=None,
285  inVisitCat=None)
286 
287  rad = calibFluxApertureRadius
288  sourceSchemaDataRef = inputRefDict['sourceSchema']
289  fgcmStarObservationCat = self.fgcmMakeAllStarObservationsfgcmMakeAllStarObservationsfgcmMakeAllStarObservations(groupedDataRefs,
290  visitCat,
291  sourceSchemaDataRef,
292  camera,
293  calibFluxApertureRadius=rad,
294  starObsDataRef=None,
295  visitCatDataRef=None,
296  inStarObsCat=None)
297 
298  butlerQC.put(visitCat, outputRefs.fgcmVisitCatalog)
299  butlerQC.put(fgcmStarObservationCat, outputRefs.fgcmStarObservations)
300 
301  fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat = self.fgcmMatchStarsfgcmMatchStars(visitCat,
302  fgcmStarObservationCat,
303  lutDataRef=lutDataRef)
304 
305  butlerQC.put(fgcmStarIdCat, outputRefs.fgcmStarIds)
306  butlerQC.put(fgcmStarIndicesCat, outputRefs.fgcmStarIndices)
307  if fgcmRefCat is not None:
308  butlerQC.put(fgcmRefCat, outputRefs.fgcmReferenceStars)
309 
310  @classmethod
311  def _makeArgumentParser(cls):
312  """Create an argument parser"""
313  parser = pipeBase.ArgumentParser(name=cls._DefaultName_DefaultName)
314  parser.add_id_argument("--id", "sourceTable_visit", help="Data ID, e.g. --id visit=6789")
315 
316  return parser
317 
318  def _groupDataRefs(self, sourceTableDataRefDict, visitSummaryDataRefDict):
319  """Group sourceTable and visitSummary dataRefs (gen3 only).
320 
321  Parameters
322  ----------
323  sourceTableDataRefDict : `dict` [`int`, `str`]
324  Dict of source tables, keyed by visit.
325  visitSummaryDataRefDict : `dict` [int, `str`]
326  Dict of visit summary catalogs, keyed by visit.
327 
328  Returns
329  -------
330  groupedDataRefs : `dict` [`int`, `list`]
331  Dictionary with sorted visit keys, and `list`s with
332  `lsst.daf.butler.DeferredDataSetHandle`. The first
333  item in the list will be the visitSummary ref, and
334  the second will be the source table ref.
335  """
336  groupedDataRefs = collections.defaultdict(list)
337  visits = sorted(sourceTableDataRefDict.keys())
338 
339  for visit in visits:
340  groupedDataRefs[visit] = [visitSummaryDataRefDict[visit],
341  sourceTableDataRefDict[visit]]
342 
343  return groupedDataRefs
344 
345  def _findAndGroupDataRefsGen2(self, butler, camera, dataRefs):
346  self.log.info("Grouping dataRefs by %s", (self.config.visitDataRefName))
347 
348  ccdIds = []
349  for detector in camera:
350  ccdIds.append(detector.getId())
351  # Insert our preferred referenceCCD first:
352  # It is fine that this is listed twice, because we only need
353  # the first calexp that is found.
354  ccdIds.insert(0, self.config.referenceCCD)
355 
356  # The visitTable building code expects a dictionary of groupedDataRefs
357  # keyed by visit, the first element as the "primary" calexp dataRef.
358  # We then append the sourceTable_visit dataRef at the end for the
359  # code which does the data reading (fgcmMakeAllStarObservations).
360 
361  groupedDataRefs = collections.defaultdict(list)
362  for dataRef in dataRefs:
363  visit = dataRef.dataId[self.config.visitDataRefName]
364 
365  # Find an existing calexp (we need for psf and metadata)
366  # and make the relevant dataRef
367  for ccdId in ccdIds:
368  try:
369  calexpRef = butler.dataRef('calexp', dataId={self.config.visitDataRefName: visit,
370  self.config.ccdDataRefName: ccdId})
371  except RuntimeError:
372  # Not found
373  continue
374 
375  # It was found. Add and quit out, since we only
376  # need one calexp per visit.
377  groupedDataRefs[visit].append(calexpRef)
378  break
379 
380  # And append this dataRef
381  groupedDataRefs[visit].append(dataRef)
382 
383  # This should be sorted by visit (the key)
384  return dict(sorted(groupedDataRefs.items()))
385 
386  def fgcmMakeAllStarObservations(self, groupedDataRefs, visitCat,
387  sourceSchemaDataRef,
388  camera,
389  calibFluxApertureRadius=None,
390  visitCatDataRef=None,
391  starObsDataRef=None,
392  inStarObsCat=None):
393  startTime = time.time()
394 
395  # If both dataRefs are None, then we assume the caller does not
396  # want to store checkpoint files. If both are set, we will
397  # do checkpoint files. And if only one is set, this is potentially
398  # unintentional and we will warn.
399  if (visitCatDataRef is not None and starObsDataRef is None
400  or visitCatDataRef is None and starObsDataRef is not None):
401  self.log.warn("Only one of visitCatDataRef and starObsDataRef are set, so "
402  "no checkpoint files will be persisted.")
403 
404  if self.config.doSubtractLocalBackground and calibFluxApertureRadius is None:
405  raise RuntimeError("Must set calibFluxApertureRadius if doSubtractLocalBackground is True.")
406 
407  # To get the correct output schema, we use similar code as fgcmBuildStarsTask
408  # We are not actually using this mapper, except to grab the outputSchema
409  sourceSchema = sourceSchemaDataRef.get().schema
410  sourceMapper = self._makeSourceMapper_makeSourceMapper(sourceSchema)
411  outputSchema = sourceMapper.getOutputSchema()
412 
413  # Construct mapping from ccd number to index
414  ccdMapping = {}
415  for ccdIndex, detector in enumerate(camera):
416  ccdMapping[detector.getId()] = ccdIndex
417 
418  approxPixelAreaFields = computeApproxPixelAreaFields(camera)
419 
420  if inStarObsCat is not None:
421  fullCatalog = inStarObsCat
422  comp1 = fullCatalog.schema.compare(outputSchema, outputSchema.EQUAL_KEYS)
423  comp2 = fullCatalog.schema.compare(outputSchema, outputSchema.EQUAL_NAMES)
424  if not comp1 or not comp2:
425  raise RuntimeError("Existing fgcmStarObservations file found with mismatched schema.")
426  else:
427  fullCatalog = afwTable.BaseCatalog(outputSchema)
428 
429  visitKey = outputSchema['visit'].asKey()
430  ccdKey = outputSchema['ccd'].asKey()
431  instMagKey = outputSchema['instMag'].asKey()
432  instMagErrKey = outputSchema['instMagErr'].asKey()
433 
434  # Prepare local background if desired
435  if self.config.doSubtractLocalBackground:
436  localBackgroundArea = np.pi*calibFluxApertureRadius**2.
437 
438  # Determine which columns we need from the sourceTable_visit catalogs
439  columns = self._get_sourceTable_visit_columns_get_sourceTable_visit_columns()
440 
441  k = 2.5/np.log(10.)
442 
443  for counter, visit in enumerate(visitCat):
444  # Check if these sources have already been read and stored in the checkpoint file
445  if visit['sources_read']:
446  continue
447 
448  expTime = visit['exptime']
449 
450  dataRef = groupedDataRefs[visit['visit']][-1]
451 
452  if isinstance(dataRef, dafPersist.ButlerDataRef):
453  srcTable = dataRef.get()
454  df = srcTable.toDataFrame(columns)
455  else:
456  df = dataRef.get(parameters={'columns': columns})
457 
458  goodSrc = self.sourceSelector.selectSources(df)
459 
460  # Need to add a selection based on the local background correction
461  # if necessary
462  if self.config.doSubtractLocalBackground:
463  localBackground = localBackgroundArea*df[self.config.localBackgroundFluxField].values
464  use, = np.where((goodSrc.selected)
465  & ((df[self.config.instFluxField].values - localBackground) > 0.0))
466  else:
467  use, = np.where(goodSrc.selected)
468 
469  tempCat = afwTable.BaseCatalog(fullCatalog.schema)
470  tempCat.resize(use.size)
471 
472  tempCat['ra'][:] = np.deg2rad(df['ra'].values[use])
473  tempCat['dec'][:] = np.deg2rad(df['decl'].values[use])
474  tempCat['x'][:] = df['x'].values[use]
475  tempCat['y'][:] = df['y'].values[use]
476  # These "visit" and "ccd" names in the parquet tables are
477  # hard-coded.
478  tempCat[visitKey][:] = df['visit'].values[use]
479  tempCat[ccdKey][:] = df['ccd'].values[use]
480  tempCat['psf_candidate'] = df['Calib_psf_candidate'].values[use]
481 
482  if self.config.doSubtractLocalBackground:
483  # At the moment we only adjust the flux and not the flux
484  # error by the background because the error on
485  # base_LocalBackground_instFlux is the rms error in the
486  # background annulus, not the error on the mean in the
487  # background estimate (which is much smaller, by sqrt(n)
488  # pixels used to estimate the background, which we do not
489  # have access to in this task). In the default settings,
490  # the annulus is sufficiently large such that these
491  # additional errors are are negligibly small (much less
492  # than a mmag in quadrature).
493 
494  # This is the difference between the mag with local background correction
495  # and the mag without local background correction.
496  tempCat['deltaMagBkg'] = (-2.5*np.log10(df[self.config.instFluxField].values[use]
497  - localBackground[use]) -
498  -2.5*np.log10(df[self.config.instFluxField].values[use]))
499  else:
500  tempCat['deltaMagBkg'][:] = 0.0
501 
502  # Need to loop over ccds here
503  for detector in camera:
504  ccdId = detector.getId()
505  # used index for all observations with a given ccd
506  use2 = (tempCat[ccdKey] == ccdId)
507  tempCat['jacobian'][use2] = approxPixelAreaFields[ccdId].evaluate(tempCat['x'][use2],
508  tempCat['y'][use2])
509  scaledInstFlux = (df[self.config.instFluxField].values[use[use2]]
510  * visit['scaling'][ccdMapping[ccdId]])
511  tempCat[instMagKey][use2] = (-2.5*np.log10(scaledInstFlux) + 2.5*np.log10(expTime))
512 
513  # Compute instMagErr from instFluxErr/instFlux, any scaling
514  # will cancel out.
515  tempCat[instMagErrKey][:] = k*(df[self.config.instFluxField + 'Err'].values[use]
516  / df[self.config.instFluxField].values[use])
517 
518  # Apply the jacobian if configured
519  if self.config.doApplyWcsJacobian:
520  tempCat[instMagKey][:] -= 2.5*np.log10(tempCat['jacobian'][:])
521 
522  fullCatalog.extend(tempCat)
523 
524  # Now do the aperture information
525  with np.warnings.catch_warnings():
526  # Ignore warnings, we will filter infinites and nans below
527  np.warnings.simplefilter("ignore")
528 
529  instMagIn = -2.5*np.log10(df[self.config.apertureInnerInstFluxField].values[use])
530  instMagErrIn = k*(df[self.config.apertureInnerInstFluxField + 'Err'].values[use]
531  / df[self.config.apertureInnerInstFluxField].values[use])
532  instMagOut = -2.5*np.log10(df[self.config.apertureOuterInstFluxField].values[use])
533  instMagErrOut = k*(df[self.config.apertureOuterInstFluxField + 'Err'].values[use]
534  / df[self.config.apertureOuterInstFluxField].values[use])
535 
536  ok = (np.isfinite(instMagIn) & np.isfinite(instMagErrIn)
537  & np.isfinite(instMagOut) & np.isfinite(instMagErrOut))
538 
539  visit['deltaAper'] = np.median(instMagIn[ok] - instMagOut[ok])
540  visit['sources_read'] = True
541 
542  self.log.info(" Found %d good stars in visit %d (deltaAper = %0.3f)",
543  use.size, visit['visit'], visit['deltaAper'])
544 
545  if ((counter % self.config.nVisitsPerCheckpoint) == 0
546  and starObsDataRef is not None and visitCatDataRef is not None):
547  # We need to persist both the stars and the visit catalog which gets
548  # additional metadata from each visit.
549  starObsDataRef.put(fullCatalog)
550  visitCatDataRef.put(visitCat)
551 
552  self.log.info("Found all good star observations in %.2f s" %
553  (time.time() - startTime))
554 
555  return fullCatalog
556 
557  def _get_sourceTable_visit_columns(self):
558  """
559  Get the sourceTable_visit columns from the config.
560 
561  Returns
562  -------
563  columns : `list`
564  List of columns to read from sourceTable_visit
565  """
566  # These "visit" and "ccd" names in the parquet tables are hard-coded.
567  columns = ['visit', 'ccd',
568  'ra', 'decl', 'x', 'y', self.config.psfCandidateName,
569  self.config.instFluxField, self.config.instFluxField + 'Err',
570  self.config.apertureInnerInstFluxField, self.config.apertureInnerInstFluxField + 'Err',
571  self.config.apertureOuterInstFluxField, self.config.apertureOuterInstFluxField + 'Err']
572  if self.sourceSelector.config.doFlags:
573  columns.extend(self.sourceSelector.config.flags.bad)
574  if self.sourceSelector.config.doUnresolved:
575  columns.append(self.sourceSelector.config.unresolved.name)
576  if self.sourceSelector.config.doIsolated:
577  columns.append(self.sourceSelector.config.isolated.parentName)
578  columns.append(self.sourceSelector.config.isolated.nChildName)
579  if self.config.doSubtractLocalBackground:
580  columns.append(self.config.localBackgroundFluxField)
581 
582  return columns
def fgcmMatchStars(self, visitCat, obsCat, lutDataRef=None)
def fgcmMakeVisitCatalog(self, camera, groupedDataRefs, bkgDataRefDict=None, visitCatDataRef=None, inVisitCat=None)
def fgcmMakeAllStarObservations(self, groupedDataRefs, visitCat, sourceSchemaDataRef, camera, calibFluxApertureRadius=None, visitCatDataRef=None, starObsDataRef=None, inStarObsCat=None)
def runQuantum(self, butlerQC, inputRefs, outputRefs)
def fgcmMakeAllStarObservations(self, groupedDataRefs, visitCat, sourceSchemaDataRef, camera, calibFluxApertureRadius=None, visitCatDataRef=None, starObsDataRef=None, inStarObsCat=None)
def _groupDataRefs(self, sourceTableDataRefDict, visitSummaryDataRefDict)
def computeApertureRadiusFromDataRef(dataRef, fluxField)
Definition: utilities.py:799
def computeApproxPixelAreaFields(camera)
Definition: utilities.py:486