Coverage for tests / test_fgcmcal_hsc.py: 22%
128 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-15 00:20 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-15 00:20 +0000
1# See COPYRIGHT file at the top of the source tree.
2#
3# This file is part of fgcmcal.
4#
5# Developed for the LSST Data Management System.
6# This product includes software developed by the LSST Project
7# (https://www.lsst.org).
8# See the COPYRIGHT file at the top-level directory of this distribution
9# for details of code ownership.
10#
11# This program is free software: you can redistribute it and/or modify
12# it under the terms of the GNU General Public License as published by
13# the Free Software Foundation, either version 3 of the License, or
14# (at your option) any later version.
15#
16# This program is distributed in the hope that it will be useful,
17# but WITHOUT ANY WARRANTY; without even the implied warranty of
18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19# GNU General Public License for more details.
20#
21# You should have received a copy of the GNU General Public License
22# along with this program. If not, see <https://www.gnu.org/licenses/>.
23"""Test the fgcmcal code with testdata_jointcal/hsc.
25Run test suite on fgcmcal using Gen3 HSC data from testdata_jointcal.
26"""
27import unittest
28import os
29import tempfile
30import numpy as np
32# Need to import pyproj to prevent file handle leakage since importing
33# pyproj automatically opens proj.db and never closes it. We can not wait
34# for some dependent code to import it whilst the test is running since then
35# the leak checker will think it is a leak.
36import pyproj # noqa: F401
38# Ensure that matplotlib doesn't try to open a display during testing.
39import matplotlib
40matplotlib.use("Agg")
42import lsst.utils # noqa: E402
43import lsst.pipe.tasks # noqa: E402
44import lsst.daf.butler.cli.cliLog # noqa: E402
46import fgcmcalTestBase # noqa: E402
49ROOT = os.path.abspath(os.path.dirname(__file__))
51I0STD = [0.08294534, 0.07877351, 0.06464688]
52I10STD = [-0.000091981, -0.00061516, -0.00063434]
53I0RECON = [0.07322179342588758, 0.0689530429, 0.05600673]
54I10RECON = [-4.490243571049125, -7.01786443508, 3.62738180611]
57class FgcmcalTestHSC(fgcmcalTestBase.FgcmcalTestBase, lsst.utils.tests.TestCase):
58 @classmethod
59 def setUpClass(cls):
60 try:
61 cls.dataDir = lsst.utils.getPackageDir('testdata_jointcal')
62 except LookupError:
63 raise unittest.SkipTest("testdata_jointcal not setup")
64 try:
65 lsst.utils.getPackageDir('obs_subaru')
66 except LookupError:
67 raise unittest.SkipTest("obs_subaru not setup")
69 lsst.daf.butler.cli.cliLog.CliLog.initLog(longlog=False)
71 cls.testDir = tempfile.mkdtemp(dir=ROOT, prefix="TestFgcm-")
73 cls._importRepository('lsst.obs.subaru.HyperSuprimeCam',
74 os.path.join(cls.dataDir, 'hsc/repo'),
75 os.path.join(cls.dataDir, 'hsc', 'exports.yaml'))
77 def test_fgcmcalPipelineBuildFromTable(self):
78 """Test running the full pipeline, using older association code.
80 This test uses the FgcmBuildStarsFromTableTask instead of the new
81 FgcmBuildFromIsolatedStarsTask.
82 """
83 # Set numpy seed for stability
84 np.random.seed(seed=1000)
86 instName = 'HSC'
87 testName = 'testfgcmcalpipe'
89 nBand = 3
90 i0Std = np.array(I0STD)
91 i10Std = np.array(I10STD)
92 i0Recon = np.array(I0RECON)
93 i10Recon = np.array(I10RECON)
95 self._testFgcmMakeLut(instName, testName,
96 nBand, i0Std, i0Recon, i10Std, i10Recon)
98 visits = [34648, 34690, 34714, 34674, 34670, 36140, 35892, 36192, 36260, 36236]
100 nStar = 305
101 nObs = 3789
103 self._testFgcmBuildStarsTable(instName, testName,
104 "physical_filter IN ('HSC-G', 'HSC-R', 'HSC-I')",
105 visits, nStar, nObs)
107 nZp = 1120
108 nGoodZp = 123
109 nOkZp = 123
110 nBadZp = 997
111 nStdStars = 237
112 nPlots = 66
114 # We need an extra config file to turn off parquet format.
115 extraConfigFile = os.path.join(self.testDir, "turn_off_parquet.py")
116 with open(extraConfigFile, "w") as f:
117 f.write("config.useParquetCatalogFormat = False\n")
119 self._testFgcmFitCycle(instName, testName,
120 0, nZp, nGoodZp, nOkZp, nBadZp, nStdStars, nPlots, skipChecks=True,
121 extraConfig=extraConfigFile)
122 self._testFgcmFitCycle(instName, testName,
123 1, nZp, nGoodZp, nOkZp, nBadZp, nStdStars, nPlots, skipChecks=True,
124 extraConfig=extraConfigFile)
126 # We need to create an extra config file to turn on "sub-ccd gray" for testing.
127 # We also want to exercise the code path setting useExposureReferenceOffset = False.
128 extraConfigFile = os.path.join(self.testDir, "cycle03_patch_config.py")
129 with open(extraConfigFile, "w") as f:
130 f.write("config.useParquetCatalogFormat = False\n")
131 f.write("config.isFinalCycle = True\n")
132 f.write("config.ccdGraySubCcdDict = {'g': True, 'r': True, 'i': True}\n")
133 f.write("config.useExposureReferenceOffset = False")
135 self._testFgcmFitCycle(instName, testName,
136 2, nZp, nGoodZp, nOkZp, nBadZp, nStdStars, nPlots,
137 extraConfig=extraConfigFile)
139 def test_fgcmcalPipeline(self):
140 """Test running the full pipeline, using new isolated star association code.
142 This test uses the FgcmBuildFromIsolatedStarsTask instead of the old
143 FgcmBuildStarsFromTableTask.
144 """
145 # Set numpy seed for stability
146 np.random.seed(seed=1000)
148 instName = 'HSC'
149 testName = 'testfgcmcalpipe'
151 nBand = 3
152 i0Std = np.array(I0STD)
153 i10Std = np.array(I10STD)
154 i0Recon = np.array(I0RECON)
155 i10Recon = np.array(I10RECON)
157 self._testFgcmMakeLut(instName, testName,
158 nBand, i0Std, i0Recon, i10Std, i10Recon)
160 visits = [34648, 34690, 34714, 34674, 34670, 36140, 35892, 36192, 36260, 36236]
162 nStar = 292
163 nObs = 1790
165 self._testFgcmBuildFromIsolatedStars(
166 instName,
167 testName,
168 "physical_filter IN ('HSC-G', 'HSC-R', 'HSC-I')",
169 visits,
170 nStar,
171 nObs,
172 )
174 nZp = 1120
175 nGoodZp = 123
176 nOkZp = 123
177 nBadZp = 997
178 nStdStars = 222
179 nPlots = 66
181 self._testFgcmFitCycle(instName, testName,
182 0, nZp, nGoodZp, nOkZp, nBadZp, nStdStars, nPlots, skipChecks=True)
183 self._testFgcmFitCycle(instName, testName,
184 1, nZp, nGoodZp, nOkZp, nBadZp, nStdStars, nPlots, skipChecks=True)
186 # We need to create an extra config file to turn on "sub-ccd gray" for testing.
187 # We also want to exercise the code path setting useExposureReferenceOffset = False.
188 extraConfigFile = os.path.join(self.testDir, "cycle03_patch_config.py")
189 with open(extraConfigFile, "w") as f:
190 f.write("config.isFinalCycle = True\n")
191 f.write("config.ccdGraySubCcdDict = {'g': True, 'r': True, 'i': True}\n")
192 f.write("config.useExposureReferenceOffset = False")
194 self._testFgcmFitCycle(instName, testName,
195 2, nZp, nGoodZp, nOkZp, nBadZp, nStdStars, nPlots,
196 extraConfig=extraConfigFile)
198 zpOffsets = np.array([-0.000842530163936317,
199 0.0047900681383907795])
201 self._testFgcmOutputProducts(instName, testName,
202 zpOffsets, 36236, 87, 'i', 1, 'hsc_rings_v1')
204 # Test a single detector illumination correction.
205 self._testFgcmOutputIlluminationCorrection(instName, testName, 51)
207 def test_fgcmcalMultipleFitPipeline(self):
208 # Set numpy seed for stability
209 np.random.seed(seed=1000)
211 instName = 'HSC'
212 testName = 'testfgcmcalmultiple'
214 nBand = 3
215 i0Std = np.array(I0STD)
216 i10Std = np.array(I10STD)
217 i0Recon = np.array(I0RECON)
218 i10Recon = np.array(I10RECON)
220 self._testFgcmMakeLut(instName, testName,
221 nBand, i0Std, i0Recon, i10Std, i10Recon)
223 visits = [34648, 34690, 34714, 34674, 34670, 36140, 35892, 36192, 36260, 36236]
225 # These are slightly different from above due to the configuration change
226 # mid-way in the separate fits.
227 zpOffsets = np.array([0.0011443052208051085,
228 0.0015734810149297118])
230 self._testFgcmMultiFit(instName, testName,
231 "physical_filter IN ('HSC-G', 'HSC-R', 'HSC-I') and skymap='hsc_rings_v1'",
232 visits, zpOffsets, 125, 64)
234 def test_fgcmcalTractPipeline(self):
235 # Set numpy seed for stability
236 np.random.seed(seed=1000)
238 instName = 'HSC'
239 testName = 'testfgcmcaltract'
241 nBand = 3
242 i0Std = np.array(I0STD)
243 i10Std = np.array(I10STD)
244 i0Recon = np.array(I0RECON)
245 i10Recon = np.array(I10RECON)
247 self._testFgcmMakeLut(instName, testName,
248 nBand, i0Std, i0Recon, i10Std, i10Recon)
250 rawRepeatability = np.array([0.0,
251 0.01201036876093324,
252 0.003979326480379284])
253 filterNCalibMap = {'HSC-R': 48,
254 'HSC-I': 75}
256 visits = [34648, 34690, 34714, 34674, 34670, 36140, 35892, 36192, 36260, 36236]
257 tract = 9697
259 self._testFgcmCalibrateTract(instName, testName,
260 visits, tract, 'hsc_rings_v1',
261 rawRepeatability, filterNCalibMap)
264class TestMemory(lsst.utils.tests.MemoryTestCase):
265 pass
268def setup_module(module):
269 lsst.utils.tests.init()
272if __name__ == "__main__": 272 ↛ 273line 272 didn't jump to line 273 because the condition on line 272 was never true
273 lsst.utils.tests.init()
274 unittest.main()