Coverage for tests/test_calibrateImage.py: 17%

225 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-13 12:19 +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/>. 

21 

22import unittest 

23import tempfile 

24 

25import astropy.units as u 

26from astropy.coordinates import SkyCoord 

27import numpy as np 

28 

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 

41 

42 

43class CalibrateImageTaskTests(lsst.utils.tests.TestCase): 

44 

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])) 

70 

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) 

76 

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) 

85 

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 

89 

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")) 

97 

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 # Use PCA psf fitter, as psfex fails if there are only 4 stars. 

104 self.config.psf_measure_psf.psfDeterminer = 'pca' 

105 # We don't have many test points, so can't match on complicated shapes. 

106 self.config.astrometry.matcher.numPointsForShape = 3 

107 # ApFlux has more noise than PsfFlux (the latter unrealistically small 

108 # in this test data), so we need to do magnitude rejection at higher 

109 # sigma, otherwise we can lose otherwise good sources. 

110 # TODO DM-39203: Once we are using Compensated Gaussian Fluxes, we 

111 # will use those fluxes here, and hopefully can remove this. 

112 self.config.astrometry.magnitudeOutlierRejectionNSigma = 9.0 

113 

114 # Something about this test dataset prefers the older fluxRatio here. 

115 self.config.star_catalog_calculation.plugins['base_ClassificationExtendedness'].fluxRatio = 0.925 

116 

117 def _check_run(self, calibrate, result, *, photo_calib): 

118 """Test the result of CalibrateImage.run(). 

119 

120 Parameters 

121 ---------- 

122 calibrate : `lsst.pipe.tasks.calibrateImage.CalibrateImageTask` 

123 Configured task that had `run` called on it. 

124 result : `lsst.pipe.base.Struct` 

125 Result of calling calibrate.run(). 

126 photo_calib : `float` 

127 Expected value of the PhotoCalib mean. 

128 """ 

129 # Background should have 4 elements: 3 from compute_psf and one from 

130 # re-estimation during source detection. 

131 self.assertEqual(len(result.background), 4) 

132 

133 # Check that the summary statistics are reasonable. 

134 summary = result.output_exposure.info.getSummaryStats() 

135 self.assertFloatsAlmostEqual(summary.psfSigma, 2.0, rtol=1e-2) 

136 self.assertFloatsAlmostEqual(summary.ra, self.sky_center.getRa().asDegrees(), rtol=1e-7) 

137 self.assertFloatsAlmostEqual(summary.dec, self.sky_center.getDec().asDegrees(), rtol=1e-7) 

138 

139 # Returned photoCalib should be the applied value, not the ==1 one on the exposure. 

140 self.assertFloatsAlmostEqual(result.applied_photo_calib.getCalibrationMean(), 

141 photo_calib, rtol=2e-3) 

142 # Should have flux/magnitudes in the catalog. 

143 self.assertIn("slot_PsfFlux_flux", result.stars.schema) 

144 self.assertIn("slot_PsfFlux_mag", result.stars.schema) 

145 

146 # Check that all necessary fields are in the output. 

147 lsst.pipe.base.testUtils.assertValidOutput(calibrate, result) 

148 

149 def test_run(self): 

150 """Test that run() returns reasonable values to be butler put. 

151 """ 

152 calibrate = CalibrateImageTask(config=self.config) 

153 calibrate.astrometry.setRefObjLoader(self.ref_loader) 

154 calibrate.photometry.match.setRefObjLoader(self.ref_loader) 

155 result = calibrate.run(exposures=self.exposure) 

156 

157 self._check_run(calibrate, result, photo_calib=self.photo_calib) 

158 

159 def test_run_2_snaps(self): 

160 """Test that run() returns reasonable values to be butler put, when 

161 passed two exposures to combine as snaps. 

162 """ 

163 calibrate = CalibrateImageTask(config=self.config) 

164 calibrate.astrometry.setRefObjLoader(self.ref_loader) 

165 calibrate.photometry.match.setRefObjLoader(self.ref_loader) 

166 result = calibrate.run(exposures=[self.exposure, self.exposure]) 

167 

168 self._check_run(calibrate, result, photo_calib=self.photo_calib/2) 

169 

170 def test_handle_snaps(self): 

171 calibrate = CalibrateImageTask(config=self.config) 

172 self.assertEqual(calibrate._handle_snaps(self.exposure), self.exposure) 

173 self.assertEqual(calibrate._handle_snaps((self.exposure, )), self.exposure) 

