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
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
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/>.
22import unittest
23import os
25from astropy import units as u
26import numpy as np
28from lsst.daf.butler import Butler
29import lsst.geom
30import lsst.pex.config
31import lsst.utils
32import lsst.pex.exceptions
34import jointcalTestBase
37# for MemoryTestCase
38def setup_module(module):
39 lsst.utils.tests.init()
42class JointcalTestHSC(jointcalTestBase.JointcalTestBase, lsst.utils.tests.TestCase):
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")
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
60 do_plot = False
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
66 input_dir = os.path.join(self.data_dir, 'hsc')
67 all_visits = [34648, 34690, 34714, 34674, 34670, 36140, 35892, 36192, 36260, 36236]
69 where = "instrument='HSC' and tract=9697 and skymap='hsc_rings_v1'"
70 inputCollections = ["refcats/gen2",
71 "HSC/testdata",
72 "HSC/calib/unbounded"]
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)
81 test_config = os.path.join(lsst.utils.getPackageDir('jointcal'), 'tests/config/hsc-config.py')
82 self.configfiles.append(test_config)
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')
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)
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]
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'])
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'}
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)
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)
158 check_output(34648, [51, 59, 67])
159 check_output(34690, [48, 56, 64])
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')]
169 self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where,
170 configOptions=configOptions, configFiles=configFiles, metrics=None, nJobs=2)
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')]
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'])
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'}
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)
204 check_output(34648, [51, 59, 67])
205 check_output(34690, [48, 56, 64])
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')]
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'])
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'}
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)
239 check_output(34648, [51, 59, 67])
240 check_output(34690, [48, 56, 64])
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')
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)
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')
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
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)
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
298 self._testJointcalTask(2, None, None, pa1, metrics=metrics)
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)
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
315 self._testJointcalTask(2, None, None, pa1, metrics=metrics)
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)
324 with self.assertRaises(lsst.pex.config.FieldValidationError):
325 self._testJointcalTask(2, None, None, pa1)
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')
343 data_refs = self._testJointcalTask(2, self.dist_rms_relative, self.dist_rms_absolute,
344 None, metrics=metrics)
346 for data_ref in data_refs:
347 with self.assertRaises(lsst.daf.persistence.butlerExceptions.NoResults):
348 data_ref.get('jointcal_photoCalib')
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')
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)
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')
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)
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')
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)
424class MemoryTester(lsst.utils.tests.MemoryTestCase):
425 pass
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()