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 __future__ import with_statement 

2from builtins import zip 

3from builtins import object 

4import os 

5import sqlite3 

6import numpy as np 

7import unittest 

8import tempfile 

9import shutil 

10import lsst.utils.tests 

11from lsst.sims.utils.CodeUtilities import sims_clean_up 

12from lsst.sims.utils import ObservationMetaData 

13from lsst.sims.catalogs.db import fileDBObject, CatalogDBObject 

14from lsst.sims.catalogs.definitions import InstanceCatalog 

15from lsst.sims.catalogs.decorators import compound 

16from lsst.sims.utils import haversine, angularSeparation 

17 

18 

19ROOT = os.path.abspath(os.path.dirname(__file__)) 

20 

21 

22def setup_module(module): 

23 lsst.utils.tests.init() 

24 

25 

26# a class of catalog that outputs all the significant figures in 

27# ra and dec so that it can be read back in to make sure that our 

28# Haversine-based query actually returns all of the points that 

29# are inside the circular bound desired 

30class BoundsCatalog(InstanceCatalog): 

31 catalog_type = 'bounds_catalog' 

32 refIdCol = 'id' 

33 column_outputs = ['id', 'raJ2000', 'decJ2000'] 

34 

35 default_formats = {'f': '%.20f'} 

36 

37 

38def twice_fn(x): 

39 return 2.0*x 

40 

41 

42class TransformationCatalog(InstanceCatalog): 

43 catalog_type = 'transformation_catalog' 

44 refIdCol = 'id' 

45 column_outputs = ['id', 'raJ2000', 'decJ2000'] 

46 default_formats = {'f': '%.12f'} 

47 transformations = {'raJ2000': twice_fn} 

48 

49 

50class BasicCatalog(InstanceCatalog): 

51 catalog_type = 'basic_catalog' 

52 refIdCol = 'id' 

53 column_outputs = ['id', 'raJ2000', 'decJ2000', 'umag', 'gmag', 'rmag', 'imag', 

54 'zmag', 'ymag'] 

55 

56 default_formats = {'f': '%.12f'} 

57 

58 

59class TestAstMixin(object): 

60 @compound('ra_corr', 'dec_corr') 

61 def get_points_corrected(self): 

62 # Fake astrometric correction 

63 ra_corr = self.column_by_name('raJ2000')+0.001 

64 dec_corr = self.column_by_name('decJ2000')+0.001 

65 return ra_corr, dec_corr 

66 

67 

68class CustomCatalog(BasicCatalog, TestAstMixin): 

69 catalog_type = 'custom_catalog' 

70 refIdCol = 'id' 

71 column_outputs = ['id', 'raJ2000', 'decJ2000', 'umag', 'gmag', 'rmag', 'imag', 

72 'zmag', 'ymag', 'ra_corr', 'dec_corr'] 

73 

74 

75def compareFiles(file1, file2): 

76 with open(file1) as fh: 

77 str1 = "".join(fh.readlines()) 

78 with open(file2) as fh: 

79 str2 = "".join(fh.readlines()) 

80 return str1 == str2 

81 

82 

83def write_star_file_db(file_name): 

84 

85 np.random.seed(88) 

86 nstars = 10000 

87 ra = np.random.random_sample(nstars)*360.0 

88 dec = (np.random.random_sample(nstars)-0.5)*180.0 

89 umag = np.random.random_sample(nstars)*10.0 + 15.0 

90 gmag = np.random.random_sample(nstars)*10.0 + 15.0 

91 rmag = np.random.random_sample(nstars)*10.0 + 15.0 

92 imag = np.random.random_sample(nstars)*10.0 + 15.0 

93 zmag = np.random.random_sample(nstars)*10.0 + 15.0 

94 ymag = np.random.random_sample(nstars)*10.0 + 15.0 

95 

96 with open(file_name, 'w') as output_file: 

97 for ix, (rr, dd, um, gm, rm, im, zm, ym) in \ 

98 enumerate(zip(ra, dec, umag, gmag, rmag, imag, zmag, ymag)): 

99 

100 output_file.write('%d %.12f %.12f %.12f %.12f %.12f %.12f %.12f %.12f\n' % 

101 (ix, rr, dd, um, gm, rm, im, zm, ym)) 

