Coverage for tests / test_metrics.py: 21%

88 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-05-01 08:55 +0000

1# This file is part of analysis_tools. 

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 <http://www.gnu.org/licenses/>. 

21from __future__ import annotations 

22 

23from unittest import TestCase, main 

24 

25import numpy as np 

26 

27import lsst.utils.tests 

28from lsst.analysis.tools.actions.vector import ConstantValue, MultiplyVector 

29from lsst.analysis.tools.atools import ( 

30 MagnitudeTool, 

31 MatchedRefCoaddCompurityTool, 

32 MatchedRefCoaddDiffColorTool, 

33 MatchedRefCoaddDiffDistanceTool, 

34 MatchedRefCoaddDiffMagTool, 

35 MatchedRefCoaddDiffPositionTool, 

36 MatchedRefCoaddDiffTool, 

37) 

38 

39 

40class MatchedRefCoaddDiffToolMinimal(MatchedRefCoaddDiffTool): 

41 """A bare-minimum implementation of a diff tool.""" 

42 

43 def get_key_flux_y(self) -> str: 

44 return self.mag_x 

45 

46 def finalize(self): 

47 if not hasattr(self.process.buildActions, "diff"): 

48 super().finalize() 

49 self._set_actions() 

50 

51 self.process.buildActions.diff = MultiplyVector( 

52 actionA=getattr(self.process.buildActions, f"mag_{self.mag_x}"), 

53 actionB=ConstantValue(value=0.001), 

54 ) 

55 

56 

57class TestDiffMatched(TestCase): 

58 def setUp(self) -> None: 

59 super().setUp() 

60 self.band_default = "analysisTools" 

61 

62 def _testMatchedRefCoaddMetricDerived( 

63 self, 

64 type_metric: type[MatchedRefCoaddCompurityTool | MatchedRefCoaddDiffColorTool], 

65 suffixes_configure: list[str] | None = None, 

66 **kwargs, 

67 ): 

68 if suffixes_configure is None: 

69 suffixes_configure = [""] 

70 plotInfo = {key: "" for key in ("plotName", "run", "tableName")} 

71 plotInfo["bands"] = [] 

72 

73 tester = type_metric(**kwargs) 

74 has_compute_chi = hasattr(tester, "compute_chi") 

75 has_configureMetrics = hasattr(tester, "configureMetrics") 

76 

77 for compute_chi in (False, True) if has_compute_chi else (None,): 

78 if has_compute_chi: 

79 tester.compute_chi = compute_chi 

80 # tester.getInputSchema won't work properly before finalizing 

81 tester.finalize() 

82 keys = list({k[0]: None for k in tester.getInputSchema()}) 

83 self.assertGreater(len(keys), 0) 

84 if has_configureMetrics: 

85 for suffix in suffixes_configure: 

86 self.assertGreater(len(list(tester.configureMetrics(attr_suffix=suffix))), 0) 

87 data = {} 

88 n_data = 10 

89 for key in keys: 

90 if key.endswith("is_pointsource"): 

91 values = (np.arange(0, n_data) % 2) == 1 

92 else: 

93 values = np.linspace(0.1, 15.0, n_data) 

94 data[key.format(band=self.band_default)] = values 

95 

96 output = tester(data, skymap=None, plotInfo=plotInfo) 

97 self.assertGreater(len(output), 0) 

98 if has_compute_chi: 

99 tester = type_metric(**kwargs) 

100 

101 def testMatchedRefCoaddMetric(self): 

102 kwargs = {key: "" for key in ("unit", "name_prefix")} 

103 # The metric can now be set up with default kwargs 

104 # Pass one at a time to test 

105 for kwarg in kwargs: 

106 kwargs_init = {kwarg: ""} 

107 tester = MatchedRefCoaddDiffToolMinimal(**kwargs_init) 

108 tester.validate() 

109 with self.assertRaises(KeyError): 

110 tester.configureMetrics() 

111 tester.finalize() 

112 tester.configureMetrics() 

113 # Failing to find any of the required keys 

114 with self.assertRaises(KeyError): 

115 tester({}) 

116 tester = MatchedRefCoaddDiffToolMinimal(**kwargs) 

117 tester.validate() 

118 with self.assertRaises(KeyError): 

119 tester.configureMetrics() 

120 tester.finalize() 

121 inputs = list(tester.getInputSchema()) 

122 n_input = len(inputs) 

123 self.assertGreater(n_input, 0) 

124 self.assertGreater(len(list(tester.configureMetrics())), 0) 

125 

126 self.assertEqual(len(inputs), n_input) 

127 data = {key.format(band="analysisTools"): np.array([0.0]) for key, *_ in inputs} 

128 # There's no metric or plot so it just returns an empty dict 

129 self.assertEqual(len(tester(data)), 0) 

130 

131 def testMatchedRefCoaddCompurity(self): 

132 self._testMatchedRefCoaddMetricDerived( 

133 MatchedRefCoaddCompurityTool, 

134 ) 

135 

136 def testMatchedRefCoaddDiffColor(self): 

137 self._testMatchedRefCoaddMetricDerived( 

138 MatchedRefCoaddDiffColorTool, 

139 suffixes_configure=["_0", "_1"], 

140 fluxes={"cmodel": MagnitudeTool.fluxes_default.cmodel_err}, 

141 mag_y1="cmodel_err", 

142 mag_y2="cmodel_err", 

143 bands={ 

144 "g": "i", 

145 "u": "z", 

146 }, 

147 name_prefix="", 

148 unit="", 

149 ) 

150 

151 def testMatchedRefCoaddDiffDistance(self): 

152 self._testMatchedRefCoaddMetricDerived( 

153 MatchedRefCoaddDiffDistanceTool, 

154 ) 

155 

156 def testMatchedRefCoaddDiffMag(self): 

157 self._testMatchedRefCoaddMetricDerived( 

158 MatchedRefCoaddDiffMagTool, 

159 fluxes={"cmodel": MagnitudeTool.fluxes_default.cmodel_err}, 

160 mag_y="cmodel", 

161 name_prefix="", 

162 unit="", 

163 ) 

164 

165 def testMatchedRefCoaddDiffPosition(self): 

166 for variable in ("x", "y"): 

167 self._testMatchedRefCoaddMetricDerived( 

168 MatchedRefCoaddDiffPositionTool, 

169 coord_meas=variable, 

170 coord_ref=variable, 

171 ) 

172 

173 

174class MyMemoryTestCase(lsst.utils.tests.MemoryTestCase): 

175 pass 

176 

177 

178def setup_module(module): 

179 lsst.utils.tests.init() 

180 

181 

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

183 lsst.utils.tests.init() 

184 main()