Coverage for tests/test_jointcal_hsc.py: 18%

Shortcuts on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

194 statements  

1# This file is part of jointcal. 

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 os 

24 

25from astropy import units as u 

26import numpy as np 

27 

28from lsst.daf.butler import Butler 

29import lsst.geom 

30import lsst.pex.config 

31import lsst.utils 

32import lsst.pex.exceptions 

33 

34import jointcalTestBase 

35 

36 

37# for MemoryTestCase 

38def setup_module(module): 

39 lsst.utils.tests.init() 

40 

41 

42class JointcalTestHSC(jointcalTestBase.JointcalTestBase, lsst.utils.tests.TestCase): 

43 

44 @classmethod 

45 def setUpClass(cls): 

46 try: 

47 cls.data_dir = lsst.utils.getPackageDir('testdata_jointcal') 

48 except LookupError: 

49 raise unittest.SkipTest("testdata_jointcal not setup") 

50 try: 

51 lsst.utils.getPackageDir('obs_subaru') 

52 except LookupError: 

53 raise unittest.SkipTest("obs_subaru not setup") 

54 

55 def setUp(self): 

56 # See Readme for an explanation of these empirical values. 

57 self.dist_rms_absolute = 21e-3*u.arcsecond 

58 self.dist_rms_relative = 7e-3*u.arcsecond 

59 

60 do_plot = False 

61 

62 # center of the hsc validation_data catalog 

63 center = lsst.geom.SpherePoint(337.710899, +0.807006, lsst.geom.degrees) 

64 radius = 0.5*lsst.geom.degrees 

65 

66 input_dir = os.path.join(self.data_dir, 'hsc') 

67 all_visits = [34648, 34690, 34714, 34674, 34670, 36140, 35892, 36192, 36260, 36236] 

68 

69 where = "instrument='HSC' and tract=9697 and skymap='hsc_rings_v1'" 

70 inputCollections = ["refcats/gen2", 

71 "HSC/testdata", 

72 "HSC/calib/unbounded"] 

73 

74 self.setUp_base(center, radius, 

75 input_dir=input_dir, 

76 all_visits=all_visits, 

77 do_plot=do_plot, 

78 where=where, 

79 inputCollections=inputCollections) 

80 

81 test_config = os.path.join(lsst.utils.getPackageDir('jointcal'), 'tests/config/hsc-config.py') 

82 self.configfiles.append(test_config) 

83 

84 def test_jointcalTask_2_visits_simple(self): 

85 self.config = lsst.jointcal.jointcal.JointcalConfig() 

86 self.config.astrometryModel = "simple" 

87 self.config.photometryModel = "simpleFlux" 

88 self.input_dir = os.path.join(self.data_dir, 'hsc/repo') 

89 

90 # See Readme for an explanation of these empirical values. 

91 pa1 = 0.016 

92 metrics = {'astrometry_collected_refStars': 568, 

93 'photometry_collected_refStars': 6485, 

94 'astrometry_prepared_refStars': 137, 

95 'photometry_prepared_refStars': 1609, 

96 'astrometry_matched_fittedStars': 2070, 

97 'photometry_matched_fittedStars': 2070, 

98 'astrometry_prepared_fittedStars': 989, 

99 'photometry_prepared_fittedStars': 1731, 

100 'astrometry_prepared_ccdImages': 6, 

101 'photometry_prepared_ccdImages': 6, 

102 'astrometry_final_chi2': 835.473, 

103 'astrometry_final_ndof': 1918, 

104 'photometry_final_chi2': 4997.62, 

105 'photometry_final_ndof': 2188 

106 } 

107 self._testJointcalTask(2, self.dist_rms_relative, self.dist_rms_absolute, pa1, metrics=metrics) 

108 

109 def test_jointcalTask_2_visits_simple_gen3(self): 

110 """Test gen3 butler jointcal.""" 

111 configOptions = {"astrometryModel": "simple", "photometryModel": "simpleFlux"} 

112 where = f" and visit in ({self.all_visits[0]},{self.all_visits[1]})" 

113 # test colorterm loading in gen3 (see DM-29884) 

114 colorterm_config = os.path.join(lsst.utils.getPackageDir('jointcal'), 

115 'tests/config/hsc-colorterms-config.py') 