102 

103 starDtype = np.dtype([('id', np.int), 

104 ('raJ2000', np.float), 

105 ('decJ2000', np.float), 

106 ('umag', np.float), 

107 ('gmag', np.float), 

108 ('rmag', np.float), 

109 ('imag', np.float), 

110 ('zmag', np.float), 

111 ('ymag', np.float)]) 

112 

113 starDB = fileDBObject(file_name, runtable='stars', dtype=starDtype, idColKey='id') 

114 starDB.raColName = 'raJ2000' 

115 starDB.decColName = 'decJ2000' 

116 

117 controlData = np.genfromtxt(file_name, dtype=starDtype) 

118 

119 return starDB, controlData 

120 

121 

122class InstanceCatalogTestCase(unittest.TestCase): 

123 

124 longMessage = True 

125 

126 @classmethod 

127 def setUpClass(cls): 

128 

129 cls.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix="scratchSpace-") 

130 cls.starTextName = os.path.join(cls.scratch_dir, 'icStarTestCatalog.txt') 

131 

132 if os.path.exists(cls.starTextName): 

133 os.unlink(cls.starTextName) 

134 

135 cls.starDB, cls.starControlData = write_star_file_db(cls.starTextName) 

136 

137 @classmethod 

138 def tearDownClass(cls): 

139 

140 if os.path.exists(cls.starTextName): 

141 os.unlink(cls.starTextName) 

142 if os.path.exists(cls.scratch_dir): 

143 shutil.rmtree(cls.scratch_dir) 

144 

145 def setUp(self): 

146 self.obsMd = ObservationMetaData(boundType = 'circle', pointingRA = 210.0, pointingDec = -60.0, 

147 boundLength=20.0, mjd=52000., bandpassName='r') 

148 

149 def testStarLike(self): 

150 """ 

151 Write a couple of catalogs. Verify that the objects that end up in the catalog fall 

152 within the pointing and that the objects that do not end up in the catalog fall 

153 outside of the pointing 

154 """ 

155 

156 catName = os.path.join(self.scratch_dir, '_starLikeCat.txt') 

157 

158 if os.path.exists(catName): 

159 os.unlink(catName) 

160 

161 # this dtype corresponds to the outputs of the catalog 

162 dtype = np.dtype([('id', np.int), 

163 ('raJ2000', np.float), 

164 ('decJ2000', np.float), 

165 ('umag', np.float), 

166 ('gmag', np.float), 

167 ('rmag', np.float), 

168 ('imag', np.float), 

169 ('zmag', np.float), 

170 ('ymag', np.float), 

171 ('ra_corr', np.float), 

172 ('dec_corr', np.float)]) 

173 

174 t = self.starDB.getCatalog('custom_catalog', obs_metadata=self.obsMd) 

175 t.write_catalog(catName) 

176 

177 testData = np.genfromtxt(catName, delimiter = ', ', dtype=dtype) 

178 

179 # make sure that something ended up in the catalog 

180 self.assertGreater(len(testData), 0) 

181 

182 # iterate over the lines in the catalog 

183 # verify that those line exist in the control data 

184 # also verify that those lines fall within the requested field of view 

185 for line in testData: 

186 ic = np.where(self.starControlData['id'] == line['id'])[0][0] 

187 self.assertAlmostEqual(line['umag'], self.starControlData['umag'][ic], 6) 

188 self.assertAlmostEqual(line['gmag'], self.starControlData['gmag'][ic], 6) 

189 self.assertAlmostEqual(line['rmag'], self.starControlData['rmag'][ic], 6) 

190 self.assertAlmostEqual(line['imag'], self.starControlData['imag'][ic], 6) 

191 self.assertAlmostEqual(line['zmag'], self.starControlData['zmag'][ic], 6) 

192 self.assertAlmostEqual(line['ymag'], self.starControlData['ymag'][ic], 6) 

193 self.assertAlmostEqual(line['raJ2000'], self.starControlData['raJ2000'][ic], 6) 

194 self.assertAlmostEqual(line['decJ2000'], self.starControlData['decJ2000'][ic], 6) 

195 self.assertAlmostEqual(line['ra_corr'], line['raJ2000']+0.001, 6) 

