Coverage for tests/test_subaru.py: 100%

42 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-10-07 22:41 +0000

1# This file is part of astro_metadata_translator. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the LICENSE file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

9# Use of this source code is governed by a 3-clause BSD-style 

10# license that can be found in the LICENSE file. 

11 

12import os.path 

13import unittest 

14 

15import astropy.time 

16import astropy.units as u 

17 

18from astro_metadata_translator import merge_headers 

19from astro_metadata_translator.tests import MetadataAssertHelper, read_test_file 

20from astro_metadata_translator.translators import HscTranslator 

21 

22TESTDIR = os.path.abspath(os.path.dirname(__file__)) 

23 

24 

25class HscTestCase(unittest.TestCase, MetadataAssertHelper): 

26 """Test HSC translations.""" 

27 

28 datadir = os.path.join(TESTDIR, "data") 

29 

30 def test_hsc_translator(self) -> None: 

31 test_data = ( 

32 ( 

33 "fitsheader-hsc.yaml", 

34 dict( 

35 telescope="Subaru", 

36 instrument="HSC", 

37 boresight_rotation_coord="sky", 

38 dark_time=30.0 * u.s, 

39 detector_exposure_id=180804850, 

40 detector_name="12", 

41 detector_unique_name="1_12", 

42 detector_num=50, 

43 detector_serial="120", 

44 exposure_id=904024, 

45 exposure_group="904024", 

46 exposure_time=30.0 * u.s, 

47 exposure_time_requested=30.0 * u.s, 

48 focus_z=3.7 * u.mm, 

49 group_counter_end=904024, 

50 group_counter_start=904024, 

51 has_simulated_content=False, 

52 object="STRIPE82L", 

53 observation_counter=904024, 

54 observation_id="HSCA90402400", 

55 observation_type="science", 

56 observation_reason="science", 

57 observing_day=20131102, 

58 observing_day_offset=astropy.time.TimeDelta(0, format="sec", scale="tai"), 

59 physical_filter="HSC-I", 

60 pressure=621.7 * u.hPa, 

61 relative_humidity=33.1, 

62 science_program="o13015", 

63 temperature=272.35 * u.K, 

64 visit_id=904024, 

65 ), 

66 ), 

67 ( 

68 "fitsheader-hsc-HSCA04090107.yaml", 

69 dict( 

70 telescope="Subaru", 

71 instrument="HSC", 

72 boresight_rotation_coord="sky", 

73 dark_time=150.0 * u.s, 

74 detector_exposure_id=8180037, 

75 detector_name="07", 

76 detector_unique_name="1_07", 

77 detector_num=37, 

78 detector_serial="061", 

79 exposure_id=40900, 

80 exposure_group="40900", 

81 exposure_time=150.0 * u.s, 

82 exposure_time_requested=150.0 * u.s, 

83 focus_z=3.83 * u.mm, 

84 group_counter_end=40900, 

85 group_counter_start=40900, 

86 has_simulated_content=False, 

87 object="SSP-Wide", 

88 observation_counter=40900, 

89 observation_id="HSCA04090000", 

90 observation_type="science", 

91 observation_reason="science", 

92 observing_day=20151010, 

93 physical_filter="HSC-R", 

94 pressure=625.4 * u.hPa, 

95 relative_humidity=8.6, 

96 science_program="o15426", 

97 temperature=278.35 * u.K, 

98 visit_id=40900, 

99 ), 

100 ), 

101 ) 

102 for file, expected in test_data: 

103 with self.subTest(f"Testing {file}"): 

104 self.assertObservationInfoFromYaml(file, dir=self.datadir, **expected) 

105 

106 def test_suprimecam_translator(self) -> None: 

107 # In this case the airmass is average during observation 

108 # but it looks like ALTITUDE is from a different time so loosen amdelta 

109 test_data = ( 

110 ( 

111 "fitsheader-suprimecam-CORR40535770.yaml", 

112 dict( 

113 telescope="Subaru", 

114 instrument="SuprimeCam", 

115 boresight_rotation_coord="unknown", 

116 dark_time=200.0 * u.s, 

117 detector_exposure_id=535770, 

118 detector_name="nausicaa", 

119 detector_unique_name="nausicaa", 

120 detector_num=0, 

121 detector_serial="w67c1", 

122 exposure_id=53577, 

123 exposure_group="53577", 

124 exposure_time=200.0 * u.s, 

125 exposure_time_requested=200.0 * u.s, 

126 group_counter_end=53577, 

127 group_counter_start=53577, 

128 has_simulated_content=False, 

129 object="Ecliptic Deep Field", 

130 observation_counter=53577, 

131 observation_id="SUPE00535770", 

132 observation_type="science", 

133 observation_reason="science", 

134 observing_day=20070423, 

135 physical_filter="W-S-R+", 

136 pressure=621.5 * u.hPa, 

137 relative_humidity=4.9, 

138 science_program="o07222", 

139 temperature=273.15 * u.K, 

140 visit_id=53577, 

141 wcs_params=dict(amdelta=0.015), 

142 ), 

143 ), 

144 ) 

145 for file, expected in test_data: 

146 with self.subTest(f"Testing {file}"): 

147 self.assertObservationInfoFromYaml(file, dir=self.datadir, **expected) 

148 

149 def test_merging_hsc(self) -> None: 

150 files = ("fitsheader-hsc-HSCA04090107.yaml", "fitsheader-hsc.yaml") 

151 headers = [read_test_file(f, dir=self.datadir) for f in files] 

152 merged = merge_headers(headers, mode="first", sort=False) 

153 

154 # The MJD-STR should come from the first file 

155 self.assertAlmostEqual(merged["MJD-STR"], 57305.34729859) 

156 

157 # If we sort then MJD-STR should come from the oldest file 

158 merged = merge_headers(headers, mode="first", sort=True) 

159 self.assertAlmostEqual(merged["MJD-STR"], 56598.26106374757) 

160 

161 # Drop headers that differ, MJD-STR should not appear 

162 merged = merge_headers(headers, mode="drop", sort=True) 

163 self.assertNotIn("MJD-STR", merged) 

164 

165 # Drop but retain first MJD-STR without sorting 

166 merged = merge_headers(headers, mode="drop", sort=False, first=["MJD-STR", "UT-STR"]) 

167 self.assertAlmostEqual(merged["MJD-STR"], 57305.34729859) 

168 self.assertEqual(merged["UT-STR"], "08:20:06.598") 

169 

170 # Drop but retain first MJD-STR 

171 merged = merge_headers(headers, mode="drop", sort=True, first=["MJD-STR", "UT-STR"]) 

172 self.assertAlmostEqual(merged["MJD-STR"], 56598.26106374757) 

173 self.assertEqual(merged["UT-STR"], "06:15:55.908") 

174 

175 def test_hsc_datetime_begin_failure_repeats(self) -> None: 

176 """Test that successive failures in to_datetime_begin() don't get 

177 hidden because caching is used on both a base translator and a derived 

178 one. 

179 """ 

180 # A header with no usable date must raise on every call to a 

181 # translator that falls back on the decorated parent method, 

182 # not just the first one. 

183 header = read_test_file("fitsheader-hsc.yaml", dir=self.datadir) 

184 del header["DATE-OBS"] 

185 translator = HscTranslator(header) 

186 for _ in range(3): 

187 with self.assertRaises(KeyError): 

188 translator.to_datetime_begin() 

189 

190 

191if __name__ == "__main__": 

192 unittest.main()