Coverage for tests/test_calibrateImage.py: 16%
238 statements
« prev ^ index » next coverage.py v7.4.3, created at 2024-02-24 10:27 +0000
« prev ^ index » next coverage.py v7.4.3, created at 2024-02-24 10:27 +0000
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/>.
22import unittest
23import tempfile
25import astropy.units as u
26from astropy.coordinates import SkyCoord
27import numpy as np
29import lsst.afw.image as afwImage
30import lsst.afw.table as afwTable
31import lsst.daf.base
32import lsst.daf.butler.tests as butlerTests
33import lsst.geom
34import lsst.meas.algorithms
35from lsst.meas.algorithms import testUtils
36import lsst.meas.extensions.psfex
37import lsst.meas.base.tests
38import lsst.pipe.base.testUtils
39from lsst.pipe.tasks.calibrateImage import CalibrateImageTask
40import lsst.utils.tests
43class CalibrateImageTaskTests(lsst.utils.tests.TestCase):
45 def setUp(self):
46 # Different x/y dimensions so they're easy to distinguish in a plot,
47 # and non-zero minimum, to help catch xy0 errors.
48 bbox = lsst.geom.Box2I(lsst.geom.Point2I(5, 4), lsst.geom.Point2I(205, 184))
49 self.sky_center = lsst.geom.SpherePoint(245.0, -45.0, lsst.geom.degrees)
50 self.photo_calib = 12.3
51 dataset = lsst.meas.base.tests.TestDataset(bbox, crval=self.sky_center, calibration=self.photo_calib)
52 # sqrt of area of a normalized 2d gaussian
53 psf_scale = np.sqrt(4*np.pi*(dataset.psfShape.getDeterminantRadius())**2)
54 noise = 10.0 # stddev of noise per pixel
55 # Sources ordered from faintest to brightest.
56 self.fluxes = np.array((6*noise*psf_scale,
57 12*noise*psf_scale,
58 45*noise*psf_scale,
59 150*noise*psf_scale,
60 400*noise*psf_scale,
61 1000*noise*psf_scale))
62 self.centroids = np.array(((162, 22),
63 (40, 70),
64 (100, 160),
65 (50, 120),
66 (92, 35),
67 (175, 154)), dtype=np.float32)
68 for flux, centroid in zip(self.fluxes, self.centroids):
69 dataset.addSource(instFlux=flux, centroid=lsst.geom.Point2D(centroid[0], centroid[1]))
71 # Bright extended source in the center of the image: should not appear
72 # in any of the output catalogs.
73 center = lsst.geom.Point2D(100, 100)
74 shape = lsst.afw.geom.Quadrupole(8, 9, 3)
75 dataset.addSource(instFlux=500*noise*psf_scale, centroid=center, shape=shape)
77 schema = dataset.makeMinimalSchema()
78 self.truth_exposure, self.truth_cat = dataset.realize(noise=noise, schema=schema)
79 # To make it look like a version=1 (nJy fluxes) refcat
80 self.truth_cat = self.truth_exposure.photoCalib.calibrateCatalog(self.truth_cat)
81 self.ref_loader = testUtils.MockReferenceObjectLoaderFromMemory([self.truth_cat])
82 metadata = lsst.daf.base.PropertyList()
83 metadata.set("REFCAT_FORMAT_VERSION", 1)
84 self.truth_cat.setMetadata(metadata)
86 # TODO: a cosmic ray (need to figure out how to insert a fake-CR)
87 # self.truth_exposure.image.array[10, 10] = 100000
88 # self.truth_exposure.variance.array[10, 10] = 100000/noise
90 # Copy the truth exposure, because CalibrateImage modifies the input.
91 # Post-ISR ccds only contain: initial WCS, VisitInfo, filter
92 self.exposure = afwImage.ExposureF(self.truth_exposure.maskedImage)
93 self.exposure.setWcs(self.truth_exposure.wcs)
94 self.exposure.info.setVisitInfo(self.truth_exposure.visitInfo)
95 # "truth" filter, to match the "truth" refcat.
96 self.exposure.setFilter(lsst.afw.image.FilterLabel(physical='truth', band="truth"))
98 # Test-specific configuration:
99 self.config = CalibrateImageTask.ConfigClass()
100 # We don't have many sources, so have to fit simpler models.
101 self.config.psf_detection.background.approxOrderX = 1
102 self.config.star_detection.background.approxOrderX = 1
103 # Only insert 2 sky sources, for simplicity.
104 self.config.star_sky_sources.nSources = 2
105 # Use PCA psf fitter, as psfex fails if there are only 4 stars.
106 self.config.psf_measure_psf.psfDeterminer = 'pca'
107 # We don't have many test points, so can't match on complicated shapes.
108 self.config.astrometry.matcher.numPointsForShape = 3
109 # ApFlux has more noise than PsfFlux (the latter unrealistically small
110 # in this test data), so we need to do magnitude rejection at higher
111 # sigma, otherwise we can lose otherwise good sources.
112 # TODO DM-39203: Once we are using Compensated Gaussian Fluxes, we
113 # will use those fluxes here, and hopefully can remove this.
114 self.config.astrometry.magnitudeOutlierRejectionNSigma = 9.0
116 # find_stars needs an id generator.
117 self.id_generator = lsst.meas.base.IdGenerator()
119 # Something about this test dataset prefers the older fluxRatio here.
120 self.config.star_catalog_calculation.plugins['base_ClassificationExtendedness'].fluxRatio = 0.925
122 def _check_run(self, calibrate, result):
123 """Test the result of CalibrateImage.run().
125 Parameters
126 ----------
127 calibrate : `lsst.pipe.tasks.calibrateImage.CalibrateImageTask`
128 Configured task that had `run` called on it.
129 result : `lsst.pipe.base.Struct`
130 Result of calling calibrate.run().
131 """
132 # Background should have 4 elements: 3 from compute_psf and one from
133 # re-estimation during source detection.
134 self.assertEqual(len(result.background), 4)
136 # Check that the summary statistics are reasonable.
137 summary = result.output_exposure.info.getSummaryStats()
138 self.assertFloatsAlmostEqual(summary.psfSigma, 2.0, rtol=1e-2)
139 self.assertFloatsAlmostEqual(summary.ra, self.sky_center.getRa().asDegrees(), rtol=1e-7)
140 self.assertFloatsAlmostEqual(summary.dec, self.sky_center.getDec().asDegrees(), rtol=1e-7)
142 # Returned photoCalib should be the applied value, not the ==1 one on the exposure.
143 self.assertFloatsAlmostEqual(result.applied_photo_calib.getCalibrationMean(),
144 self.photo_calib, rtol=2e-3)
145 # Should have flux/magnitudes in the afw and astropy catalogs
146 self.assertIn("slot_PsfFlux_flux", result.stars_footprints.schema)
147 self.assertIn("slot_PsfFlux_mag", result.stars_footprints.schema)
148 self.assertEqual(result.stars["slot_PsfFlux_flux"].unit, u.nJy)
149 self.assertEqual(result.stars["slot_PsfFlux_mag"].unit, u.ABmag)
151 # Should have detected all S/N >= 10 sources plus 2 sky sources, whether 1 or 2 snaps.
152 self.assertEqual(len(result.stars), 7)
153 # Did the psf flags get propagated from the psf_stars catalog?
154 self.assertEqual(result.stars["calib_psf_used"].sum(), 3)
156 # Check that all necessary fields are in the output.
157 lsst.pipe.base.testUtils.assertValidOutput(calibrate, result)
159 def test_run(self):
160 """Test that run() returns reasonable values to be butler put.
161 """
162 calibrate = CalibrateImageTask(config=self.config)
163 calibrate.astrometry.setRefObjLoader(self.ref_loader)
164 calibrate.photometry.match.setRefObjLoader(self.ref_loader)
165 result = calibrate.run(exposures=self.exposure)
167 self._check_run(calibrate, result)
169 def test_run_2_snaps(self):
170 """Test that run() returns reasonable values to be butler put, when
171 passed two exposures to combine as snaps.
172 """
173 calibrate = CalibrateImageTask(config=self.config)
174 calibrate.astrometry.setRefObjLoader(self.ref_loader)
175 calibrate.photometry.match.setRefObjLoader(self.ref_loader)
176 # Halve the flux in each exposure to get the expected visit sum.
177 self.exposure.image /= 2
178 self.exposure.variance /= 2
179 result = calibrate.run(exposures=[self.exposure, self.exposure])
181 self._check_run(calibrate, result)
183 def test_handle_snaps(self):
184 calibrate = CalibrateImageTask(config=self.config)
185 self.assertEqual(calibrate._handle_snaps(self.exposure), self.exposure)
186 self.assertEqual(calibrate._handle_snaps((self.exposure, )), self.exposure)
187 self.assertEqual(calibrate._handle_snaps(self.exposure), self.exposure)
188 with self.assertRaisesRegex(RuntimeError, "Can only process 1 or 2 snaps, not 0."):
189 calibrate._handle_snaps([])
190 with self.assertRaisesRegex(RuntimeError, "Can only process 1 or 2 snaps, not 3."):
191 calibrate._handle_snaps(3*[self.exposure])
193 def test_compute_psf(self):
194 """Test that our brightest sources are found by _compute_psf(),
195 that a PSF is assigned to the expopsure.
196 """
197 calibrate = CalibrateImageTask(config=self.config)
198 psf_stars, background, candidates = calibrate._compute_psf(self.exposure)
200 # Background should have 3 elements: initial subtraction, and two from
201 # re-estimation during the two detection passes.
202 self.assertEqual(len(background), 3)
204 # Only the point-sources with S/N > 50 should be in this output.
205 self.assertEqual(psf_stars["calib_psf_used"].sum(), 3)
206 # Sort in order of brightness, to easily compare with expected positions.
207 psf_stars.sort(psf_stars.getPsfFluxSlot().getMeasKey())
208 for record, flux, center in zip(psf_stars[::-1], self.fluxes, self.centroids[self.fluxes > 50]):
209 self.assertFloatsAlmostEqual(record.getX(), center[0], rtol=0.01)
210 self.assertFloatsAlmostEqual(record.getY(), center[1], rtol=0.01)
211 # PsfFlux should match the values inserted.
212 self.assertFloatsAlmostEqual(record["slot_PsfFlux_instFlux"], flux, rtol=0.01)
214 # TODO: While debugging DM-32701, we're using PCA instead of psfex.
215 # Check that we got a useable PSF.
216 # self.assertIsInstance(self.exposure.psf, lsst.meas.extensions.psfex.PsfexPsf)
217 self.assertIsInstance(self.exposure.psf, lsst.meas.algorithms.PcaPsf)
218 # TestDataset sources have PSF radius=2 pixels.
219 radius = self.exposure.psf.computeShape(self.exposure.psf.getAveragePosition()).getDeterminantRadius()
220 self.assertFloatsAlmostEqual(radius, 2.0, rtol=1e-2)
222 # To look at images for debugging (`setup display_ds9` and run ds9):
223 # import lsst.afw.display
224 # display = lsst.afw.display.getDisplay()
225 # display.mtv(self.exposure)
227 def test_measure_aperture_correction(self):
228 """Test that _measure_aperture_correction() assigns an ApCorrMap to the
229 exposure.
230 """
231 calibrate = CalibrateImageTask(config=self.config)
232 psf_stars, background, candidates = calibrate._compute_psf(self.exposure)
234 # First check that the exposure doesn't have an ApCorrMap.
235 self.assertIsNone(self.exposure.apCorrMap)
236 calibrate._measure_aperture_correction(self.exposure, psf_stars)
237 self.assertIsInstance(self.exposure.apCorrMap, afwImage.ApCorrMap)
239 def test_find_stars(self):
240 """Test that _find_stars() correctly identifies the S/N>10 stars
241 in the image and returns them in the output catalog.
242 """
243 calibrate = CalibrateImageTask(config=self.config)
244 psf_stars, background, candidates = calibrate._compute_psf(self.exposure)
245 calibrate._measure_aperture_correction(self.exposure, psf_stars)
247 stars = calibrate._find_stars(self.exposure, background, self.id_generator)
249 # Background should have 4 elements: 3 from compute_psf and one from
250 # re-estimation during source detection.
251 self.assertEqual(len(background), 4)
253 # Only 5 psf-like sources with S/N>10 should be in the output catalog,
254 # plus two sky sources.
255 self.assertEqual(len(stars), 7)
256 self.assertTrue(stars.isContiguous())
257 # Sort in order of brightness, to easily compare with expected positions.
258 stars.sort(stars.getPsfFluxSlot().getMeasKey())
259 for record, flux, center in zip(stars[::-1], self.fluxes, self.centroids[self.fluxes > 50]):
260 self.assertFloatsAlmostEqual(record.getX(), center[0], rtol=0.01)
261 self.assertFloatsAlmostEqual(record.getY(), center[1], rtol=0.01)
262 self.assertFloatsAlmostEqual(record["slot_PsfFlux_instFlux"], flux, rtol=0.01)
264 def test_astrometry(self):
265 """Test that the fitted WCS gives good catalog coordinates.
266 """
267 calibrate = CalibrateImageTask(config=self.config)
268 calibrate.astrometry.setRefObjLoader(self.ref_loader)
269 psf_stars, background, candidates = calibrate._compute_psf(self.exposure)
270 calibrate._measure_aperture_correction(self.exposure, psf_stars)
271 stars = calibrate._find_stars(self.exposure, background, self.id_generator)
273 calibrate._fit_astrometry(self.exposure, stars)
275 # Check that we got reliable matches with the truth coordinates.
276 sky = stars["sky_source"]
277 fitted = SkyCoord(stars[~sky]['coord_ra'], stars[~sky]['coord_dec'], unit="radian")
278 truth = SkyCoord(self.truth_cat['coord_ra'], self.truth_cat['coord_dec'], unit="radian")
279 idx, d2d, _ = fitted.match_to_catalog_sky(truth)
280 np.testing.assert_array_less(d2d.to_value(u.milliarcsecond), 35.0)
282 def test_photometry(self):
283 """Test that the fitted photoCalib matches the one we generated,
284 and that the exposure is calibrated.
285 """
286 calibrate = CalibrateImageTask(config=self.config)
287 calibrate.astrometry.setRefObjLoader(self.ref_loader)
288 calibrate.photometry.match.setRefObjLoader(self.ref_loader)
289 psf_stars, background, candidates = calibrate._compute_psf(self.exposure)
290 calibrate._measure_aperture_correction(self.exposure, psf_stars)
291 stars = calibrate._find_stars(self.exposure, background, self.id_generator)
292 calibrate._fit_astrometry(self.exposure, stars)
294 stars, matches, meta, photoCalib = calibrate._fit_photometry(self.exposure, stars)
296 # NOTE: With this test data, PhotoCalTask returns calibrationErr==0,
297 # so we can't check that the photoCal error has been set.
298 self.assertFloatsAlmostEqual(photoCalib.getCalibrationMean(), self.photo_calib, rtol=2e-3)
299 # The exposure should be calibrated by the applied photoCalib.
300 self.assertFloatsAlmostEqual(self.exposure.image.array/self.truth_exposure.image.array,
301 self.photo_calib, rtol=2e-3)
302 # PhotoCalib on the exposure must be identically 1.
303 self.assertEqual(self.exposure.photoCalib.getCalibrationMean(), 1.0)
305 # Check that we got reliable magnitudes and fluxes vs. truth, ignoring
306 # sky sources.
307 sky = stars["sky_source"]
308 fitted = SkyCoord(stars[~sky]['coord_ra'], stars[~sky]['coord_dec'], unit="radian")
309 truth = SkyCoord(self.truth_cat['coord_ra'], self.truth_cat['coord_dec'], unit="radian")
310 idx, _, _ = fitted.match_to_catalog_sky(truth)
311 # Because the input variance image does not include contributions from
312 # the sources, we can't use fluxErr as a bound on the measurement
313 # quality here.
314 self.assertFloatsAlmostEqual(stars[~sky]['slot_PsfFlux_flux'],
315 self.truth_cat['truth_flux'][idx],
316 rtol=0.1)
317 self.assertFloatsAlmostEqual(stars[~sky]['slot_PsfFlux_mag'],
318 self.truth_cat['truth_mag'][idx],
319 rtol=0.01)
321 def test_match_psf_stars(self):
322 """Test that _match_psf_stars() flags the correct stars as psf stars
323 and candidates.
324 """
325 calibrate = CalibrateImageTask(config=self.config)
326 psf_stars, background, candidates = calibrate._compute_psf(self.exposure)
327 calibrate._measure_aperture_correction(self.exposure, psf_stars)
328 stars = calibrate._find_stars(self.exposure, background, self.id_generator)
330 # There should be no psf-related flags set at first.
331 self.assertEqual(stars["calib_psf_candidate"].sum(), 0)
332 self.assertEqual(stars["calib_psf_used"].sum(), 0)
333 self.assertEqual(stars["calib_psf_reserved"].sum(), 0)
335 calibrate._match_psf_stars(psf_stars, stars)
337 # Sort in order of brightness; the psf stars are the 3 brightest, with
338 # two sky sources as the faintest.
339 stars.sort(stars.getPsfFluxSlot().getMeasKey())
340 # sort() above leaves the catalog non-contiguous.
341 stars = stars.copy(deep=True)
342 np.testing.assert_array_equal(stars["calib_psf_candidate"],
343 [False, False, False, False, True, True, True])
344 np.testing.assert_array_equal(stars["calib_psf_used"], [False, False, False, False, True, True, True])
345 # Too few sources to reserve any in these tests.
346 self.assertEqual(stars["calib_psf_reserved"].sum(), 0)
349class CalibrateImageTaskRunQuantumTests(lsst.utils.tests.TestCase):
350 """Tests of ``CalibrateImageTask.runQuantum``, which need a test butler,
351 but do not need real images.
352 """
353 def setUp(self):
354 instrument = "testCam"
355 exposure0 = 101
356 exposure1 = 101
357 visit = 100101
358 detector = 42
360 # Create a and populate a test butler for runQuantum tests.
361 self.repo_path = tempfile.TemporaryDirectory(ignore_cleanup_errors=True)
362 self.repo = butlerTests.makeTestRepo(self.repo_path.name)
364 # A complete instrument record is necessary for the id generator.
365 instrumentRecord = self.repo.dimensions["instrument"].RecordClass(
366 name=instrument, visit_max=1e6, exposure_max=1e6, detector_max=128,
367 class_name="lsst.obs.base.instrument_tests.DummyCam",
368 )
369 self.repo.registry.syncDimensionData("instrument", instrumentRecord)
371 # dataIds for fake data
372 butlerTests.addDataIdValue(self.repo, "exposure", exposure0)
373 butlerTests.addDataIdValue(self.repo, "exposure", exposure1)
374 butlerTests.addDataIdValue(self.repo, "visit", visit)
375 butlerTests.addDataIdValue(self.repo, "detector", detector)
377 # inputs
378 butlerTests.addDatasetType(self.repo, "postISRCCD", {"instrument", "exposure", "detector"},
379 "ExposureF")
380 butlerTests.addDatasetType(self.repo, "gaia_dr3_20230707", {"htm7"}, "SimpleCatalog")
381 butlerTests.addDatasetType(self.repo, "ps1_pv3_3pi_20170110", {"htm7"}, "SimpleCatalog")
383 # outputs
384 butlerTests.addDatasetType(self.repo, "initial_pvi", {"instrument", "visit", "detector"},
385 "ExposureF")
386 butlerTests.addDatasetType(self.repo, "initial_stars_footprints_detector",
387 {"instrument", "visit", "detector"},
388 "SourceCatalog")
389 butlerTests.addDatasetType(self.repo, "initial_stars_detector",
390 {"instrument", "visit", "detector"},
391 "ArrowAstropy")
392 butlerTests.addDatasetType(self.repo, "initial_photoCalib_detector",
393 {"instrument", "visit", "detector"},
394 "PhotoCalib")
395 # optional outputs
396 butlerTests.addDatasetType(self.repo, "initial_pvi_background", {"instrument", "visit", "detector"},
397 "Background")
398 butlerTests.addDatasetType(self.repo, "initial_psf_stars_footprints_detector",
399 {"instrument", "visit", "detector"},
400 "SourceCatalog")
401 butlerTests.addDatasetType(self.repo, "initial_psf_stars_detector",
402 {"instrument", "visit", "detector"},
403 "ArrowAstropy")
404 butlerTests.addDatasetType(self.repo,
405 "initial_astrometry_match_detector",
406 {"instrument", "visit", "detector"},
407 "Catalog")
408 butlerTests.addDatasetType(self.repo,
409 "initial_photometry_match_detector",
410 {"instrument", "visit", "detector"},
411 "Catalog")
413 # dataIds
414 self.exposure0_id = self.repo.registry.expandDataId(
415 {"instrument": instrument, "exposure": exposure0, "detector": detector})
416 self.exposure1_id = self.repo.registry.expandDataId(
417 {"instrument": instrument, "exposure": exposure1, "detector": detector})
418 self.visit_id = self.repo.registry.expandDataId(
419 {"instrument": instrument, "visit": visit, "detector": detector})
420 self.htm_id = self.repo.registry.expandDataId({"htm7": 42})
422 # put empty data
423 self.butler = butlerTests.makeTestCollection(self.repo)
424 self.butler.put(afwImage.ExposureF(), "postISRCCD", self.exposure0_id)
425 self.butler.put(afwTable.SimpleCatalog(), "gaia_dr3_20230707", self.htm_id)
426 self.butler.put(afwTable.SimpleCatalog(), "ps1_pv3_3pi_20170110", self.htm_id)
428 def tearDown(self):
429 self.repo_path.cleanup()
431 def test_runQuantum(self):
432 task = CalibrateImageTask()
433 lsst.pipe.base.testUtils.assertValidInitOutput(task)
435 quantum = lsst.pipe.base.testUtils.makeQuantum(
436 task, self.butler, self.visit_id,
437 {"exposures": [self.exposure0_id],
438 "astrometry_ref_cat": [self.htm_id],
439 "photometry_ref_cat": [self.htm_id],
440 # outputs
441 "output_exposure": self.visit_id,
442 "stars": self.visit_id,
443 "stars_footprints": self.visit_id,
444 "background": self.visit_id,
445 "psf_stars": self.visit_id,
446 "psf_stars_footprints": self.visit_id,
447 "applied_photo_calib": self.visit_id,
448 "initial_pvi_background": self.visit_id,
449 "astrometry_matches": self.visit_id,
450 "photometry_matches": self.visit_id,
451 })
452 mock_run = lsst.pipe.base.testUtils.runTestQuantum(task, self.butler, quantum)
454 # Ensure the reference loaders have been configured.
455 self.assertEqual(task.astrometry.refObjLoader.name, "gaia_dr3_20230707")
456 self.assertEqual(task.photometry.match.refObjLoader.name, "ps1_pv3_3pi_20170110")
457 # Check that the proper kwargs are passed to run().
458 self.assertEqual(mock_run.call_args.kwargs.keys(), {"exposures", "id_generator"})
460 def test_runQuantum_2_snaps(self):
461 task = CalibrateImageTask()
462 lsst.pipe.base.testUtils.assertValidInitOutput(task)
464 quantum = lsst.pipe.base.testUtils.makeQuantum(
465 task, self.butler, self.visit_id,
466 {"exposures": [self.exposure0_id, self.exposure1_id],
467 "astrometry_ref_cat": [self.htm_id],
468 "photometry_ref_cat": [self.htm_id],
469 # outputs
470 "output_exposure": self.visit_id,
471 "stars": self.visit_id,
472 "stars_footprints": self.visit_id,
473 "background": self.visit_id,
474 "psf_stars": self.visit_id,
475 "psf_stars_footprints": self.visit_id,
476 "applied_photo_calib": self.visit_id,
477 "initial_pvi_background": self.visit_id,
478 "astrometry_matches": self.visit_id,
479 "photometry_matches": self.visit_id,
480 })
481 mock_run = lsst.pipe.base.testUtils.runTestQuantum(task, self.butler, quantum)
483 # Ensure the reference loaders have been configured.
484 self.assertEqual(task.astrometry.refObjLoader.name, "gaia_dr3_20230707")
485 self.assertEqual(task.photometry.match.refObjLoader.name, "ps1_pv3_3pi_20170110")
486 # Check that the proper kwargs are passed to run().
487 self.assertEqual(mock_run.call_args.kwargs.keys(), {"exposures", "id_generator"})
489 def test_runQuantum_no_optional_outputs(self):
490 config = CalibrateImageTask.ConfigClass()
491 config.optional_outputs = None
492 task = CalibrateImageTask(config=config)
493 lsst.pipe.base.testUtils.assertValidInitOutput(task)
495 quantum = lsst.pipe.base.testUtils.makeQuantum(
496 task, self.butler, self.visit_id,
497 {"exposures": [self.exposure0_id],
498 "astrometry_ref_cat": [self.htm_id],
499 "photometry_ref_cat": [self.htm_id],
500 # outputs
501 "output_exposure": self.visit_id,
502 "stars": self.visit_id,
503 "stars_footprints": self.visit_id,
504 "applied_photo_calib": self.visit_id,
505 "background": self.visit_id,
506 })
507 mock_run = lsst.pipe.base.testUtils.runTestQuantum(task, self.butler, quantum)
509 # Ensure the reference loaders have been configured.
510 self.assertEqual(task.astrometry.refObjLoader.name, "gaia_dr3_20230707")
511 self.assertEqual(task.photometry.match.refObjLoader.name, "ps1_pv3_3pi_20170110")
512 # Check that the proper kwargs are passed to run().
513 self.assertEqual(mock_run.call_args.kwargs.keys(), {"exposures", "id_generator"})
515 def test_lintConnections(self):
516 """Check that the connections are self-consistent.
517 """
518 Connections = CalibrateImageTask.ConfigClass.ConnectionsClass
519 lsst.pipe.base.testUtils.lintConnections(Connections)
522def setup_module(module):
523 lsst.utils.tests.init()
526class MemoryTestCase(lsst.utils.tests.MemoryTestCase):
527 pass
530if __name__ == "__main__": 530 ↛ 531line 530 didn't jump to line 531, because the condition on line 530 was never true
531 lsst.utils.tests.init()
532 unittest.main()