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, initInputs=None, butler=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')
369 sourceSchema = sourceSchemaDataRef.get(
'src_schema', immediate=
True).schema
374 calibFluxApertureRadius=rad,
375 starObsDataRef=starObsDataRef,
376 visitCatDataRef=visitCatDataRef,
377 inStarObsCat=inStarObsCat)
378 visitCatDataRef.put(visitCat)
379 starObsDataRef.put(fgcmStarObservationCat)
382 if self.config.doReferenceMatches:
383 lutDataRef = butler.dataRef(
'fgcmLookUpTable')
386 fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat = self.
fgcmMatchStarsfgcmMatchStars(visitCat,
387 fgcmStarObservationCat,
388 lutDataRef=lutDataRef)
391 butler.put(fgcmStarIdCat,
'fgcmStarIds')
392 butler.put(fgcmStarIndicesCat,
'fgcmStarIndices')
393 if fgcmRefCat
is not None:
394 butler.put(fgcmRefCat,
'fgcmReferenceStars')
397 def _findAndGroupDataRefsGen2(self, butler, camera, dataRefs):
399 Find and group dataRefs (by visit); Gen2 only.
403 butler : `lsst.daf.persistence.Butler`
405 camera : `lsst.afw.cameraGeom.Camera`
406 Camera from the butler.
407 dataRefs : `list` of `lsst.daf.persistence.ButlerDataRef`
408 Data references for the input visits.
412 groupedDataRefs : `dict` [`int`, `list`]
413 Dictionary with sorted visit keys, and `list`s of
414 `lsst.daf.persistence.ButlerDataRef`
416 raise NotImplementedError(
"_findAndGroupDataRefsGen2 not implemented.")
422 calibFluxApertureRadius=None,
423 visitCatDataRef=None,
427 Compile all good star observations from visits in visitCat. Checkpoint files
428 will be stored if both visitCatDataRef and starObsDataRef are not None.
432 groupedDataRefs : `dict` of `list`s
433 Lists of `~lsst.daf.persistence.ButlerDataRef` or
434 `~lsst.daf.butler.DeferredDatasetHandle`, grouped by visit.
435 visitCat : `~afw.table.BaseCatalog`
436 Catalog with visit data for FGCM
437 sourceSchema : `~lsst.afw.table.Schema`
438 Schema for the input src catalogs.
439 camera : `~lsst.afw.cameraGeom.Camera`
440 calibFluxApertureRadius : `float`, optional
441 Aperture radius for calibration flux.
442 visitCatDataRef : `~lsst.daf.persistence.ButlerDataRef`, optional
443 Dataref to write visitCat for checkpoints
444 starObsDataRef : `~lsst.daf.persistence.ButlerDataRef`, optional
445 Dataref to write the star observation catalog for checkpoints.
446 inStarObsCat : `~afw.table.BaseCatalog`
447 Input observation catalog. If this is incomplete, observations
448 will be appended from when it was cut off.
452 fgcmStarObservations : `afw.table.BaseCatalog`
453 Full catalog of good observations.
457 RuntimeError: Raised if doSubtractLocalBackground is True and
458 calibFluxApertureRadius is not set.
460 raise NotImplementedError(
"fgcmMakeAllStarObservations not implemented.")
463 visitCatDataRef=None, inVisitCat=None):
465 Make a visit catalog with all the keys from each visit
469 camera: `lsst.afw.cameraGeom.Camera`
470 Camera from the butler
471 groupedDataRefs: `dict`
472 Dictionary with visit keys, and `list`s of
473 `lsst.daf.persistence.ButlerDataRef`
474 bkgDataRefDict: `dict`, optional
475 Dictionary of gen3 dataRefHandles for background info.
476 visitCatDataRef: `lsst.daf.persistence.ButlerDataRef`, optional
477 Dataref to write visitCat for checkpoints
478 inVisitCat: `afw.table.BaseCatalog`, optional
479 Input (possibly incomplete) visit catalog
483 visitCat: `afw.table.BaseCatalog`
486 self.log.info(
"Assembling visitCatalog from %d %ss" %
487 (len(groupedDataRefs), self.config.visitDataRefName))
491 if inVisitCat
is None:
494 visitCat = afwTable.BaseCatalog(schema)
495 visitCat.reserve(len(groupedDataRefs))
496 visitCat.resize(len(groupedDataRefs))
498 visitCat[
'visit'] = list(groupedDataRefs.keys())
500 visitCat[
'sources_read'] =
False
502 visitCat = inVisitCat
507 bkgDataRefDict=bkgDataRefDict,
508 visitCatDataRef=visitCatDataRef)
512 def _fillVisitCatalog(self, visitCat, groupedDataRefs, bkgDataRefDict=None,
513 visitCatDataRef=None):
515 Fill the visit catalog with visit metadata
519 visitCat : `afw.table.BaseCatalog`
520 Visit catalog. See _makeFgcmVisitSchema() for schema definition.
521 groupedDataRefs : `dict`
522 Dictionary with visit keys, and `list`s of
523 `lsst.daf.persistence.ButlerDataRef` or
524 `lsst.daf.butler.DeferredDatasetHandle`
525 visitCatDataRef : `lsst.daf.persistence.ButlerDataRef`, optional
526 Dataref to write ``visitCat`` for checkpoints. Gen2 only.
527 bkgDataRefDict : `dict`, optional
528 Dictionary of Gen3 `lsst.daf.butler.DeferredDatasetHandle`
531 bbox = geom.BoxI(geom.PointI(0, 0), geom.PointI(1, 1))
533 for i, visit
in enumerate(groupedDataRefs):
540 if visitCat[
'used'][i]:
543 if (i % self.config.nVisitsPerCheckpoint) == 0:
544 self.log.info(
"Retrieving metadata for %s %d (%d/%d)" %
545 (self.config.visitDataRefName, visit, i, len(groupedDataRefs)))
547 if visitCatDataRef
is not None:
548 visitCatDataRef.put(visitCat)
550 dataRef = groupedDataRefs[visit][0]
551 if isinstance(dataRef, dafPersist.ButlerDataRef):
554 exp = dataRef.get(datasetType=
'calexp_sub', bbox=bbox)
555 visitInfo = exp.getInfo().getVisitInfo()
556 label = dataRef.get(datasetType=
'calexp_filterLabel')
557 physicalFilter = label.physicalLabel
559 psfSigma = psf.computeShape().getDeterminantRadius()
562 summary = dataRef.get()
564 summaryRow = summary.find(self.config.referenceCCD)
565 if summaryRow
is None:
567 summaryRow = summary[0]
569 summaryDetector = summaryRow[
'id']
570 visitInfo = summaryRow.getVisitInfo()
571 physicalFilter = summaryRow[
'physical_filter']
573 goodSigma, = np.where(summary[
'psfSigma'] > 0)
574 if goodSigma.size > 2:
575 psfSigma = np.median(summary[
'psfSigma'][goodSigma])
577 psfSigma = np.mean(summary[
'psfSigma'][goodSigma])
583 rec[
'physicalFilter'] = physicalFilter
587 radec = visitInfo.getBoresightRaDec()
588 rec[
'telra'] = radec.getRa().asDegrees()
589 rec[
'teldec'] = radec.getDec().asDegrees()
590 rec[
'telha'] = visitInfo.getBoresightHourAngle().asDegrees()
591 rec[
'telrot'] = visitInfo.getBoresightRotAngle().asDegrees()
592 rec[
'mjd'] = visitInfo.getDate().get(system=DateTime.MJD)
593 rec[
'exptime'] = visitInfo.getExposureTime()
596 rec[
'pmb'] = visitInfo.getWeather().getAirPressure() / 100
600 rec[
'scaling'][:] = 1.0
602 rec[
'deltaAper'] = 0.0
603 rec[
'psfSigma'] = psfSigma
605 if self.config.doModelErrorsWithBackground:
607 if isinstance(dataRef, dafPersist.ButlerDataRef):
609 det = dataRef.dataId[self.config.ccdDataRefName]
610 if dataRef.datasetExists(datasetType=
'calexpBackground'):
611 bgList = dataRef.get(datasetType=
'calexpBackground')
617 bkgRef = bkgDataRefDict[(visit, summaryDetector)]
618 bgList = bkgRef.get()
624 bgStats = (bg[0].getStatsImage().getImage().array
626 rec[
'skyBackground'] = sum(np.median(bg[np.isfinite(bg)])
for bg
in bgStats)
628 self.log.warn(
'Sky background not found for visit %d / ccd %d' %
630 rec[
'skyBackground'] = -1.0
632 rec[
'skyBackground'] = -1.0
636 def _makeSourceMapper(self, sourceSchema):
638 Make a schema mapper for fgcm sources
642 sourceSchema: `afwTable.Schema`
643 Default source schema from the butler
647 sourceMapper: `afwTable.schemaMapper`
648 Mapper to the FGCM source schema
652 sourceMapper = afwTable.SchemaMapper(sourceSchema)
655 sourceMapper.addMapping(sourceSchema[
'coord_ra'].asKey(),
'ra')
656 sourceMapper.addMapping(sourceSchema[
'coord_dec'].asKey(),
'dec')
657 sourceMapper.addMapping(sourceSchema[
'slot_Centroid_x'].asKey(),
'x')
658 sourceMapper.addMapping(sourceSchema[
'slot_Centroid_y'].asKey(),
'y')
664 sourceMapper.addMapping(sourceSchema[self.config.psfCandidateName].asKey(),
667 sourceMapper.editOutputSchema().addField(
668 "psf_candidate", type=
'Flag',
669 doc=(
"Flag set if the source was a candidate for PSF determination, "
670 "as determined by the star selector."))
673 sourceMapper.editOutputSchema().addField(
674 "visit", type=np.int32, doc=
"Visit number")
675 sourceMapper.editOutputSchema().addField(
676 "ccd", type=np.int32, doc=
"CCD number")
677 sourceMapper.editOutputSchema().addField(
678 "instMag", type=np.float32, doc=
"Instrumental magnitude")
679 sourceMapper.editOutputSchema().addField(
680 "instMagErr", type=np.float32, doc=
"Instrumental magnitude error")
681 sourceMapper.editOutputSchema().addField(
682 "jacobian", type=np.float32, doc=
"Relative pixel scale from wcs jacobian")
683 sourceMapper.editOutputSchema().addField(
684 "deltaMagBkg", type=np.float32, doc=
"Change in magnitude due to local background offset")
690 Use FGCM code to match observations into unique stars.
694 visitCat: `afw.table.BaseCatalog`
695 Catalog with visit data for fgcm
696 obsCat: `afw.table.BaseCatalog`
697 Full catalog of star observations for fgcm
698 lutDataRef: `lsst.daf.persistence.ButlerDataRef` or
699 `lsst.daf.butler.DeferredDatasetHandle`, optional
700 Data reference to fgcm look-up table (used if matching reference stars).
704 fgcmStarIdCat: `afw.table.BaseCatalog`
705 Catalog of unique star identifiers and index keys
706 fgcmStarIndicesCat: `afwTable.BaseCatalog`
707 Catalog of unique star indices
708 fgcmRefCat: `afw.table.BaseCatalog`
709 Catalog of matched reference stars.
710 Will be None if `config.doReferenceMatches` is False.
714 visitFilterNames = np.zeros(len(visitCat), dtype=
'a30')
715 for i
in range(len(visitCat)):
716 visitFilterNames[i] = visitCat[i][
'physicalFilter']
719 visitIndex = np.searchsorted(visitCat[
'visit'],
722 obsFilterNames = visitFilterNames[visitIndex]
724 if self.config.doReferenceMatches:
726 lutCat = lutDataRef.get()
728 stdFilterDict = {filterName: stdFilter
for (filterName, stdFilter)
in
729 zip(lutCat[0][
'physicalFilters'].split(
','),
730 lutCat[0][
'stdPhysicalFilters'].split(
','))}
731 stdLambdaDict = {stdFilter: stdLambda
for (stdFilter, stdLambda)
in
732 zip(lutCat[0][
'stdPhysicalFilters'].split(
','),
733 lutCat[0][
'lambdaStdFilter'])}
740 self.log.info(
"Using the following reference filters: %s" %
741 (
', '.join(referenceFilterNames)))
745 referenceFilterNames = []
748 starConfig = {
'logger': self.log,
749 'filterToBand': self.config.physicalFilterMap,
750 'requiredBands': self.config.requiredBands,
751 'minPerBand': self.config.minPerBand,
752 'matchRadius': self.config.matchRadius,
753 'isolationRadius': self.config.isolationRadius,
754 'matchNSide': self.config.matchNside,
755 'coarseNSide': self.config.coarseNside,
756 'densNSide': self.config.densityCutNside,
757 'densMaxPerPixel': self.config.densityCutMaxPerPixel,
758 'primaryBands': self.config.primaryBands,
759 'referenceFilterNames': referenceFilterNames}
762 fgcmMakeStars = fgcm.FgcmMakeStars(starConfig)
770 conv = obsCat[0][
'ra'].asDegrees() / float(obsCat[0][
'ra'])
771 fgcmMakeStars.makePrimaryStars(obsCat[
'ra'] * conv,
772 obsCat[
'dec'] * conv,
773 filterNameArray=obsFilterNames,
777 fgcmMakeStars.makeMatchedStars(obsCat[
'ra'] * conv,
778 obsCat[
'dec'] * conv,
781 if self.config.doReferenceMatches:
782 fgcmMakeStars.makeReferenceMatches(self.fgcmLoadReferenceCatalog)
789 fgcmStarIdCat = afwTable.BaseCatalog(objSchema)
790 fgcmStarIdCat.reserve(fgcmMakeStars.objIndexCat.size)
791 for i
in range(fgcmMakeStars.objIndexCat.size):
792 fgcmStarIdCat.addNew()
795 fgcmStarIdCat[
'fgcm_id'][:] = fgcmMakeStars.objIndexCat[
'fgcm_id']
796 fgcmStarIdCat[
'ra'][:] = fgcmMakeStars.objIndexCat[
'ra']
797 fgcmStarIdCat[
'dec'][:] = fgcmMakeStars.objIndexCat[
'dec']
798 fgcmStarIdCat[
'obsArrIndex'][:] = fgcmMakeStars.objIndexCat[
'obsarrindex']
799 fgcmStarIdCat[
'nObs'][:] = fgcmMakeStars.objIndexCat[
'nobs']
803 fgcmStarIndicesCat = afwTable.BaseCatalog(obsSchema)
804 fgcmStarIndicesCat.reserve(fgcmMakeStars.obsIndexCat.size)
805 for i
in range(fgcmMakeStars.obsIndexCat.size):
806 fgcmStarIndicesCat.addNew()
808 fgcmStarIndicesCat[
'obsIndex'][:] = fgcmMakeStars.obsIndexCat[
'obsindex']
810 if self.config.doReferenceMatches:
813 fgcmRefCat = afwTable.BaseCatalog(refSchema)
814 fgcmRefCat.reserve(fgcmMakeStars.referenceCat.size)
816 for i
in range(fgcmMakeStars.referenceCat.size):
819 fgcmRefCat[
'fgcm_id'][:] = fgcmMakeStars.referenceCat[
'fgcm_id']
820 fgcmRefCat[
'refMag'][:, :] = fgcmMakeStars.referenceCat[
'refMag']
821 fgcmRefCat[
'refMagErr'][:, :] = fgcmMakeStars.referenceCat[
'refMagErr']
824 md.set(
"REFSTARS_FORMAT_VERSION", REFSTARS_FORMAT_VERSION)
825 md.set(
"FILTERNAMES", referenceFilterNames)
826 fgcmRefCat.setMetadata(md)
831 return fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat
833 def _makeFgcmVisitSchema(self, nCcd):
835 Make a schema for an fgcmVisitCatalog
840 Number of CCDs in the camera
844 schema: `afwTable.Schema`
847 schema = afwTable.Schema()
848 schema.addField(
'visit', type=np.int32, doc=
"Visit number")
849 schema.addField(
'physicalFilter', type=str, size=30, doc=
"Physical filter")
850 schema.addField(
'telra', type=np.float64, doc=
"Pointing RA (deg)")
851 schema.addField(
'teldec', type=np.float64, doc=
"Pointing Dec (deg)")
852 schema.addField(
'telha', type=np.float64, doc=
"Pointing Hour Angle (deg)")
853 schema.addField(
'telrot', type=np.float64, doc=
"Camera rotation (deg)")
854 schema.addField(
'mjd', type=np.float64, doc=
"MJD of visit")
855 schema.addField(
'exptime', type=np.float32, doc=
"Exposure time")
856 schema.addField(
'pmb', type=np.float32, doc=
"Pressure (millibar)")
857 schema.addField(
'psfSigma', type=np.float32, doc=
"PSF sigma (reference CCD)")
858 schema.addField(
'deltaAper', type=np.float32, doc=
"Delta-aperture")
859 schema.addField(
'skyBackground', type=np.float32, doc=
"Sky background (ADU) (reference CCD)")
861 schema.addField(
'deepFlag', type=np.int32, doc=
"Deep observation")
862 schema.addField(
'scaling', type=
'ArrayD', doc=
"Scaling applied due to flat adjustment",
864 schema.addField(
'used', type=np.int32, doc=
"This visit has been ingested.")
865 schema.addField(
'sources_read', type=
'Flag', doc=
"This visit had sources read.")
869 def _makeFgcmObjSchema(self):
871 Make a schema for the objIndexCat from fgcmMakeStars
875 schema: `afwTable.Schema`
878 objSchema = afwTable.Schema()
879 objSchema.addField(
'fgcm_id', type=np.int32, doc=
'FGCM Unique ID')
881 objSchema.addField(
'ra', type=np.float64, doc=
'Mean object RA (deg)')
882 objSchema.addField(
'dec', type=np.float64, doc=
'Mean object Dec (deg)')
883 objSchema.addField(
'obsArrIndex', type=np.int32,
884 doc=
'Index in obsIndexTable for first observation')
885 objSchema.addField(
'nObs', type=np.int32, doc=
'Total number of observations')
889 def _makeFgcmObsSchema(self):
891 Make a schema for the obsIndexCat from fgcmMakeStars
895 schema: `afwTable.Schema`
898 obsSchema = afwTable.Schema()
899 obsSchema.addField(
'obsIndex', type=np.int32, doc=
'Index in observation table')
903 def _makeFgcmRefSchema(self, nReferenceBands):
905 Make a schema for the referenceCat from fgcmMakeStars
909 nReferenceBands: `int`
910 Number of reference bands
914 schema: `afwTable.Schema`
917 refSchema = afwTable.Schema()
918 refSchema.addField(
'fgcm_id', type=np.int32, doc=
'FGCM Unique ID')
919 refSchema.addField(
'refMag', type=
'ArrayF', doc=
'Reference magnitude array (AB)',
920 size=nReferenceBands)
921 refSchema.addField(
'refMagErr', type=
'ArrayF', doc=
'Reference magnitude error array',
922 size=nReferenceBands)
926 def _getReferenceFilterNames(self, visitCat, stdFilterDict, stdLambdaDict):
928 Get the reference filter names, in wavelength order, from the visitCat and
929 information from the look-up-table.
933 visitCat: `afw.table.BaseCatalog`
934 Catalog with visit data for FGCM
935 stdFilterDict: `dict`
936 Mapping of filterName to stdFilterName from LUT
937 stdLambdaDict: `dict`
938 Mapping of stdFilterName to stdLambda from LUT
942 referenceFilterNames: `list`
943 Wavelength-ordered list of reference filter names
947 filterNames = np.unique(visitCat.asAstropy()[
'physicalFilter'])
950 stdFilterNames = {stdFilterDict[filterName]
for filterName
in filterNames}
953 referenceFilterNames = sorted(stdFilterNames, key=stdLambdaDict.get)
955 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)