Coverage for tests/testOpsimFieldSlicer.py : 26%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from builtins import zip
2from builtins import str
3import matplotlib
4matplotlib.use("Agg")
5import numpy as np
6import matplotlib
7matplotlib.use('Agg')
8import numpy.ma as ma
9import unittest
10from lsst.sims.maf.slicers.opsimFieldSlicer import OpsimFieldSlicer
11from lsst.sims.maf.slicers.uniSlicer import UniSlicer
12import warnings
13import lsst.utils.tests
15warnings.simplefilter('always')
18def makeFieldData():
19 """Set up sample field data."""
20 # These are a subset of the fields from opsim.
21 fieldId = [2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015,
22 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030,
23 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045,
24 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060,
25 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075,
26 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090,
27 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100]
28 ra_rad = [1.4961071750760884, 4.009380232682723, 2.2738050744968632, 2.7527439701957053,
29 6.043715459855715, 0.23946974745438585, 3.4768050063149119, 2.8063803008646744,
30 4.0630173623005916, 2.2201678117208452, 4.7334418014345294, 1.5497433725869068,
31 5.9900783302378473, 0.29310704352081429, 5.3196557553180082, 0.96352968501972802,
32 5.9359027094472925, 0.34728263102270451, 4.6792656480113752, 1.6039197923263617,
33 4.1171937820400464, 2.1659915251395399, 5.3738319087411623, 0.90935339843842322,
34 3.4226285865754575, 2.8605567206041291, 4.6243097210206079, 1.658875319842678,
35 5.4287873030993294, 0.85439793750118176, 5.8809462498239249, 0.40223922380247534,
36 4.1721494427145123, 2.1110359976232238, 3.3676726595846915, 2.9155126475948951,
37 3.3118314978483459, 2.9713538093312404, 4.2279900718200034, 2.0551952353595833,
38 4.5684690919151176, 1.7147163484226187, 5.4846279322030744, 0.79855764129106599,
39 5.8251056207201799, 0.45807965317074106, 5.769146214630454, 0.51403882623283237,
40 4.5125086205619365, 1.7706764203013494, 5.5405873382928013, 0.74259816862400985,
41 4.283950276856884, 1.9992351634808523, 3.2558718254423198, 3.0273134817372669,
42 5.0265477131110696, 1.256637460910367, 3.7699109179914521, 2.5132743891881342,
43 0.0, 3.7165246581483231, 2.5666606490312627, 4.9731614532679407, 1.3100238539116456,
44 6.2297990473364582, 0.053386447097758416, 3.8232977104671799, 2.4598875967124063,
45 5.079933972955943, 1.2032510679073434, 4.4557055250397459, 1.82747964898169,
46 3.1990676646549288, 3.084117642524657, 5.7123425864756632, 0.57084272070392295,
47 5.5973914990801914, 0.68579407441569451, 4.3407541713279745, 1.9424311358516118,
48 3.6631498498956194, 2.6200354572839668, 6.1764234401365998, 0.10676173388483716,
49 4.9197863787006817, 1.3633986621626044, 3.8766735839833384, 2.4065117231962478,
50 5.1333101127866563, 1.1498751943929302, 3.1415926535897931, 5.6548662438290274,
51 0.62831906335055854, 4.3982294487094107, 1.884955858470176, 3.9300611754079662,
52 2.3531241317716196, 4.8663995862232081, 1.4167858541145277]
53 dec_rad = [-0.25205231807872636, -0.25205228478831621, -0.25205228478831621, -0.25205228478831621,
54 -0.25205145255075168, -0.25205145255075168, -0.24630904473998308, -0.24630904473998308,
55 -0.24630894487049795, -0.24630894487049795, -0.24630801276519362, -0.24630801276519362,
56 -0.24630799611998855, -0.24630799611998855, -0.24630796283132372, -0.24630796283132372,
57 -0.24014665642446359, -0.24014665642446359, -0.24014665642446359, -0.24014665642446359,
58 -0.24014655655672376, -0.24014655655672376, -0.24014653991151874, -0.24014653991151874,
59 -0.24014648997764879, -0.24014648997764879, -0.23394214023110541, -0.23394214023110541,
60 -0.23394209029549018, -0.23394209029549018, -0.23394204036162028, -0.23394204036162028,
61 -0.23394204036162028, -0.23394204036162028, -0.23394204036162028, -0.23394204036162028,
62 -0.22802912366201158, -0.22802912366201158, -0.22802899050386166, -0.22802899050386166,
63 -0.22802897385865656, -0.22802897385865656, -0.22802897385865656, -0.22802897385865656,
64 -0.22802804175335223, -0.22802804175335223, -0.22161461721627795, -0.22161461721627795,
65 -0.22161461721627795, -0.22161461721627795, -0.22161456728240808, -0.22161456728240808,
66 -0.2216145339919979, -0.2216145339919979, -0.22161446741292293, -0.22161446741292293,
67 -0.21924843187676188, -0.21924843187676188, -0.21924838194289203, -0.21924838194289203,
68 -0.2192483652976869, -0.2185302106194596, -0.2185302106194596, -0.2185292785141553,
69 -0.2185292785141553, -0.2185292785141553, -0.2185292785141553, -0.21852919528987524,
70 -0.21852919528987524, -0.21852916200121042, -0.21852916200121042, -0.21669173065121086,
71 -0.21669173065121086, -0.21669169736254604, -0.21669169736254604, -0.21669083183457133,
72 -0.21669083183457133, -0.21669076525549638, -0.21669076525549638, -0.2166907319650862,
73 -0.2166907319650862, -0.21643082408833589, -0.21643082408833589, -0.21643080744313081,
74 -0.21643080744313081, -0.21643077415446602, -0.21643077415446602, -0.21643074086405584,
75 -0.21643074086405584, -0.21643062435111099, -0.21643062435111099, -0.21479804002474462,
76 -0.21479794015525952, -0.21479794015525952, -0.21479784028751969, -0.21479784028751969,
77 -0.21311147675042988, -0.21311147675042988, -0.2131105113547154, -0.2131105113547154]
78 fieldId = np.array(fieldId, 'int')
79 ra_rad = np.array(ra_rad, 'float')
80 dec_rad = np.array(dec_rad, 'float')
81 fieldData = np.core.records.fromarrays([fieldId, np.degrees(ra_rad), np.degrees(dec_rad)],
82 names=['fieldId', 'fieldRA', 'fieldDec'])
83 return fieldData
86def makeDataValues(fieldData, size=10000, min=0., max=1., random=None):
87 """Generate a simple array of numbers, evenly arranged between min/max, but (optional) random order."""
88 datavalues = np.arange(0, size, dtype='float')
89 datavalues *= (float(max) - float(min)) / (datavalues.max() - datavalues.min())
90 datavalues += min
91 if random is None:
92 raise RuntimeError("Must pass in random number seed as kwarg 'random'")
94 rng = np.random.RandomState(random)
95 randorder = rng.rand(size)
96 randind = np.argsort(randorder)
97 datavalues = datavalues[randind]
98 # Add valid fieldId values to match data values
99 fieldId = np.zeros(len(datavalues), 'int')
100 idxs = rng.rand(size) * len(fieldData['fieldId'])
101 for i, d in enumerate(datavalues):
102 fieldId[i] = fieldData[int(idxs[i])][0]
103 simData = np.core.records.fromarrays([fieldId, datavalues], names=['fieldId', 'testdata'])
104 return simData
107class TestOpsimFieldSlicerSetup(unittest.TestCase):
109 def setUp(self):
110 self.testslicer = OpsimFieldSlicer()
111 self.fieldData = makeFieldData()
112 self.simData = makeDataValues(self.fieldData, random=88)
114 def tearDown(self):
115 del self.testslicer
116 self.testslicer = None
118 def testSlicertype(self):
119 """Test instantiation of slicer sets slicer type as expected."""
120 self.assertEqual(self.testslicer.slicerName, self.testslicer.__class__.__name__)
121 self.assertEqual(self.testslicer.slicerName, 'OpsimFieldSlicer')
123 def testSlicerNbins(self):
124 """Test that generate expected number of bins for a given set of fields."""
125 self.assertEqual(self.testslicer.nslice, None)
126 self.testslicer.setupSlicer(self.simData, self.fieldData)
127 self.assertEqual(self.testslicer.nslice, len(self.fieldData['fieldId']))
130class TestOpsimFieldSlicerEqual(unittest.TestCase):
132 def setUp(self):
133 self.testslicer = OpsimFieldSlicer()
134 self.fieldData = makeFieldData()
135 self.simData = makeDataValues(self.fieldData, random=56)
136 self.testslicer.setupSlicer(self.simData, self.fieldData)
138 def tearDown(self):
139 del self.testslicer
140 self.testslicer = None
142 def testSlicerEquivalence(self):
143 """Test that slicers are marked equal when appropriate, and unequal when appropriate."""
144 # Note that opsimfield slicers are considered 'equal' when all fieldId's, RA and Decs match.
145 testslicer2 = OpsimFieldSlicer()
146 fieldData2 = np.copy(self.fieldData)
147 testslicer2.setupSlicer(self.simData, fieldData2)
148 # These slicers should be equal.
149 self.assertTrue(self.testslicer == testslicer2)
150 self.assertFalse(self.testslicer != testslicer2)
151 # These slicers should not be equal.
152 fieldData2['fieldId'] = fieldData2['fieldId'] + 1
153 testslicer2.setupSlicer(self.simData, fieldData2)
154 self.assertTrue(self.testslicer != testslicer2)
155 self.assertFalse(self.testslicer == testslicer2)
156 # Test a slicer that is not the same kind.
157 testslicer2 = UniSlicer()
158 self.assertNotEqual(self.testslicer, testslicer2)
159 # Test slicers that haven't been setup
160 ts1 = OpsimFieldSlicer()
161 ts2 = OpsimFieldSlicer()
163 self.assertTrue(ts1 == ts2)
164 self.assertFalse(ts1 != ts2)
165 # Set up one with an odd value.
166 ts2 = OpsimFieldSlicer(fieldRaColName='WackyName')
167 self.assertTrue(ts1 != ts2)
168 self.assertFalse(ts1 == ts2)
171@unittest.skip('Skipping because warning does not seem to trigger reliably on py2.')
172class TestOpsimFieldSlicerWarning(unittest.TestCase):
174 def setUp(self):
175 self.testslicer = OpsimFieldSlicer()
176 self.fieldData = makeFieldData()
177 self.simData = makeDataValues(self.fieldData, random=4532)
179 def tearDown(self):
180 del self.testslicer
181 self.testslicer = None
183 def testWarning(self):
184 self.testslicer.setupSlicer(self.simData, self.fieldData)
185 with warnings.catch_warnings(record=True) as w:
186 self.testslicer.setupSlicer(self.simData, self.fieldData)
187 self.assertEqual(len(w), 1)
188 self.assertIn("Re-setting up an OpsimFieldSlicer", str(w[-1].message))
191class TestOpsimFieldSlicerIteration(unittest.TestCase):
193 def setUp(self):
194 self.testslicer = OpsimFieldSlicer(latLonDeg=True)
195 self.fieldData = makeFieldData()
196 self.simData = makeDataValues(self.fieldData, random=776221)
197 self.testslicer.setupSlicer(self.simData, self.fieldData)
199 def tearDown(self):
200 del self.testslicer
201 self.testslicer = None
203 def testIteration(self):
204 """Test iteration goes through expected range and ra/dec are in expected range (radians)."""
205 for fid, ra, dec, s in zip(self.fieldData['fieldId'], np.radians(self.fieldData['fieldRA']),
206 np.radians(self.fieldData['fieldDec']), self.testslicer):
207 self.assertEqual(fid, s['slicePoint']['sid'])
208 self.assertEqual(ra, s['slicePoint']['ra'])
209 self.assertEqual(dec, s['slicePoint']['dec'])
210 self.assertGreaterEqual(s['slicePoint']['sid'], 0)
211 self.assertLessEqual(s['slicePoint']['ra'], 2*np.pi)
212 self.assertGreaterEqual(s['slicePoint']['dec'], -np.pi)
213 self.assertLessEqual(s['slicePoint']['dec'], np.pi)
215 def testGetItem(self):
216 """Test getting indexed value."""
217 for i, s in enumerate(self.testslicer):
218 dict1 = s
219 dict2 = self.testslicer[i]
220 np.testing.assert_array_equal(dict1['idxs'], dict2['idxs'])
221 self.assertDictEqual(dict1['slicePoint'], dict2['slicePoint'])
222 n = 0
223 self.assertEqual(self.testslicer[n]['slicePoint']['sid'], self.fieldData['fieldId'][n])
224 self.assertEqual(self.testslicer[n]['slicePoint']['ra'], np.radians(self.fieldData['fieldRA'][n]))
225 self.assertEqual(self.testslicer[n]['slicePoint']['dec'], np.radians(self.fieldData['fieldDec'][n]))
226 n = len(self.testslicer) - 1
227 self.assertEqual(self.testslicer[n]['slicePoint']['sid'], self.fieldData['fieldId'][n])
228 self.assertEqual(self.testslicer[n]['slicePoint']['ra'], np.radians(self.fieldData['fieldRA'][n]))
229 self.assertEqual(self.testslicer[n]['slicePoint']['dec'], np.radians(self.fieldData['fieldDec'][n]))
232class TestOpsimFieldSlicerSlicing(unittest.TestCase):
233 # Note that this is really testing baseSpatialSlicer, as slicing is done there for healpix grid
235 def setUp(self):
236 self.testslicer = OpsimFieldSlicer()
237 self.fieldData = makeFieldData()
238 self.simData = makeDataValues(self.fieldData, random=98)
240 def tearDown(self):
241 del self.testslicer
242 self.testslicer = None
244 def testSlicing(self):
245 """Test slicing returns (all) data points which match fieldId values."""
246 # Test that slicing fails before setupBinner
247 self.assertRaises(NotImplementedError, self.testslicer._sliceSimData, 0)
248 # Set up slicer.
249 self.testslicer.setupSlicer(self.simData, self.fieldData)
250 for s in self.testslicer:
251 didxs = np.where(self.simData['fieldId'] == s['slicePoint']['sid'])
252 binidxs = s['idxs']
253 self.assertEqual(len(binidxs), len(didxs[0]))
254 if len(binidxs) > 0:
255 didxs = np.sort(didxs[0])
256 binidxs = np.sort(binidxs)
257 np.testing.assert_equal(self.simData['testdata'][didxs], self.simData['testdata'][binidxs])
260class TestOpsimFieldSlicerPlotting(unittest.TestCase):
262 def setUp(self):
263 rng = np.random.RandomState(65332)
264 self.testslicer = OpsimFieldSlicer()
265 self.fieldData = makeFieldData()
266 self.simData = makeDataValues(self.fieldData, random=462)
267 self.testslicer.setupSlicer(self.simData, self.fieldData)
269 self.metricdata = ma.MaskedArray(data=np.zeros(len(self.testslicer), dtype='float'),
270 mask=np.zeros(len(self.testslicer), 'bool'),
271 fill_value=self.testslicer.badval)
272 for i, s in enumerate(self.testslicer):
273 idxs = s['idxs']
274 if len(idxs) > 0:
275 self.metricdata.data[i] = np.mean(self.simData['testdata'][idxs])
276 else:
277 self.metricdata.mask[i] = True
278 self.metricdata2 = ma.MaskedArray(data=rng.rand(len(self.testslicer)),
279 mask=np.zeros(len(self.testslicer), 'bool'),
280 fill_value=self.testslicer.badval)
282 def tearDown(self):
283 del self.testslicer
284 self.testslicer = None
287class TestMemory(lsst.utils.tests.MemoryTestCase):
288 pass
291def setup_module(module):
292 lsst.utils.tests.init()
295if __name__ == "__main__": 295 ↛ 296line 295 didn't jump to line 296, because the condition on line 295 was never true
296 lsst.utils.tests.init()
297 unittest.main()