116 configFiles = [os.path.join(lsst.utils.getPackageDir('jointcal'), 

117 'tests/config/config-gen3-hsc.py'), 

118 colorterm_config] 

119 

120 metrics = {'astrometry_collected_refStars': 568, 

121 'photometry_collected_refStars': 6478, 

122 'astrometry_prepared_refStars': 137, 

123 'photometry_prepared_refStars': 1609, 

124 'astrometry_matched_fittedStars': 2070, 

125 'photometry_matched_fittedStars': 2070, 

126 'astrometry_prepared_fittedStars': 989, 

127 'photometry_prepared_fittedStars': 1731, 

128 'astrometry_prepared_ccdImages': 6, 

129 'photometry_prepared_ccdImages': 6, 

130 'astrometry_final_chi2': 835.473, 

131 'astrometry_final_ndof': 1918, 

132 'photometry_final_chi2': 4977.2, 

133 'photometry_final_ndof': 2188 

134 } 

135 repo = self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where, 

136 configOptions=configOptions, configFiles=configFiles, metrics=metrics) 

137 # TODO DM-28863: this does not currently test anything other than the code 

138 # running without raising and that it writes non-empty output. 

139 butler = Butler(repo, collections=['HSC/tests/all']) 

140 

141 def check_output(visit, detectors): 

142 """Check that there is something for each detector, and only 

143 entries for the correct detectors.""" 

144 dataId = {'visit': visit, 'instrument': 'HSC', 'tract': 9697, 'skymap': 'hsc_rings_v1'} 

145 

146 catalog = butler.get('jointcalPhotoCalibCatalog', dataId) 

147 for record in catalog: 

148 self.assertIsInstance(record.getPhotoCalib(), lsst.afw.image.PhotoCalib, 

149 msg=f"visit {visit}: {record}") 

150 np.testing.assert_array_equal(catalog['id'], detectors) 

151 

152 catalog = butler.get('jointcalSkyWcsCatalog', dataId) 

153 for record in catalog: 

154 self.assertIsInstance(record.getWcs(), lsst.afw.geom.SkyWcs, 

155 msg=f"visit {visit}: {record}") 

156 np.testing.assert_array_equal(catalog['id'], detectors) 

157 

158 check_output(34648, [51, 59, 67]) 

159 check_output(34690, [48, 56, 64]) 

160 

161 def test_jointcalTask_ri_visits_2_bands_simple_gen3_dm32207(self): 

162 """Test gen3 butler jointcal putting 2 bands in same repo.""" 

163 configOptions = {"astrometryModel": "simple", "photometryModel": "simpleFlux"} 

164 where = (f" and visit in ({self.all_visits[0]},{self.all_visits[1]}," 

165 f"{self.all_visits[5]},{self.all_visits[6]})") 

166 configFiles = [os.path.join(lsst.utils.getPackageDir('jointcal'), 

167 'tests/config/config-gen3-hsc.py')] 

168 

169 self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where, 

170 configOptions=configOptions, configFiles=configFiles, metrics=None, nJobs=2) 

171 

172 def test_jointcalTask_2_visits_simple_astrometry_no_photometry_gen3(self): 

173 """Test gen3 butler jointcal, no photometry.""" 

174 configOptions = {"astrometryModel": "simple", "doPhotometry": False} 

175 where = f" and visit in ({self.all_visits[0]},{self.all_visits[1]})" 

176 configFiles = [os.path.join(lsst.utils.getPackageDir('jointcal'), 

177 'tests/config/config-gen3-hsc.py')] 

178 

179 metrics = {'astrometry_collected_refStars': 568, 

180 'astrometry_prepared_refStars': 137, 

181 'astrometry_matched_fittedStars': 2070, 

182 'astrometry_prepared_fittedStars': 989, 

183 'astrometry_prepared_ccdImages': 6, 

184 'astrometry_final_chi2': 835.473, 

185 'astrometry_final_ndof': 1918, 

186 } 

187 repo = self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where, 

188 configOptions=configOptions, configFiles=configFiles, metrics=metrics) 

189 # TODO DM-28863: this does not currently test anything other than the code 

190 # running without raising and that it writes non-empty output. 

191 butler = Butler(repo, collections=['HSC/tests/all']) 