196 self.assertAlmostEqual(line['dec_corr'], line['decJ2000']+0.001, 6) 

197 dl = haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), 

198 self.obsMd._pointingRA, self.obsMd._pointingDec) 

199 

200 self.assertLess(np.degrees(dl), self.obsMd.boundLength) 

201 

202 # examine the lines that did not fall in the catalog 

203 lines_not_in_catalog = [] 

204 for id_val in self.starControlData['id']: 

205 if id_val not in testData['id']: 

206 lines_not_in_catalog.append(id_val) 

207 lines_not_in_catalog = np.array(lines_not_in_catalog) 

208 

209 self.assertGreater(len(lines_not_in_catalog), 0) 

210 

211 # make sure that those lines are, indeed, outside of the field of view 

212 for ic in lines_not_in_catalog: 

213 dl = haversine(self.obsMd._pointingRA, self.obsMd._pointingDec, 

214 np.radians(self.starControlData['raJ2000'][ic]), 

215 np.radians(self.starControlData['decJ2000'][ic])) 

216 

217 msg = '\nRA %e Dec %e\n' % (self.starControlData['raJ2000'][ic], self.starControlData['decJ2000'][ic]) 

218 msg += 'pointing RA %e Dec %e\n' % (self.obsMd.pointingRA, self.obsMd.pointingDec) 

219 self.assertGreater(np.degrees(dl), self.obsMd.boundLength, msg=msg) 

220 

221 if os.path.exists(catName): 

222 os.unlink(catName) 

223 

224 # now do the same thing for the basic catalog class 

225 

226 dtype = np.dtype([('id', np.int), 

227 ('raJ2000', np.float), 

228 ('decJ2000', np.float), 

229 ('umag', np.float), 

230 ('gmag', np.float), 

231 ('rmag', np.float), 

232 ('imag', np.float), 

233 ('zmag', np.float), 

234 ('ymag', np.float)]) 

235 

236 t = self.starDB.getCatalog('basic_catalog', obs_metadata=self.obsMd) 

237 t.write_catalog(catName) 

238 

239 testData = np.genfromtxt(catName, delimiter = ', ', dtype=dtype) 

240 

241 # make sure that something ended up in the catalog 

242 self.assertGreater(len(testData), 0) 

243 

244 # iterate over the lines in the catalog 

245 # verify that those line exist in the control data 

246 # also verify that those lines fall within the requested field of view 

247 for line in testData: 

248 ic = np.where(self.starControlData['id'] == line['id'])[0][0] 

249 self.assertAlmostEqual(line['umag'], self.starControlData['umag'][ic], 6) 

250 self.assertAlmostEqual(line['gmag'], self.starControlData['gmag'][ic], 6) 

251 self.assertAlmostEqual(line['rmag'], self.starControlData['rmag'][ic], 6) 

252 self.assertAlmostEqual(line['imag'], self.starControlData['imag'][ic], 6) 

253 self.assertAlmostEqual(line['zmag'], self.starControlData['zmag'][ic], 6) 

254 self.assertAlmostEqual(line['ymag'], self.starControlData['ymag'][ic], 6) 

255 self.assertAlmostEqual(line['raJ2000'], self.starControlData['raJ2000'][ic], 6) 

256 self.assertAlmostEqual(line['decJ2000'], self.starControlData['decJ2000'][ic], 6) 

257 dl = haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), 

258 self.obsMd._pointingRA, self.obsMd._pointingDec) 

259 

260 self.assertLess(np.degrees(dl), self.obsMd.boundLength) 

261 

262 # examine the lines that did not fall in the catalog 

263 lines_not_in_catalog = [] 

264 for id_val in self.starControlData['id']: 

265 if id_val not in testData['id']: 

266 lines_not_in_catalog.append(id_val) 

267 lines_not_in_catalog = np.array(lines_not_in_catalog) 

268 

269 self.assertGreater(len(lines_not_in_catalog), 0) 

270 

271 # make sure that those lines are, indeed, outside of the field of view 

272 for ic in lines_not_in_catalog: 

273 dl = haversine(self.obsMd._pointingRA, self.obsMd._pointingDec, 

274 np.radians(self.starControlData['raJ2000'][ic]), 

275 np.radians(self.starControlData['decJ2000'][ic])) 