174 self.assertEqual(calibrate._handle_snaps(self.exposure), self.exposure) 

175 with self.assertRaisesRegex(RuntimeError, "Can only process 1 or 2 snaps, not 0."): 

176 calibrate._handle_snaps([]) 

177 with self.assertRaisesRegex(RuntimeError, "Can only process 1 or 2 snaps, not 3."): 

178 calibrate._handle_snaps(3*[self.exposure]) 

179 

180 def test_compute_psf(self): 

181 """Test that our brightest sources are found by _compute_psf(), 

182 that a PSF is assigned to the expopsure. 

183 """ 

184 calibrate = CalibrateImageTask(config=self.config) 

185 psf_stars, background, candidates = calibrate._compute_psf(self.exposure) 

186 

187 # Background should have 3 elements: initial subtraction, and two from 

188 # re-estimation during the two detection passes. 

189 self.assertEqual(len(background), 3) 

190 

191 # Only the point-sources with S/N > 50 should be in this output. 

192 self.assertEqual(psf_stars["calib_psf_used"].sum(), 3) 

193 # Sort in order of brightness, to easily compare with expected positions. 

194 psf_stars.sort(psf_stars.getPsfFluxSlot().getMeasKey()) 

195 for record, flux, center in zip(psf_stars[::-1], self.fluxes, self.centroids[self.fluxes > 50]): 

196 self.assertFloatsAlmostEqual(record.getX(), center[0], rtol=0.01) 

197 self.assertFloatsAlmostEqual(record.getY(), center[1], rtol=0.01) 

198 # PsfFlux should match the values inserted. 

199 self.assertFloatsAlmostEqual(record["slot_PsfFlux_instFlux"], flux, rtol=0.01) 

200 

201 # TODO: While debugging DM-32701, we're using PCA instead of psfex. 

202 # Check that we got a useable PSF. 

203 # self.assertIsInstance(self.exposure.psf, lsst.meas.extensions.psfex.PsfexPsf) 

204 self.assertIsInstance(self.exposure.psf, lsst.meas.algorithms.PcaPsf) 

205 # TestDataset sources have PSF radius=2 pixels. 

206 radius = self.exposure.psf.computeShape(self.exposure.psf.getAveragePosition()).getDeterminantRadius() 

207 self.assertFloatsAlmostEqual(radius, 2.0, rtol=1e-2) 

208 

209 # To look at images for debugging (`setup display_ds9` and run ds9): 

210 # import lsst.afw.display 

211 # display = lsst.afw.display.getDisplay() 

212 # display.mtv(self.exposure) 

213 

214 def test_measure_aperture_correction(self): 

215 """Test that _measure_aperture_correction() assigns an ApCorrMap to the 

216 exposure. 

217 """ 

218 calibrate = CalibrateImageTask(config=self.config) 

219 psf_stars, background, candidates = calibrate._compute_psf(self.exposure) 

220 

221 # First check that the exposure doesn't have an ApCorrMap. 

222 self.assertIsNone(self.exposure.apCorrMap) 

223 calibrate._measure_aperture_correction(self.exposure, psf_stars) 

224 self.assertIsInstance(self.exposure.apCorrMap, afwImage.ApCorrMap) 

225 

226 def test_find_stars(self): 

227 """Test that _find_stars() correctly identifies the S/N>10 stars 

228 in the image and returns them in the output catalog. 

229 """ 

230 calibrate = CalibrateImageTask(config=self.config) 

231 psf_stars, background, candidates = calibrate._compute_psf(self.exposure) 

232 calibrate._measure_aperture_correction(self.exposure, psf_stars) 

233 

234 stars = calibrate._find_stars(self.exposure, background) 

235 

236 # Background should have 4 elements: 3 from compute_psf and one from 

237 # re-estimation during source detection. 

238 self.assertEqual(len(background), 4) 

239 

240 # Only psf-like sources with S/N>10 should be in the output catalog. 

241 self.assertEqual(len(stars), 5) 

242 self.assertTrue(psf_stars.isContiguous()) 

243 # Sort in order of brightness, to easily compare with expected positions. 

244 psf_stars.sort(psf_stars.getPsfFluxSlot().getMeasKey()) 

245 for record, flux, center in zip(psf_stars[::-1], self.fluxes, self.centroids[self.fluxes > 50]): 

246 self.assertFloatsAlmostEqual(record.getX(), center[0], rtol=0.01) 

247 self.assertFloatsAlmostEqual(record.getY(), center[1], rtol=0.01) 