192 

193 def check_output(visit, detectors): 

194 """Check that there is something for each detector, and only 

195 entries for the correct detectors.""" 

196 dataId = {'visit': visit, 'instrument': 'HSC', 'tract': 9697, 'skymap': 'hsc_rings_v1'} 

197 

198 catalog = butler.get('jointcalSkyWcsCatalog', dataId) 

199 for record in catalog: 

200 self.assertIsInstance(record.getWcs(), lsst.afw.geom.SkyWcs, 

201 msg=f"visit {visit}: {record}") 

202 np.testing.assert_array_equal(catalog['id'], detectors) 

203 

204 check_output(34648, [51, 59, 67]) 

205 check_output(34690, [48, 56, 64]) 

206 

207 def test_jointcalTask_2_visits_simple_photometry_no_astrometry_gen3(self): 

208 """Test gen3 butler jointcal, no astrometry.""" 

209 configOptions = {"doAstrometry": False, "photometryModel": "simpleFlux"} 

210 where = f" and visit in ({self.all_visits[0]},{self.all_visits[1]})" 

211 configFiles = [os.path.join(lsst.utils.getPackageDir('jointcal'), 

212 'tests/config/config-gen3-hsc.py')] 

213 

214 metrics = {'photometry_collected_refStars': 6485, 

215 'photometry_prepared_refStars': 1609, 

216 'photometry_matched_fittedStars': 2070, 

217 'photometry_prepared_fittedStars': 1731, 

218 'photometry_prepared_ccdImages': 6, 

219 'photometry_final_chi2': 4997.62, 

220 'photometry_final_ndof': 2188 

221 } 

222 repo = self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where, 

223 configOptions=configOptions, configFiles=configFiles, metrics=metrics) 

224 # TODO DM-28863: this does not currently test anything other than the code 

225 # running without raising and that it writes non-empty output. 

226 butler = Butler(repo, collections=['HSC/tests/all']) 

227 

228 def check_output(visit, detectors): 

229 """Check that there is something for each detector, and only 

230 entries for the correct detectors.""" 

231 dataId = {'visit': visit, 'instrument': 'HSC', 'tract': 9697, 'skymap': 'hsc_rings_v1'} 

232 

233 catalog = butler.get('jointcalPhotoCalibCatalog', dataId) 

234 for record in catalog: 

235 self.assertIsInstance(record.getPhotoCalib(), lsst.afw.image.PhotoCalib, 

236 msg=f"visit {visit}: {record}") 

237 np.testing.assert_array_equal(catalog['id'], detectors) 

238 

239 check_output(34648, [51, 59, 67]) 

240 check_output(34690, [48, 56, 64]) 

241 

242 def test_jointcalTask_10_visits_simple_astrometry_no_photometry(self): 

243 """Test all 10 visits with different filters. 

244 Testing photometry doesn't make sense for this currently. 

245 """ 

246 self.config = lsst.jointcal.jointcal.JointcalConfig() 

247 self.config.astrometryModel = "simple" 

248 self.config.doPhotometry = False 

249 self.jointcalStatistics.do_photometry = False 

250 self.input_dir = os.path.join(self.data_dir, 'hsc/repo') 

251 

252 # See Readme for an explanation of these empirical values. 

253 dist_rms_absolute = 23e-3*u.arcsecond 

254 dist_rms_relative = 13e-3*u.arcsecond 

255 pa1 = None 

256 metrics = {'astrometry_collected_refStars': 1316, 

257 'astrometry_prepared_refStars': 318, 

258 'astrometry_matched_fittedStars': 5860, 

259 'astrometry_prepared_fittedStars': 3568, 

260 'astrometry_prepared_ccdImages': 30, 

261 'astrometry_final_chi2': 10225.31, 

262 'astrometry_final_ndof': 18576, 

263 } 

264 self._testJointcalTask(10, dist_rms_relative, dist_rms_absolute, pa1, metrics=metrics) 

265 

266 def setup_jointcalTask_2_visits_simplePhotometry(self): 

267 """Set default values for the simplePhotometry tests, and make it so 

268 the differences between each test and the defaults are more obvious. 

269 """ 

270 self.config = lsst.jointcal.jointcal.JointcalConfig() 