276 

277 self.assertGreater(np.degrees(dl), self.obsMd.boundLength) 

278 

279 if os.path.exists(catName): 

280 os.unlink(catName) 

281 

282 def test_transformation(self): 

283 """ 

284 Test that transformations are applied to columns in an InstanceCatalog 

285 """ 

286 catName = os.path.join(self.scratch_dir, 

287 'transformation_catalog.txt') 

288 

289 if os.path.exists(catName): 

290 os.unlink(catName) 

291 

292 t = self.starDB.getCatalog('transformation_catalog', obs_metadata=self.obsMd) 

293 t.write_catalog(catName) 

294 

295 dtype = np.dtype([('id', np.int), 

296 ('raJ2000', np.float), 

297 ('decJ2000', np.float)]) 

298 

299 testData = np.genfromtxt(catName, delimiter=', ', dtype=dtype) 

300 self.assertGreater(len(testData), 0) 

301 for line in testData: 

302 ic = np.where(self.starControlData['id'] == line['id'])[0][0] 

303 self.assertAlmostEqual(line['decJ2000'], self.starControlData['decJ2000'][ic], 5) 

304 self.assertAlmostEqual(line['raJ2000'], 2.0*self.starControlData['raJ2000'][ic], 5) 

305 

306 if os.path.exists(catName): 

307 os.unlink(catName) 

308 

309 def test_iter_catalog(self): 

310 """ 

311 Test that iter_catalog returns the same results as write_catalog 

312 """ 

313 

314 obs = ObservationMetaData(pointingRA=10.0, pointingDec=-20.0, 

315 boundLength=50.0, boundType='circle') 

316 

317 cat = BasicCatalog(self.starDB, obs_metadata=obs) 

318 cat_name = os.path.join(self.scratch_dir, 'iter_catalog_control.txt') 

319 cat.write_catalog(cat_name) 

320 with open(cat_name, 'r') as in_file: 

321 in_lines = in_file.readlines() 

322 self.assertGreater(len(in_lines), 1) 

323 self.assertLess(len(in_lines), len(self.starControlData)) 

324 

325 cat = BasicCatalog(self.starDB, obs_metadata=obs) 

326 line_ct = 0 

327 for line in cat.iter_catalog(): 

328 str_line = '%d, %.12f, %.12f, %.12f, %.12f, %.12f, %.12f, %.12f, %.12f\n' % \ 

329 (line[0], line[1], line[2], line[3], line[4], line[5], line[6], line[7], line[8]) 

330 self.assertIn(str_line, in_lines) 

331 line_ct += 1 

332 self.assertEqual(line_ct, len(in_lines)-1) 

333 

334 if os.path.exists(cat_name): 

335 os.unlink(cat_name) 

336 

337 def test_iter_catalog_chunks(self): 

338 """ 

339 Test that iter_catalog_chunks returns the same results as write_catalog 

340 """ 

341 

342 obs = ObservationMetaData(pointingRA=10.0, pointingDec=-20.0, 

343 boundLength=50.0, boundType='circle') 

344 

345 cat = BasicCatalog(self.starDB, obs_metadata=obs) 

346 cat_name = os.path.join(self.scratch_dir, 'iter_catalog_chunks_control.txt') 

347 cat.write_catalog(cat_name) 

348 with open(cat_name, 'r') as in_file: 

349 in_lines = in_file.readlines() 

350 self.assertGreater(len(in_lines), 1) 

351 self.assertLess(len(in_lines), len(self.starControlData)) 

352 

353 cat = BasicCatalog(self.starDB, obs_metadata=obs) 

354 line_ct = 0 

355 for chunk, chunk_map in cat.iter_catalog_chunks(chunk_size=7): 

356 for ix in range(len(chunk[0])): 

357 str_line = '%d, %.12f, %.12f, %.12f, %.12f, %.12f, %.12f, %.12f, %.12f\n' % \ 

358 (chunk[0][ix], chunk[1][ix], chunk[2][ix], chunk[3][ix], chunk[4][ix], 

359 chunk[5][ix], chunk[6][ix], chunk[7][ix], chunk[8][ix]) 

360 

361 self.assertIn(str_line, in_lines) 

