Hide keyboard shortcuts

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 

14 

15warnings.simplefilter('always') 

16 

17 

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 

84 

85 

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'") 

93 

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 

105 

106 

107class TestOpsimFieldSlicerSetup(unittest.TestCase): 

108 

109 def setUp(self): 

110 self.testslicer = OpsimFieldSlicer() 

111 self.fieldData = makeFieldData() 

112 self.simData = makeDataValues(self.fieldData, random=88) 

113 

114 def tearDown(self): 

115 del self.testslicer 

116 self.testslicer = None 

117 

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') 

122 

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'])) 

128 

129 

130class TestOpsimFieldSlicerEqual(unittest.TestCase): 

131 

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) 

137 

138 def tearDown(self): 

139 del self.testslicer 

140 self.testslicer = None 

141 

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() 

162 

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) 

169 

170 

171@unittest.skip('Skipping because warning does not seem to trigger reliably on py2.') 

172class TestOpsimFieldSlicerWarning(unittest.TestCase): 

173 

174 def setUp(self): 

175 self.testslicer = OpsimFieldSlicer() 

176 self.fieldData = makeFieldData() 

177 self.simData = makeDataValues(self.fieldData, random=4532) 

178 

179 def tearDown(self): 

180 del self.testslicer 

181 self.testslicer = None 

182 

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)) 

189 

190 

191class TestOpsimFieldSlicerIteration(unittest.TestCase): 

192 

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) 

198 

199 def tearDown(self): 

200 del self.testslicer 

201 self.testslicer = None 

202 

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) 

214 

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])) 

230 

231 

232class TestOpsimFieldSlicerSlicing(unittest.TestCase): 

233 # Note that this is really testing baseSpatialSlicer, as slicing is done there for healpix grid 

234 

235 def setUp(self): 

236 self.testslicer = OpsimFieldSlicer() 

237 self.fieldData = makeFieldData() 

238 self.simData = makeDataValues(self.fieldData, random=98) 

239 

240 def tearDown(self): 

241 del self.testslicer 

242 self.testslicer = None 

243 

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]) 

258 

259 

260class TestOpsimFieldSlicerPlotting(unittest.TestCase): 

261 

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) 

268 

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) 

281 

282 def tearDown(self): 

283 del self.testslicer 

284 self.testslicer = None 

285 

286 

287class TestMemory(lsst.utils.tests.MemoryTestCase): 

288 pass 

289 

290 

291def setup_module(module): 

292 lsst.utils.tests.init() 

293 

294 

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()