248 self.assertFloatsAlmostEqual(record["slot_PsfFlux_instFlux"], flux, rtol=0.01) 

249 

250 def test_astrometry(self): 

251 """Test that the fitted WCS gives good catalog coordinates. 

252 """ 

253 calibrate = CalibrateImageTask(config=self.config) 

254 calibrate.astrometry.setRefObjLoader(self.ref_loader) 

255 psf_stars, background, candidates = calibrate._compute_psf(self.exposure) 

256 calibrate._measure_aperture_correction(self.exposure, psf_stars) 

257 stars = calibrate._find_stars(self.exposure, background) 

258 

259 calibrate._fit_astrometry(self.exposure, stars) 

260 

261 # Check that we got reliable matches with the truth coordinates. 

262 fitted = SkyCoord(stars['coord_ra'], stars['coord_dec'], unit="radian") 

263 truth = SkyCoord(self.truth_cat['coord_ra'], self.truth_cat['coord_dec'], unit="radian") 

264 idx, d2d, _ = fitted.match_to_catalog_sky(truth) 

265 np.testing.assert_array_less(d2d.to_value(u.milliarcsecond), 35.0) 

266 

267 def test_photometry(self): 

268 """Test that the fitted photoCalib matches the one we generated, 

269 and that the exposure is calibrated. 

270 """ 

271 calibrate = CalibrateImageTask(config=self.config) 

272 calibrate.astrometry.setRefObjLoader(self.ref_loader) 

273 calibrate.photometry.match.setRefObjLoader(self.ref_loader) 

274 psf_stars, background, candidates = calibrate._compute_psf(self.exposure) 

275 calibrate._measure_aperture_correction(self.exposure, psf_stars) 

276 stars = calibrate._find_stars(self.exposure, background) 

277 calibrate._fit_astrometry(self.exposure, stars) 

278 

279 stars, matches, meta, photoCalib = calibrate._fit_photometry(self.exposure, stars) 

280 

281 # NOTE: With this test data, PhotoCalTask returns calibrationErr==0, 

282 # so we can't check that the photoCal error has been set. 

283 self.assertFloatsAlmostEqual(photoCalib.getCalibrationMean(), self.photo_calib, rtol=2e-3) 

284 # The exposure should be calibrated by the applied photoCalib. 

285 self.assertFloatsAlmostEqual(self.exposure.image.array/self.truth_exposure.image.array, 

286 self.photo_calib, rtol=2e-3) 

287 # PhotoCalib on the exposure must be identically 1. 

288 self.assertEqual(self.exposure.photoCalib.getCalibrationMean(), 1.0) 

289 

290 # Check that we got reliable magnitudes and fluxes vs. truth. 

291 fitted = SkyCoord(stars['coord_ra'], stars['coord_dec'], unit="radian") 

292 truth = SkyCoord(self.truth_cat['coord_ra'], self.truth_cat['coord_dec'], unit="radian") 

293 idx, _, _ = fitted.match_to_catalog_sky(truth) 

294 # Because the input variance image does not include contributions from 

295 # the sources, we can't use fluxErr as a bound on the measurement 

296 # quality here. 

297 self.assertFloatsAlmostEqual(stars['slot_PsfFlux_flux'], self.truth_cat['truth_flux'][idx], rtol=0.1) 

298 self.assertFloatsAlmostEqual(stars['slot_PsfFlux_mag'], self.truth_cat['truth_mag'][idx], rtol=0.01) 

299 

300 def test_match_psf_stars(self): 

301 """Test that _match_psf_stars() flags the correct stars as psf stars 

302 and candidates. 

303 """ 

304 calibrate = CalibrateImageTask(config=self.config) 

305 psf_stars, background, candidates = calibrate._compute_psf(self.exposure) 

306 calibrate._measure_aperture_correction(self.exposure, psf_stars) 

307 stars = calibrate._find_stars(self.exposure, background) 

308 

309 # There should be no psf-related flags set at first. 

310 self.assertEqual(stars["calib_psf_candidate"].sum(), 0) 

311 self.assertEqual(stars["calib_psf_used"].sum(), 0) 

312 self.assertEqual(stars["calib_psf_reserved"].sum(), 0) 

313 

314 calibrate._match_psf_stars(psf_stars, stars) 

315 

316 # Sort in order of brightness; the psf stars are the 3 brightest. 

317 stars.sort(stars.getPsfFluxSlot().getMeasKey()) 

318 # sort() above leaves the catalog non-contiguous. 

319 stars = stars.copy(deep=True) 

