Coverage for tests/test_threshold_specification.py: 15%
75 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-01 09:54 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-11-01 09:54 +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 unittest
23import operator
25import astropy.units as u
27from lsst.verify import Name, Job
28from lsst.verify.spec import ThresholdSpecification
31class ThresholdSpecificationTestCase(unittest.TestCase):
32 """Test ThresholdSpecification class functionality."""
34 def test_init(self):
35 """Test initialization patterns."""
36 # with a fully-specified Name
37 s1 = ThresholdSpecification(
38 Name('validate_drp.AM1.design'),
39 5. * u.marcsec,
40 '<')
42 # with a fully-specified string-based name
43 s2 = ThresholdSpecification(
44 'validate_drp.AM1.design',
45 5. * u.marcsec,
46 '<')
47 self.assertEqual(s1, s2)
49 # bad operator
50 with self.assertRaises(TypeError):
51 ThresholdSpecification(
52 'validate_drp.AM1.design',
53 5. * u.marcsec,
54 '<<')
56 # bad quantity
57 with self.assertRaises(TypeError):
58 ThresholdSpecification(
59 'validate_drp.AM1.design',
60 5.,
61 '<')
63 # bad name
64 with self.assertRaises(TypeError):
65 ThresholdSpecification(
66 Name(metric='validate_drp'),
67 5. * u.marcsec,
68 '<')
70 def test_equality(self):
71 """test __eq__."""
72 s1 = ThresholdSpecification(
73 Name('validate_drp.AM1.design'),
74 5. * u.marcsec,
75 '<')
77 # with compatible units
78 s3 = ThresholdSpecification(
79 Name('validate_drp.AM1.design'),
80 5e-3 * u.arcsec,
81 '<')
82 self.assertEqual(s1, s3)
84 # incompatible names
85 s4 = ThresholdSpecification(
86 Name('validate_drp.AM1.stretch'),
87 5. * u.marcsec,
88 '<')
89 self.assertNotEqual(s1, s4)
91 # incompatible threshold
92 s5 = ThresholdSpecification(
93 Name('validate_drp.AM1.design'),
94 5. * u.arcsec,
95 '<')
96 self.assertNotEqual(s1, s5)
98 # incompatible operator
99 s6 = ThresholdSpecification(
100 Name('validate_drp.AM1.design'),
101 5. * u.marcsec,
102 '>')
103 self.assertNotEqual(s1, s6)
105 def test_spec(self):
106 """Test creating and accessing a specification from a quantity."""
107 s = ThresholdSpecification('design', 5 * u.mag, '<')
108 self.assertEqual(s.name, Name(spec='design'))
109 self.assertEqual(s.type, 'threshold')
110 self.assertEqual(s.threshold.value, 5.)
111 self.assertEqual(s.threshold.unit, u.mag)
112 self.assertEqual(s.operator_str, '<')
113 # Sanity-check repr
114 self.assertIn('ThresholdSpecification', repr(s))
115 self.assertIn('design', repr(s))
116 self.assertIn('Quantity', repr(s))
117 self.assertIn('mag', repr(s))
118 self.assertIn('5', repr(s))
120 # Test specification check method
121 self.assertTrue(
122 s.check(4 * u.mag)
123 )
124 self.assertTrue(
125 s.check(4000 * u.mmag)
126 )
127 self.assertFalse(
128 s.check(6. * u.mag)
129 )
130 self.assertFalse(
131 s.check(6000. * u.mmag)
132 )
133 with self.assertRaises(u.UnitConversionError):
134 s.check(2. * u.arcmin)
135 with self.assertRaises(u.UnitsError):
136 s.check(2.)
138 # test json output
139 json_data = s.json
140 self.assertEqual(json_data['name'], 'design')
141 self.assertEqual(json_data['threshold']['value'], 5.)
142 self.assertEqual(json_data['threshold']['unit'], 'mag')
143 self.assertEqual(json_data['threshold']['operator'], '<')
145 # rebuild from json
146 s3 = ThresholdSpecification.deserialize(**json_data)
147 self.assertEqual(s, s3)
149 # test datum output
150 d = s.datum
151 self.assertEqual(d.quantity, 5. * u.mag)
152 self.assertEqual(d.label, 'design')
154 def test_convert_operator_str(self):
155 """Test that strings can be converted into operators."""
156 self.assertEqual(
157 ThresholdSpecification.convert_operator_str('<'),
158 operator.lt)
160 self.assertEqual(
161 ThresholdSpecification.convert_operator_str('<='),
162 operator.le)
164 self.assertEqual(
165 ThresholdSpecification.convert_operator_str('>'),
166 operator.gt)
168 self.assertEqual(
169 ThresholdSpecification.convert_operator_str('>='),
170 operator.ge)
172 self.assertEqual(
173 ThresholdSpecification.convert_operator_str('=='),
174 operator.eq)
176 self.assertEqual(
177 ThresholdSpecification.convert_operator_str('!='),
178 operator.ne)
180 with self.assertRaises(ValueError):
181 ThresholdSpecification.convert_operator_str('<<'),
183 def test_query_metadata(self):
184 job = Job(meta={'filter_name': 'r',
185 'camera': 'MegaCam'})
186 s1 = ThresholdSpecification(
187 Name('validate_drp.AM1.design_r'),
188 5. * u.marcsec, '<',
189 metadata_query={'filter_name': 'r'})
190 s2 = ThresholdSpecification(
191 Name('validate_drp.AM1.design_i'),
192 5. * u.marcsec, '<',
193 metadata_query={'filter_name': 'i'})
194 s3 = ThresholdSpecification(
195 Name('validate_drp.AM1.design_HSC_r'),
196 5. * u.marcsec, '<',
197 metadata_query={'filter_name': 'r', 'camera': 'HSC'})
199 self.assertTrue(s1.query_metadata(job.meta))
200 self.assertFalse(s2.query_metadata(job.meta))
201 self.assertFalse(s3.query_metadata(job.meta))
204if __name__ == "__main__": 204 ↛ 205line 204 didn't jump to line 205, because the condition on line 204 was never true
205 unittest.main()