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'"
71 self.setUp_base(center, radius,
72 input_dir=input_dir,
73 all_visits=all_visits,
74 do_plot=do_plot,
75 where=where)
77 test_config = os.path.join(lsst.utils.getPackageDir('jointcal'), 'tests/config/hsc-config.py')
78 self.configfiles.append(test_config)
80 def test_jointcalTask_2_visits_simple(self):
81 self.config = lsst.jointcal.jointcal.JointcalConfig()
82 self.config.astrometryModel = "simple"
83 self.config.photometryModel = "simpleFlux"
85 # See Readme for an explanation of these empirical values.
86 pa1 = 0.016
87 metrics = {'astrometry_collected_refStars': 568,
88 'photometry_collected_refStars': 6485,
89 'astrometry_prepared_refStars': 137,
90 'photometry_prepared_refStars': 1609,
91 'astrometry_matched_fittedStars': 2070,
92 'photometry_matched_fittedStars': 2070,
93 'astrometry_prepared_fittedStars': 989,
94 'photometry_prepared_fittedStars': 1731,
95 'astrometry_prepared_ccdImages': 6,
96 'photometry_prepared_ccdImages': 6,
97 'astrometry_final_chi2': 835.473,
98 'astrometry_final_ndof': 1918,
99 'photometry_final_chi2': 4997.62,
100 'photometry_final_ndof': 2188
101 }
102 self._testJointcalTask(2, self.dist_rms_relative, self.dist_rms_absolute, pa1, metrics=metrics)
104 def test_jointcalTask_2_visits_simple_gen3(self):
105 """Test gen3 butler jointcal."""
106 configOptions = {"astrometryModel": "simple", "photometryModel": "simpleFlux"}
107 where = f" and visit in ({self.all_visits[0]},{self.all_visits[1]})"
108 # test colorterm loading in gen3 (see DM-29884)
109 colorterm_config = os.path.join(lsst.utils.getPackageDir('jointcal'),
110 'tests/config/hsc-colorterms-config.py')
111 metrics = {'astrometry_collected_refStars': 568,
112 'photometry_collected_refStars': 6478,
113 'astrometry_prepared_refStars': 137,
114 'photometry_prepared_refStars': 1609,
115 'astrometry_matched_fittedStars': 2070,
116 'photometry_matched_fittedStars': 2070,
117 'astrometry_prepared_fittedStars': 989,
118 'photometry_prepared_fittedStars': 1731,
119 'astrometry_prepared_ccdImages': 6,
120 'photometry_prepared_ccdImages': 6,
121 'astrometry_final_chi2': 835.473,
122 'astrometry_final_ndof': 1918,
123 'photometry_final_chi2': 4977.2,
124 'photometry_final_ndof': 2188
125 }
126 self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where,
127 configOptions=configOptions, metrics=metrics, configFiles=[colorterm_config])
128 # TODO DM-28863: this does not currently test anything other than the code
129 # running without raising and that it writes non-empty output.
130 butler = Butler(self.repo, collections=['HSC/testdata/jointcal'])
132 def check_output(visit, detectors):
133 """Check that there is something for each detector, and only
134 entries for the correct detectors."""
135 dataId = {'visit': visit, 'instrument': 'HSC', 'tract': 9697}
137 catalog = butler.get('jointcalPhotoCalibCatalog', dataId)
138 for record in catalog:
139 self.assertIsInstance(record.getPhotoCalib(), lsst.afw.image.PhotoCalib,
140 msg=f"visit {visit}: {record}")
141 np.testing.assert_array_equal(catalog['id'], detectors)
143 catalog = butler.get('jointcalSkyWcsCatalog', dataId)
144 for record in catalog:
145 self.assertIsInstance(record.getWcs(), lsst.afw.geom.SkyWcs,
146 msg=f"visit {visit}: {record}")
147 np.testing.assert_array_equal(catalog['id'], detectors)
149 check_output(34648, [51, 59, 67])
150 check_output(34690, [48, 56, 64])
152 def test_jointcalTask_ri_visits_2_bands_simple_gen3_dm32207(self):
153 """Test gen3 butler jointcal putting 2 bands in same repo."""
154 configOptions = {"astrometryModel": "simple", "photometryModel": "simpleFlux"}
155 where = (f" and visit in ({self.all_visits[0]},{self.all_visits[1]},"
156 f"{self.all_visits[5]},{self.all_visits[6]})")
158 self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where,
159 configOptions=configOptions, metrics=None, nJobs=2)
161 def test_jointcalTask_2_visits_simple_astrometry_no_photometry_gen3(self):
162 """Test gen3 butler jointcal, no photometry."""
163 configOptions = {"astrometryModel": "simple", "doPhotometry": False}
164 where = f" and visit in ({self.all_visits[0]},{self.all_visits[1]})"
166 metrics = {'astrometry_collected_refStars': 568,
167 'astrometry_prepared_refStars': 137,
168 'astrometry_matched_fittedStars': 2070,
169 'astrometry_prepared_fittedStars': 989,
170 'astrometry_prepared_ccdImages': 6,
171 'astrometry_final_chi2': 835.473,
172 'astrometry_final_ndof': 1918,
173 }
174 self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where,
175 configOptions=configOptions, metrics=metrics)
176 # TODO DM-28863: this does not currently test anything other than the code
177 # running without raising and that it writes non-empty output.
178 butler = Butler(self.repo, collections=['HSC/testdata/jointcal'])
180 def check_output(visit, detectors):
181 """Check that there is something for each detector, and only
182 entries for the correct detectors."""
183 dataId = {'visit': visit, 'instrument': 'HSC', 'tract': 9697}
185 catalog = butler.get('jointcalSkyWcsCatalog', dataId)
186 for record in catalog:
187 self.assertIsInstance(record.getWcs(), lsst.afw.geom.SkyWcs,
188 msg=f"visit {visit}: {record}")
189 np.testing.assert_array_equal(catalog['id'], detectors)
191 check_output(34648, [51, 59, 67])
192 check_output(34690, [48, 56, 64])
194 def test_jointcalTask_2_visits_simple_photometry_no_astrometry_gen3(self):
195 """Test gen3 butler jointcal, no astrometry."""
196 configOptions = {"doAstrometry": False, "photometryModel": "simpleFlux"}
197 where = f" and visit in ({self.all_visits[0]},{self.all_visits[1]})"
199 metrics = {'photometry_collected_refStars': 6485,
200 'photometry_prepared_refStars': 1609,
201 'photometry_matched_fittedStars': 2070,
202 'photometry_prepared_fittedStars': 1731,
203 'photometry_prepared_ccdImages': 6,
204 'photometry_final_chi2': 4997.62,
205 'photometry_final_ndof': 2188
206 }
207 self._runGen3Jointcal("lsst.obs.subaru.HyperSuprimeCam", "HSC", whereSuffix=where,
208 configOptions=configOptions, metrics=metrics)
209 # TODO DM-28863: this does not currently test anything other than the code
210 # running without raising and that it writes non-empty output.
211 butler = Butler(self.repo, collections=['HSC/testdata/jointcal'])
213 def check_output(visit, detectors):
214 """Check that there is something for each detector, and only
215 entries for the correct detectors."""
216 dataId = {'visit': visit, 'instrument': 'HSC', 'tract': 9697}
218 catalog = butler.get('jointcalPhotoCalibCatalog', dataId)
219 for record in catalog:
220 self.assertIsInstance(record.getPhotoCalib(), lsst.afw.image.PhotoCalib,
221 msg=f"visit {visit}: {record}")
222 np.testing.assert_array_equal(catalog['id'], detectors)
224 check_output(34648, [51, 59, 67])
225 check_output(34690, [48, 56, 64])
227 def test_jointcalTask_10_visits_simple_astrometry_no_photometry(self):
228 """Test all 10 visits with different filters.
229 Testing photometry doesn't make sense for this currently.
230 """
232 self.config = lsst.jointcal.jointcal.JointcalConfig()
233 self.config.astrometryModel = "simple"
234 self.config.doPhotometry = False
235 self.jointcalStatistics.do_photometry = False
237 # See Readme for an explanation of these empirical values.
238 dist_rms_absolute = 23e-3*u.arcsecond
239 dist_rms_relative = 13e-3*u.arcsecond
240 pa1 = None
241 metrics = {'astrometry_collected_refStars': 1316,
242 'astrometry_prepared_refStars': 318,
243 'astrometry_matched_fittedStars': 5860,
244 'astrometry_prepared_fittedStars': 3568,
245 'astrometry_prepared_ccdImages': 30,
246 'astrometry_final_chi2': 10225.31,
247 'astrometry_final_ndof': 18576,
248 }
249 self._testJointcalTask(10, dist_rms_relative, dist_rms_absolute, pa1, metrics=metrics)
251 def setup_jointcalTask_2_visits_simplePhotometry(self):
252 """Set default values for the simplePhotometry tests, and make it so
253 the differences between each test and the defaults are more obvious.
254 """
255 self.config = lsst.jointcal.jointcal.JointcalConfig()
256 self.config.photometryModel = "simpleFlux"
257 self.config.doAstrometry = False
258 self.jointcalStatistics.do_astrometry = False
260 # See Readme for an explanation of these empirical values.
261 pa1 = 0.016
262 metrics = {'photometry_collected_refStars': 6485,
263 'photometry_prepared_refStars': 1609,
264 'photometry_matched_fittedStars': 2070,
265 'photometry_prepared_fittedStars': 1731,
266 'photometry_prepared_ccdImages': 6,
267 'photometry_final_chi2': 4997.62,
268 'photometry_final_ndof': 2188
269 }
270 return pa1, metrics
272 def test_jointcalTask_2_visits_simpleFlux(self):
273 pa1, metrics = self.setup_jointcalTask_2_visits_simplePhotometry()
274 self._testJointcalTask(2, None, None, pa1, metrics=metrics)
276 def test_jointcalTask_2_visits_simpleMagnitude(self):
277 pa1, metrics = self.setup_jointcalTask_2_visits_simplePhotometry()
278 self.config.photometryModel = "simpleMagnitude"
279 metrics['photometry_final_chi2'] = 5236.91
280 metrics['photometry_final_ndof'] = 2200
282 self._testJointcalTask(2, None, None, pa1, metrics=metrics)
284 def test_jointcalTask_2_visits_simpleMagnitude_colorterms(self):
285 """Test that colorterms are applied and change the fit."""
286 pa1, metrics = self.setup_jointcalTask_2_visits_simplePhotometry()
287 self.config.photometryModel = "simpleMagnitude"
288 test_config = os.path.join(lsst.utils.getPackageDir('jointcal'),
289 'tests/config/hsc-colorterms-config.py')
290 self.configfiles.append(test_config)
292 # slightly fewer refstars because they each need the specific filters required by the colorterms
293 metrics['photometry_collected_refStars'] = 6478
294 # Final chi2 should be different, but I don't have an a-priori reason
295 # to expect it to be larger or smaller.
296 metrics['photometry_final_chi2'] = 5181.25
297 metrics['photometry_final_ndof'] = 2197
299 self._testJointcalTask(2, None, None, pa1, metrics=metrics)
301 def test_jointcalTask_2_visits_simpleMagnitude_colorterms_no_library(self):
302 """Fail Config validation if the color term library isn't defined."""
303 pa1, metrics = self.setup_jointcalTask_2_visits_simplePhotometry()
304 test_config = os.path.join(lsst.utils.getPackageDir('jointcal'),
305 'tests/config/hsc-colorterms_no_library-config.py')
306 self.configfiles.append(test_config)
308 with self.assertRaises(lsst.pex.config.FieldValidationError):
309 self._testJointcalTask(2, None, None, pa1)
311 def test_JointcalTask_2_visits_simple_astrometry_no_photometry(self):
312 """Test turning off fitting photometry."""
313 metrics = {'astrometry_collected_refStars': 568,
314 'astrometry_prepared_refStars': 137,
315 'astrometry_matched_fittedStars': 2070,
316 'astrometry_prepared_fittedStars': 989,
317 'astrometry_prepared_ccdImages': 6,
318 'astrometry_final_chi2': 835.473,
319 'astrometry_final_ndof': 1918,
320 }
321 self.config = lsst.jointcal.jointcal.JointcalConfig()
322 self.config.astrometryModel = "simple"
323 self.config.doPhotometry = False
324 self.jointcalStatistics.do_photometry = False
326 data_refs = self._testJointcalTask(2, self.dist_rms_relative, self.dist_rms_absolute,
327 None, metrics=metrics)
329 for data_ref in data_refs:
330 with self.assertRaises(lsst.daf.persistence.butlerExceptions.NoResults):
331 data_ref.get('jointcal_photoCalib')
333 def test_jointcalTask_2_visits_simple_astrometry_no_photometry_match_cut_10(self):
334 """A larger matching radius will result in more associated fittedStars,
335 and a somewhat worse final fit because stars that should not have been
336 associated, were.
337 """
338 self.config = lsst.jointcal.jointcal.JointcalConfig()
339 self.config.astrometryModel = "simple"
340 self.config.matchCut = 10.0 # TODO: once DM-6885 is fixed, we need to put `*lsst.geom.arcseconds`
341 self.config.doPhotometry = False
342 self.jointcalStatistics.do_photometry = False
344 # Slightly larger absolute astrometry RMS because of the larger matching radius
345 dist_rms_absolute = 23e-3*u.arcsecond
346 metrics = {'astrometry_collected_refStars': 568,
347 'astrometry_prepared_refStars': 211,
348 'astrometry_matched_fittedStars': 2070,
349 'astrometry_prepared_fittedStars': 1042,
350 'astrometry_prepared_ccdImages': 6,
351 'astrometry_final_chi2': 819.608,
352 'astrometry_final_ndof': 1872,
353 }
354 pa1 = None
355 self._testJointcalTask(2, self.dist_rms_relative, dist_rms_absolute, pa1, metrics=metrics)
357 def test_jointcalTask_3_visits_simple_astrometry_no_photometry(self):
358 """3 visit, default config to compare with min_measurements_3 test."""
359 self.config = lsst.jointcal.jointcal.JointcalConfig()
360 self.config.astrometryModel = "simple"
361 self.config.minMeasurements = 2
362 self.config.doPhotometry = False
363 self.jointcalStatistics.do_photometry = False
365 # More visits and slightly worse relative and absolute rms.
366 dist_rms_relative = 8.3e-3*u.arcsecond
367 dist_rms_absolute = 24e-3*u.arcsecond
368 metrics = {'astrometry_collected_refStars': 1038,
369 'astrometry_prepared_refStars': 209,
370 'astrometry_matched_fittedStars': 3199,
371 'astrometry_prepared_fittedStars': 1282,
372 'astrometry_prepared_ccdImages': 9,
373 'astrometry_final_chi2': 1221.63,
374 'astrometry_final_ndof': 2892,
375 }
376 pa1 = None
377 self._testJointcalTask(3, dist_rms_relative, dist_rms_absolute, pa1, metrics=metrics)
379 def test_jointcalTask_3_visits_simple_astrometry_no_photometry_min_measurements_3(self):
380 """Raising min_measurements to 3 will reduce the number of selected
381 fitted stars (and thus the chisq and Ndof), but should not change the
382 other values."""
383 self.config = lsst.jointcal.jointcal.JointcalConfig()
384 self.config.minMeasurements = 3
385 self.config.astrometryModel = "simple"
386 self.config.doPhotometry = False
387 self.jointcalStatistics.do_photometry = False
389 # More visits and slightly worse relative and absolute rms.
390 dist_rms_relative = 11e-3*u.arcsecond
391 dist_rms_absolute = 24e-3*u.arcsecond
392 metrics = {'astrometry_collected_refStars': 1038,
393 'astrometry_prepared_refStars': 209,
394 'astrometry_matched_fittedStars': 3199,
395 'astrometry_prepared_fittedStars': 432,
396 'astrometry_prepared_ccdImages': 9,
397 'astrometry_final_chi2': 567.433,
398 'astrometry_final_ndof': 1286,
399 }
400 pa1 = None
401 self._testJointcalTask(3, dist_rms_relative, dist_rms_absolute, pa1, metrics=metrics)
404class MemoryTester(lsst.utils.tests.MemoryTestCase):
405 pass
408if __name__ == "__main__": 408 ↛ 409line 408 didn't jump to line 409, because the condition on line 408 was never true
409 lsst.utils.tests.init()
410 unittest.main()