LSST Applications 26.0.0,g0265f82a02+6660c170cc,g07994bdeae+30b05a742e,g0a0026dc87+17526d298f,g0a60f58ba1+17526d298f,g0e4bf8285c+96dd2c2ea9,g0ecae5effc+c266a536c8,g1e7d6db67d+6f7cb1f4bb,g26482f50c6+6346c0633c,g2bbee38e9b+6660c170cc,g2cc88a2952+0a4e78cd49,g3273194fdb+f6908454ef,g337abbeb29+6660c170cc,g337c41fc51+9a8f8f0815,g37c6e7c3d5+7bbafe9d37,g44018dc512+6660c170cc,g4a941329ef+4f7594a38e,g4c90b7bd52+5145c320d2,g58be5f913a+bea990ba40,g635b316a6c+8d6b3a3e56,g67924a670a+bfead8c487,g6ae5381d9b+81bc2a20b4,g93c4d6e787+26b17396bd,g98cecbdb62+ed2cb6d659,g98ffbb4407+81bc2a20b4,g9ddcbc5298+7f7571301f,ga1e77700b3+99e9273977,gae46bcf261+6660c170cc,gb2715bf1a1+17526d298f,gc86a011abf+17526d298f,gcf0d15dbbd+96dd2c2ea9,gdaeeff99f8+0d8dbea60f,gdb4ec4c597+6660c170cc,ge23793e450+96dd2c2ea9,gf041782ebf+171108ac67
LSST Data Management Base Package
Loading...
Searching...
No Matches
calibrateImage.py
Go to the documentation of this file.
1# This file is part of pipe_tasks.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22import lsst.afw.table as afwTable
23import lsst.afw.image as afwImage
27from lsst.meas.algorithms import sourceSelector
30import lsst.meas.extensions.shapeHSM
31import lsst.pex.config as pexConfig
32import lsst.pipe.base as pipeBase
33from lsst.pipe.base import connectionTypes
34from lsst.utils.timer import timeMethod
35
36from . import measurePsf, repair, setPrimaryFlags, photoCal, computeExposureSummaryStats
37
38
39class CalibrateImageConnections(pipeBase.PipelineTaskConnections,
40 dimensions=("instrument", "visit", "detector")):
41
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",),
47 deferLoad=True,
48 multiple=True,
49 )
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",),
55 deferLoad=True,
56 multiple=True
57 )
58
59 exposure = connectionTypes.Input(
60 doc="Exposure to be calibrated, and detected and measured on.",
61 name="postISRCCD",
62 storageClass="Exposure",
63 dimensions=["instrument", "exposure", "detector"],
64 )
65
66 # outputs
67 initial_stars_schema = connectionTypes.InitOutput(
68 doc="Schema of the output initial stars catalog.",
69 name="initial_stars_schema",
70 storageClass="SourceCatalog",
71 )
72
73 # TODO: We want some kind of flag on Exposures/Catalogs to make it obvious
74 # which components had failed to be computed/persisted
75 output_exposure = connectionTypes.Output(
76 doc="Photometrically calibrated exposure with fitted calibrations and summary statistics.",
77 name="initial_pvi",
78 storageClass="ExposureF",
79 dimensions=("instrument", "visit", "detector"),
80 )
81 # TODO DM-40061: persist a parquet version of this!
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"],
88 )
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"),
94 )
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"),
100 )
101
102 # Optional outputs
103
104 # TODO: We need to decide on what intermediate outputs we want to save,
105 # and which to save by default.
106 # TODO DM-40061: persist a parquet version of this!
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"],
113 )
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"),
119 )
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"),
125 )
126
127 def __init__(self, *, config=None):
128 super().__init__(config=config)
129 if not config.optional_outputs:
130 self.outputs.remove("psf_stars")
131 self.outputs.remove("astrometry_matches")
132 self.outputs.remove("photometry_matches")
133
134
135class CalibrateImageConfig(pipeBase.PipelineTaskConfig, pipelineConnections=CalibrateImageConnections):
136 optional_outputs = pexConfig.ListField(
137 doc="Which optional outputs to save (as their connection name)?",
138 dtype=str,
139 # TODO: note somewhere to disable this for benchmarking, but should
140 # we always have it on for production runs?
141 default=["psf_stars", "astrometry_matches", "photometry_matches"],
142 optional=True
143 )
144
145 # subtasks used during psf characterization
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.",
150 )
151 psf_repair = pexConfig.ConfigurableField(
152 target=repair.RepairTask,
153 doc="Task to repair cosmic rays on the exposure before PSF determination.",
154 )
155 psf_subtract_background = pexConfig.ConfigurableField(
157 doc="Task to perform intial background subtraction, before first detection pass.",
158 )
159 psf_detection = pexConfig.ConfigurableField(
161 doc="Task to detect sources for PSF determination."
162 )
163 psf_source_measurement = pexConfig.ConfigurableField(
165 doc="Task to measure sources to be used for psf estimation."
166 )
167 psf_measure_psf = pexConfig.ConfigurableField(
169 doc="Task to measure the psf on bright sources."
170 )
171
172 # TODO DM-39203: we can remove aperture correction from this task once we are
173 # using the shape-based star/galaxy code.
174 measure_aperture_correction = pexConfig.ConfigurableField(
176 doc="Task to compute the aperture correction from the bright stars."
177 )
178
179 # subtasks used during star measurement
180 star_detection = pexConfig.ConfigurableField(
182 doc="Task to detect stars to return in the output catalog."
183 )
184 star_deblend = pexConfig.ConfigurableField(
186 doc="Split blended sources into their components"
187 )
188 star_measurement = pexConfig.ConfigurableField(
190 doc="Task to measure stars to return in the output catalog."
191 )
192 star_apply_aperture_correction = pexConfig.ConfigurableField(
194 doc="Task to apply aperture corrections to the selected stars."
195 )
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."
200 )
201 star_set_primary_flags = pexConfig.ConfigurableField(
203 doc="Task to add isPrimary to the catalog."
204 )
205 star_selector = lsst.meas.algorithms.sourceSelectorRegistry.makeField(
206 default="science",
207 doc="Task to select isolated stars to use for calibration."
208 )
209
210 # final calibrations and statistics
211 astrometry = pexConfig.ConfigurableField(
213 doc="Task to perform astrometric calibration to fit a WCS.",
214 )
215 astrometry_ref_loader = pexConfig.ConfigField(
217 doc="Configuration of reference object loader for astrometric fit.",
218 )
219 photometry = pexConfig.ConfigurableField(
221 doc="Task to perform photometric calibration to fit a PhotoCalib.",
222 )
223 photometry_ref_loader = pexConfig.ConfigField(
225 doc="Configuration of reference object loader for photometric fit.",
226 )
227
228 compute_summary_stats = pexConfig.ConfigurableField(
230 doc="Task to to compute summary statistics on the calibrated exposure."
231 )
232
233 def setDefaults(self):
234 super().setDefaults()
235
236 # Use a very broad PSF here, to throughly reject CRs.
237 # TODO investigation: a large initial psf guess may make stars look
238 # like CRs for very good seeing images.
239 self.install_simple_psf.fwhm = 4
240
241 # Only use high S/N sources for PSF determination.
242 self.psf_detection.thresholdValue = 50.0
243 self.psf_detection.thresholdType = "pixel_stdev"
244 # TODO investigation: Probably want False here, but that may require
245 # tweaking the background spatial scale, to make it small enough to
246 # prevent extra peaks in the wings of bright objects.
247 self.psf_detection.doTempLocalBackground = False
248 # NOTE: we do want reEstimateBackground=True in psf_detection, so that
249 # each measurement step is done with the best background available.
250
251 # Minimal measurement plugins for PSF determination.
252 # TODO DM-39203: We can drop GaussianFlux and PsfFlux, if we use
253 # shapeHSM/moments for star/galaxy separation.
254 # TODO DM-39203: we can remove aperture correction from this task once
255 # we are using the shape-based star/galaxy code.
256 self.psf_source_measurement.plugins = ["base_PixelFlags",
257 "base_SdssCentroid",
258 "ext_shapeHSM_HsmSourceMoments",
259 "base_CircularApertureFlux",
260 "base_GaussianFlux",
261 "base_PsfFlux",
262 ]
263 self.psf_source_measurement.slots.shape = "ext_shapeHSM_HsmSourceMoments"
264 # Only measure apertures we need for PSF measurement.
265 # TODO DM-40064: psfex has a hard-coded value of 9 in a psfex-config
266 # file: make that configurable and/or change it to 12 to be consistent
267 # with our other uses?
268 # https://github.com/lsst/meas_extensions_psfex/blob/main/config/default-lsst.psfex#L14
269 self.psf_source_measurement.plugins["base_CircularApertureFlux"].radii = [9.0, 12.0]
270
271 self.psf_measure_psf.starSelector["objectSize"].doFluxLimit = False
272 self.psf_measure_psf.starSelector["objectSize"].doSignalToNoiseLimit = True
273
274 # No extendeness information available: we need the aperture
275 # corrections to determine that.
276 self.measure_aperture_correction.sourceSelector["science"].doUnresolved = False
277 self.measure_aperture_correction.sourceSelector["science"].flags.good = ["calib_psf_used"]
278 self.measure_aperture_correction.sourceSelector["science"].flags.bad = []
279
280 # TODO investigation: how faint do we have to detect, to be able to
281 # deblend, etc? We may need star_selector to have a separate value,
282 # and do initial detection at S/N>5.0?
283 # Detection for good S/N for astrometry/photometry and other
284 # downstream tasks.
285 self.star_detection.thresholdValue = 10.0
286 self.star_detection.thresholdType = "pixel_stdev"
287 self.star_measurement.plugins = ["base_PixelFlags",
288 "base_SdssCentroid",
289 "ext_shapeHSM_HsmSourceMoments",
290 'ext_shapeHSM_HsmPsfMoments',
291 "base_GaussianFlux",
292 "base_PsfFlux",
293 "base_CircularApertureFlux",
294 ]
295 self.star_measurement.slots.psfShape = "ext_shapeHSM_HsmPsfMoments"
296 self.star_measurement.slots.shape = "ext_shapeHSM_HsmSourceMoments"
297 # Only measure the apertures we need for star selection.
298 self.star_measurement.plugins["base_CircularApertureFlux"].radii = [12.0]
299 # Restrict footprint area to prevent memory blowup on huge footprints.
300 self.star_deblend.maxFootprintArea = 10000
301
302 # Select isolated stars with reliable measurements and no bad flags.
303 self.star_selector["science"].doFlags = True
304 self.star_selector["science"].doUnresolved = True
305 self.star_selector["science"].doSignalToNoise = True
306 self.star_selector["science"].doIsolated = True
307 self.star_selector["science"].signalToNoise.minimum = 10.0
308
309 # Use the affine WCS fitter (assumes we have a good camera geometry).
310 self.astrometry.wcsFitter.retarget(lsst.meas.astrom.FitAffineWcsTask)
311 # phot_g_mean is the primary Gaia band for all input bands.
312 self.astrometry_ref_loader.anyFilterMapsToThis = "phot_g_mean"
313
314 # Reject magnitude outliers (TODO DM-39796: should be task default)
315 self.astrometry.doMagnitudeOutlierRejection = True
316
317 # Do not subselect during fitting; we already selected good stars.
318 self.astrometry.sourceSelector = "null"
319 self.photometry.match.sourceSelection.retarget(sourceSelector.NullSourceSelectorTask)
320
321 # All sources should be good for PSF summary statistics.
322 self.compute_summary_stats.starSelection = "calib_photometry_used"
323
324
325class CalibrateImageTask(pipeBase.PipelineTask):
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.
329
330 Parameters
331 ----------
332 initial_stars_schema : `lsst.afw.table.Schema`
333 Schema of the initial_stars output catalog.
334 """
335 _DefaultName = "calibrateImage"
336 ConfigClass = CalibrateImageConfig
337
338 def __init__(self, initial_stars_schema=None, **kwargs):
339 super().__init__(**kwargs)
340
341 # PSF determination subtasks
342 self.makeSubtask("install_simple_psf")
343 self.makeSubtask("psf_repair")
344 self.makeSubtask("psf_subtract_background")
345 self.psf_schema = afwTable.SourceTable.makeMinimalSchema()
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)
349
350 self.makeSubtask("measure_aperture_correction", schema=self.psf_schema)
351
352 # star measurement subtasks
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")
362
363 self.makeSubtask("astrometry", schema=initial_stars_schema)
364 self.makeSubtask("photometry", schema=initial_stars_schema)
365
366 self.makeSubtask("compute_summary_stats")
367
368 # For the butler to persist it.
369 self.initial_stars_schema = afwTable.SourceCatalog(initial_stars_schema)
370
371 def runQuantum(self, butlerQC, inputRefs, outputRefs):
372 inputs = butlerQC.get(inputRefs)
373
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)
380
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)
387
388 outputs = self.run(**inputs)
389
390 butlerQC.put(outputs, outputRefs)
391
392 @timeMethod
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.
396
397 Parameters
398 ----------
399 exposure : `lsst.afw.image.Exposure`
400 Post-ISR exposure, with an initial WCS, VisitInfo, and Filter.
401 Modified in-place during processing.
402
403 Returns
404 -------
405 result : `lsst.pipe.base.Struct`
406 Results as a struct with attributes:
407
408 ``output_exposure``
409 Calibrated exposure, with pixels in nJy units.
411 ``stars``
412 Stars that were used to calibrate the exposure, with
413 calibrated fluxes and magnitudes.
415 ``psf_stars``
416 Stars that were used to determine the image PSF.
418 ``background``
419 Background that was fit to the exposure when detecting
420 ``stars``. (`lsst.afw.math.BackgroundList`)
421 ``applied_photo_calib``
422 Photometric calibration that was fit to the star catalog and
423 applied to the exposure. (`lsst.afw.image.PhotoCalib`)
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.
430 """
431 psf_stars, background, candidates = self._compute_psf(exposure)
432
433 self._measure_aperture_correction(exposure, psf_stars)
434
435 stars = self._find_stars(exposure, background)
436
437 astrometry_matches, astrometry_meta = self._fit_astrometry(exposure, stars)
438 stars, photometry_matches, photometry_meta, photo_calib = self._fit_photometry(exposure, stars)
439
440 self._summarize(exposure, stars, background)
441
442 if self.config.optional_outputs:
443 astrometry_matches = lsst.meas.astrom.denormalizeMatches(astrometry_matches, astrometry_meta)
444 photometry_matches = lsst.meas.astrom.denormalizeMatches(photometry_matches, photometry_meta)
445
446 return pipeBase.Struct(output_exposure=exposure,
447 stars=stars,
448 psf_stars=psf_stars,
449 background=background,
450 applied_photo_calib=photo_calib,
451 astrometry_matches=astrometry_matches,
452 photometry_matches=photometry_matches)
453
454 def _compute_psf(self, exposure, guess_psf=True):
455 """Find bright sources detected on an exposure and fit a PSF model to
456 them, repairing likely cosmic rays before detection.
457
458 Repair, detect, measure, and compute PSF twice, to ensure the PSF
459 model does not include contributions from cosmic rays.
460
461 Parameters
462 ----------
463 exposure : `lsst.afw.image.Exposure`
464 Exposure to detect and measure bright stars on.
465
466 Returns
467 -------
469 Catalog of detected bright sources.
470 background : `lsst.afw.math.BackgroundList`
471 Background that was fit to the exposure during detection.
473 PSF candidates returned by the psf determiner.
474 """
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)
477
478 background = self.psf_subtract_background.run(exposure=exposure).background
479 self.psf_repair.run(exposure=exposure, keepCRs=True)
480
481 table = afwTable.SourceTable.make(self.psf_schema)
482 # Re-estimate the background during this detection step, so that
483 # measurement uses the most accurate background-subtraction.
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)
487 # Replace the initial PSF with something simpler for the second
488 # repair/detect/measure/measure_psf step: this can help it converge.
489 self.install_simple_psf.run(exposure=exposure)
490
491 self.log.info("Re-running repair, detection, and PSF measurement using new simple PSF.")
492 # TODO investigation: Should we only re-run repair here, to use the
493 # new PSF? Maybe we *do* need to re-run measurement with PsfFlux, to
494 # use the fitted PSF?
495 # TODO investigation: do we need a separate measurement task here
496 # for the post-psf_measure_psf step, since we only want to do PsfFlux
497 # and GaussianFlux *after* we have a PSF? Maybe that's not relevant
498 # once DM-39203 is merged?
499 self.psf_repair.run(exposure=exposure, keepCRs=True)
500 # Re-estimate the background during this detection step, so that
501 # measurement uses the most accurate background-subtraction.
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)
505
506 # PSF is set on exposure; only return candidates for optional saving.
507 return detections.sources, background, psf_result.cellSet
508
509 def _measure_aperture_correction(self, exposure, bright_sources):
510 """Measure and set the ApCorrMap on the Exposure, using
511 previously-measured bright sources.
512
513 Parameters
514 ----------
515 exposure : `lsst.afw.image.Exposure`
516 Exposure to set the ApCorrMap on.
517 bright_sources : `lsst.afw.table.SourceCatalog`
518 Catalog of detected bright sources; modified to include columns
519 necessary for point source determination for the aperture correction
520 calculation.
521 """
522 result = self.measure_aperture_correction.run(exposure, bright_sources)
523 exposure.setApCorrMap(result.apCorrMap)
524
525 def _find_stars(self, exposure, background):
526 """Detect stars on an exposure that has a PSF model, and measure their
527 PSF, circular aperture, compensated gaussian fluxes.
528
529 Parameters
530 ----------
531 exposure : `lsst.afw.image.Exposure`
532 Exposure to set the ApCorrMap on.
533 background : `lsst.afw.math.BackgroundList`
534 Background that was fit to the exposure during detection;
535 modified in-place during subsequent detection.
536
537 Returns
538 -------
539 stars : `SourceCatalog`
540 Sources that are very likely to be stars, with a limited set of
541 measurements performed on them.
542 """
543 table = afwTable.SourceTable.make(self.initial_stars_schema.schema)
544 # Re-estimate the background during this detection step, so that
545 # measurement uses the most accurate background-subtraction.
546 detections = self.star_detection.run(table=table, exposure=exposure, background=background)
547 sources = detections.sources
548 # TODO investigation: Could this deblender throw away blends of non-PSF sources?
549 self.star_deblend.run(exposure=exposure, sources=sources)
550 # The deblender may not produce a contiguous catalog; ensure
551 # contiguity for subsequent tasks.
552 if not sources.isContiguous():
553 sources = sources.copy(deep=True)
554
555 # Measure everything, and use those results to select only stars.
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)
560
561 result = self.star_selector.run(sources)
562 # The star selector may not produce a contiguous catalog.
563 if not result.sourceCat.isContiguous():
564 return result.sourceCat.copy(deep=True)
565 else:
566 return result.sourceCat
567
568 def _fit_astrometry(self, exposure, stars):
569 """Fit an astrometric model to the data and return the reference
570 matches used in the fit, and the fitted WCS.
571
572 Parameters
573 ----------
574 exposure : `lsst.afw.image.Exposure`
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.
580
581 Returns
582 -------
583 matches : `list` [`lsst.afw.table.ReferenceMatch`]
584 Reference/stars matches used in the fit.
585 """
586 result = self.astrometry.run(stars, exposure)
587 return result.matches, result.matchMeta
588
589 def _fit_photometry(self, exposure, stars):
590 """Fit a photometric model to the data and return the reference
591 matches used in the fit, and the fitted PhotoCalib.
592
593 Parameters
594 ----------
595 exposure : `lsst.afw.image.Exposure`
596 Exposure that is being fit, to get PSF and other metadata from.
597 Modified to be in nanojanksy units, with an assigned photoCalib
598 identically 1.
600 Good stars selected for use in calibration.
601
602 Returns
603 -------
604 calibrated_stars : `lsst.afw.table.SourceCatalog`
605 Star catalog with flux/magnitude columns computed from the fitted
606 photoCalib.
607 matches : `list` [`lsst.afw.table.ReferenceMatch`]
608 Reference/stars matches used in the fit.
609 photoCalib : `lsst.afw.image.PhotoCalib`
610 Photometric calibration that was fit to the star catalog.
611 """
612 result = self.photometry.run(exposure, stars)
613 calibrated_stars = result.photoCalib.calibrateCatalog(stars)
614 exposure.maskedImage = result.photoCalib.calibrateImage(exposure.maskedImage)
615 identity = afwImage.PhotoCalib(1.0,
616 result.photoCalib.getCalibrationErr(),
617 bbox=exposure.getBBox())
618 exposure.setPhotoCalib(identity)
619
620 return calibrated_stars, result.matches, result.matchMeta, result.photoCalib
621
622 def _summarize(self, exposure, stars, background):
623 """Compute summary statistics on the exposure and update in-place the
624 calibrations attached to it.
625
626 Parameters
627 ----------
628 exposure : `lsst.afw.image.Exposure`
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.
633 background : `lsst.afw.math.BackgroundList`
634 Background that was fit to the exposure during detection of the
635 above stars.
636 """
637 # TODO investigation: because this takes the photoCalib from the
638 # exposure, photometric summary values may be "incorrect" (i.e. they
639 # will reflect the ==1 nJy calibration on the exposure, not the
640 # applied calibration). This needs to be checked.
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.
Definition Exposure.h:72
The photometric calibration of an exposure.
Definition PhotoCalib.h:114
A collection of SpatialCells covering an entire image.
Defines the fields and offsets for a table.
Definition Schema.h:51
runQuantum(self, butlerQC, inputRefs, outputRefs)
_measure_aperture_correction(self, exposure, bright_sources)
_summarize(self, exposure, stars, background)
Lightweight representation of a geometric match between two records.
Definition Match.h:67