Coverage for tests/test_job.py: 11%

89 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-04-12 02:15 -0700

1# This file is part of verify. 

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/>. 

21 

22import astropy.units as u 

23import unittest 

24 

25from lsst.verify import (Job, Metric, ThresholdSpecification, Measurement, 

26 MeasurementSet, MetricSet, SpecificationSet, Datum, 

27 Blob) 

28 

29 

30class JobTestCase(unittest.TestCase): 

31 """Test Job classes.""" 

32 

33 def setUp(self): 

34 # Mock metrics 

35 self.metric_photrms = Metric('test.PhotRms', 'Photometric RMS', 'mmag') 

36 self.metric_photmed = Metric('test.PhotMedian', 

37 'Median magntidue', 'mag') 

38 self.metric_set = MetricSet([self.metric_photrms, self.metric_photmed]) 

39 

40 # Mock specifications 

41 self.spec_photrms_design = ThresholdSpecification( 

42 'test.PhotRms.design', 20. * u.mmag, '<' 

43 ) 

44 self.spec_set = SpecificationSet([self.spec_photrms_design]) 

45 

46 # Mock measurements 

47 self.meas_photrms = Measurement( 

48 self.metric_photrms, 15 * u.mmag, 

49 notes={'note': 'value'}) 

50 self.meas_photrms.extras['n_stars'] = Datum( 

51 250, 

52 label='N stars', 

53 description='Number of stars included in RMS estimate') 

54 self.measurement_set = MeasurementSet([self.meas_photrms]) 

55 

56 # Metrics for Job 2 

57 self.metric_test_2 = Metric('test2.SourceCount', 'Source Count', '') 

58 self.blob_test_2 = Blob( 

59 'test2_blob', 

60 sn=Datum(50 * u.dimensionless_unscaled, label='S/N')) 

61 self.metric_set_2 = MetricSet([self.metric_test_2]) 

62 

63 # Specifications for Job 2 

64 self.spec_test_2 = ThresholdSpecification( 

65 'test2.SourceCount.design', 100 * u.dimensionless_unscaled, '>=') 

66 self.spec_set_2 = SpecificationSet([self.spec_test_2]) 

67 

68 # Measurements for Job 2 

69 self.meas_test_2_SourceCount = Measurement( 

70 self.metric_test_2, 200 * u.dimensionless_unscaled) 

71 self.meas_test_2_SourceCount.link_blob(self.blob_test_2) 

72 self.measurement_set_2 = MeasurementSet([self.meas_test_2_SourceCount]) 

73 

74 def test_job(self): 

75 """Create a Job from object sets.""" 

76 job = Job(metrics=self.metric_set, specs=self.spec_set, 

77 measurements=self.measurement_set) 

78 

79 # Test object access via properties 

80 self.assertIn('test.PhotRms.design', job.specs) 

81 self.assertIn('test.PhotRms', job.metrics) 

82 self.assertIn('test.PhotRms', job.measurements) 

83 

84 # Test metadata access 

85 self.assertIn('test.PhotRms.note', job.meta) 

86 self.assertEqual(job.meta['test.PhotRms.note'], 'value') 

87 # measurement metadata is always prefixed 

88 self.assertNotIn('note', job.meta) 

89 

90 job.meta['job-level-key'] = 'yes' 

91 self.assertEqual(job.meta['job-level-key'], 'yes') 

92 self.assertIn('job-level-key', job.meta) 

93 

94 self.assertEqual(len(job.meta), 2) 

95 

96 job.meta.update({'test.PhotRms.note2': 'foo', 

97 'dataset': 'ci_hsc'}) 

98 # note2 should be in measurement notes 

99 self.assertEqual( 

100 job.measurements['test.PhotRms'].notes['note2'], 

101 'foo') 

102 self.assertEqual(job.meta['dataset'], 'ci_hsc') 

103 # Delete measurement and job-level metadata 

104 del job.meta['test.PhotRms.note2'] 

105 self.assertNotIn('test.PhotRms.note2', job.meta) 

