21"""Base class for BuildStars using src tables or sourceTable_visit tables.
31import lsst.daf.persistence
as dafPersist
32import lsst.pex.config
as pexConfig
33import lsst.pipe.base
as pipeBase
34import lsst.afw.table
as afwTable
35import lsst.geom
as geom
36from lsst.daf.base
import PropertyList
37from lsst.daf.base.dateTime
import DateTime
38from lsst.meas.algorithms.sourceSelector
import sourceSelectorRegistry
40from .utilities
import computeApertureRadiusFromDataRef
41from .fgcmLoadReferenceCatalog
import FgcmLoadReferenceCatalogTask
45REFSTARS_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 randomSeed = pexConfig.Field(
85 doc=
"Random seed for high density down-sampling.",
90 matchNside = pexConfig.Field(
91 doc=
"Healpix Nside for matching",
95 coarseNside = pexConfig.Field(
96 doc=
"Healpix coarse Nside for partitioning matches",
103 physicalFilterMap = pexConfig.DictField(
104 doc=
"Mapping from 'physicalFilter' to band.",
109 requiredBands = pexConfig.ListField(
110 doc=
"Bands required for each star",
114 primaryBands = pexConfig.ListField(
115 doc=(
"Bands for 'primary' star matches. "
116 "A star must be observed in one of these bands to be considered "
117 "as a calibration star."),
121 visitDataRefName = pexConfig.Field(
122 doc=
"dataRef name for the 'visit' field, usually 'visit'.",
126 ccdDataRefName = pexConfig.Field(
127 doc=
"dataRef name for the 'ccd' field, usually 'ccd' or 'detector'.",
131 doApplyWcsJacobian = pexConfig.Field(
132 doc=
"Apply the jacobian of the WCS to the star observations prior to fit?",
136 doModelErrorsWithBackground = pexConfig.Field(
137 doc=
"Model flux errors with background term?",
141 psfCandidateName = pexConfig.Field(
142 doc=
"Name of field with psf candidate flag for propagation",
144 default=
"calib_psf_candidate"
146 doSubtractLocalBackground = pexConfig.Field(
147 doc=(
"Subtract the local background before performing calibration? "
148 "This is only supported for circular aperture calibration fluxes."),
152 localBackgroundFluxField = pexConfig.Field(
153 doc=
"Full name of the local background instFlux field to use.",
155 default=
'base_LocalBackground_instFlux'
157 sourceSelector = sourceSelectorRegistry.makeField(
158 doc=
"How to select sources",
161 apertureInnerInstFluxField = pexConfig.Field(
162 doc=(
"Full name of instFlux field that contains inner aperture "
163 "flux for aperture correction proxy"),
165 default=
'base_CircularApertureFlux_12_0_instFlux'
167 apertureOuterInstFluxField = pexConfig.Field(
168 doc=(
"Full name of instFlux field that contains outer aperture "
169 "flux for aperture correction proxy"),
171 default=
'base_CircularApertureFlux_17_0_instFlux'
173 doReferenceMatches = pexConfig.Field(
174 doc=
"Match reference catalog as additional constraint on calibration",
178 fgcmLoadReferenceCatalog = pexConfig.ConfigurableField(
179 target=FgcmLoadReferenceCatalogTask,
180 doc=
"FGCM reference object loader",
182 nVisitsPerCheckpoint = pexConfig.Field(
183 doc=
"Number of visits read between checkpoints",
190 sourceSelector.setDefaults()
192 sourceSelector.doFlags =
True
193 sourceSelector.doUnresolved =
True
194 sourceSelector.doSignalToNoise =
True
195 sourceSelector.doIsolated =
True
197 sourceSelector.signalToNoise.minimum = 10.0
198 sourceSelector.signalToNoise.maximum = 1000.0
202 sourceSelector.unresolved.maximum = 0.5
206 """Subclass of TaskRunner for FgcmBuildStars tasks
208 fgcmBuildStarsTask.run() and fgcmBuildStarsTableTask.run() take a number of
209 arguments, one of which
is the butler (
for persistence
and mapper data),
210 and a list of dataRefs extracted
from the command line. Note that FGCM
211 runs on a large set of dataRefs,
and not on single dataRef/tract/patch.
212 This
class transforms the process arguments generated by the ArgumentParser
213 into the arguments expected by FgcmBuildStarsTask.run(). This runner does
214 not use any parallelization.
219 Return a list with one element: a tuple
with the butler
and
223 return [(parsedCmd.butler, parsedCmd.id.refList)]
229 args: `tuple` with (butler, dataRefList)
233 exitStatus: `list`
with `lsst.pipe.base.Struct`
234 exitStatus (0: success; 1: failure)
236 butler, dataRefList = args
238 task = self.TaskClass(config=self.config, log=self.log)
242 task.runDataRef(butler, dataRefList)
245 task.runDataRef(butler, dataRefList)
246 except Exception
as e:
248 task.log.fatal(
"Failed: %s" % e)
249 if not isinstance(e, pipeBase.TaskError):
250 traceback.print_exc(file=sys.stderr)
252 task.writeMetadata(butler)
255 return [pipeBase.Struct(exitStatus=exitStatus)]
259 Run the task, with no multiprocessing
263 parsedCmd: `lsst.pipe.base.ArgumentParser` parsed command line
268 if self.precall(parsedCmd):
270 resultList = self(targetList[0])
277 Base task to build stars for FGCM
global calibration
281 butler : `lsst.daf.persistence.Butler`
283 def __init__(self, initInputs=None, butler=None, **kwargs):
286 self.makeSubtask(
"sourceSelector")
288 self.sourceSelector.log.setLevel(self.sourceSelector.log.WARN)
291 def _getMetadataName(self):
297 Cross-match and make star list
for FGCM Input
301 butler: `lsst.daf.persistence.Butler`
302 dataRefs: `list` of `lsst.daf.persistence.ButlerDataRef`
303 Source data references
for the input visits.
307 RuntimeErrror: Raised
if `config.doReferenceMatches`
is set
and
308 an fgcmLookUpTable
is not available,
or if computeFluxApertureRadius()
309 fails
if the calibFlux
is not a CircularAperture flux.
311 datasetType = dataRefs[0].butlerSubset.datasetType
312 self.log.info("Running with %d %s dataRefs", len(dataRefs), datasetType)
314 if self.config.doReferenceMatches:
315 self.makeSubtask(
"fgcmLoadReferenceCatalog", butler=butler)
317 if not butler.datasetExists(
'fgcmLookUpTable'):
318 raise RuntimeError(
"Must have fgcmLookUpTable if using config.doReferenceMatches")
321 calibFluxApertureRadius =
None
322 if self.config.doSubtractLocalBackground:
325 self.config.instFluxField)
326 except RuntimeError
as e:
327 raise RuntimeError(
"Could not determine aperture radius from %s. "
328 "Cannot use doSubtractLocalBackground." %
329 (self.config.instFluxField))
from e
331 camera = butler.get(
'camera')
339 visitCatDataRef = butler.dataRef(
'fgcmVisitCatalog')
340 filename = visitCatDataRef.get(
'fgcmVisitCatalog_filename')[0]
341 if os.path.exists(filename):
343 inVisitCat = visitCatDataRef.get()
344 if len(inVisitCat) != len(groupedDataRefs):
345 raise RuntimeError(
"Existing visitCatalog found, but has an inconsistent "
346 "number of visits. Cannot continue.")
351 visitCatDataRef=visitCatDataRef,
352 inVisitCat=inVisitCat)
355 visitCatDataRef.put(visitCat)
357 starObsDataRef = butler.dataRef(
'fgcmStarObservations')
358 filename = starObsDataRef.get(
'fgcmStarObservations_filename')[0]
359 if os.path.exists(filename):
360 inStarObsCat = starObsDataRef.get()
364 rad = calibFluxApertureRadius
365 sourceSchemaDataRef = butler.dataRef(
'src_schema')
366 sourceSchema = sourceSchemaDataRef.get(
'src_schema', immediate=
True).schema
371 calibFluxApertureRadius=rad,
372 starObsDataRef=starObsDataRef,
373 visitCatDataRef=visitCatDataRef,
374 inStarObsCat=inStarObsCat)
375 visitCatDataRef.put(visitCat)
376 starObsDataRef.put(fgcmStarObservationCat)
379 if self.config.doReferenceMatches:
380 lutDataRef = butler.dataRef(
'fgcmLookUpTable')
383 fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat = self.
fgcmMatchStarsfgcmMatchStars(visitCat,
384 fgcmStarObservationCat,
385 lutDataRef=lutDataRef)
388 butler.put(fgcmStarIdCat,
'fgcmStarIds')
389 butler.put(fgcmStarIndicesCat,
'fgcmStarIndices')
390 if fgcmRefCat
is not None:
391 butler.put(fgcmRefCat,
'fgcmReferenceStars')
394 def _findAndGroupDataRefsGen2(self, butler, camera, dataRefs):
396 Find and group dataRefs (by visit); Gen2 only.
400 butler : `lsst.daf.persistence.Butler`
402 camera : `lsst.afw.cameraGeom.Camera`
403 Camera
from the butler.
404 dataRefs : `list` of `lsst.daf.persistence.ButlerDataRef`
405 Data references
for the input visits.
409 groupedDataRefs : `dict` [`int`, `list`]
410 Dictionary
with sorted visit keys,
and `list`s of
411 `lsst.daf.persistence.ButlerDataRef`
413 raise NotImplementedError(
"_findAndGroupDataRefsGen2 not implemented.")
419 calibFluxApertureRadius=None,
420 visitCatDataRef=None,
424 Compile all good star observations from visits
in visitCat. Checkpoint files
425 will be stored
if both visitCatDataRef
and starObsDataRef are
not None.
429 groupedDataRefs : `dict` of `list`s
430 Lists of `~lsst.daf.persistence.ButlerDataRef`
or
431 `~lsst.daf.butler.DeferredDatasetHandle`, grouped by visit.
432 visitCat : `~afw.table.BaseCatalog`
433 Catalog
with visit data
for FGCM
434 sourceSchema : `~lsst.afw.table.Schema`
435 Schema
for the input src catalogs.
436 camera : `~lsst.afw.cameraGeom.Camera`
437 calibFluxApertureRadius : `float`, optional
438 Aperture radius
for calibration flux.
439 visitCatDataRef : `~lsst.daf.persistence.ButlerDataRef`, optional
440 Dataref to write visitCat
for checkpoints
441 starObsDataRef : `~lsst.daf.persistence.ButlerDataRef`, optional
442 Dataref to write the star observation catalog
for checkpoints.
443 inStarObsCat : `~afw.table.BaseCatalog`
444 Input observation catalog. If this
is incomplete, observations
445 will be appended
from when it was cut off.
449 fgcmStarObservations : `afw.table.BaseCatalog`
450 Full catalog of good observations.
454 RuntimeError: Raised
if doSubtractLocalBackground
is True and
455 calibFluxApertureRadius
is not set.
457 raise NotImplementedError(
"fgcmMakeAllStarObservations not implemented.")
460 visitCatDataRef=None, inVisitCat=None):
462 Make a visit catalog with all the keys
from each visit
466 camera: `lsst.afw.cameraGeom.Camera`
467 Camera
from the butler
468 groupedDataRefs: `dict`
469 Dictionary
with visit keys,
and `list`s of
470 `lsst.daf.persistence.ButlerDataRef`
471 bkgDataRefDict: `dict`, optional
472 Dictionary of gen3 dataRefHandles
for background info.
473 visitCatDataRef: `lsst.daf.persistence.ButlerDataRef`, optional
474 Dataref to write visitCat
for checkpoints
475 inVisitCat: `afw.table.BaseCatalog`, optional
476 Input (possibly incomplete) visit catalog
480 visitCat: `afw.table.BaseCatalog`
483 self.log.info("Assembling visitCatalog from %d %ss" %
484 (len(groupedDataRefs), self.config.visitDataRefName))
488 if inVisitCat
is None:
491 visitCat = afwTable.BaseCatalog(schema)
492 visitCat.reserve(len(groupedDataRefs))
493 visitCat.resize(len(groupedDataRefs))
495 visitCat[
'visit'] = list(groupedDataRefs.keys())
497 visitCat[
'sources_read'] =
False
499 visitCat = inVisitCat
504 bkgDataRefDict=bkgDataRefDict,
505 visitCatDataRef=visitCatDataRef)
509 def _fillVisitCatalog(self, visitCat, groupedDataRefs, bkgDataRefDict=None,
510 visitCatDataRef=None):
512 Fill the visit catalog with visit metadata
516 visitCat : `afw.table.BaseCatalog`
517 Visit catalog. See _makeFgcmVisitSchema()
for schema definition.
518 groupedDataRefs : `dict`
519 Dictionary
with visit keys,
and `list`s of
520 `lsst.daf.persistence.ButlerDataRef`
or
521 `lsst.daf.butler.DeferredDatasetHandle`
522 visitCatDataRef : `lsst.daf.persistence.ButlerDataRef`, optional
523 Dataref to write ``visitCat``
for checkpoints. Gen2 only.
524 bkgDataRefDict : `dict`, optional
525 Dictionary of Gen3 `lsst.daf.butler.DeferredDatasetHandle`
528 bbox = geom.BoxI(geom.PointI(0, 0), geom.PointI(1, 1))
530 for i, visit
in enumerate(groupedDataRefs):
537 if visitCat[
'used'][i]:
540 if (i % self.config.nVisitsPerCheckpoint) == 0:
541 self.log.info(
"Retrieving metadata for %s %d (%d/%d)" %
542 (self.config.visitDataRefName, visit, i, len(groupedDataRefs)))
544 if visitCatDataRef
is not None:
545 visitCatDataRef.put(visitCat)
547 dataRef = groupedDataRefs[visit][0]
548 if isinstance(dataRef, dafPersist.ButlerDataRef):
551 exp = dataRef.get(datasetType=
'calexp_sub', bbox=bbox)
552 visitInfo = exp.getInfo().getVisitInfo()
553 label = dataRef.get(datasetType=
'calexp_filterLabel')
554 physicalFilter = label.physicalLabel
556 bbox = dataRef.get(datasetType=
'calexp_bbox')
557 psfSigma = psf.computeShape(bbox.getCenter()).getDeterminantRadius()
560 summary = dataRef.get()
562 summaryRow = summary.find(self.config.referenceCCD)
563 if summaryRow
is None:
565 summaryRow = summary[0]
567 summaryDetector = summaryRow[
'id']
568 visitInfo = summaryRow.getVisitInfo()
569 physicalFilter = summaryRow[
'physical_filter']
571 goodSigma, = np.where(summary[
'psfSigma'] > 0)
572 if goodSigma.size > 2:
573 psfSigma = np.median(summary[
'psfSigma'][goodSigma])
575 psfSigma = np.mean(summary[
'psfSigma'][goodSigma])
581 rec[
'physicalFilter'] = physicalFilter
585 radec = visitInfo.getBoresightRaDec()
586 rec[
'telra'] = radec.getRa().asDegrees()
587 rec[
'teldec'] = radec.getDec().asDegrees()
588 rec[
'telha'] = visitInfo.getBoresightHourAngle().asDegrees()
589 rec[
'telrot'] = visitInfo.getBoresightRotAngle().asDegrees()
590 rec[
'mjd'] = visitInfo.getDate().get(system=DateTime.MJD)
591 rec[
'exptime'] = visitInfo.getExposureTime()
594 rec[
'pmb'] = visitInfo.getWeather().getAirPressure() / 100
598 rec[
'scaling'][:] = 1.0
600 rec[
'deltaAper'] = 0.0
601 rec[
'psfSigma'] = psfSigma
603 if self.config.doModelErrorsWithBackground:
605 if isinstance(dataRef, dafPersist.ButlerDataRef):
607 det = dataRef.dataId[self.config.ccdDataRefName]
608 if dataRef.datasetExists(datasetType=
'calexpBackground'):
609 bgList = dataRef.get(datasetType=
'calexpBackground')
615 bkgRef = bkgDataRefDict[(visit, summaryDetector)]
616 bgList = bkgRef.get()
622 bgStats = (bg[0].getStatsImage().getImage().array
624 rec[
'skyBackground'] = sum(np.median(bg[np.isfinite(bg)])
for bg
in bgStats)
626 self.log.warning(
'Sky background not found for visit %d / ccd %d' %
628 rec[
'skyBackground'] = -1.0
630 rec[
'skyBackground'] = -1.0
634 def _makeSourceMapper(self, sourceSchema):
636 Make a schema mapper for fgcm sources
640 sourceSchema: `afwTable.Schema`
641 Default source schema
from the butler
645 sourceMapper: `afwTable.schemaMapper`
646 Mapper to the FGCM source schema
650 sourceMapper = afwTable.SchemaMapper(sourceSchema)
653 sourceMapper.addMapping(sourceSchema[
'coord_ra'].asKey(),
'ra')
654 sourceMapper.addMapping(sourceSchema[
'coord_dec'].asKey(),
'dec')
655 sourceMapper.addMapping(sourceSchema[
'slot_Centroid_x'].asKey(),
'x')
656 sourceMapper.addMapping(sourceSchema[
'slot_Centroid_y'].asKey(),
'y')
662 sourceMapper.addMapping(sourceSchema[self.config.psfCandidateName].asKey(),
665 sourceMapper.editOutputSchema().addField(
666 "psf_candidate", type=
'Flag',
667 doc=(
"Flag set if the source was a candidate for PSF determination, "
668 "as determined by the star selector."))
671 sourceMapper.editOutputSchema().addField(
672 "visit", type=np.int32, doc=
"Visit number")
673 sourceMapper.editOutputSchema().addField(
674 "ccd", type=np.int32, doc=
"CCD number")
675 sourceMapper.editOutputSchema().addField(
676 "instMag", type=np.float32, doc=
"Instrumental magnitude")
677 sourceMapper.editOutputSchema().addField(
678 "instMagErr", type=np.float32, doc=
"Instrumental magnitude error")
679 sourceMapper.editOutputSchema().addField(
680 "jacobian", type=np.float32, doc=
"Relative pixel scale from wcs jacobian")
681 sourceMapper.editOutputSchema().addField(
682 "deltaMagBkg", type=np.float32, doc=
"Change in magnitude due to local background offset")
688 Use FGCM code to match observations into unique stars.
692 visitCat: `afw.table.BaseCatalog`
693 Catalog with visit data
for fgcm
694 obsCat: `afw.table.BaseCatalog`
695 Full catalog of star observations
for fgcm
696 lutDataRef: `lsst.daf.persistence.ButlerDataRef`
or
697 `lsst.daf.butler.DeferredDatasetHandle`, optional
698 Data reference to fgcm look-up table (used
if matching reference stars).
702 fgcmStarIdCat: `afw.table.BaseCatalog`
703 Catalog of unique star identifiers
and index keys
704 fgcmStarIndicesCat: `afwTable.BaseCatalog`
705 Catalog of unique star indices
706 fgcmRefCat: `afw.table.BaseCatalog`
707 Catalog of matched reference stars.
708 Will be
None if `config.doReferenceMatches`
is False.
712 visitFilterNames = np.zeros(len(visitCat), dtype=
'a30')
713 for i
in range(len(visitCat)):
714 visitFilterNames[i] = visitCat[i][
'physicalFilter']
717 visitIndex = np.searchsorted(visitCat[
'visit'],
720 obsFilterNames = visitFilterNames[visitIndex]
722 if self.config.doReferenceMatches:
724 lutCat = lutDataRef.get()
726 stdFilterDict = {filterName: stdFilter
for (filterName, stdFilter)
in
727 zip(lutCat[0][
'physicalFilters'].split(
','),
728 lutCat[0][
'stdPhysicalFilters'].split(
','))}
729 stdLambdaDict = {stdFilter: stdLambda
for (stdFilter, stdLambda)
in
730 zip(lutCat[0][
'stdPhysicalFilters'].split(
','),
731 lutCat[0][
'lambdaStdFilter'])}
738 self.log.info(
"Using the following reference filters: %s" %
739 (
', '.join(referenceFilterNames)))
743 referenceFilterNames = []
746 starConfig = {
'logger': self.log,
747 'filterToBand': self.config.physicalFilterMap,
748 'requiredBands': self.config.requiredBands,
749 'minPerBand': self.config.minPerBand,
750 'matchRadius': self.config.matchRadius,
751 'isolationRadius': self.config.isolationRadius,
752 'matchNSide': self.config.matchNside,
753 'coarseNSide': self.config.coarseNside,
754 'densNSide': self.config.densityCutNside,
755 'densMaxPerPixel': self.config.densityCutMaxPerPixel,
756 'randomSeed': self.config.randomSeed,
757 'primaryBands': self.config.primaryBands,
758 'referenceFilterNames': referenceFilterNames}
761 fgcmMakeStars = fgcm.FgcmMakeStars(starConfig)
769 conv = obsCat[0][
'ra'].asDegrees() / float(obsCat[0][
'ra'])
770 fgcmMakeStars.makePrimaryStars(obsCat[
'ra'] * conv,
771 obsCat[
'dec'] * conv,
772 filterNameArray=obsFilterNames,
776 fgcmMakeStars.makeMatchedStars(obsCat[
'ra'] * conv,
777 obsCat[
'dec'] * conv,
780 if self.config.doReferenceMatches:
781 fgcmMakeStars.makeReferenceMatches(self.fgcmLoadReferenceCatalog)
788 fgcmStarIdCat = afwTable.BaseCatalog(objSchema)
789 fgcmStarIdCat.reserve(fgcmMakeStars.objIndexCat.size)
790 for i
in range(fgcmMakeStars.objIndexCat.size):
791 fgcmStarIdCat.addNew()
794 fgcmStarIdCat[
'fgcm_id'][:] = fgcmMakeStars.objIndexCat[
'fgcm_id']
795 fgcmStarIdCat[
'ra'][:] = fgcmMakeStars.objIndexCat[
'ra']
796 fgcmStarIdCat[
'dec'][:] = fgcmMakeStars.objIndexCat[
'dec']
797 fgcmStarIdCat[
'obsArrIndex'][:] = fgcmMakeStars.objIndexCat[
'obsarrindex']
798 fgcmStarIdCat[
'nObs'][:] = fgcmMakeStars.objIndexCat[
'nobs']
802 fgcmStarIndicesCat = afwTable.BaseCatalog(obsSchema)
803 fgcmStarIndicesCat.reserve(fgcmMakeStars.obsIndexCat.size)
804 for i
in range(fgcmMakeStars.obsIndexCat.size):
805 fgcmStarIndicesCat.addNew()
807 fgcmStarIndicesCat[
'obsIndex'][:] = fgcmMakeStars.obsIndexCat[
'obsindex']
809 if self.config.doReferenceMatches:
812 fgcmRefCat = afwTable.BaseCatalog(refSchema)
813 fgcmRefCat.reserve(fgcmMakeStars.referenceCat.size)
815 for i
in range(fgcmMakeStars.referenceCat.size):
818 fgcmRefCat[
'fgcm_id'][:] = fgcmMakeStars.referenceCat[
'fgcm_id']
819 fgcmRefCat[
'refMag'][:, :] = fgcmMakeStars.referenceCat[
'refMag']
820 fgcmRefCat[
'refMagErr'][:, :] = fgcmMakeStars.referenceCat[
'refMagErr']
823 md.set(
"REFSTARS_FORMAT_VERSION", REFSTARS_FORMAT_VERSION)
824 md.set(
"FILTERNAMES", referenceFilterNames)
825 fgcmRefCat.setMetadata(md)
830 return fgcmStarIdCat, fgcmStarIndicesCat, fgcmRefCat
832 def _makeFgcmVisitSchema(self, nCcd):
834 Make a schema for an fgcmVisitCatalog
839 Number of CCDs
in the camera
843 schema: `afwTable.Schema`
846 schema = afwTable.Schema()
847 schema.addField('visit', type=np.int32, doc=
"Visit number")
848 schema.addField(
'physicalFilter', type=str, size=30, doc=
"Physical filter")
849 schema.addField(
'telra', type=np.float64, doc=
"Pointing RA (deg)")
850 schema.addField(
'teldec', type=np.float64, doc=
"Pointing Dec (deg)")
851 schema.addField(
'telha', type=np.float64, doc=
"Pointing Hour Angle (deg)")
852 schema.addField(
'telrot', type=np.float64, doc=
"Camera rotation (deg)")
853 schema.addField(
'mjd', type=np.float64, doc=
"MJD of visit")
854 schema.addField(
'exptime', type=np.float32, doc=
"Exposure time")
855 schema.addField(
'pmb', type=np.float32, doc=
"Pressure (millibar)")
856 schema.addField(
'psfSigma', type=np.float32, doc=
"PSF sigma (reference CCD)")
857 schema.addField(
'deltaAper', type=np.float32, doc=
"Delta-aperture")
858 schema.addField(
'skyBackground', type=np.float32, doc=
"Sky background (ADU) (reference CCD)")
860 schema.addField(
'deepFlag', type=np.int32, doc=
"Deep observation")
861 schema.addField(
'scaling', type=
'ArrayD', doc=
"Scaling applied due to flat adjustment",
863 schema.addField(
'used', type=np.int32, doc=
"This visit has been ingested.")
864 schema.addField(
'sources_read', type=
'Flag', doc=
"This visit had sources read.")
868 def _makeFgcmObjSchema(self):
870 Make a schema for the objIndexCat
from fgcmMakeStars
874 schema: `afwTable.Schema`
877 objSchema = afwTable.Schema()
878 objSchema.addField('fgcm_id', type=np.int32, doc=
'FGCM Unique ID')
880 objSchema.addField(
'ra', type=np.float64, doc=
'Mean object RA (deg)')
881 objSchema.addField(
'dec', type=np.float64, doc=
'Mean object Dec (deg)')
882 objSchema.addField(
'obsArrIndex', type=np.int32,
883 doc=
'Index in obsIndexTable for first observation')
884 objSchema.addField(
'nObs', type=np.int32, doc=
'Total number of observations')
888 def _makeFgcmObsSchema(self):
890 Make a schema for the obsIndexCat
from fgcmMakeStars
894 schema: `afwTable.Schema`
897 obsSchema = afwTable.Schema()
898 obsSchema.addField('obsIndex', type=np.int32, doc=
'Index in observation table')
902 def _makeFgcmRefSchema(self, nReferenceBands):
904 Make a schema for the referenceCat
from fgcmMakeStars
908 nReferenceBands: `int`
909 Number of reference bands
913 schema: `afwTable.Schema`
916 refSchema = afwTable.Schema()
917 refSchema.addField('fgcm_id', type=np.int32, doc=
'FGCM Unique ID')
918 refSchema.addField(
'refMag', type=
'ArrayF', doc=
'Reference magnitude array (AB)',
919 size=nReferenceBands)
920 refSchema.addField(
'refMagErr', type=
'ArrayF', doc=
'Reference magnitude error array',
921 size=nReferenceBands)
925 def _getReferenceFilterNames(self, visitCat, stdFilterDict, stdLambdaDict):
927 Get the reference filter names, in wavelength order,
from the visitCat
and
928 information
from the look-up-table.
932 visitCat: `afw.table.BaseCatalog`
933 Catalog
with visit data
for FGCM
934 stdFilterDict: `dict`
935 Mapping of filterName to stdFilterName
from LUT
936 stdLambdaDict: `dict`
937 Mapping of stdFilterName to stdLambda
from LUT
941 referenceFilterNames: `list`
942 Wavelength-ordered list of reference filter names
946 filterNames = np.unique(visitCat.asAstropy()[
'physicalFilter'])
949 stdFilterNames = {stdFilterDict[filterName]
for filterName
in filterNames}
952 referenceFilterNames = sorted(stdFilterNames, key=stdLambdaDict.get)
954 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)