271 self.config.photometryModel = "simpleFlux" 

272 self.config.doAstrometry = False 

273 self.jointcalStatistics.do_astrometry = False 

274 self.input_dir = os.path.join(self.data_dir, 'hsc/repo') 

275 

276 # See Readme for an explanation of these empirical values. 

277 pa1 = 0.016 

278 metrics = {'photometry_collected_refStars': 6485, 

279 'photometry_prepared_refStars': 1609, 

280 'photometry_matched_fittedStars': 2070, 

281 'photometry_prepared_fittedStars': 1731, 

282 'photometry_prepared_ccdImages': 6, 

283 'photometry_final_chi2': 4997.62, 

284 'photometry_final_ndof': 2188 

285 } 

286 return pa1, metrics 

287 

288 def test_jointcalTask_2_visits_simpleFlux(self): 

289 pa1, metrics = self.setup_jointcalTask_2_visits_simplePhotometry() 

290 self._testJointcalTask(2, None, None, pa1, metrics=metrics) 

291 

292 def test_jointcalTask_2_visits_simpleMagnitude(self): 

293 pa1, metrics = self.setup_jointcalTask_2_visits_simplePhotometry() 

294 self.config.photometryModel = "simpleMagnitude" 

295 metrics['photometry_final_chi2'] = 5236.91 

296 metrics['photometry_final_ndof'] = 2200 

297 

298 self._testJointcalTask(2, None, None, pa1, metrics=metrics) 

299 

300 def test_jointcalTask_2_visits_simpleMagnitude_colorterms(self): 

301 """Test that colorterms are applied and change the fit.""" 

302 pa1, metrics = self.setup_jointcalTask_2_visits_simplePhotometry() 

303 self.config.photometryModel = "simpleMagnitude" 

304 test_config = os.path.join(lsst.utils.getPackageDir('jointcal'), 

305 'tests/config/hsc-colorterms-config.py') 

306 self.configfiles.append(test_config) 

307 

308 # slightly fewer refstars because they each need the specific filters required by the colorterms 

309 metrics['photometry_collected_refStars'] = 6478 

310 # Final chi2 should be different, but I don't have an a-priori reason 

311 # to expect it to be larger or smaller. 

312 metrics['photometry_final_chi2'] = 5181.25 

313 metrics['photometry_final_ndof'] = 2197 

314 

315 self._testJointcalTask(2, None, None, pa1, metrics=metrics) 

316 

317 def test_jointcalTask_2_visits_simpleMagnitude_colorterms_no_library(self): 

318 """Fail Config validation if the color term library isn't defined.""" 

319 pa1, metrics = self.setup_jointcalTask_2_visits_simplePhotometry() 

320 test_config = os.path.join(lsst.utils.getPackageDir('jointcal'), 

321 'tests/config/hsc-colorterms_no_library-config.py') 

322 self.configfiles.append(test_config) 

323 

324 with self.assertRaises(lsst.pex.config.FieldValidationError): 

325 self._testJointcalTask(2, None, None, pa1) 

326 

327 def test_JointcalTask_2_visits_simple_astrometry_no_photometry(self): 

328 """Test turning off fitting photometry.""" 

329 metrics = {'astrometry_collected_refStars': 568, 

330 'astrometry_prepared_refStars': 137, 

331 'astrometry_matched_fittedStars': 2070, 

332 'astrometry_prepared_fittedStars': 989, 

333 'astrometry_prepared_ccdImages': 6, 

334 'astrometry_final_chi2': 835.473, 

335 'astrometry_final_ndof': 1918, 

336 } 

337 self.config = lsst.jointcal.jointcal.JointcalConfig() 

338 self.config.astrometryModel = "simple" 

339 self.config.doPhotometry = False 

340 self.jointcalStatistics.do_photometry = False 

341 self.input_dir = os.path.join(self.data_dir, 'hsc/repo') 

342 

343 data_refs = self._testJointcalTask(2, self.dist_rms_relative, self.dist_rms_absolute, 

344 None, metrics=metrics) 

345 

346 for data_ref in data_refs: 

347 with self.assertRaises(lsst.daf.persistence.butlerExceptions.NoResults): 

348 data_ref.get('jointcal_photoCalib') 

349 