362 line_ct += 1 

363 

364 self.assertEqual(line_ct, len(in_lines)-1) 

365 

366 if os.path.exists(cat_name): 

367 os.unlink(cat_name) 

368 

369 

370 

371class boundingBoxTest(unittest.TestCase): 

372 

373 @classmethod 

374 def setUpClass(cls): 

375 cls.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix="scratchSpace-") 

376 cls.starTextName = os.path.join(cls.scratch_dir, 

377 'bbStarTestCatalog.txt') 

378 

379 cls.starDB, cls.starControlData = write_star_file_db(cls.starTextName) 

380 

381 @classmethod 

382 def tearDownClass(cls): 

383 sims_clean_up() 

384 if os.path.exists(cls.starTextName): 

385 os.unlink(cls.starTextName) 

386 for file_name in os.listdir(cls.scratch_dir): 

387 os.unlink(os.path.join(cls.scratch_dir, file_name)) 

388 if os.path.exists(cls.scratch_dir): 

389 shutil.rmtree(cls.scratch_dir) 

390 

391 def setUp(self): 

392 

393 self.RAmin = 190. 

394 self.RAmax = 210. 

395 self.DECmin = -70. 

396 self.DECmax = -50. 

397 

398 self.RAcenter = 200. 

399 self.DECcenter = -60. 

400 self.radius = 10.0 

401 

402 self.obsMdCirc = ObservationMetaData(boundType='circle', 

403 pointingRA=self.RAcenter, 

404 pointingDec=self.DECcenter, 

405 boundLength=self.radius, mjd=52000., bandpassName='r') 

406 

407 self.obsMdBox = ObservationMetaData(boundType='box', pointingRA=0.5*(self.RAmax+self.RAmin), 

408 pointingDec=0.5*(self.DECmin+self.DECmax), 

409 boundLength=np.array([0.5*(self.RAmax-self.RAmin), 

410 0.5*(self.DECmax-self.DECmin)]), 

411 mjd=52000., bandpassName='r') 

412 

413 def testBoxBounds(self): 

414 """ 

415 Make sure that box_bound_constraint in sims.catalogs.db.dbConnection.py 

416 does not admit any objects outside of the bounding box 

417 """ 

418 

419 catName = os.path.join(self.scratch_dir, 'box_test_catalog.txt') 

420 

421 myCatalog = self.starDB.getCatalog('bounds_catalog', obs_metadata = self.obsMdBox) 

422 

423 myIterator = myCatalog.iter_catalog(chunk_size=10) 

424 

425 for line in myIterator: 

426 self.assertGreater(line[1], self.RAmin) 

427 self.assertLess(line[1], self.RAmax) 

428 self.assertGreater(line[2], self.DECmin) 

429 self.assertLess(line[2], self.DECmax) 

430 

431 myCatalog.write_catalog(catName) 

432 

433 # now we will test for the completeness of the box bounds 

434 

435 dtype = np.dtype([('id', np.int), 

436 ('raJ2000', np.float), 

437 ('decJ2000', np.float)]) 

438 

439 testData = np.genfromtxt(catName, dtype=dtype, delimiter=', ') 

440 

441 for line in testData: 

442 self.assertGreater(line['raJ2000'], self.RAmin) 

443 self.assertGreater(line['decJ2000'], self.DECmin) 

444 self.assertLess(line['raJ2000'], self.RAmax) 

445 self.assertLess(line['decJ2000'], self.DECmax) 

446 

447 ct = 0 

448 for line in self.starControlData: 

449 if line['id'] not in testData['id']: 

450 ct += 1 

451 in_bounds = ((line['raJ2000'] < self.RAmax) and (line['raJ2000'] > self.RAmin) and 

452 (line['decJ2000'] < self.DECmax) and (line['decJ2000'] > self.DECmin)) 

453 

454 msg = 'violates bounds\nRA: %e < %e <%e\nDec: %e < %e < %e\n' % \ 

455 (self.RAmin, line['raJ2000'], self.RAmax, 

456 self.DECmin, line['decJ2000'], self.DECmax) 

457 

458 self.assertFalse(in_bounds, msg=msg) 

459 

460 self.assertGreater(ct, 0) 

461 

462 if os.path.exists(catName): 

