21 """Base class for BuildStars using src tables or sourceTable_visit tables.
31 import lsst.daf.persistence
as dafPersist
32 import lsst.pex.config
as pexConfig
33 import lsst.pipe.base
as pipeBase
34 import lsst.afw.table
as afwTable
35 import lsst.geom
as geom
36 from lsst.daf.base
import PropertyList
37 from lsst.daf.base.dateTime
import DateTime
38 from lsst.meas.algorithms.sourceSelector
import sourceSelectorRegistry
40 from .utilities
import computeApertureRadiusFromDataRef
41 from .fgcmLoadReferenceCatalog
import FgcmLoadReferenceCatalogTask
45 REFSTARS_FORMAT_VERSION = 1
47 __all__ = [
'FgcmBuildStarsConfigBase',
'FgcmBuildStarsRunner',
'FgcmBuildStarsBaseTask']
51 """Base config for FgcmBuildStars tasks"""
53 instFluxField = pexConfig.Field(
54 doc=(
"Faull name of the source instFlux field to use, including 'instFlux'. "
55 "The associated flag will be implicitly included in badFlags"),
57 default=
'slot_CalibFlux_instFlux',
59 minPerBand = pexConfig.Field(
60 doc=
"Minimum observations per band",
64 matchRadius = pexConfig.Field(
65 doc=
"Match radius (arcseconds)",
69 isolationRadius = pexConfig.Field(
70 doc=
"Isolation radius (arcseconds)",
74 densityCutNside = pexConfig.Field(
75 doc=
"Density cut healpix nside",
79 densityCutMaxPerPixel = pexConfig.Field(
80 doc=
"Density cut number of stars per pixel",
84 matchNside = pexConfig.Field(
85 doc=
"Healpix Nside for matching",
89 coarseNside = pexConfig.Field(
90 doc=
"Healpix coarse Nside for partitioning matches",
97 physicalFilterMap = pexConfig.DictField(
98 doc=
"Mapping from 'physicalFilter' to band.",
103 requiredBands = pexConfig.ListField(
104 doc=
"Bands required for each star",
108 primaryBands = pexConfig.ListField(
109 doc=(
"Bands for 'primary' star matches. "
110 "A star must be observed in one of these bands to be considered "
111 "as a calibration star."),
115 visitDataRefName = pexConfig.Field(
116 doc=
"dataRef name for the 'visit' field, usually 'visit'.",
120 ccdDataRefName = pexConfig.Field(
121 doc=
"dataRef name for the 'ccd' field, usually 'ccd' or 'detector'.",
125 doApplyWcsJacobian = pexConfig.Field(
126 doc=
"Apply the jacobian of the WCS to the star observations prior to fit?",
130 doModelErrorsWithBackground = pexConfig.Field(
131 doc=
"Model flux errors with background term?",
135 psfCandidateName = pexConfig.Field(
136 doc=
"Name of field with psf candidate flag for propagation",
138 default=
"calib_psf_candidate"
140 doSubtractLocalBackground = pexConfig.Field(
141 doc=(
"Subtract the local background before performing calibration? "
142 "This is only supported for circular aperture calibration fluxes."),
146 localBackgroundFluxField = pexConfig.Field(
147 doc=
"Full name of the local background instFlux field to use.",
149 default=
'base_LocalBackground_instFlux'
151 sourceSelector = sourceSelectorRegistry.makeField(
152 doc=
"How to select sources",
155 apertureInnerInstFluxField = pexConfig.Field(
156 doc=(
"Full name of instFlux field that contains inner aperture "
157 "flux for aperture correction proxy"),
159 default=
'base_CircularApertureFlux_12_0_instFlux'
161 apertureOuterInstFluxField = pexConfig.Field(
162 doc=(
"Full name of instFlux field that contains outer aperture "
163 "flux for aperture correction proxy"),
165 default=
'base_CircularApertureFlux_17_0_instFlux'
167 doReferenceMatches = pexConfig.Field(
168 doc=
"Match reference catalog as additional constraint on calibration",
172 fgcmLoadReferenceCatalog = pexConfig.ConfigurableField(
173 target=FgcmLoadReferenceCatalogTask,
174 doc=
"FGCM reference object loader",
176 nVisitsPerCheckpoint = pexConfig.Field(
177 doc=
"Number of visits read between checkpoints",
184 sourceSelector.setDefaults()
186 sourceSelector.doFlags =
True
187 sourceSelector.doUnresolved =
True
188 sourceSelector.doSignalToNoise =
True
189 sourceSelector.doIsolated =
True
191 sourceSelector.signalToNoise.minimum = 10.0
192 sourceSelector.signalToNoise.maximum = 1000.0
196 sourceSelector.unresolved.maximum = 0.5
200 """Subclass of TaskRunner for FgcmBuildStars tasks
202 fgcmBuildStarsTask.run() and fgcmBuildStarsTableTask.run() take a number of
203 arguments, one of which is the butler (for persistence and mapper data),
204 and a list of dataRefs extracted from the command line. Note that FGCM
205 runs on a large set of dataRefs, and not on single dataRef/tract/patch.
206 This class transforms the process arguments generated by the ArgumentParser
207 into the arguments expected by FgcmBuildStarsTask.run(). This runner does
208 not use any parallelization.
213 Return a list with one element: a tuple with the butler and
217 return [(parsedCmd.butler, parsedCmd.id.refList)]
223 args: `tuple` with (butler, dataRefList)
227 exitStatus: `list` with `lsst.pipe.base.Struct`
228 exitStatus (0: success; 1: failure)
230 butler, dataRefList = args
232 task = self.TaskClass(config=self.config, log=self.log)
236 task.runDataRef(butler, dataRefList)
239 task.runDataRef(butler, dataRefList)
240 except Exception
as e:
242 task.log.fatal(
"Failed: %s" % e)
243 if not isinstance(e, pipeBase.TaskError):
244 traceback.print_exc(file=sys.stderr)
246 task.writeMetadata(butler)
249 return [pipeBase.Struct(exitStatus=exitStatus)]
253 Run the task, with no multiprocessing
257 parsedCmd: `lsst.pipe.base.ArgumentParser` parsed command line
262 if self.precall(parsedCmd):
264 resultList = self(targetList[0])
271 Base task to build stars for FGCM global calibration
275 butler : `lsst.daf.persistence.Butler`
277 def __init__(self, initInputs=None, butler=None, **kwargs):
280 self.makeSubtask(
"sourceSelector")
282 self.sourceSelector.log.setLevel(self.sourceSelector.log.WARN)
285 def _getMetadataName(self):
291 Cross-match and make star list for FGCM Input
295 butler: `lsst.daf.persistence.Butler`
296 dataRefs: `list` of `lsst.daf.persistence.ButlerDataRef`
297 Source data references for the input visits.
301 RuntimeErrror: Raised if `config.doReferenceMatches` is set and
302 an fgcmLookUpTable is not available, or if computeFluxApertureRadius()
303 fails if the calibFlux is not a CircularAperture flux.
305 datasetType = dataRefs[0].butlerSubset.datasetType
306 self.log.info(
"Running with %d %s dataRefs", len(dataRefs), datasetType)
308 if self.config.doReferenceMatches:
309 self.makeSubtask(
"fgcmLoadReferenceCatalog", butler=butler)
311 if not butler.datasetExists(
'fgcmLookUpTable'):
312 raise RuntimeError(
"Must have fgcmLookUpTable if using config.doReferenceMatches")
315 calibFluxApertureRadius =
None
316 if self.config.doSubtractLocalBackground:
319 self.config.instFluxField)
320 except RuntimeError
as e:
321 raise RuntimeError(
"Could not determine aperture radius from %s. "
322 "Cannot use doSubtractLocalBackground." %
323 (self.config.instFluxField))
from e
325 camera = butler.get(
'camera')
333 visitCatDataRef = butler.dataRef(
'fgcmVisitCatalog')
334 filename = visitCatDataRef.get(
'fgcmVisitCatalog_filename')[0]
335 if os.path.exists(filename):
337 inVisitCat = visitCatDataRef.get()
338 if len(inVisitCat) != len(groupedDataRefs):
339 raise RuntimeError(
"Existing visitCatalog found, but has an inconsistent "
340 "number of visits. Cannot continue.")
345 visitCatDataRef=visitCatDataRef,
346 inVisitCat=inVisitCat)
349 visitCatDataRef.put(visitCat)
351 starObsDataRef = butler.dataRef(
'fgcmStarObservations')
352 filename = starObsDataRef.get(
'fgcmStarObservations_filename')[0]
353 if os.path.exists(filename):
354 inStarObsCat = starObsDataRef.get()
358 rad = calibFluxApertureRadius
359 sourceSchemaDataRef = butler.dataRef(
'src_schema')
360 sourceSchema = sourceSchemaDataRef.get(
'src_schema', immediate=
True).schema
365 calibFluxApertureRadius=rad,
366 starObsDataRef=starObsDataRef,
367 visitCatDataRef=visitCatDataRef,
368 inStarObsCat=inStarObsCat)
369 visitCatDataRef.put(visitCat)
370 starObsDataRef.put(fgcmStarObservationCat)
373 if self.config.doReferenceMatches:
374 lutDataRef = butler.dataRef(
'fgcmLookUpTable')
377 fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat = self.
fgcmMatchStarsfgcmMatchStars(visitCat,
378 fgcmStarObservationCat,
379 lutDataRef=lutDataRef)
382 butler.put(fgcmStarIdCat,
'fgcmStarIds')
383 butler.put(fgcmStarIndicesCat,
'fgcmStarIndices')
384 if fgcmRefCat
is not None:
385 butler.put(fgcmRefCat,
'fgcmReferenceStars')
388 def _findAndGroupDataRefsGen2(self, butler, camera, dataRefs):
390 Find and group dataRefs (by visit); Gen2 only.
394 butler : `lsst.daf.persistence.Butler`
396 camera : `lsst.afw.cameraGeom.Camera`
397 Camera from the butler.
398 dataRefs : `list` of `lsst.daf.persistence.ButlerDataRef`
399 Data references for the input visits.
403 groupedDataRefs : `dict` [`int`, `list`]
404 Dictionary with sorted visit keys, and `list`s of
405 `lsst.daf.persistence.ButlerDataRef`
407 raise NotImplementedError(
"_findAndGroupDataRefsGen2 not implemented.")
413 calibFluxApertureRadius=None,
414 visitCatDataRef=None,
418 Compile all good star observations from visits in visitCat. Checkpoint files
419 will be stored if both visitCatDataRef and starObsDataRef are not None.
423 groupedDataRefs : `dict` of `list`s
424 Lists of `~lsst.daf.persistence.ButlerDataRef` or
425 `~lsst.daf.butler.DeferredDatasetHandle`, grouped by visit.
426 visitCat : `~afw.table.BaseCatalog`
427 Catalog with visit data for FGCM
428 sourceSchema : `~lsst.afw.table.Schema`
429 Schema for the input src catalogs.
430 camera : `~lsst.afw.cameraGeom.Camera`
431 calibFluxApertureRadius : `float`, optional
432 Aperture radius for calibration flux.
433 visitCatDataRef : `~lsst.daf.persistence.ButlerDataRef`, optional
434 Dataref to write visitCat for checkpoints
435 starObsDataRef : `~lsst.daf.persistence.ButlerDataRef`, optional
436 Dataref to write the star observation catalog for checkpoints.
437 inStarObsCat : `~afw.table.BaseCatalog`
438 Input observation catalog. If this is incomplete, observations
439 will be appended from when it was cut off.
443 fgcmStarObservations : `afw.table.BaseCatalog`
444 Full catalog of good observations.
448 RuntimeError: Raised if doSubtractLocalBackground is True and
449 calibFluxApertureRadius is not set.
451 raise NotImplementedError(
"fgcmMakeAllStarObservations not implemented.")
454 visitCatDataRef=None, inVisitCat=None):
456 Make a visit catalog with all the keys from each visit
460 camera: `lsst.afw.cameraGeom.Camera`
461 Camera from the butler
462 groupedDataRefs: `dict`
463 Dictionary with visit keys, and `list`s of
464 `lsst.daf.persistence.ButlerDataRef`
465 bkgDataRefDict: `dict`, optional
466 Dictionary of gen3 dataRefHandles for background info.
467 visitCatDataRef: `lsst.daf.persistence.ButlerDataRef`, optional
468 Dataref to write visitCat for checkpoints
469 inVisitCat: `afw.table.BaseCatalog`, optional
470 Input (possibly incomplete) visit catalog
474 visitCat: `afw.table.BaseCatalog`
477 self.log.info(
"Assembling visitCatalog from %d %ss" %
478 (len(groupedDataRefs), self.config.visitDataRefName))
482 if inVisitCat
is None:
485 visitCat = afwTable.BaseCatalog(schema)
486 visitCat.reserve(len(groupedDataRefs))
487 visitCat.resize(len(groupedDataRefs))
489 visitCat[
'visit'] = list(groupedDataRefs.keys())
491 visitCat[
'sources_read'] =
False
493 visitCat = inVisitCat
498 bkgDataRefDict=bkgDataRefDict,
499 visitCatDataRef=visitCatDataRef)
503 def _fillVisitCatalog(self, visitCat, groupedDataRefs, bkgDataRefDict=None,
504 visitCatDataRef=None):
506 Fill the visit catalog with visit metadata
510 visitCat : `afw.table.BaseCatalog`
511 Visit catalog. See _makeFgcmVisitSchema() for schema definition.
512 groupedDataRefs : `dict`
513 Dictionary with visit keys, and `list`s of
514 `lsst.daf.persistence.ButlerDataRef` or
515 `lsst.daf.butler.DeferredDatasetHandle`
516 visitCatDataRef : `lsst.daf.persistence.ButlerDataRef`, optional
517 Dataref to write ``visitCat`` for checkpoints. Gen2 only.
518 bkgDataRefDict : `dict`, optional
519 Dictionary of Gen3 `lsst.daf.butler.DeferredDatasetHandle`
522 bbox = geom.BoxI(geom.PointI(0, 0), geom.PointI(1, 1))
524 for i, visit
in enumerate(groupedDataRefs):
531 if visitCat[
'used'][i]:
534 if (i % self.config.nVisitsPerCheckpoint) == 0:
535 self.log.info(
"Retrieving metadata for %s %d (%d/%d)" %
536 (self.config.visitDataRefName, visit, i, len(groupedDataRefs)))
538 if visitCatDataRef
is not None:
539 visitCatDataRef.put(visitCat)
541 dataRef = groupedDataRefs[visit][0]
542 if isinstance(dataRef, dafPersist.ButlerDataRef):
545 exp = dataRef.get(datasetType=
'calexp_sub', bbox=bbox)
546 visitInfo = exp.getInfo().getVisitInfo()
547 label = dataRef.get(datasetType=
'calexp_filterLabel')
548 physicalFilter = label.physicalLabel
550 psfSigma = psf.computeShape().getDeterminantRadius()
553 summary = dataRef.get()
555 summaryRow = summary.find(self.config.referenceCCD)
556 if summaryRow
is None:
558 summaryRow = summary[0]
560 summaryDetector = summaryRow[
'id']
561 visitInfo = summaryRow.getVisitInfo()
562 physicalFilter = summaryRow[
'physical_filter']
564 goodSigma, = np.where(summary[
'psfSigma'] > 0)
565 if goodSigma.size > 2:
566 psfSigma = np.median(summary[
'psfSigma'][goodSigma])
568 psfSigma = np.mean(summary[
'psfSigma'][goodSigma])
574 rec[
'physicalFilter'] = physicalFilter
578 radec = visitInfo.getBoresightRaDec()
579 rec[
'telra'] = radec.getRa().asDegrees()
580 rec[
'teldec'] = radec.getDec().asDegrees()
581 rec[
'telha'] = visitInfo.getBoresightHourAngle().asDegrees()
582 rec[
'telrot'] = visitInfo.getBoresightRotAngle().asDegrees()
583 rec[
'mjd'] = visitInfo.getDate().get(system=DateTime.MJD)
584 rec[
'exptime'] = visitInfo.getExposureTime()
587 rec[
'pmb'] = visitInfo.getWeather().getAirPressure() / 100
591 rec[
'scaling'][:] = 1.0
593 rec[
'deltaAper'] = 0.0
594 rec[
'psfSigma'] = psfSigma
596 if self.config.doModelErrorsWithBackground:
598 if isinstance(dataRef, dafPersist.ButlerDataRef):
600 det = dataRef.dataId[self.config.ccdDataRefName]
601 if dataRef.datasetExists(datasetType=
'calexpBackground'):
602 bgList = dataRef.get(datasetType=
'calexpBackground')
608 bkgRef = bkgDataRefDict[(visit, summaryDetector)]
609 bgList = bkgRef.get()
615 bgStats = (bg[0].getStatsImage().getImage().array
617 rec[
'skyBackground'] = sum(np.median(bg[np.isfinite(bg)])
for bg
in bgStats)
619 self.log.warn(
'Sky background not found for visit %d / ccd %d' %
621 rec[
'skyBackground'] = -1.0
623 rec[
'skyBackground'] = -1.0
627 def _makeSourceMapper(self, sourceSchema):
629 Make a schema mapper for fgcm sources
633 sourceSchema: `afwTable.Schema`
634 Default source schema from the butler
638 sourceMapper: `afwTable.schemaMapper`
639 Mapper to the FGCM source schema
643 sourceMapper = afwTable.SchemaMapper(sourceSchema)
646 sourceMapper.addMapping(sourceSchema[
'coord_ra'].asKey(),
'ra')
647 sourceMapper.addMapping(sourceSchema[
'coord_dec'].asKey(),
'dec')
648 sourceMapper.addMapping(sourceSchema[
'slot_Centroid_x'].asKey(),
'x')
649 sourceMapper.addMapping(sourceSchema[
'slot_Centroid_y'].asKey(),
'y')
655 sourceMapper.addMapping(sourceSchema[self.config.psfCandidateName].asKey(),
658 sourceMapper.editOutputSchema().addField(
659 "psf_candidate", type=
'Flag',
660 doc=(
"Flag set if the source was a candidate for PSF determination, "
661 "as determined by the star selector."))
664 sourceMapper.editOutputSchema().addField(
665 "visit", type=np.int32, doc=
"Visit number")
666 sourceMapper.editOutputSchema().addField(
667 "ccd", type=np.int32, doc=
"CCD number")
668 sourceMapper.editOutputSchema().addField(
669 "instMag", type=np.float32, doc=
"Instrumental magnitude")
670 sourceMapper.editOutputSchema().addField(
671 "instMagErr", type=np.float32, doc=
"Instrumental magnitude error")
672 sourceMapper.editOutputSchema().addField(
673 "jacobian", type=np.float32, doc=
"Relative pixel scale from wcs jacobian")
674 sourceMapper.editOutputSchema().addField(
675 "deltaMagBkg", type=np.float32, doc=
"Change in magnitude due to local background offset")
681 Use FGCM code to match observations into unique stars.
685 visitCat: `afw.table.BaseCatalog`
686 Catalog with visit data for fgcm
687 obsCat: `afw.table.BaseCatalog`
688 Full catalog of star observations for fgcm
689 lutDataRef: `lsst.daf.persistence.ButlerDataRef` or
690 `lsst.daf.butler.DeferredDatasetHandle`, optional
691 Data reference to fgcm look-up table (used if matching reference stars).
695 fgcmStarIdCat: `afw.table.BaseCatalog`
696 Catalog of unique star identifiers and index keys
697 fgcmStarIndicesCat: `afwTable.BaseCatalog`
698 Catalog of unique star indices
699 fgcmRefCat: `afw.table.BaseCatalog`
700 Catalog of matched reference stars.
701 Will be None if `config.doReferenceMatches` is False.
705 visitFilterNames = np.zeros(len(visitCat), dtype=
'a30')
706 for i
in range(len(visitCat)):
707 visitFilterNames[i] = visitCat[i][
'physicalFilter']
710 visitIndex = np.searchsorted(visitCat[
'visit'],
713 obsFilterNames = visitFilterNames[visitIndex]
715 if self.config.doReferenceMatches:
717 lutCat = lutDataRef.get()
719 stdFilterDict = {filterName: stdFilter
for (filterName, stdFilter)
in
720 zip(lutCat[0][
'physicalFilters'].split(
','),
721 lutCat[0][
'stdPhysicalFilters'].split(
','))}
722 stdLambdaDict = {stdFilter: stdLambda
for (stdFilter, stdLambda)
in
723 zip(lutCat[0][
'stdPhysicalFilters'].split(
','),
724 lutCat[0][
'lambdaStdFilter'])}
731 self.log.info(
"Using the following reference filters: %s" %
732 (
', '.join(referenceFilterNames)))
736 referenceFilterNames = []
739 starConfig = {
'logger': self.log,
740 'filterToBand': self.config.physicalFilterMap,
741 'requiredBands': self.config.requiredBands,
742 'minPerBand': self.config.minPerBand,
743 'matchRadius': self.config.matchRadius,
744 'isolationRadius': self.config.isolationRadius,
745 'matchNSide': self.config.matchNside,
746 'coarseNSide': self.config.coarseNside,
747 'densNSide': self.config.densityCutNside,
748 'densMaxPerPixel': self.config.densityCutMaxPerPixel,
749 'primaryBands': self.config.primaryBands,
750 'referenceFilterNames': referenceFilterNames}
753 fgcmMakeStars = fgcm.FgcmMakeStars(starConfig)
761 conv = obsCat[0][
'ra'].asDegrees() / float(obsCat[0][
'ra'])
762 fgcmMakeStars.makePrimaryStars(obsCat[
'ra'] * conv,
763 obsCat[
'dec'] * conv,
764 filterNameArray=obsFilterNames,
768 fgcmMakeStars.makeMatchedStars(obsCat[
'ra'] * conv,
769 obsCat[
'dec'] * conv,
772 if self.config.doReferenceMatches:
773 fgcmMakeStars.makeReferenceMatches(self.fgcmLoadReferenceCatalog)
780 fgcmStarIdCat = afwTable.BaseCatalog(objSchema)
781 fgcmStarIdCat.reserve(fgcmMakeStars.objIndexCat.size)
782 for i
in range(fgcmMakeStars.objIndexCat.size):
783 fgcmStarIdCat.addNew()
786 fgcmStarIdCat[
'fgcm_id'][:] = fgcmMakeStars.objIndexCat[
'fgcm_id']
787 fgcmStarIdCat[
'ra'][:] = fgcmMakeStars.objIndexCat[
'ra']
788 fgcmStarIdCat[
'dec'][:] = fgcmMakeStars.objIndexCat[
'dec']
789 fgcmStarIdCat[
'obsArrIndex'][:] = fgcmMakeStars.objIndexCat[
'obsarrindex']
790 fgcmStarIdCat[
'nObs'][:] = fgcmMakeStars.objIndexCat[
'nobs']
794 fgcmStarIndicesCat = afwTable.BaseCatalog(obsSchema)
795 fgcmStarIndicesCat.reserve(fgcmMakeStars.obsIndexCat.size)
796 for i
in range(fgcmMakeStars.obsIndexCat.size):
797 fgcmStarIndicesCat.addNew()
799 fgcmStarIndicesCat[
'obsIndex'][:] = fgcmMakeStars.obsIndexCat[
'obsindex']
801 if self.config.doReferenceMatches:
804 fgcmRefCat = afwTable.BaseCatalog(refSchema)
805 fgcmRefCat.reserve(fgcmMakeStars.referenceCat.size)
807 for i
in range(fgcmMakeStars.referenceCat.size):
810 fgcmRefCat[
'fgcm_id'][:] = fgcmMakeStars.referenceCat[
'fgcm_id']
811 fgcmRefCat[
'refMag'][:, :] = fgcmMakeStars.referenceCat[
'refMag']
812 fgcmRefCat[
'refMagErr'][:, :] = fgcmMakeStars.referenceCat[
'refMagErr']
815 md.set(
"REFSTARS_FORMAT_VERSION", REFSTARS_FORMAT_VERSION)
816 md.set(
"FILTERNAMES", referenceFilterNames)
817 fgcmRefCat.setMetadata(md)
822 return fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat
824 def _makeFgcmVisitSchema(self, nCcd):
826 Make a schema for an fgcmVisitCatalog
831 Number of CCDs in the camera
835 schema: `afwTable.Schema`
838 schema = afwTable.Schema()
839 schema.addField(
'visit', type=np.int32, doc=
"Visit number")
840 schema.addField(
'physicalFilter', type=str, size=30, doc=
"Physical filter")
841 schema.addField(
'telra', type=np.float64, doc=
"Pointing RA (deg)")
842 schema.addField(
'teldec', type=np.float64, doc=
"Pointing Dec (deg)")
843 schema.addField(
'telha', type=np.float64, doc=
"Pointing Hour Angle (deg)")
844 schema.addField(
'telrot', type=np.float64, doc=
"Camera rotation (deg)")
845 schema.addField(
'mjd', type=np.float64, doc=
"MJD of visit")
846 schema.addField(
'exptime', type=np.float32, doc=
"Exposure time")
847 schema.addField(
'pmb', type=np.float32, doc=
"Pressure (millibar)")
848 schema.addField(
'psfSigma', type=np.float32, doc=
"PSF sigma (reference CCD)")
849 schema.addField(
'deltaAper', type=np.float32, doc=
"Delta-aperture")
850 schema.addField(
'skyBackground', type=np.float32, doc=
"Sky background (ADU) (reference CCD)")
852 schema.addField(
'deepFlag', type=np.int32, doc=
"Deep observation")
853 schema.addField(
'scaling', type=
'ArrayD', doc=
"Scaling applied due to flat adjustment",
855 schema.addField(
'used', type=np.int32, doc=
"This visit has been ingested.")
856 schema.addField(
'sources_read', type=
'Flag', doc=
"This visit had sources read.")
860 def _makeFgcmObjSchema(self):
862 Make a schema for the objIndexCat from fgcmMakeStars
866 schema: `afwTable.Schema`
869 objSchema = afwTable.Schema()
870 objSchema.addField(
'fgcm_id', type=np.int32, doc=
'FGCM Unique ID')
872 objSchema.addField(
'ra', type=np.float64, doc=
'Mean object RA (deg)')
873 objSchema.addField(
'dec', type=np.float64, doc=
'Mean object Dec (deg)')
874 objSchema.addField(
'obsArrIndex', type=np.int32,
875 doc=
'Index in obsIndexTable for first observation')
876 objSchema.addField(
'nObs', type=np.int32, doc=
'Total number of observations')
880 def _makeFgcmObsSchema(self):
882 Make a schema for the obsIndexCat from fgcmMakeStars
886 schema: `afwTable.Schema`
889 obsSchema = afwTable.Schema()
890 obsSchema.addField(
'obsIndex', type=np.int32, doc=
'Index in observation table')
894 def _makeFgcmRefSchema(self, nReferenceBands):
896 Make a schema for the referenceCat from fgcmMakeStars
900 nReferenceBands: `int`
901 Number of reference bands
905 schema: `afwTable.Schema`
908 refSchema = afwTable.Schema()
909 refSchema.addField(
'fgcm_id', type=np.int32, doc=
'FGCM Unique ID')
910 refSchema.addField(
'refMag', type=
'ArrayF', doc=
'Reference magnitude array (AB)',
911 size=nReferenceBands)
912 refSchema.addField(
'refMagErr', type=
'ArrayF', doc=
'Reference magnitude error array',
913 size=nReferenceBands)
917 def _getReferenceFilterNames(self, visitCat, stdFilterDict, stdLambdaDict):
919 Get the reference filter names, in wavelength order, from the visitCat and
920 information from the look-up-table.
924 visitCat: `afw.table.BaseCatalog`
925 Catalog with visit data for FGCM
926 stdFilterDict: `dict`
927 Mapping of filterName to stdFilterName from LUT
928 stdLambdaDict: `dict`
929 Mapping of stdFilterName to stdLambda from LUT
933 referenceFilterNames: `list`
934 Wavelength-ordered list of reference filter names
938 filterNames = np.unique(visitCat.asAstropy()[
'physicalFilter'])
941 stdFilterNames = {stdFilterDict[filterName]
for filterName
in filterNames}
944 referenceFilterNames = sorted(stdFilterNames, key=stdLambdaDict.get)
946 return referenceFilterNames
def fgcmMatchStars(self, visitCat, obsCat, lutDataRef=None)
def _makeFgcmVisitSchema(self, nCcd)
def _getReferenceFilterNames(self, visitCat, stdFilterDict, stdLambdaDict)
def runDataRef(self, butler, dataRefs)
def _makeFgcmObjSchema(self)
def _fillVisitCatalog(self, visitCat, groupedDataRefs, bkgDataRefDict=None, visitCatDataRef=None)
def fgcmMakeAllStarObservations(self, groupedDataRefs, visitCat, sourceSchema, camera, calibFluxApertureRadius=None, visitCatDataRef=None, starObsDataRef=None, inStarObsCat=None)
def __init__(self, initInputs=None, butler=None, **kwargs)
def _makeFgcmObsSchema(self)
def fgcmMakeVisitCatalog(self, camera, groupedDataRefs, bkgDataRefDict=None, visitCatDataRef=None, inVisitCat=None)
def _findAndGroupDataRefsGen2(self, butler, camera, dataRefs)
def _makeFgcmRefSchema(self, nReferenceBands)
def getTargetList(parsedCmd)
def computeApertureRadiusFromDataRef(dataRef, fluxField)