320 np.testing.assert_array_equal(stars["calib_psf_candidate"], [False, False, True, True, True]) 

321 np.testing.assert_array_equal(stars["calib_psf_used"], [False, False, True, True, True]) 

322 # Too few sources to reserve any in these tests. 

323 self.assertEqual(stars["calib_psf_reserved"].sum(), 0) 

324 

325 

326class CalibrateImageTaskRunQuantumTests(lsst.utils.tests.TestCase): 

327 """Tests of ``CalibrateImageTask.runQuantum``, which need a test butler, 

328 but do not need real images. 

329 """ 

330 def setUp(self): 

331 instrument = "testCam" 

332 exposure0 = 101 

333 exposure1 = 101 

334 visit = 100101 

335 detector = 42 

336 

337 # Create a and populate a test butler for runQuantum tests. 

338 self.repo_path = tempfile.TemporaryDirectory(ignore_cleanup_errors=True) 

339 self.repo = butlerTests.makeTestRepo(self.repo_path.name) 

340 

341 # dataIds for fake data 

342 butlerTests.addDataIdValue(self.repo, "instrument", instrument) 

343 butlerTests.addDataIdValue(self.repo, "exposure", exposure0) 

344 butlerTests.addDataIdValue(self.repo, "exposure", exposure1) 

345 butlerTests.addDataIdValue(self.repo, "visit", visit) 

346 butlerTests.addDataIdValue(self.repo, "detector", detector) 

347 

348 # inputs 

349 butlerTests.addDatasetType(self.repo, "postISRCCD", {"instrument", "exposure", "detector"}, 

350 "ExposureF") 

351 butlerTests.addDatasetType(self.repo, "gaia_dr3_20230707", {"htm7"}, "SimpleCatalog") 

352 butlerTests.addDatasetType(self.repo, "ps1_pv3_3pi_20170110", {"htm7"}, "SimpleCatalog") 

353 

354 # outputs 

355 butlerTests.addDatasetType(self.repo, "initial_pvi", {"instrument", "visit", "detector"}, 

356 "ExposureF") 

357 butlerTests.addDatasetType(self.repo, "initial_stars_footprints_detector", 

358 {"instrument", "visit", "detector"}, 

359 "SourceCatalog") 

360 butlerTests.addDatasetType(self.repo, "initial_photoCalib_detector", 

361 {"instrument", "visit", "detector"}, 

362 "PhotoCalib") 

363 # optional outputs 

364 butlerTests.addDatasetType(self.repo, "initial_pvi_background", {"instrument", "visit", "detector"}, 

365 "Background") 

366 butlerTests.addDatasetType(self.repo, "initial_psf_stars_footprints", 

367 {"instrument", "visit", "detector"}, 

368 "SourceCatalog") 

369 butlerTests.addDatasetType(self.repo, 

370 "initial_astrometry_match_detector", 

371 {"instrument", "visit", "detector"}, 

372 "Catalog") 

373 butlerTests.addDatasetType(self.repo, 

374 "initial_photometry_match_detector", 

375 {"instrument", "visit", "detector"}, 

376 "Catalog") 

377 

378 # dataIds 

379 self.exposure0_id = self.repo.registry.expandDataId( 

380 {"instrument": instrument, "exposure": exposure0, "detector": detector}) 

381 self.exposure1_id = self.repo.registry.expandDataId( 

382 {"instrument": instrument, "exposure": exposure1, "detector": detector}) 

383 self.visit_id = self.repo.registry.expandDataId( 

384 {"instrument": instrument, "visit": visit, "detector": detector}) 

385 self.htm_id = self.repo.registry.expandDataId({"htm7": 42}) 

386 

387 # put empty data 

388 self.butler = butlerTests.makeTestCollection(self.repo) 

389 self.butler.put(afwImage.ExposureF(), "postISRCCD", self.exposure0_id) 

390 self.butler.put(afwTable.SimpleCatalog(), "gaia_dr3_20230707", self.htm_id) 

391 self.butler.put(afwTable.SimpleCatalog(), "ps1_pv3_3pi_20170110", self.htm_id) 

392 

393 def tearDown(self): 

394 self.repo_path.cleanup() 

395 

396 def test_runQuantum(self): 

397 task = CalibrateImageTask() 

398 lsst.pipe.base.testUtils.assertValidInitOutput(task) 

399 