463 os.unlink(catName) 

464 

465 def testCircBounds(self): 

466 

467 """ 

468 Make sure that circular_bound_constraint in sims.catalogs.db.dbConnection.py 

469 does not admit any objects outside of the bounding circle 

470 """ 

471 

472 catName = os.path.join(self.scratch_dir, 

473 'circular_test_catalog.txt') 

474 

475 if os.path.exists(catName): 

476 os.unlink(catName) 

477 

478 myCatalog = self.starDB.getCatalog('bounds_catalog', obs_metadata = self.obsMdCirc) 

479 myIterator = myCatalog.iter_catalog(chunk_size=10) 

480 

481 for line in myIterator: 

482 rtest = np.degrees(haversine(np.radians(self.RAcenter), np.radians(self.DECcenter), 

483 np.radians(line[1]), np.radians(line[2]))) 

484 

485 self.assertLess(rtest, self.radius) 

486 

487 myCatalog.write_catalog(catName) 

488 

489 # now we will test for the completeness of the circular bounds 

490 

491 dtype = np.dtype([('id', np.int), 

492 ('raJ2000', np.float), 

493 ('decJ2000', np.float)]) 

494 

495 testData = np.genfromtxt(catName, dtype=dtype, delimiter=', ') 

496 

497 self.assertGreater(len(testData), 0) 

498 

499 for line in testData: 

500 dl = np.degrees(haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), 

501 np.radians(self.RAcenter), np.radians(self.DECcenter))) 

502 

503 self.assertLess(dl, self.radius) 

504 

505 ct = 0 

506 for line in self.starControlData: 

507 if line['id'] not in testData['id']: 

508 ct += 1 

509 dl = np.degrees(haversine(np.radians(line['raJ2000']), np.radians(line['decJ2000']), 

510 np.radians(self.RAcenter), np.radians(self.DECcenter))) 

511 

512 self.assertGreater(dl, self.radius) 

513 

514 self.assertGreater(ct, 0) 

515 

516 if os.path.exists(catName): 

517 os.unlink(catName) 

518 

519 def test_negative_RA(self): 

520 """ 

521 Test that spatial queries behave correctly around RA=0 

522 """ 

523 rng = np.random.RandomState(81234122) 

524 db_name = os.path.join(self.scratch_dir, 'neg_ra.db') 

525 with sqlite3.connect(db_name) as connection: 

526 cursor = connection.cursor() 

527 cursor.execute('''CREATE TABLE neg_ra_table 

528 (cat_id int, ra real, dec real)''') 

529 

530 connection.commit() 

531 n_samples = 1000 

532 id_val = np.arange(n_samples, dtype=int) + 1 

533 ra = 10.0*(rng.random_sample(n_samples)-0.5) 

534 dec = rng.random_sample(n_samples)-0.5 

535 values = ((int(ii), rr, dd) for ii, rr, dd in zip(id_val, ra, dec)) 

536 cursor.executemany('''INSERT INTO neg_ra_table VALUES (?, ?, ?)''', values) 

537 connection.commit() 

538 

539 class negativeRaCatalogDBClass(CatalogDBObject): 

540 tableid = 'neg_ra_table' 

541 idColKey = 'cat_id' 

542 raColName = 'ra' 

543 decColName = 'dec' 

544 objectTypeId = 126 

545 

546 class negativeRaCatalogClass(InstanceCatalog): 

547 column_outputs = ['cat_id', 'ra', 'dec'] 

548 delimiter = ' ' 

549 

550 db = negativeRaCatalogDBClass(database=db_name, driver='sqlite') 

551 

552 boundLength=0.2 

553 pra = 359.9 

554 pdec = 0.0 

555 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, 

556 boundType='circle', boundLength=boundLength) 

557 

558 

559 cat = negativeRaCatalogClass(db, obs_metadata=obs) 

560 cat_name = os.path.join(self.scratch_dir, 'neg_ra_cat.txt') 

561 cat.write_catalog(cat_name) 

562 valid = np.where(angularSeparation(pra, pdec, ra, dec)<boundLength) 

563 self.assertGreater(len(valid[0]), 0) 

564 self.assertLess(len(valid[0]), n_samples) 