106 self.assertNotIn('note2', job.measurements['test.PhotRms'].notes) 

107 del job.meta['dataset'] 

108 self.assertNotIn('dataset', job.meta) 

109 

110 self.assertEqual( 

111 job.meta.keys(), 

112 set(['job-level-key', 'test.PhotRms.note']) 

113 ) 

114 self.assertEqual( 

115 set([key for key in job.meta]), 

116 set(['job-level-key', 'test.PhotRms.note']) 

117 ) 

118 keys = set() 

119 for key, _ in job.meta.items(): 

120 keys.add(key) 

121 self.assertEqual(keys, set(['job-level-key', 'test.PhotRms.note'])) 

122 

123 self.assertEqual(len(job.meta.keys()), len(job.meta.values())) 

124 

125 # Add a new measurement 

126 m = Measurement('test.PhotMedian', 28.5 * u.mag, 

127 notes={'aperture_corr': True}) 

128 job.measurements.insert(m) 

129 self.assertIn('test.PhotMedian', job.measurements) 

130 self.assertEqual(job.meta['test.PhotMedian.aperture_corr'], True) 

131 

132 # Test serialization 

133 json_doc = job.json 

134 

135 self.assertIn('measurements', json_doc) 

136 self.assertEqual(len(json_doc['measurements']), len(job.measurements)) 

137 

138 self.assertIn('blobs', json_doc) 

139 

140 self.assertIn('metrics', json_doc) 

141 self.assertEqual(len(json_doc['metrics']), len(job.metrics)) 

142 

143 self.assertIn('specs', json_doc) 

144 self.assertEqual(len(json_doc['specs']), len(job.specs)) 

145 

146 self.assertIn('meta', json_doc) 

147 self.assertEqual(len(json_doc['meta']), len(job.meta)) 

148 

149 new_job = Job.deserialize(**json_doc) 

150 self.assertEqual(job, new_job) 

151 

152 # check job-to-measurement metadata deserialization 

153 self.assertEqual( 

154 new_job.measurements['test.PhotRms'].notes['note'], 

155 'value') 

156 self.assertEqual( 

157 new_job.meta['test.PhotRms.note'], 

158 'value') 

159 self.assertEqual( 

160 new_job.meta['job-level-key'], 

161 'yes') 

162 

163 def test_job_iadd(self): 

164 job_1 = Job(metrics=self.metric_set, specs=self.spec_set, 

165 measurements=self.measurement_set) 

166 job_2 = Job(metrics=self.metric_set_2, specs=self.spec_set_2, 

167 measurements=self.measurement_set_2) 

168 

169 job_1 += job_2 

170 

171 self.assertIn(self.metric_photrms.name, job_1.metrics) 

172 self.assertIn(self.metric_test_2.name, job_1.metrics) 

173 self.assertIn('test.PhotRms.design', job_1.specs) 

174 self.assertIn('test2.SourceCount.design', job_1.specs) 

175 self.assertIn('test.PhotRms', job_1.measurements) 

176 self.assertIn('test2.SourceCount', job_1.measurements) 

177 self.assertIn('test.PhotRms', job_1.measurements['test.PhotRms'].blobs) 

178 self.assertIn( 

179 'test2_blob', 

180 job_1.measurements['test2.SourceCount'].blobs) 

181 

182 def test_metric_package_reload(self): 

183 # Create a Job without Metric definitions 

184 meas = Measurement('validate_drp.PA1', 15 * u.mmag) 

185 measurement_set = MeasurementSet([meas]) 

186 

187 job = Job(measurements=measurement_set) 

188 job.reload_metrics_package('verify_metrics') 

189 

190 # Should now have metrics and specs 

191 self.assertTrue(len(job.specs) > 0) 

192 self.assertTrue(len(job.metrics) > 0) 

193 self.assertIsInstance( 

194 job.measurements['validate_drp.PA1'].metric, 

195 

196 Metric) 

197 

198 

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

200 unittest.main()