400 quantum = lsst.pipe.base.testUtils.makeQuantum( 

401 task, self.butler, self.visit_id, 

402 {"exposures": [self.exposure0_id], 

403 "astrometry_ref_cat": [self.htm_id], 

404 "photometry_ref_cat": [self.htm_id], 

405 # outputs 

406 "output_exposure": self.visit_id, 

407 "stars": self.visit_id, 

408 "background": self.visit_id, 

409 "psf_stars": self.visit_id, 

410 "applied_photo_calib": self.visit_id, 

411 "initial_pvi_background": self.visit_id, 

412 "astrometry_matches": self.visit_id, 

413 "photometry_matches": self.visit_id, 

414 }) 

415 mock_run = lsst.pipe.base.testUtils.runTestQuantum(task, self.butler, quantum) 

416 

417 # Ensure the reference loaders have been configured. 

418 self.assertEqual(task.astrometry.refObjLoader.name, "gaia_dr3_20230707") 

419 self.assertEqual(task.photometry.match.refObjLoader.name, "ps1_pv3_3pi_20170110") 

420 # Check that the proper kwargs are passed to run(). 

421 self.assertEqual(mock_run.call_args.kwargs.keys(), {"exposures"}) 

422 

423 def test_runQuantum_2_snaps(self): 

424 task = CalibrateImageTask() 

425 lsst.pipe.base.testUtils.assertValidInitOutput(task) 

426 

427 quantum = lsst.pipe.base.testUtils.makeQuantum( 

428 task, self.butler, self.visit_id, 

429 {"exposures": [self.exposure0_id, self.exposure1_id], 

430 "astrometry_ref_cat": [self.htm_id], 

431 "photometry_ref_cat": [self.htm_id], 

432 # outputs 

433 "output_exposure": self.visit_id, 

434 "stars": self.visit_id, 

435 "background": self.visit_id, 

436 "psf_stars": self.visit_id, 

437 "applied_photo_calib": self.visit_id, 

438 "initial_pvi_background": self.visit_id, 

439 "astrometry_matches": self.visit_id, 

440 "photometry_matches": self.visit_id, 

441 }) 

442 mock_run = lsst.pipe.base.testUtils.runTestQuantum(task, self.butler, quantum) 

443 

444 # Ensure the reference loaders have been configured. 

445 self.assertEqual(task.astrometry.refObjLoader.name, "gaia_dr3_20230707") 

446 self.assertEqual(task.photometry.match.refObjLoader.name, "ps1_pv3_3pi_20170110") 

447 # Check that the proper kwargs are passed to run(). 

448 self.assertEqual(mock_run.call_args.kwargs.keys(), {"exposures"}) 

449 

450 def test_runQuantum_no_optional_outputs(self): 

451 config = CalibrateImageTask.ConfigClass() 

452 config.optional_outputs = None 

453 task = CalibrateImageTask(config=config) 

454 lsst.pipe.base.testUtils.assertValidInitOutput(task) 

455 

456 quantum = lsst.pipe.base.testUtils.makeQuantum( 

457 task, self.butler, self.visit_id, 

458 {"exposures": [self.exposure0_id], 

459 "astrometry_ref_cat": [self.htm_id], 

460 "photometry_ref_cat": [self.htm_id], 

461 # outputs 

462 "output_exposure": self.visit_id, 

463 "stars": self.visit_id, 

464 "applied_photo_calib": self.visit_id, 

465 "background": self.visit_id, 

466 }) 

467 mock_run = lsst.pipe.base.testUtils.runTestQuantum(task, self.butler, quantum) 

468 

469 # Ensure the reference loaders have been configured. 

470 self.assertEqual(task.astrometry.refObjLoader.name, "gaia_dr3_20230707") 

471 self.assertEqual(task.photometry.match.refObjLoader.name, "ps1_pv3_3pi_20170110") 

472 # Check that the proper kwargs are passed to run(). 

473 self.assertEqual(mock_run.call_args.kwargs.keys(), {"exposures"}) 

474 

475 def test_lintConnections(self): 

476 """Check that the connections are self-consistent. 

477 """ 

478 Connections = CalibrateImageTask.ConfigClass.ConnectionsClass 

479 lsst.pipe.base.testUtils.lintConnections(Connections) 

480 

481 

482def setup_module(module): 

483 lsst.utils.tests.init() 

484 

485 

486class MemoryTestCase(lsst.utils.tests.MemoryTestCase): 

487 pass 

488 

489 

490if __name__ == "__main__": 490 ↛ 491line 490 didn't jump to line 491, because the condition on line 490 was never true

491 lsst.utils.tests.init() 

492 unittest.main()