565 valid_pos = np.where(np.logical_and(angularSeparation(pra, pdec, ra, dec)<boundLength, 

566 ra>0.0)) 

567 valid_neg = np.where(np.logical_and(angularSeparation(pra, pdec, ra, dec)<boundLength, 

568 ra<0.0)) 

569 self.assertGreater(len(valid_pos[0]), 0) 

570 self.assertGreater(len(valid_neg[0]), 0) 

571 self.assertLess(len(valid_pos[0]), len(valid[0])) 

572 valid_id = id_val[valid] 

573 valid_ra = ra[valid] 

574 valid_dec = dec[valid] 

575 

576 cat_dtype = np.dtype([('cat_id', int), ('ra', float), ('dec', float)]) 

577 cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) 

578 np.testing.assert_array_equal(cat_data['cat_id'], valid_id) 

579 np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) 

580 np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) 

581 

582 # now try it when RA is specified as negative 

583 pra = -0.1 

584 pdec = 0.0 

585 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, 

586 boundType='circle', boundLength=boundLength) 

587 

588 cat = negativeRaCatalogClass(db, obs_metadata=obs) 

589 cat.write_catalog(cat_name) 

590 

591 cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) 

592 np.testing.assert_array_equal(cat_data['cat_id'], valid_id) 

593 np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) 

594 np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) 

595 

596 # test it on a box 

597 pra = 359.9 

598 pdec = 0.0 

599 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, 

600 boundType='box', boundLength=boundLength) 

601 

602 cat = negativeRaCatalogClass(db, obs_metadata=obs) 

603 dec_min = pdec-boundLength 

604 dec_max = pdec+boundLength 

605 

606 valid_id = [] 

607 valid_ra = [] 

608 valid_dec = [] 

609 for rr, dd, ii in zip(ra, dec, id_val): 

610 if dd>dec_max or dd<dec_min: 

611 continue 

612 if np.abs(rr+0.1)<boundLength: 

613 valid_id.append(ii) 

614 valid_ra.append(rr) 

615 valid_dec.append(dd) 

616 valid_id = np.array(valid_id) 

617 valid_ra = np.array(valid_ra) 

618 valid_dec = np.array(valid_dec) 

619 

620 cat.write_catalog(cat_name) 

621 cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) 

622 np.testing.assert_array_equal(cat_data['cat_id'], valid_id) 

623 np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) 

624 np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) 

625 

626 # try when defined at negative 

627 pra = -0.1 

628 pdec = 0.0 

629 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, 

630 boundType='box', boundLength=boundLength) 

631 

632 cat = negativeRaCatalogClass(db, obs_metadata=obs) 

633 cat.write_catalog(cat_name) 

634 cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) 

635 np.testing.assert_array_equal(cat_data['cat_id'], valid_id) 

636 np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) 

637 np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) 

638 del db 

639 if os.path.exists(db_name): 

640 os.unlink(db_name) 

641 

642 def test_very_positive_RA(self): 

643 """ 

644 Test that spatial queries behave correctly around RA=0 (when RA>350) 

645 """ 

646 rng = np.random.RandomState(81234122) 

647 db_name = os.path.join(self.scratch_dir, 'very_pos_ra.db') 

648 with sqlite3.connect(db_name) as connection: 

649 cursor = connection.cursor() 

650 cursor.execute('''CREATE TABLE neg_ra_table 

651 (cat_id int, ra real, dec real)''') 

652 

653 connection.commit() 

654 n_samples = 1000 

655 id_val = np.arange(n_samples, dtype=int) + 1 

656 ra = 10.0*(rng.random_sample(n_samples)-0.5) 

657 neg_dex = np.where(ra<0.0) 

658 ra[neg_dex] += 360.0 

659 dec = rng.random_sample(n_samples)-0.5 

660 values = ((int(ii), rr, dd) for ii, rr, dd in zip(id_val, ra, dec)) 

661 cursor.executemany('''INSERT INTO neg_ra_table VALUES (?, ?, ?)''', values) 

662 connection.commit() 

663 

664 class veryPositiveRaCatalogDBClass(CatalogDBObject): 

665 tableid = 'neg_ra_table' 

666 idColKey = 'cat_id' 

667 raColName = 'ra' 

668 decColName = 'dec' 

