30import lsst.meas.extensions.shapeHSM
34from lsst.utils.timer
import timeMethod
36from .
import measurePsf, repair, setPrimaryFlags, photoCal, computeExposureSummaryStats
40 dimensions=(
"instrument",
"visit",
"detector")):
42 astrometry_ref_cat = connectionTypes.PrerequisiteInput(
43 doc=
"Reference catalog to use for astrometric calibration.",
44 name=
"gaia_dr2_20200414",
45 storageClass=
"SimpleCatalog",
46 dimensions=(
"skypix",),
50 photometry_ref_cat = connectionTypes.PrerequisiteInput(
51 doc=
"Reference catalog to use for photometric calibration.",
52 name=
"ps1_pv3_3pi_20170110",
53 storageClass=
"SimpleCatalog",
54 dimensions=(
"skypix",),
59 exposure = connectionTypes.Input(
60 doc=
"Exposure to be calibrated, and detected and measured on.",
62 storageClass=
"Exposure",
63 dimensions=[
"instrument",
"exposure",
"detector"],
67 initial_stars_schema = connectionTypes.InitOutput(
68 doc=
"Schema of the output initial stars catalog.",
69 name=
"initial_stars_schema",
70 storageClass=
"SourceCatalog",
75 output_exposure = connectionTypes.Output(
76 doc=
"Photometrically calibrated exposure with fitted calibrations and summary statistics.",
78 storageClass=
"ExposureF",
79 dimensions=(
"instrument",
"visit",
"detector"),
82 stars = connectionTypes.Output(
83 doc=
"Catalog of unresolved sources detected on the calibrated exposure; "
84 "includes source footprints.",
85 name=
"initial_stars_footprints_detector",
86 storageClass=
"SourceCatalog",
87 dimensions=[
"instrument",
"visit",
"detector"],
89 applied_photo_calib = connectionTypes.Output(
90 doc=
"Photometric calibration that was applied to exposure.",
91 name=
"initial_photoCalib_detector",
92 storageClass=
"PhotoCalib",
93 dimensions=(
"instrument",
"visit",
"detector"),
95 background = connectionTypes.Output(
96 doc=
"Background models estimated during calibration task.",
97 name=
"initial_pvi_background",
98 storageClass=
"Background",
99 dimensions=(
"instrument",
"visit",
"detector"),
107 psf_stars = connectionTypes.Output(
108 doc=
"Catalog of bright unresolved sources detected on the exposure used for PSF determination; "
109 "includes source footprints.",
110 name=
"initial_psf_stars_footprints",
111 storageClass=
"SourceCatalog",
112 dimensions=[
"instrument",
"visit",
"detector"],
114 astrometry_matches = connectionTypes.Output(
115 doc=
"Source to reference catalog matches from the astrometry solver.",
116 name=
"initial_astrometry_match_detector",
117 storageClass=
"Catalog",
118 dimensions=(
"instrument",
"visit",
"detector"),
120 photometry_matches = connectionTypes.Output(
121 doc=
"Source to reference catalog matches from the photometry solver.",
122 name=
"initial_photometry_match_detector",
123 storageClass=
"Catalog",
124 dimensions=(
"instrument",
"visit",
"detector"),
129 if not config.optional_outputs:
130 self.outputs.remove(
"psf_stars")
131 self.outputs.remove(
"astrometry_matches")
132 self.outputs.remove(
"photometry_matches")
136 optional_outputs = pexConfig.ListField(
137 doc=
"Which optional outputs to save (as their connection name)?",
141 default=[
"psf_stars",
"astrometry_matches",
"photometry_matches"],
146 install_simple_psf = pexConfig.ConfigurableField(
148 doc=
"Task to install a simple PSF model into the input exposure to use "
149 "when detecting bright sources for PSF estimation.",
151 psf_repair = pexConfig.ConfigurableField(
153 doc=
"Task to repair cosmic rays on the exposure before PSF determination.",
155 psf_subtract_background = pexConfig.ConfigurableField(
157 doc=
"Task to perform intial background subtraction, before first detection pass.",
159 psf_detection = pexConfig.ConfigurableField(
161 doc=
"Task to detect sources for PSF determination."
163 psf_source_measurement = pexConfig.ConfigurableField(
165 doc=
"Task to measure sources to be used for psf estimation."
167 psf_measure_psf = pexConfig.ConfigurableField(
169 doc=
"Task to measure the psf on bright sources."
174 measure_aperture_correction = pexConfig.ConfigurableField(
176 doc=
"Task to compute the aperture correction from the bright stars."
180 star_detection = pexConfig.ConfigurableField(
182 doc=
"Task to detect stars to return in the output catalog."
184 star_deblend = pexConfig.ConfigurableField(
186 doc=
"Split blended sources into their components"
188 star_measurement = pexConfig.ConfigurableField(
190 doc=
"Task to measure stars to return in the output catalog."
192 star_apply_aperture_correction = pexConfig.ConfigurableField(
194 doc=
"Task to apply aperture corrections to the selected stars."
196 star_catalog_calculation = pexConfig.ConfigurableField(
198 doc=
"Task to compute extendedness values on the star catalog, "
199 "for the star selector to remove extended sources."
201 star_set_primary_flags = pexConfig.ConfigurableField(
203 doc=
"Task to add isPrimary to the catalog."
205 star_selector = lsst.meas.algorithms.sourceSelectorRegistry.makeField(
207 doc=
"Task to select isolated stars to use for calibration."
211 astrometry = pexConfig.ConfigurableField(
213 doc=
"Task to perform astrometric calibration to fit a WCS.",
215 astrometry_ref_loader = pexConfig.ConfigField(
217 doc=
"Configuration of reference object loader for astrometric fit.",
219 photometry = pexConfig.ConfigurableField(
221 doc=
"Task to perform photometric calibration to fit a PhotoCalib.",
223 photometry_ref_loader = pexConfig.ConfigField(
225 doc=
"Configuration of reference object loader for photometric fit.",
228 compute_summary_stats = pexConfig.ConfigurableField(
230 doc=
"Task to to compute summary statistics on the calibrated exposure."
258 "ext_shapeHSM_HsmSourceMoments",
259 "base_CircularApertureFlux",
272 self.
psf_measure_psf.starSelector[
"objectSize"].doSignalToNoiseLimit =
True
289 "ext_shapeHSM_HsmSourceMoments",
290 'ext_shapeHSM_HsmPsfMoments',
293 "base_CircularApertureFlux",
315 self.
astrometry.doMagnitudeOutlierRejection =
True
319 self.
photometry.match.sourceSelection.retarget(sourceSelector.NullSourceSelectorTask)
326 """Compute the PSF, aperture corrections, astrometric and photometric
327 calibrations, and summary statistics
for a single science exposure,
and
328 produce a catalog of brighter stars that were used to calibrate it.
333 Schema of the initial_stars output catalog.
335 _DefaultName = "calibrateImage"
336 ConfigClass = CalibrateImageConfig
338 def __init__(self, initial_stars_schema=None, **kwargs):
339 super().__init__(**kwargs)
342 self.makeSubtask(
"install_simple_psf")
343 self.makeSubtask(
"psf_repair")
344 self.makeSubtask(
"psf_subtract_background")
346 self.makeSubtask(
"psf_detection", schema=self.
psf_schema)
347 self.makeSubtask(
"psf_source_measurement", schema=self.
psf_schema)
348 self.makeSubtask(
"psf_measure_psf", schema=self.
psf_schema)
350 self.makeSubtask(
"measure_aperture_correction", schema=self.
psf_schema)
353 if initial_stars_schema
is None:
354 initial_stars_schema = afwTable.SourceTable.makeMinimalSchema()
355 self.makeSubtask(
"star_detection", schema=initial_stars_schema)
356 self.makeSubtask(
"star_deblend", schema=initial_stars_schema)
357 self.makeSubtask(
"star_measurement", schema=initial_stars_schema)
358 self.makeSubtask(
"star_apply_aperture_correction", schema=initial_stars_schema)
359 self.makeSubtask(
"star_catalog_calculation", schema=initial_stars_schema)
360 self.makeSubtask(
"star_set_primary_flags", schema=initial_stars_schema, isSingleFrame=
True)
361 self.makeSubtask(
"star_selector")
363 self.makeSubtask(
"astrometry", schema=initial_stars_schema)
364 self.makeSubtask(
"photometry", schema=initial_stars_schema)
366 self.makeSubtask(
"compute_summary_stats")
372 inputs = butlerQC.get(inputRefs)
375 dataIds=[ref.datasetRef.dataId
for ref
in inputRefs.astrometry_ref_cat],
376 refCats=inputs.pop(
"astrometry_ref_cat"),
377 name=self.config.connections.astrometry_ref_cat,
378 config=self.config.astrometry_ref_loader, log=self.log)
379 self.astrometry.setRefObjLoader(astrometry_loader)
382 dataIds=[ref.datasetRef.dataId
for ref
in inputRefs.photometry_ref_cat],
383 refCats=inputs.pop(
"photometry_ref_cat"),
384 name=self.config.connections.photometry_ref_cat,
385 config=self.config.photometry_ref_loader, log=self.log)
386 self.photometry.match.setRefObjLoader(photometry_loader)
388 outputs = self.
run(**inputs)
390 butlerQC.put(outputs, outputRefs)
393 def run(self, *, exposure):
394 """Find stars and perform psf measurement, then do a deeper detection
395 and measurement
and calibrate astrometry
and photometry
from that.
400 Post-ISR exposure,
with an initial WCS, VisitInfo,
and Filter.
401 Modified
in-place during processing.
405 result : `lsst.pipe.base.Struct`
406 Results
as a struct
with attributes:
409 Calibrated exposure,
with pixels
in nJy units.
412 Stars that were used to calibrate the exposure,
with
413 calibrated fluxes
and magnitudes.
416 Stars that were used to determine the image PSF.
419 Background that was fit to the exposure when detecting
421 ``applied_photo_calib``
422 Photometric calibration that was fit to the star catalog
and
424 ``astrometry_matches``
425 Reference catalog stars matches used
in the astrometric fit.
427 ``photometry_matches``
428 Reference catalog stars matches used
in the photometric fit.
431 psf_stars, background, candidates = self._compute_psf(exposure)
437 astrometry_matches, astrometry_meta = self._fit_astrometry(exposure, stars)
438 stars, photometry_matches, photometry_meta, photo_calib = self._fit_photometry(exposure, stars)
442 if self.config.optional_outputs:
446 return pipeBase.Struct(output_exposure=exposure,
449 background=background,
450 applied_photo_calib=photo_calib,
451 astrometry_matches=astrometry_matches,
452 photometry_matches=photometry_matches)
455 """Find bright sources detected on an exposure and fit a PSF model to
456 them, repairing likely cosmic rays before detection.
458 Repair, detect, measure, and compute PSF twice, to ensure the PSF
459 model does
not include contributions
from cosmic rays.
464 Exposure to detect
and measure bright stars on.
469 Catalog of detected bright sources.
471 Background that was fit to the exposure during detection.
473 PSF candidates returned by the psf determiner.
475 self.log.info("First pass detection with Guassian PSF FWHM=%s", self.config.install_simple_psf.fwhm)
476 self.install_simple_psf.run(exposure=exposure)
478 background = self.psf_subtract_background.run(exposure=exposure).background
479 self.psf_repair.run(exposure=exposure, keepCRs=
True)
481 table = afwTable.SourceTable.make(self.
psf_schema)
484 detections = self.psf_detection.run(table=table, exposure=exposure, background=background)
485 self.psf_source_measurement.run(detections.sources, exposure)
486 psf_result = self.psf_measure_psf.run(exposure=exposure, sources=detections.sources)
489 self.install_simple_psf.run(exposure=exposure)
491 self.log.info(
"Re-running repair, detection, and PSF measurement using new simple PSF.")
499 self.psf_repair.run(exposure=exposure, keepCRs=
True)
502 detections = self.psf_detection.run(table=table, exposure=exposure, background=background)
503 self.psf_source_measurement.run(detections.sources, exposure)
504 psf_result = self.psf_measure_psf.run(exposure=exposure, sources=detections.sources)
507 return detections.sources, background, psf_result.cellSet
510 """Measure and set the ApCorrMap on the Exposure, using
511 previously-measured bright sources.
516 Exposure to set the ApCorrMap on.
518 Catalog of detected bright sources; modified to include columns
519 necessary for point source determination
for the aperture correction
522 result = self.measure_aperture_correction.run(exposure, bright_sources)
523 exposure.setApCorrMap(result.apCorrMap)
526 """Detect stars on an exposure that has a PSF model, and measure their
527 PSF, circular aperture, compensated gaussian fluxes.
532 Exposure to set the ApCorrMap on.
534 Background that was fit to the exposure during detection;
535 modified in-place during subsequent detection.
539 stars : `SourceCatalog`
540 Sources that are very likely to be stars,
with a limited set of
541 measurements performed on them.
546 detections = self.star_detection.run(table=table, exposure=exposure, background=background)
547 sources = detections.sources
549 self.star_deblend.run(exposure=exposure, sources=sources)
552 if not sources.isContiguous():
553 sources = sources.copy(deep=
True)
556 self.star_measurement.run(sources, exposure)
557 self.star_apply_aperture_correction.run(sources, exposure.info.getApCorrMap())
558 self.star_catalog_calculation.run(sources)
559 self.star_set_primary_flags.run(sources)
561 result = self.star_selector.run(sources)
563 if not result.sourceCat.isContiguous():
564 return result.sourceCat.copy(deep=
True)
566 return result.sourceCat
569 """Fit an astrometric model to the data and return the reference
570 matches used in the fit,
and the fitted WCS.
575 Exposure that
is being fit, to get PSF
and other metadata
from.
576 Modified to add the fitted skyWcs.
577 stars : `SourceCatalog`
578 Good stars selected
for use
in calibration,
with RA/Dec coordinates
579 computed
from the pixel positions
and fitted WCS.
584 Reference/stars matches used
in the fit.
586 result = self.astrometry.run(stars, exposure)
587 return result.matches, result.matchMeta
590 """Fit a photometric model to the data and return the reference
591 matches used in the fit,
and the fitted PhotoCalib.
596 Exposure that
is being fit, to get PSF
and other metadata
from.
597 Modified to be
in nanojanksy units,
with an assigned photoCalib
600 Good stars selected
for use
in calibration.
605 Star catalog
with flux/magnitude columns computed
from the fitted
608 Reference/stars matches used
in the fit.
610 Photometric calibration that was fit to the star catalog.
612 result = self.photometry.run(exposure, stars)
613 calibrated_stars = result.photoCalib.calibrateCatalog(stars)
614 exposure.maskedImage = result.photoCalib.calibrateImage(exposure.maskedImage)
616 result.photoCalib.getCalibrationErr(),
617 bbox=exposure.getBBox())
618 exposure.setPhotoCalib(identity)
620 return calibrated_stars, result.matches, result.matchMeta, result.photoCalib
623 """Compute summary statistics on the exposure and update in-place the
624 calibrations attached to it.
629 Exposure that was calibrated, to get PSF and other metadata
from.
630 Modified to contain the computed summary statistics.
631 stars : `SourceCatalog`
632 Good stars selected used
in calibration.
634 Background that was fit to the exposure during detection of the
641 summary = self.compute_summary_stats.run(exposure, stars, background)
642 exposure.info.setSummaryStats(summary)
A class to contain the data, WCS, and other information needed to describe an image of the sky.
The photometric calibration of an exposure.
A collection of SpatialCells covering an entire image.
Defines the fields and offsets for a table.
measure_aperture_correction
__init__(self, *config=None)
runQuantum(self, butlerQC, inputRefs, outputRefs)
_compute_psf(self, exposure, guess_psf=True)
_fit_photometry(self, exposure, stars)
_measure_aperture_correction(self, exposure, bright_sources)
_fit_astrometry(self, exposure, stars)
_find_stars(self, exposure, background)
_summarize(self, exposure, stars, background)
Lightweight representation of a geometric match between two records.