Coverage for tests/test_job.py: 11%
89 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-24 10:09 +0000
« prev ^ index » next coverage.py v7.5.0, created at 2024-04-24 10:09 +0000
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 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']))
123 self.assertEqual(len(job.meta.keys()), len(job.meta.values()))
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)
132 # Test serialization
133 json_doc = job.json
135 self.assertIn('measurements', json_doc)
136 self.assertEqual(len(json_doc['measurements']), len(job.measurements))
138 self.assertIn('blobs', json_doc)
140 self.assertIn('metrics', json_doc)
141 self.assertEqual(len(json_doc['metrics']), len(job.metrics))
143 self.assertIn('specs', json_doc)
144 self.assertEqual(len(json_doc['specs']), len(job.specs))
146 self.assertIn('meta', json_doc)
147 self.assertEqual(len(json_doc['meta']), len(job.meta))
149 new_job = Job.deserialize(**json_doc)
150 self.assertEqual(job, new_job)
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')
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)
169 job_1 += job_2
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)
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])
187 job = Job(measurements=measurement_set)
188 job.reload_metrics_package('verify_metrics')
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,
196 Metric)
199if __name__ == "__main__": 199 ↛ 200line 199 didn't jump to line 200, because the condition on line 199 was never true
200 unittest.main()