350 def test_jointcalTask_2_visits_simple_astrometry_no_photometry_match_cut_10(self): 

351 """A larger matching radius will result in more associated fittedStars, 

352 and a somewhat worse final fit because stars that should not have been 

353 associated, were. 

354 """ 

355 self.config = lsst.jointcal.jointcal.JointcalConfig() 

356 self.config.astrometryModel = "simple" 

357 self.config.matchCut = 10.0 # TODO: once DM-6885 is fixed, we need to put `*lsst.geom.arcseconds` 

358 self.config.doPhotometry = False 

359 self.jointcalStatistics.do_photometry = False 

360 self.input_dir = os.path.join(self.data_dir, 'hsc/repo') 

361 

362 # Slightly larger absolute astrometry RMS because of the larger matching radius 

363 dist_rms_absolute = 23e-3*u.arcsecond 

364 metrics = {'astrometry_collected_refStars': 568, 

365 'astrometry_prepared_refStars': 211, 

366 'astrometry_matched_fittedStars': 2070, 

367 'astrometry_prepared_fittedStars': 1042, 

368 'astrometry_prepared_ccdImages': 6, 

369 'astrometry_final_chi2': 819.608, 

370 'astrometry_final_ndof': 1872, 

371 } 

372 pa1 = None 

373 self._testJointcalTask(2, self.dist_rms_relative, dist_rms_absolute, pa1, metrics=metrics) 

374 

375 def test_jointcalTask_3_visits_simple_astrometry_no_photometry(self): 

376 """3 visit, default config to compare with min_measurements_3 test.""" 

377 self.config = lsst.jointcal.jointcal.JointcalConfig() 

378 self.config.astrometryModel = "simple" 

379 self.config.minMeasurements = 2 

380 self.config.doPhotometry = False 

381 self.jointcalStatistics.do_photometry = False 

382 self.input_dir = os.path.join(self.data_dir, 'hsc/repo') 

383 

384 # More visits and slightly worse relative and absolute rms. 

385 dist_rms_relative = 8.3e-3*u.arcsecond 

386 dist_rms_absolute = 24e-3*u.arcsecond 

387 metrics = {'astrometry_collected_refStars': 1038, 

388 'astrometry_prepared_refStars': 209, 

389 'astrometry_matched_fittedStars': 3199, 

390 'astrometry_prepared_fittedStars': 1282, 

391 'astrometry_prepared_ccdImages': 9, 

392 'astrometry_final_chi2': 1221.63, 

393 'astrometry_final_ndof': 2892, 

394 } 

395 pa1 = None 

396 self._testJointcalTask(3, dist_rms_relative, dist_rms_absolute, pa1, metrics=metrics) 

397 

398 def test_jointcalTask_3_visits_simple_astrometry_no_photometry_min_measurements_3(self): 

399 """Raising min_measurements to 3 will reduce the number of selected 

400 fitted stars (and thus the chisq and Ndof), but should not change the 

401 other values.""" 

402 self.config = lsst.jointcal.jointcal.JointcalConfig() 

403 self.config.minMeasurements = 3 

404 self.config.astrometryModel = "simple" 

405 self.config.doPhotometry = False 

406 self.jointcalStatistics.do_photometry = False 

407 self.input_dir = os.path.join(self.data_dir, 'hsc/repo') 

408 

409 # More visits and slightly worse relative and absolute rms. 

410 dist_rms_relative = 11e-3*u.arcsecond 

411 dist_rms_absolute = 24e-3*u.arcsecond 

412 metrics = {'astrometry_collected_refStars': 1038, 

413 'astrometry_prepared_refStars': 209, 

414 'astrometry_matched_fittedStars': 3199, 

415 'astrometry_prepared_fittedStars': 432, 

416 'astrometry_prepared_ccdImages': 9, 

417 'astrometry_final_chi2': 567.433, 

418 'astrometry_final_ndof': 1286, 

419 } 

420 pa1 = None 

421 self._testJointcalTask(3, dist_rms_relative, dist_rms_absolute, pa1, metrics=metrics) 

422 

423 

424class MemoryTester(lsst.utils.tests.MemoryTestCase): 

425 pass 

426 

427 

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

429 lsst.utils.tests.init() 

430 unittest.main()