37from lsst.obs.base
import ExposureIdInfo
39import lsst.pipe.base.connectionTypes
as cT
44from .forcedMeasurement
import ForcedMeasurementTask
45from .applyApCorr
import ApplyApCorrTask
46from .catalogCalculation
import CatalogCalculationTask
48__all__ = (
"ForcedPhotCcdConfig",
"ForcedPhotCcdTask",
49 "ForcedPhotCcdFromDataFrameTask",
"ForcedPhotCcdFromDataFrameConfig")
53 dimensions=(
"instrument",
"visit",
"detector",
"skymap",
"tract"),
54 defaultTemplates={
"inputCoaddName":
"deep",
55 "inputName":
"calexp",
56 "skyWcsName":
"jointcal",
57 "photoCalibName":
"fgcm"}):
58 inputSchema = cT.InitInput(
59 doc=
"Schema for the input measurement catalogs.",
60 name=
"{inputCoaddName}Coadd_ref_schema",
61 storageClass=
"SourceCatalog",
63 outputSchema = cT.InitOutput(
64 doc=
"Schema for the output forced measurement catalogs.",
65 name=
"forced_src_schema",
66 storageClass=
"SourceCatalog",
69 doc=
"Input exposure to perform photometry on.",
71 storageClass=
"ExposureF",
72 dimensions=[
"instrument",
"visit",
"detector"],
75 doc=
"Catalog of shapes and positions at which to force photometry.",
76 name=
"{inputCoaddName}Coadd_ref",
77 storageClass=
"SourceCatalog",
78 dimensions=[
"skymap",
"tract",
"patch"],
83 doc=
"SkyMap dataset that defines the coordinate system of the reference catalog.",
84 name=BaseSkyMap.SKYMAP_DATASET_TYPE_NAME,
85 storageClass=
"SkyMap",
86 dimensions=[
"skymap"],
89 doc=
"Input Sky Correction to be subtracted from the calexp if doApplySkyCorr=True",
91 storageClass=
"Background",
92 dimensions=(
"instrument",
"visit",
"detector"),
94 externalSkyWcsTractCatalog = cT.Input(
95 doc=(
"Per-tract, per-visit wcs calibrations. These catalogs use the detector "
96 "id for the catalog id, sorted on id for fast lookup."),
97 name=
"{skyWcsName}SkyWcsCatalog",
98 storageClass=
"ExposureCatalog",
99 dimensions=[
"instrument",
"visit",
"tract"],
101 externalSkyWcsGlobalCatalog = cT.Input(
102 doc=(
"Per-visit wcs calibrations computed globally (with no tract information). "
103 "These catalogs use the detector id for the catalog id, sorted on id for "
105 name=
"{skyWcsName}SkyWcsCatalog",
106 storageClass=
"ExposureCatalog",
107 dimensions=[
"instrument",
"visit"],
109 externalPhotoCalibTractCatalog = cT.Input(
110 doc=(
"Per-tract, per-visit photometric calibrations. These catalogs use the "
111 "detector id for the catalog id, sorted on id for fast lookup."),
112 name=
"{photoCalibName}PhotoCalibCatalog",
113 storageClass=
"ExposureCatalog",
114 dimensions=[
"instrument",
"visit",
"tract"],
116 externalPhotoCalibGlobalCatalog = cT.Input(
117 doc=(
"Per-visit photometric calibrations computed globally (with no tract "
118 "information). These catalogs use the detector id for the catalog id, "
119 "sorted on id for fast lookup."),
120 name=
"{photoCalibName}PhotoCalibCatalog",
121 storageClass=
"ExposureCatalog",
122 dimensions=[
"instrument",
"visit"],
124 finalizedPsfApCorrCatalog = cT.Input(
125 doc=(
"Per-visit finalized psf models and aperture correction maps. "
126 "These catalogs use the detector id for the catalog id, "
127 "sorted on id for fast lookup."),
128 name=
"finalized_psf_ap_corr_catalog",
129 storageClass=
"ExposureCatalog",
130 dimensions=[
"instrument",
"visit"],
133 doc=
"Output forced photometry catalog.",
135 storageClass=
"SourceCatalog",
136 dimensions=[
"instrument",
"visit",
"detector",
"skymap",
"tract"],
139 def __init__(self, *, config=None):
140 super().__init__(config=config)
141 if not config.doApplySkyCorr:
142 self.inputs.remove(
"skyCorr")
143 if config.doApplyExternalSkyWcs:
144 if config.useGlobalExternalSkyWcs:
145 self.inputs.remove(
"externalSkyWcsTractCatalog")
147 self.inputs.remove(
"externalSkyWcsGlobalCatalog")
149 self.inputs.remove(
"externalSkyWcsTractCatalog")
150 self.inputs.remove(
"externalSkyWcsGlobalCatalog")
151 if config.doApplyExternalPhotoCalib:
152 if config.useGlobalExternalPhotoCalib:
153 self.inputs.remove(
"externalPhotoCalibTractCatalog")
155 self.inputs.remove(
"externalPhotoCalibGlobalCatalog")
157 self.inputs.remove(
"externalPhotoCalibTractCatalog")
158 self.inputs.remove(
"externalPhotoCalibGlobalCatalog")
159 if not config.doApplyFinalizedPsf:
160 self.inputs.remove(
"finalizedPsfApCorrCatalog")
163class ForcedPhotCcdConfig(pipeBase.PipelineTaskConfig,
164 pipelineConnections=ForcedPhotCcdConnections):
165 """Config class for forced measurement driver task."""
167 target=ForcedMeasurementTask,
168 doc=
"subtask to do forced measurement"
171 doc=
"coadd name: typically one of deep or goodSeeing",
178 doc=
"Run subtask to apply aperture corrections"
181 target=ApplyApCorrTask,
182 doc=
"Subtask to apply aperture corrections"
185 target=CatalogCalculationTask,
186 doc=
"Subtask to run catalogCalculation plugins on catalog"
190 doc=
"Apply meas_mosaic ubercal results to input calexps?",
192 deprecated=
"Deprecated by DM-23352; use doApplyExternalPhotoCalib and doApplyExternalSkyWcs instead",
197 doc=(
"Whether to apply external photometric calibration via an "
198 "`lsst.afw.image.PhotoCalib` object."),
203 doc=(
"When using doApplyExternalPhotoCalib, use 'global' calibrations "
204 "that are not run per-tract. When False, use per-tract photometric "
205 "calibration files.")
210 doc=(
"Whether to apply external astrometric calibration via an "
211 "`lsst.afw.geom.SkyWcs` object."),
216 doc=(
"When using doApplyExternalSkyWcs, use 'global' calibrations "
217 "that are not run per-tract. When False, use per-tract wcs "
223 doc=
"Whether to apply finalized psf models and aperture correction map.",
228 doc=
"Apply sky correction?",
233 doc=
"Add photometric calibration variance to warp variance plane?",
237 doc=
"Where to obtain footprints to install in the measurement catalog, prior to measurement.",
239 "transformed":
"Transform footprints from the reference catalog (downgrades HeavyFootprints).",
240 "psf": (
"Use the scaled shape of the PSF at the position of each source (does not generate "
241 "HeavyFootprints)."),
244 default=
"transformed",
248 doc=
"Scaling factor to apply to the PSF shape when footprintSource='psf' (ignored otherwise).",
252 def setDefaults(self):
256 super().setDefaults()
257 self.measurement.plugins.names |= [
'base_LocalPhotoCalib',
'base_LocalWcs']
258 self.catalogCalculation.plugins.names = []
261class ForcedPhotCcdTask(pipeBase.PipelineTask):
262 """A pipeline task for performing forced measurement on CCD images.
267 Deprecated
and unused. Should always be `
None`.
269 The schema of the reference catalog, passed to the constructor of the
270 references subtask. Optional, but must be specified
if ``initInputs``
271 is not;
if both are specified, ``initInputs`` takes precedence.
273 Dictionary that can contain a key ``inputSchema`` containing the
274 schema. If present will override the value of ``refSchema``.
276 Keyword arguments are passed to the supertask constructor.
279 ConfigClass = ForcedPhotCcdConfig
280 _DefaultName = "forcedPhotCcd"
283 def __init__(self, butler=None, refSchema=None, initInputs=None, **kwds):
284 super().__init__(**kwds)
286 if butler
is not None:
287 warnings.warn(
"The 'butler' parameter is no longer used and can be safely removed.",
288 category=FutureWarning, stacklevel=2)
291 if initInputs
is not None:
292 refSchema = initInputs[
'inputSchema'].schema
294 if refSchema
is None:
295 raise ValueError(
"No reference schema provided.")
297 self.makeSubtask(
"measurement", refSchema=refSchema)
301 if self.config.doApCorr:
302 self.makeSubtask(
"applyApCorr", schema=self.measurement.schema)
303 self.makeSubtask(
'catalogCalculation', schema=self.measurement.schema)
306 def runQuantum(self, butlerQC, inputRefs, outputRefs):
307 inputs = butlerQC.get(inputRefs)
309 tract = butlerQC.quantum.dataId[
'tract']
310 skyMap = inputs.pop(
'skyMap')
311 inputs[
'refWcs'] = skyMap[tract].getWcs()
314 skyCorr = inputs.pop(
'skyCorr',
None)
315 if self.config.useGlobalExternalSkyWcs:
316 externalSkyWcsCatalog = inputs.pop(
'externalSkyWcsGlobalCatalog',
None)
318 externalSkyWcsCatalog = inputs.pop(
'externalSkyWcsTractCatalog',
None)
319 if self.config.useGlobalExternalPhotoCalib:
320 externalPhotoCalibCatalog = inputs.pop(
'externalPhotoCalibGlobalCatalog',
None)
322 externalPhotoCalibCatalog = inputs.pop(
'externalPhotoCalibTractCatalog',
None)
323 finalizedPsfApCorrCatalog = inputs.pop(
'finalizedPsfApCorrCatalog',
None)
325 inputs[
'exposure'] = self.prepareCalibratedExposure(
328 externalSkyWcsCatalog=externalSkyWcsCatalog,
329 externalPhotoCalibCatalog=externalPhotoCalibCatalog,
330 finalizedPsfApCorrCatalog=finalizedPsfApCorrCatalog
333 inputs[
'refCat'] = self.mergeAndFilterReferences(inputs[
'exposure'], inputs[
'refCat'],
336 if inputs[
'refCat']
is None:
337 self.log.info(
"No WCS for exposure %s. No %s catalog will be written.",
338 butlerQC.quantum.dataId, outputRefs.measCat.datasetType.name)
340 inputs[
'measCat'], inputs[
'exposureId'] = self.generateMeasCat(inputRefs.exposure.dataId,
342 inputs[
'refCat'], inputs[
'refWcs'],
344 self.attachFootprints(inputs[
'measCat'], inputs[
'refCat'], inputs[
'exposure'], inputs[
'refWcs'])
345 outputs = self.run(**inputs)
346 butlerQC.put(outputs, outputRefs)
348 def prepareCalibratedExposure(self, exposure, skyCorr=None, externalSkyWcsCatalog=None,
349 externalPhotoCalibCatalog=None, finalizedPsfApCorrCatalog=None):
350 """Prepare a calibrated exposure and apply external calibrations
351 and sky corrections
if so configured.
356 Input exposure to adjust calibrations.
357 skyCorr : `lsst.afw.math.backgroundList`, optional
358 Sky correction frame to apply
if doApplySkyCorr=
True.
360 Exposure catalog
with external skyWcs to be applied
361 if config.doApplyExternalSkyWcs=
True. Catalog uses the detector id
362 for the catalog id, sorted on id
for fast lookup.
364 Exposure catalog
with external photoCalib to be applied
365 if config.doApplyExternalPhotoCalib=
True. Catalog uses the detector
366 id
for the catalog id, sorted on id
for fast lookup.
368 Exposure catalog
with finalized psf models
and aperture correction
369 maps to be applied
if config.doApplyFinalizedPsf=
True. Catalog uses
370 the detector id
for the catalog id, sorted on id
for fast lookup.
375 Exposure
with adjusted calibrations.
377 detectorId = exposure.getInfo().getDetector().getId()
379 if externalPhotoCalibCatalog
is not None:
380 row = externalPhotoCalibCatalog.find(detectorId)
382 self.log.warning(
"Detector id %s not found in externalPhotoCalibCatalog; "
383 "Using original photoCalib.", detectorId)
385 photoCalib = row.getPhotoCalib()
386 if photoCalib
is None:
387 self.log.warning(
"Detector id %s has None for photoCalib in externalPhotoCalibCatalog; "
388 "Using original photoCalib.", detectorId)
390 exposure.setPhotoCalib(photoCalib)
392 if externalSkyWcsCatalog
is not None:
393 row = externalSkyWcsCatalog.find(detectorId)
395 self.log.warning(
"Detector id %s not found in externalSkyWcsCatalog; "
396 "Using original skyWcs.", detectorId)
398 skyWcs = row.getWcs()
400 self.log.warning(
"Detector id %s has None for skyWcs in externalSkyWcsCatalog; "
401 "Using original skyWcs.", detectorId)
403 exposure.setWcs(skyWcs)
405 if finalizedPsfApCorrCatalog
is not None:
406 row = finalizedPsfApCorrCatalog.find(detectorId)
408 self.log.warning(
"Detector id %s not found in finalizedPsfApCorrCatalog; "
409 "Using original psf.", detectorId)
412 apCorrMap = row.getApCorrMap()
413 if psf
is None or apCorrMap
is None:
414 self.log.warning(
"Detector id %s has None for psf/apCorrMap in "
415 "finalizedPsfApCorrCatalog; Using original psf.", detectorId)
418 exposure.setApCorrMap(apCorrMap)
420 if skyCorr
is not None:
421 exposure.maskedImage -= skyCorr.getImage()
425 def mergeAndFilterReferences(self, exposure, refCats, refWcs):
426 """Filter reference catalog so that all sources are within the
427 boundaries of the exposure.
432 Exposure to generate the catalog for.
433 refCats : sequence of `lsst.daf.butler.DeferredDatasetHandle`
434 Handles
for catalogs of shapes
and positions at which to force
436 refWcs : `lsst.afw.image.SkyWcs`
437 Reference world coordinate system.
442 Filtered catalog of forced sources to measure.
446 The majority of this code
is based on the methods of
454 expWcs = exposure.getWcs()
456 self.log.info(
"Exposure has no WCS. Returning None for mergedRefCat.")
458 expRegion = exposure.getBBox(lsst.afw.image.PARENT)
460 expBoxCorners = expBBox.getCorners()
461 expSkyCorners = [expWcs.pixelToSky(corner).getVector()
for
462 corner
in expBoxCorners]
470 for refCat
in refCats:
471 refCat = refCat.get()
472 if mergedRefCat
is None:
475 for record
in refCat:
476 if (expPolygon.contains(record.getCoord().getVector())
and record.getParent()
478 record.setFootprint(record.getFootprint())
479 mergedRefCat.append(record)
480 containedIds.add(record.getId())
481 if mergedRefCat
is None:
482 raise RuntimeError(
"No reference objects for forced photometry.")
486 def generateMeasCat(self, exposureDataId, exposure, refCat, refWcs, idPackerName):
487 """Generate a measurement catalog.
491 exposureDataId : `DataId`
492 Butler dataId for this exposure.
494 Exposure to generate the catalog
for.
496 Catalog of shapes
and positions at which to force photometry.
497 refWcs : `lsst.afw.image.SkyWcs`
498 Reference world coordinate system.
499 This parameter
is not currently used.
501 Type of ID packer to construct
from the registry.
506 Catalog of forced sources to measure.
508 Unique binary id associated
with the input exposure
510 exposureIdInfo = ExposureIdInfo.fromDataId(exposureDataId, idPackerName)
511 idFactory = exposureIdInfo.makeSourceIdFactory()
513 measCat = self.measurement.generateMeasCat(exposure, refCat, refWcs,
515 return measCat, exposureIdInfo.expId
517 def run(self, measCat, exposure, refCat, refWcs, exposureId=None):
518 """Perform forced measurement on a single exposure.
523 The measurement catalog, based on the sources listed in the
526 The measurement image upon which to perform forced detection.
528 The reference catalog of sources to measure.
529 refWcs : `lsst.afw.image.SkyWcs`
530 The WCS
for the references.
532 Optional unique exposureId used
for random seed
in measurement
537 result : `lsst.pipe.base.Struct`
538 Structure
with fields:
541 Catalog of forced measurement results
544 self.measurement.run(measCat, exposure, refCat, refWcs, exposureId=exposureId)
545 if self.config.doApCorr:
546 self.applyApCorr.run(
548 apCorrMap=exposure.getInfo().getApCorrMap()
550 self.catalogCalculation.run(measCat)
552 return pipeBase.Struct(measCat=measCat)
554 def attachFootprints(self, sources, refCat, exposure, refWcs):
555 """Attach footprints to blank sources prior to measurements.
560 be
in the pixel coordinate system of the image being measured,
while
561 the actual detections may start out
in a different coordinate system.
563 Subclasses of this
class may implement this method
to define how
566 This default implementation transforms depends on the
567 ``footprintSource`` configuration parameter.
569 if self.config.footprintSource ==
"transformed":
570 return self.measurement.attachTransformedFootprints(sources, refCat, exposure, refWcs)
571 elif self.config.footprintSource ==
"psf":
572 return self.measurement.attachPsfShapeFootprints(sources, exposure,
573 scaling=self.config.psfFootprintScaling)
576class ForcedPhotCcdFromDataFrameConnections(PipelineTaskConnections,
577 dimensions=(
"instrument",
"visit",
"detector",
"skymap",
"tract"),
578 defaultTemplates={
"inputCoaddName":
"goodSeeing",
579 "inputName":
"calexp",
580 "skyWcsName":
"jointcal",
581 "photoCalibName":
"fgcm"}):
583 doc=
"Catalog of positions at which to force photometry.",
584 name=
"{inputCoaddName}Diff_fullDiaObjTable",
585 storageClass=
"DataFrame",
586 dimensions=[
"skymap",
"tract",
"patch"],
591 doc=
"Input exposure to perform photometry on.",
593 storageClass=
"ExposureF",
594 dimensions=[
"instrument",
"visit",
"detector"],
597 doc=
"Input Sky Correction to be subtracted from the calexp if doApplySkyCorr=True",
599 storageClass=
"Background",
600 dimensions=(
"instrument",
"visit",
"detector"),
602 externalSkyWcsTractCatalog = cT.Input(
603 doc=(
"Per-tract, per-visit wcs calibrations. These catalogs use the detector "
604 "id for the catalog id, sorted on id for fast lookup."),
605 name=
"{skyWcsName}SkyWcsCatalog",
606 storageClass=
"ExposureCatalog",
607 dimensions=[
"instrument",
"visit",
"tract"],
609 externalSkyWcsGlobalCatalog = cT.Input(
610 doc=(
"Per-visit wcs calibrations computed globally (with no tract information). "
611 "These catalogs use the detector id for the catalog id, sorted on id for "
613 name=
"{skyWcsName}SkyWcsCatalog",
614 storageClass=
"ExposureCatalog",
615 dimensions=[
"instrument",
"visit"],
617 externalPhotoCalibTractCatalog = cT.Input(
618 doc=(
"Per-tract, per-visit photometric calibrations. These catalogs use the "
619 "detector id for the catalog id, sorted on id for fast lookup."),
620 name=
"{photoCalibName}PhotoCalibCatalog",
621 storageClass=
"ExposureCatalog",
622 dimensions=[
"instrument",
"visit",
"tract"],
624 externalPhotoCalibGlobalCatalog = cT.Input(
625 doc=(
"Per-visit photometric calibrations computed globally (with no tract "
626 "information). These catalogs use the detector id for the catalog id, "
627 "sorted on id for fast lookup."),
628 name=
"{photoCalibName}PhotoCalibCatalog",
629 storageClass=
"ExposureCatalog",
630 dimensions=[
"instrument",
"visit"],
632 finalizedPsfApCorrCatalog = cT.Input(
633 doc=(
"Per-visit finalized psf models and aperture correction maps. "
634 "These catalogs use the detector id for the catalog id, "
635 "sorted on id for fast lookup."),
636 name=
"finalized_psf_ap_corr_catalog",
637 storageClass=
"ExposureCatalog",
638 dimensions=[
"instrument",
"visit"],
641 doc=
"Output forced photometry catalog.",
642 name=
"forced_src_diaObject",
643 storageClass=
"SourceCatalog",
644 dimensions=[
"instrument",
"visit",
"detector",
"skymap",
"tract"],
646 outputSchema = cT.InitOutput(
647 doc=
"Schema for the output forced measurement catalogs.",
648 name=
"forced_src_diaObject_schema",
649 storageClass=
"SourceCatalog",
652 def __init__(self, *, config=None):
653 super().__init__(config=config)
654 if not config.doApplySkyCorr:
655 self.inputs.remove(
"skyCorr")
656 if config.doApplyExternalSkyWcs:
657 if config.useGlobalExternalSkyWcs:
658 self.inputs.remove(
"externalSkyWcsTractCatalog")
660 self.inputs.remove(
"externalSkyWcsGlobalCatalog")
662 self.inputs.remove(
"externalSkyWcsTractCatalog")
663 self.inputs.remove(
"externalSkyWcsGlobalCatalog")
664 if config.doApplyExternalPhotoCalib:
665 if config.useGlobalExternalPhotoCalib:
666 self.inputs.remove(
"externalPhotoCalibTractCatalog")
668 self.inputs.remove(
"externalPhotoCalibGlobalCatalog")
670 self.inputs.remove(
"externalPhotoCalibTractCatalog")
671 self.inputs.remove(
"externalPhotoCalibGlobalCatalog")
672 if not config.doApplyFinalizedPsf:
673 self.inputs.remove(
"finalizedPsfApCorrCatalog")
676class ForcedPhotCcdFromDataFrameConfig(ForcedPhotCcdConfig,
677 pipelineConnections=ForcedPhotCcdFromDataFrameConnections):
678 def setDefaults(self):
679 super().setDefaults()
680 self.footprintSource =
"psf"
681 self.measurement.doReplaceWithNoise =
False
682 self.measurement.plugins.names = [
"base_LocalPhotoCalib",
"base_LocalWcs",
"base_LocalBackground",
683 "base_TransformedCentroidFromCoord",
"base_PsfFlux",
685 self.measurement.copyColumns = {
'id':
'diaObjectId',
'coord_ra':
'coord_ra',
'coord_dec':
'coord_dec'}
686 self.measurement.slots.centroid =
"base_TransformedCentroidFromCoord"
687 self.measurement.slots.psfFlux =
"base_PsfFlux"
688 self.measurement.slots.shape =
None
692 if self.footprintSource ==
"transformed":
693 raise ValueError(
"Cannot transform footprints from reference catalog, "
694 "because DataFrames can't hold footprints.")
697class ForcedPhotCcdFromDataFrameTask(ForcedPhotCcdTask):
698 """Force Photometry on a per-detector exposure with coords from a DataFrame
700 Uses input from a DataFrame instead of SourceCatalog
701 like the base
class ForcedPhotCcd does.
702 Writes out a SourceCatalog so that the downstream
703 WriteForcedSourceTableTask can be reused
with output
from this Task.
705 _DefaultName = "forcedPhotCcdFromDataFrame"
706 ConfigClass = ForcedPhotCcdFromDataFrameConfig
708 def __init__(self, butler=None, refSchema=None, initInputs=None, **kwds):
710 pipeBase.PipelineTask.__init__(self, **kwds)
712 if butler
is not None:
713 warnings.warn(
"The 'butler' parameter is no longer used and can be safely removed.",
714 category=FutureWarning, stacklevel=2)
719 if self.config.doApCorr:
720 self.makeSubtask(
"applyApCorr", schema=self.measurement.schema)
721 self.makeSubtask(
'catalogCalculation', schema=self.measurement.schema)
725 inputs = butlerQC.get(inputRefs)
728 inputs[
'refWcs'] =
None
731 skyCorr = inputs.pop(
'skyCorr',
None)
732 if self.config.useGlobalExternalSkyWcs:
733 externalSkyWcsCatalog = inputs.pop(
'externalSkyWcsGlobalCatalog',
None)
735 externalSkyWcsCatalog = inputs.pop(
'externalSkyWcsTractCatalog',
None)
736 if self.config.useGlobalExternalPhotoCalib:
737 externalPhotoCalibCatalog = inputs.pop(
'externalPhotoCalibGlobalCatalog',
None)
739 externalPhotoCalibCatalog = inputs.pop(
'externalPhotoCalibTractCatalog',
None)
740 finalizedPsfApCorrCatalog = inputs.pop(
'finalizedPsfApCorrCatalog',
None)
742 inputs[
'exposure'] = self.prepareCalibratedExposure(
745 externalSkyWcsCatalog=externalSkyWcsCatalog,
746 externalPhotoCalibCatalog=externalPhotoCalibCatalog,
747 finalizedPsfApCorrCatalog=finalizedPsfApCorrCatalog
750 self.log.info(
"Filtering ref cats: %s",
','.join([
str(i.dataId)
for i
in inputs[
'refCat']]))
751 if inputs[
"exposure"].getWcs()
is not None:
752 refCat = self.
df2RefCat([i.get(parameters={
"columns": [
'diaObjectId',
'ra',
'decl']})
753 for i
in inputs[
'refCat']],
754 inputs[
'exposure'].
getBBox(), inputs[
'exposure'].getWcs())
755 inputs[
'refCat'] = refCat
757 inputs[
'measCat'], inputs[
'exposureId'] = self.generateMeasCat(
758 inputRefs.exposure.dataId, inputs[
'exposure'], inputs[
'refCat'], inputs[
'refWcs'],
762 self.attachFootprints(inputs[
"measCat"], inputs[
"refCat"], inputs[
"exposure"], inputs[
"refWcs"])
763 outputs = self.run(**inputs)
765 butlerQC.put(outputs, outputRefs)
767 self.log.info(
"No WCS for %s. Skipping and no %s catalog will be written.",
768 butlerQC.quantum.dataId, outputRefs.measCat.datasetType.name)
771 """Convert list of DataFrames to reference catalog
773 Concatenate list of DataFrames presumably from multiple patches
and
774 downselect rows that overlap the exposureBBox using the exposureWcs.
778 dfList : `list` of `pandas.DataFrame`
779 Each element containst diaObjects
with ra/decl position
in degrees
780 Columns
'diaObjectId',
'ra',
'decl' are expected
782 Bounding box on which to select rows that overlap
784 World coordinate system to convert sky coords
in ref cat to
785 pixel coords
with which to compare
with exposureBBox
790 Source Catalog
with minimal schema that overlaps exposureBBox
792 df = pd.concat(dfList)
795 mapping = exposureWcs.getTransform().getMapping()
796 x, y = mapping.applyInverse(np.array(df[[
'ra',
'decl']].values*2*np.pi/360).T)
802 """Create minimal schema SourceCatalog from a pandas DataFrame.
804 The forced measurement subtask expects this as input.
808 df : `pandas.DataFrame`
809 DiaObjects
with locations
and ids.
814 Output catalog
with minimal schema.
818 outputCatalog.reserve(len(df))
820 for diaObjectId, ra, decl
in df[[
'ra',
'decl']].itertuples():
821 outputRecord = outputCatalog.addNew()
822 outputRecord.setId(diaObjectId)
A 2-dimensional celestial WCS that transform pixels to ICRS RA/Dec, using the LSST standard for pixel...
A class to contain the data, WCS, and other information needed to describe an image of the sky.
Custom catalog class for ExposureRecord/Table.
Defines the fields and offsets for a table.
Table class that contains measurements made on a single exposure.
static Schema makeMinimalSchema()
Return a minimal schema for Source tables and records.
static Key< RecordId > getParentKey()
Key for the parent ID.
A floating-point coordinate rectangle geometry.
An integer coordinate rectangle.
Point in an unspecified spherical coordinate system.
def df2RefCat(self, dfList, exposureBBox, exposureWcs)
def runQuantum(self, butlerQC, inputRefs, outputRefs)
def df2SourceCat(self, df)
ConvexPolygon is a closed convex polygon on the unit sphere.