Coverage for tests/test_job.py: 11%
88 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 22:32 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 22:32 -0800
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/>.
22import astropy.units as u
23import unittest
25from lsst.verify import (Job, Metric, ThresholdSpecification, Measurement,
26 MeasurementSet, MetricSet, SpecificationSet, Datum,
27 Blob)
30class JobTestCase(unittest.TestCase):
31 """Test Job classes."""
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])
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])
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])
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])
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])
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])
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)
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)
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)
90 job.meta['job-level-key'] = 'yes'
91 self.assertEqual(job.meta['job-level-key'], 'yes')
92 self.assertIn('job-level-key', job.meta)
94 self.assertEqual(len(job.meta), 2)
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)
110 self.assertEqual(
111 set(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, value in job.meta.items():
120 keys.add(key)
121 self.assertEqual(keys, set(['job-level-key', 'test.PhotRms.note']))
123 # Add a new measurement
124 m = Measurement('test.PhotMedian', 28.5 * u.mag,
125 notes={'aperture_corr': True})
126 job.measurements.insert(m)
127 self.assertIn('test.PhotMedian', job.measurements)
128 self.assertEqual(job.meta['test.PhotMedian.aperture_corr'], True)
130 # Test serialization
131 json_doc = job.json
133 self.assertIn('measurements', json_doc)
134 self.assertEqual(len(json_doc['measurements']), len(job.measurements))
136 self.assertIn('blobs', json_doc)
138 self.assertIn('metrics', json_doc)
139 self.assertEqual(len(json_doc['metrics']), len(job.metrics))
141 self.assertIn('specs', json_doc)
142 self.assertEqual(len(json_doc['specs']), len(job.specs))
144 self.assertIn('meta', json_doc)
145 self.assertEqual(len(json_doc['meta']), len(job.meta))
147 new_job = Job.deserialize(**json_doc)
148 self.assertEqual(job, new_job)
150 # check job-to-measurement metadata deserialization
151 self.assertEqual(
152 new_job.measurements['test.PhotRms'].notes['note'],
153 'value')
154 self.assertEqual(
155 new_job.meta['test.PhotRms.note'],
156 'value')
157 self.assertEqual(
158 new_job.meta['job-level-key'],
159 'yes')
161 def test_job_iadd(self):
162 job_1 = Job(metrics=self.metric_set, specs=self.spec_set,
163 measurements=self.measurement_set)
164 job_2 = Job(metrics=self.metric_set_2, specs=self.spec_set_2,
165 measurements=self.measurement_set_2)
167 job_1 += job_2
169 self.assertIn(self.metric_photrms.name, job_1.metrics)
170 self.assertIn(self.metric_test_2.name, job_1.metrics)
171 self.assertIn('test.PhotRms.design', job_1.specs)
172 self.assertIn('test2.SourceCount.design', job_1.specs)
173 self.assertIn('test.PhotRms', job_1.measurements)
174 self.assertIn('test2.SourceCount', job_1.measurements)
175 self.assertIn('test.PhotRms', job_1.measurements['test.PhotRms'].blobs)
176 self.assertIn(
177 'test2_blob',
178 job_1.measurements['test2.SourceCount'].blobs)
180 def test_metric_package_reload(self):
181 # Create a Job without Metric definitions
182 meas = Measurement('validate_drp.PA1', 15 * u.mmag)
183 measurement_set = MeasurementSet([meas])
185 job = Job(measurements=measurement_set)
186 job.reload_metrics_package('verify_metrics')
188 # Should now have metrics and specs
189 self.assertTrue(len(job.specs) > 0)
190 self.assertTrue(len(job.metrics) > 0)
191 self.assertIsInstance(
192 job.measurements['validate_drp.PA1'].metric,
194 Metric)
197if __name__ == "__main__": 197 ↛ 198line 197 didn't jump to line 198, because the condition on line 197 was never true
198 unittest.main()