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",
94 filterMap = pexConfig.DictField(
95 doc=
"Mapping from 'filterName' to band.",
99 deprecated=(
"This field is no longer used, and has been deprecated by "
100 "DM-28088. It will be removed after v22. Use "
101 "physicalFilterMap instead.")
106 physicalFilterMap = pexConfig.DictField(
107 doc=
"Mapping from 'physicalFilter' to band.",
112 requiredBands = pexConfig.ListField(
113 doc=
"Bands required for each star",
117 primaryBands = pexConfig.ListField(
118 doc=(
"Bands for 'primary' star matches. "
119 "A star must be observed in one of these bands to be considered "
120 "as a calibration star."),
124 visitDataRefName = pexConfig.Field(
125 doc=
"dataRef name for the 'visit' field, usually 'visit'.",
129 ccdDataRefName = pexConfig.Field(
130 doc=
"dataRef name for the 'ccd' field, usually 'ccd' or 'detector'.",
134 doApplyWcsJacobian = pexConfig.Field(
135 doc=
"Apply the jacobian of the WCS to the star observations prior to fit?",
139 doModelErrorsWithBackground = pexConfig.Field(
140 doc=
"Model flux errors with background term?",
144 psfCandidateName = pexConfig.Field(
145 doc=
"Name of field with psf candidate flag for propagation",
147 default=
"calib_psf_candidate"
149 doSubtractLocalBackground = pexConfig.Field(
150 doc=(
"Subtract the local background before performing calibration? "
151 "This is only supported for circular aperture calibration fluxes."),
155 localBackgroundFluxField = pexConfig.Field(
156 doc=
"Full name of the local background instFlux field to use.",
158 default=
'base_LocalBackground_instFlux'
160 sourceSelector = sourceSelectorRegistry.makeField(
161 doc=
"How to select sources",
164 apertureInnerInstFluxField = pexConfig.Field(
165 doc=(
"Full name of instFlux field that contains inner aperture "
166 "flux for aperture correction proxy"),
168 default=
'base_CircularApertureFlux_12_0_instFlux'
170 apertureOuterInstFluxField = pexConfig.Field(
171 doc=(
"Full name of instFlux field that contains outer aperture "
172 "flux for aperture correction proxy"),
174 default=
'base_CircularApertureFlux_17_0_instFlux'
176 doReferenceMatches = pexConfig.Field(
177 doc=
"Match reference catalog as additional constraint on calibration",
181 fgcmLoadReferenceCatalog = pexConfig.ConfigurableField(
182 target=FgcmLoadReferenceCatalogTask,
183 doc=
"FGCM reference object loader",
185 nVisitsPerCheckpoint = pexConfig.Field(
186 doc=
"Number of visits read between checkpoints",
193 sourceSelector.setDefaults()
195 sourceSelector.doFlags =
True
196 sourceSelector.doUnresolved =
True
197 sourceSelector.doSignalToNoise =
True
198 sourceSelector.doIsolated =
True
200 sourceSelector.signalToNoise.minimum = 10.0
201 sourceSelector.signalToNoise.maximum = 1000.0
205 sourceSelector.unresolved.maximum = 0.5
209 """Subclass of TaskRunner for FgcmBuildStars tasks
211 fgcmBuildStarsTask.run() and fgcmBuildStarsTableTask.run() take a number of
212 arguments, one of which is the butler (for persistence and mapper data),
213 and a list of dataRefs extracted from the command line. Note that FGCM
214 runs on a large set of dataRefs, and not on single dataRef/tract/patch.
215 This class transforms the process arguments generated by the ArgumentParser
216 into the arguments expected by FgcmBuildStarsTask.run(). This runner does
217 not use any parallelization.
222 Return a list with one element: a tuple with the butler and
226 return [(parsedCmd.butler, parsedCmd.id.refList)]
232 args: `tuple` with (butler, dataRefList)
236 exitStatus: `list` with `lsst.pipe.base.Struct`
237 exitStatus (0: success; 1: failure)
239 butler, dataRefList = args
241 task = self.TaskClass(config=self.config, log=self.log)
245 task.runDataRef(butler, dataRefList)
248 task.runDataRef(butler, dataRefList)
249 except Exception
as e:
251 task.log.fatal(
"Failed: %s" % e)
252 if not isinstance(e, pipeBase.TaskError):
253 traceback.print_exc(file=sys.stderr)
255 task.writeMetadata(butler)
258 return [pipeBase.Struct(exitStatus=exitStatus)]
262 Run the task, with no multiprocessing
266 parsedCmd: `lsst.pipe.base.ArgumentParser` parsed command line
271 if self.precall(parsedCmd):
273 resultList = self(targetList[0])
280 Base task to build stars for FGCM global calibration
284 butler : `lsst.daf.persistence.Butler`
286 def __init__(self, butler=None, initInputs=None, **kwargs):
289 self.makeSubtask(
"sourceSelector")
291 self.sourceSelector.log.setLevel(self.sourceSelector.log.WARN)
294 def _getMetadataName(self):
300 Cross-match and make star list for FGCM Input
304 butler: `lsst.daf.persistence.Butler`
305 dataRefs: `list` of `lsst.daf.persistence.ButlerDataRef`
306 Source data references for the input visits.
310 RuntimeErrror: Raised if `config.doReferenceMatches` is set and
311 an fgcmLookUpTable is not available, or if computeFluxApertureRadius()
312 fails if the calibFlux is not a CircularAperture flux.
314 datasetType = dataRefs[0].butlerSubset.datasetType
315 self.log.info(
"Running with %d %s dataRefs", len(dataRefs), datasetType)
317 if self.config.doReferenceMatches:
318 self.makeSubtask(
"fgcmLoadReferenceCatalog", butler=butler)
320 if not butler.datasetExists(
'fgcmLookUpTable'):
321 raise RuntimeError(
"Must have fgcmLookUpTable if using config.doReferenceMatches")
324 calibFluxApertureRadius =
None
325 if self.config.doSubtractLocalBackground:
328 self.config.instFluxField)
329 except RuntimeError
as e:
330 raise RuntimeError(
"Could not determine aperture radius from %s. "
331 "Cannot use doSubtractLocalBackground." %
332 (self.config.instFluxField))
from e
334 camera = butler.get(
'camera')
342 visitCatDataRef = butler.dataRef(
'fgcmVisitCatalog')
343 filename = visitCatDataRef.get(
'fgcmVisitCatalog_filename')[0]
344 if os.path.exists(filename):
346 inVisitCat = visitCatDataRef.get()
347 if len(inVisitCat) != len(groupedDataRefs):
348 raise RuntimeError(
"Existing visitCatalog found, but has an inconsistent "
349 "number of visits. Cannot continue.")
354 visitCatDataRef=visitCatDataRef,
355 inVisitCat=inVisitCat)
358 visitCatDataRef.put(visitCat)
360 starObsDataRef = butler.dataRef(
'fgcmStarObservations')
361 filename = starObsDataRef.get(
'fgcmStarObservations_filename')[0]
362 if os.path.exists(filename):
363 inStarObsCat = starObsDataRef.get()
367 rad = calibFluxApertureRadius
368 sourceSchemaDataRef = butler.dataRef(
'src_schema')
373 calibFluxApertureRadius=rad,
374 starObsDataRef=starObsDataRef,
375 visitCatDataRef=visitCatDataRef,
376 inStarObsCat=inStarObsCat)
377 visitCatDataRef.put(visitCat)
378 starObsDataRef.put(fgcmStarObservationCat)
381 if self.config.doReferenceMatches:
382 lutDataRef = butler.dataRef(
'fgcmLookUpTable')
385 fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat = self.
fgcmMatchStarsfgcmMatchStars(visitCat,
386 fgcmStarObservationCat,
387 lutDataRef=lutDataRef)
390 butler.put(fgcmStarIdCat,
'fgcmStarIds')
391 butler.put(fgcmStarIndicesCat,
'fgcmStarIndices')
392 if fgcmRefCat
is not None:
393 butler.put(fgcmRefCat,
'fgcmReferenceStars')
396 def _findAndGroupDataRefs(self, camera, dataRefs, butler=None, calexpDataRefDict=None):
398 Find and group dataRefs (by visit). For Gen2 usage, set butler, and for
399 Gen3, use calexpDataRefDict
403 camera : `lsst.afw.cameraGeom.Camera`
404 Camera from the butler.
405 dataRefs : `list` of `lsst.daf.persistence.ButlerDataRef` or
406 `lsst.daf.butler.DeferredDatasetHandle`
407 Data references for the input visits.
408 butler : `lsst.daf.persistence.Butler`, optional
409 Gen2 butler when used as CommandLineTask
410 calexpDataRefDict : `dict`, optional
411 Dictionary of Gen3 deferred data refs for calexps
415 groupedDataRefs : `OrderedDict` [`int`, `list`]
416 Dictionary with sorted visit keys, and `list`s of
417 `lsst.daf.persistence.ButlerDataRef` or
418 `lsst.daf.butler.DeferredDatasetHandle`
422 RuntimeError : Raised if neither or both of butler and dataRefDict are set.
424 raise NotImplementedError(
"_findAndGroupDataRefs not implemented.")
430 calibFluxApertureRadius=None,
431 visitCatDataRef=None,
435 Compile all good star observations from visits in visitCat. Checkpoint files
436 will be stored if both visitCatDataRef and starObsDataRef are not None.
440 groupedDataRefs: `dict` of `list`s
441 Lists of `~lsst.daf.persistence.ButlerDataRef` or
442 `~lsst.daf.butler.DeferredDatasetHandle`, grouped by visit.
443 visitCat: `~afw.table.BaseCatalog`
444 Catalog with visit data for FGCM
445 sourceSchemaDataRef: `~lsst.daf.persistence.ButlerDataRef` or
446 `~lsst.daf.butler.DeferredDatasetHandle`
447 DataRef for the schema of the src catalogs.
448 camera: `~lsst.afw.cameraGeom.Camera`
449 calibFluxApertureRadius: `float`, optional
450 Aperture radius for calibration flux.
451 visitCatDataRef: `~lsst.daf.persistence.ButlerDataRef`, optional
452 Dataref to write visitCat for checkpoints
453 starObsDataRef: `~lsst.daf.persistence.ButlerDataRef`, optional
454 Dataref to write the star observation catalog for checkpoints.
455 inStarObsCat: `~afw.table.BaseCatalog`
456 Input observation catalog. If this is incomplete, observations
457 will be appended from when it was cut off.
461 fgcmStarObservations: `afw.table.BaseCatalog`
462 Full catalog of good observations.
466 RuntimeError: Raised if doSubtractLocalBackground is True and
467 calibFluxApertureRadius is not set.
469 raise NotImplementedError(
"fgcmMakeAllStarObservations not implemented.")
472 visitCatDataRef=None, inVisitCat=None):
474 Make a visit catalog with all the keys from each visit
478 camera: `lsst.afw.cameraGeom.Camera`
479 Camera from the butler
480 groupedDataRefs: `dict`
481 Dictionary with visit keys, and `list`s of
482 `lsst.daf.persistence.ButlerDataRef`
483 bkgDataRefDict: `dict`, optional
484 Dictionary of gen3 dataRefHandles for background info.
485 visitCatDataRef: `lsst.daf.persistence.ButlerDataRef`, optional
486 Dataref to write visitCat for checkpoints
487 inVisitCat: `afw.table.BaseCatalog`, optional
488 Input (possibly incomplete) visit catalog
492 visitCat: `afw.table.BaseCatalog`
495 self.log.info(
"Assembling visitCatalog from %d %ss" %
496 (len(groupedDataRefs), self.config.visitDataRefName))
500 if inVisitCat
is None:
503 visitCat = afwTable.BaseCatalog(schema)
504 visitCat.reserve(len(groupedDataRefs))
505 visitCat.resize(len(groupedDataRefs))
507 visitCat[
'visit'] = list(groupedDataRefs.keys())
509 visitCat[
'sources_read'] =
False
511 visitCat = inVisitCat
516 bkgDataRefDict=bkgDataRefDict,
517 visitCatDataRef=visitCatDataRef)
521 def _fillVisitCatalog(self, visitCat, groupedDataRefs, bkgDataRefDict=None,
522 visitCatDataRef=None):
524 Fill the visit catalog with visit metadata
528 visitCat: `afw.table.BaseCatalog`
529 Catalog with schema from _makeFgcmVisitSchema()
530 groupedDataRefs: `dict`
531 Dictionary with visit keys, and `list`s of
532 `lsst.daf.persistence.ButlerDataRef`
533 visitCatDataRef: `lsst.daf.persistence.ButlerDataRef`, optional
534 Dataref to write visitCat for checkpoints
535 bkgDataRefDict: `dict`, optional
536 Dictionary of gen3 dataRefHandles for background info. FIXME
538 bbox = geom.BoxI(geom.PointI(0, 0), geom.PointI(1, 1))
540 for i, visit
in enumerate(groupedDataRefs):
547 if visitCat[
'used'][i]:
550 if (i % self.config.nVisitsPerCheckpoint) == 0:
551 self.log.info(
"Retrieving metadata for %s %d (%d/%d)" %
552 (self.config.visitDataRefName, visit, i, len(groupedDataRefs)))
554 if visitCatDataRef
is not None:
555 visitCatDataRef.put(visitCat)
560 dataRef = groupedDataRefs[visit][0]
561 if isinstance(dataRef, dafPersist.ButlerDataRef):
562 exp = dataRef.get(datasetType=
'calexp_sub', bbox=bbox)
563 visitInfo = exp.getInfo().getVisitInfo()
564 label = dataRef.get(datasetType=
'calexp_filterLabel')
565 physicalFilter = label.physicalLabel
568 visitInfo = dataRef.get(component=
'visitInfo')
571 physicalFilter = dataRef.dataId[
'physical_filter']
572 psf = dataRef.get(component=
'psf')
576 rec[
'physicalFilter'] = physicalFilter
580 radec = visitInfo.getBoresightRaDec()
581 rec[
'telra'] = radec.getRa().asDegrees()
582 rec[
'teldec'] = radec.getDec().asDegrees()
583 rec[
'telha'] = visitInfo.getBoresightHourAngle().asDegrees()
584 rec[
'telrot'] = visitInfo.getBoresightRotAngle().asDegrees()
585 rec[
'mjd'] = visitInfo.getDate().get(system=DateTime.MJD)
586 rec[
'exptime'] = visitInfo.getExposureTime()
589 rec[
'pmb'] = visitInfo.getWeather().getAirPressure() / 100
593 rec[
'scaling'][:] = 1.0
595 rec[
'deltaAper'] = 0.0
597 rec[
'psfSigma'] = psf.computeShape().getDeterminantRadius()
599 if self.config.doModelErrorsWithBackground:
601 if isinstance(dataRef, dafPersist.ButlerDataRef):
602 det = dataRef.dataId[self.config.ccdDataRefName]
603 if dataRef.datasetExists(datasetType=
'calexpBackground'):
604 bgList = dataRef.get(datasetType=
'calexpBackground')
607 det = dataRef.dataId.byName()[
'detector']
609 bkgRef = bkgDataRefDict[(visit, det)]
610 bgList = bkgRef.get()
616 bgStats = (bg[0].getStatsImage().getImage().array
618 rec[
'skyBackground'] = sum(np.median(bg[np.isfinite(bg)])
for bg
in bgStats)
620 self.log.warn(
'Sky background not found for visit %d / ccd %d' %
622 rec[
'skyBackground'] = -1.0
624 rec[
'skyBackground'] = -1.0
628 def _makeSourceMapper(self, sourceSchema):
630 Make a schema mapper for fgcm sources
634 sourceSchema: `afwTable.Schema`
635 Default source schema from the butler
639 sourceMapper: `afwTable.schemaMapper`
640 Mapper to the FGCM source schema
644 sourceMapper = afwTable.SchemaMapper(sourceSchema)
647 sourceMapper.addMapping(sourceSchema[
'coord_ra'].asKey(),
'ra')
648 sourceMapper.addMapping(sourceSchema[
'coord_dec'].asKey(),
'dec')
649 sourceMapper.addMapping(sourceSchema[
'slot_Centroid_x'].asKey(),
'x')
650 sourceMapper.addMapping(sourceSchema[
'slot_Centroid_y'].asKey(),
'y')
656 sourceMapper.addMapping(sourceSchema[self.config.psfCandidateName].asKey(),
659 sourceMapper.editOutputSchema().addField(
660 "psf_candidate", type=
'Flag',
661 doc=(
"Flag set if the source was a candidate for PSF determination, "
662 "as determined by the star selector."))
665 sourceMapper.editOutputSchema().addField(
666 "visit", type=np.int32, doc=
"Visit number")
667 sourceMapper.editOutputSchema().addField(
668 "ccd", type=np.int32, doc=
"CCD number")
669 sourceMapper.editOutputSchema().addField(
670 "instMag", type=np.float32, doc=
"Instrumental magnitude")
671 sourceMapper.editOutputSchema().addField(
672 "instMagErr", type=np.float32, doc=
"Instrumental magnitude error")
673 sourceMapper.editOutputSchema().addField(
674 "jacobian", type=np.float32, doc=
"Relative pixel scale from wcs jacobian")
675 sourceMapper.editOutputSchema().addField(
676 "deltaMagBkg", type=np.float32, doc=
"Change in magnitude due to local background offset")
682 Use FGCM code to match observations into unique stars.
686 visitCat: `afw.table.BaseCatalog`
687 Catalog with visit data for fgcm
688 obsCat: `afw.table.BaseCatalog`
689 Full catalog of star observations for fgcm
690 lutDataRef: `lsst.daf.persistence.ButlerDataRef` or
691 `lsst.daf.butler.DeferredDatasetHandle`, optional
692 Data reference to fgcm look-up table (used if matching reference stars).
696 fgcmStarIdCat: `afw.table.BaseCatalog`
697 Catalog of unique star identifiers and index keys
698 fgcmStarIndicesCat: `afwTable.BaseCatalog`
699 Catalog of unique star indices
700 fgcmRefCat: `afw.table.BaseCatalog`
701 Catalog of matched reference stars.
702 Will be None if `config.doReferenceMatches` is False.
706 visitFilterNames = np.zeros(len(visitCat), dtype=
'a30')
707 for i
in range(len(visitCat)):
708 visitFilterNames[i] = visitCat[i][
'physicalFilter']
711 visitIndex = np.searchsorted(visitCat[
'visit'],
714 obsFilterNames = visitFilterNames[visitIndex]
716 if self.config.doReferenceMatches:
718 lutCat = lutDataRef.get()
720 stdFilterDict = {filterName: stdFilter
for (filterName, stdFilter)
in
721 zip(lutCat[0][
'physicalFilters'].split(
','),
722 lutCat[0][
'stdPhysicalFilters'].split(
','))}
723 stdLambdaDict = {stdFilter: stdLambda
for (stdFilter, stdLambda)
in
724 zip(lutCat[0][
'stdPhysicalFilters'].split(
','),
725 lutCat[0][
'lambdaStdFilter'])}
732 self.log.info(
"Using the following reference filters: %s" %
733 (
', '.join(referenceFilterNames)))
737 referenceFilterNames = []
740 starConfig = {
'logger': self.log,
741 'filterToBand': self.config.physicalFilterMap,
742 'requiredBands': self.config.requiredBands,
743 'minPerBand': self.config.minPerBand,
744 'matchRadius': self.config.matchRadius,
745 'isolationRadius': self.config.isolationRadius,
746 'matchNSide': self.config.matchNside,
747 'coarseNSide': self.config.coarseNside,
748 'densNSide': self.config.densityCutNside,
749 'densMaxPerPixel': self.config.densityCutMaxPerPixel,
750 'primaryBands': self.config.primaryBands,
751 'referenceFilterNames': referenceFilterNames}
754 fgcmMakeStars = fgcm.FgcmMakeStars(starConfig)
762 conv = obsCat[0][
'ra'].asDegrees() / float(obsCat[0][
'ra'])
763 fgcmMakeStars.makePrimaryStars(obsCat[
'ra'] * conv,
764 obsCat[
'dec'] * conv,
765 filterNameArray=obsFilterNames,
769 fgcmMakeStars.makeMatchedStars(obsCat[
'ra'] * conv,
770 obsCat[
'dec'] * conv,
773 if self.config.doReferenceMatches:
774 fgcmMakeStars.makeReferenceMatches(self.fgcmLoadReferenceCatalog)
781 fgcmStarIdCat = afwTable.BaseCatalog(objSchema)
782 fgcmStarIdCat.reserve(fgcmMakeStars.objIndexCat.size)
783 for i
in range(fgcmMakeStars.objIndexCat.size):
784 fgcmStarIdCat.addNew()
787 fgcmStarIdCat[
'fgcm_id'][:] = fgcmMakeStars.objIndexCat[
'fgcm_id']
788 fgcmStarIdCat[
'ra'][:] = fgcmMakeStars.objIndexCat[
'ra']
789 fgcmStarIdCat[
'dec'][:] = fgcmMakeStars.objIndexCat[
'dec']
790 fgcmStarIdCat[
'obsArrIndex'][:] = fgcmMakeStars.objIndexCat[
'obsarrindex']
791 fgcmStarIdCat[
'nObs'][:] = fgcmMakeStars.objIndexCat[
'nobs']
795 fgcmStarIndicesCat = afwTable.BaseCatalog(obsSchema)
796 fgcmStarIndicesCat.reserve(fgcmMakeStars.obsIndexCat.size)
797 for i
in range(fgcmMakeStars.obsIndexCat.size):
798 fgcmStarIndicesCat.addNew()
800 fgcmStarIndicesCat[
'obsIndex'][:] = fgcmMakeStars.obsIndexCat[
'obsindex']
802 if self.config.doReferenceMatches:
805 fgcmRefCat = afwTable.BaseCatalog(refSchema)
806 fgcmRefCat.reserve(fgcmMakeStars.referenceCat.size)
808 for i
in range(fgcmMakeStars.referenceCat.size):
811 fgcmRefCat[
'fgcm_id'][:] = fgcmMakeStars.referenceCat[
'fgcm_id']
812 fgcmRefCat[
'refMag'][:, :] = fgcmMakeStars.referenceCat[
'refMag']
813 fgcmRefCat[
'refMagErr'][:, :] = fgcmMakeStars.referenceCat[
'refMagErr']
816 md.set(
"REFSTARS_FORMAT_VERSION", REFSTARS_FORMAT_VERSION)
817 md.set(
"FILTERNAMES", referenceFilterNames)
818 fgcmRefCat.setMetadata(md)
823 return fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat
825 def _makeFgcmVisitSchema(self, nCcd):
827 Make a schema for an fgcmVisitCatalog
832 Number of CCDs in the camera
836 schema: `afwTable.Schema`
839 schema = afwTable.Schema()
840 schema.addField(
'visit', type=np.int32, doc=
"Visit number")
841 schema.addField(
'physicalFilter', type=str, size=30, doc=
"Physical filter")
842 schema.addField(
'telra', type=np.float64, doc=
"Pointing RA (deg)")
843 schema.addField(
'teldec', type=np.float64, doc=
"Pointing Dec (deg)")
844 schema.addField(
'telha', type=np.float64, doc=
"Pointing Hour Angle (deg)")
845 schema.addField(
'telrot', type=np.float64, doc=
"Camera rotation (deg)")
846 schema.addField(
'mjd', type=np.float64, doc=
"MJD of visit")
847 schema.addField(
'exptime', type=np.float32, doc=
"Exposure time")
848 schema.addField(
'pmb', type=np.float32, doc=
"Pressure (millibar)")
849 schema.addField(
'psfSigma', type=np.float32, doc=
"PSF sigma (reference CCD)")
850 schema.addField(
'deltaAper', type=np.float32, doc=
"Delta-aperture")
851 schema.addField(
'skyBackground', type=np.float32, doc=
"Sky background (ADU) (reference CCD)")
853 schema.addField(
'deepFlag', type=np.int32, doc=
"Deep observation")
854 schema.addField(
'scaling', type=
'ArrayD', doc=
"Scaling applied due to flat adjustment",
856 schema.addField(
'used', type=np.int32, doc=
"This visit has been ingested.")
857 schema.addField(
'sources_read', type=
'Flag', doc=
"This visit had sources read.")
861 def _makeFgcmObjSchema(self):
863 Make a schema for the objIndexCat from fgcmMakeStars
867 schema: `afwTable.Schema`
870 objSchema = afwTable.Schema()
871 objSchema.addField(
'fgcm_id', type=np.int32, doc=
'FGCM Unique ID')
873 objSchema.addField(
'ra', type=np.float64, doc=
'Mean object RA (deg)')
874 objSchema.addField(
'dec', type=np.float64, doc=
'Mean object Dec (deg)')
875 objSchema.addField(
'obsArrIndex', type=np.int32,
876 doc=
'Index in obsIndexTable for first observation')
877 objSchema.addField(
'nObs', type=np.int32, doc=
'Total number of observations')
881 def _makeFgcmObsSchema(self):
883 Make a schema for the obsIndexCat from fgcmMakeStars
887 schema: `afwTable.Schema`
890 obsSchema = afwTable.Schema()
891 obsSchema.addField(
'obsIndex', type=np.int32, doc=
'Index in observation table')
895 def _makeFgcmRefSchema(self, nReferenceBands):
897 Make a schema for the referenceCat from fgcmMakeStars
901 nReferenceBands: `int`
902 Number of reference bands
906 schema: `afwTable.Schema`
909 refSchema = afwTable.Schema()
910 refSchema.addField(
'fgcm_id', type=np.int32, doc=
'FGCM Unique ID')
911 refSchema.addField(
'refMag', type=
'ArrayF', doc=
'Reference magnitude array (AB)',
912 size=nReferenceBands)
913 refSchema.addField(
'refMagErr', type=
'ArrayF', doc=
'Reference magnitude error array',
914 size=nReferenceBands)
918 def _getReferenceFilterNames(self, visitCat, stdFilterDict, stdLambdaDict):
920 Get the reference filter names, in wavelength order, from the visitCat and
921 information from the look-up-table.
925 visitCat: `afw.table.BaseCatalog`
926 Catalog with visit data for FGCM
927 stdFilterDict: `dict`
928 Mapping of filterName to stdFilterName from LUT
929 stdLambdaDict: `dict`
930 Mapping of stdFilterName to stdLambda from LUT
934 referenceFilterNames: `list`
935 Wavelength-ordered list of reference filter names
939 filterNames = np.unique(visitCat.asAstropy()[
'physicalFilter'])
942 stdFilterNames = {stdFilterDict[filterName]
for filterName
in filterNames}
945 referenceFilterNames = sorted(stdFilterNames, key=stdLambdaDict.get)
947 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 _findAndGroupDataRefs(self, camera, dataRefs, butler=None, calexpDataRefDict=None)
def _makeFgcmObsSchema(self)
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 __init__(self, butler=None, initInputs=None, **kwargs)
def _makeFgcmRefSchema(self, nReferenceBands)
def getTargetList(parsedCmd)
def computeApertureRadiusFromDataRef(dataRef, fluxField)