669 objectTypeId = 126 

670 

671 class veryPositiveRaCatalogClass(InstanceCatalog): 

672 column_outputs = ['cat_id', 'ra', 'dec'] 

673 delimiter = ' ' 

674 

675 db = veryPositiveRaCatalogDBClass(database=db_name, driver='sqlite') 

676 

677 boundLength=0.2 

678 pra = 359.9 

679 pdec = 0.0 

680 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, 

681 boundType='circle', boundLength=boundLength) 

682 

683 

684 cat = veryPositiveRaCatalogClass(db, obs_metadata=obs) 

685 cat_name = os.path.join(self.scratch_dir, 'very_pos_ra_cat.txt') 

686 cat.write_catalog(cat_name) 

687 valid = np.where(angularSeparation(pra, pdec, ra, dec)<boundLength) 

688 self.assertGreater(len(valid[0]), 0) 

689 self.assertLess(len(valid[0]), n_samples) 

690 valid_pos = np.where(np.logical_and(angularSeparation(pra, pdec, ra, dec)<boundLength, 

691 ra<350.0)) 

692 valid_neg = np.where(np.logical_and(angularSeparation(pra, pdec, ra, dec)<boundLength, 

693 ra>350.0)) 

694 self.assertGreater(len(valid_pos[0]), 0) 

695 self.assertGreater(len(valid_neg[0]), 0) 

696 self.assertLess(len(valid_pos[0]), len(valid[0])) 

697 valid_id = id_val[valid] 

698 valid_ra = ra[valid] 

699 valid_dec = dec[valid] 

700 

701 cat_dtype = np.dtype([('cat_id', int), ('ra', float), ('dec', float)]) 

702 cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) 

703 np.testing.assert_array_equal(cat_data['cat_id'], valid_id) 

704 np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) 

705 np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) 

706 

707 # now try it when RA is specified as negative 

708 pra = -0.1 

709 pdec = 0.0 

710 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, 

711 boundType='circle', boundLength=boundLength) 

712 

713 cat = veryPositiveRaCatalogClass(db, obs_metadata=obs) 

714 cat.write_catalog(cat_name) 

715 

716 cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) 

717 np.testing.assert_array_equal(cat_data['cat_id'], valid_id) 

718 np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) 

719 np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) 

720 

721 # test it on a box 

722 pra = 359.9 

723 pdec = 0.0 

724 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, 

725 boundType='box', boundLength=boundLength) 

726 

727 cat = veryPositiveRaCatalogClass(db, obs_metadata=obs) 

728 

729 dec_min = pdec-boundLength 

730 dec_max = pdec+boundLength 

731 

732 valid_id = [] 

733 valid_ra = [] 

734 valid_dec = [] 

735 for rr, dd, ii in zip(ra, dec, id_val): 

736 if dd>dec_max or dd<dec_min: 

737 continue 

738 if np.abs(rr-359.9)<boundLength or (rr+0.1)<boundLength: 

739 valid_id.append(ii) 

740 valid_ra.append(rr) 

741 valid_dec.append(dd) 

742 valid_id = np.array(valid_id) 

743 valid_ra = np.array(valid_ra) 

744 valid_dec = np.array(valid_dec) 

745 

746 cat.write_catalog(cat_name) 

747 cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) 

748 np.testing.assert_array_equal(cat_data['cat_id'], valid_id) 

749 np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) 

750 np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) 

751 

752 # try when defined at negative 

753 pra = -0.1 

754 pdec = 0.0 

755 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, 

756 boundType='box', boundLength=boundLength) 

757 

758 cat = veryPositiveRaCatalogClass(db, obs_metadata=obs) 

759 cat.write_catalog(cat_name) 

760 cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) 

761 np.testing.assert_array_equal(cat_data['cat_id'], valid_id) 

762 np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) 

763 np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) 

764 del db 

765 if os.path.exists(db_name): 

766 os.unlink(db_name) 

767 

768 

769class MemoryTestClass(lsst.utils.tests.MemoryTestCase): 

770 pass 

771 

772 

773if __name__ == "__main__": 773 ↛ 774line 773 didn't jump to line 774, because the condition on line 773 was never true

774 lsst.utils.tests.init() 

775 unittest.main()