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 

2import unittest 

3import os 

4import numpy as np 

5import sqlite3 

6import json 

7import tempfile 

8import shutil 

9from astropy import units as u 

10from astropy.modeling import models 

11 

12import lsst.utils.tests 

13from lsst.utils import getPackageDir 

14from lsst.utils.tests import getTempFilePath 

15from lsst.sims.catalogs.db import CatalogDBObject 

16from lsst.sims.catUtils.mixins import VariabilityStars 

17from lsst.sims.catUtils.mixins import MLTflaringMixin 

18from lsst.sims.catalogs.definitions import InstanceCatalog 

19from lsst.sims.catUtils.mixins import PhotometryStars 

20from lsst.sims.utils import ObservationMetaData 

21from lsst.sims.photUtils import SedList, BandpassDict, Sed 

22from lsst.sims.utils import radiansFromArcsec 

23from lsst.sims.photUtils import PhotometricParameters 

24from lsst.sims.utils.CodeUtilities import sims_clean_up 

25from lsst.sims.utils import defaultSpecMap 

26 

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

28 

29 

30def setup_module(module): 

31 lsst.utils.tests.init() 

32 

33 

34class MLT_test_DB(CatalogDBObject): 

35 objid = 'mlt_test' 

36 tableid = 'mlt_test' 

37 idColKey = 'id' 

38 raColName = 'ra' 

39 decColName = 'decl' 

40 objectTypeId = 66 

41 

42 columns = [('id','simobjid', int), 

43 ('raJ2000', 'ra*PI()/180.'), 

44 ('decJ2000', 'decl*PI()/180.'), 

45 ('parallax', 'parallax*PI()/648000000.'), 

46 ('variabilityParameters', 'varParamStr', str, 256), 

47 ('sedFilename', 'sedfilename', str, 40), 

48 ('ebv', 'galacticAv/3.1')] 

49 

50 

51class QuiescentCatalog(PhotometryStars, InstanceCatalog): 

52 column_outputs = ['id', 'lsst_u', 'lsst_g'] 

53 

54class FlaringCatalog(PhotometryStars, VariabilityStars, 

55 MLTflaringMixin, InstanceCatalog): 

56 column_outputs = ['id', 'lsst_u', 'lsst_g'] 

57 

58 

59class MLT_flare_test_case(unittest.TestCase): 

60 

61 longMessage = True 

62 

63 @classmethod 

64 def setUpClass(cls): 

65 cls.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix="MLT_flare_test_case-") 

66 

67 # Create a dummy mlt light curve file 

68 cls.mlt_lc_name = os.path.join(cls.scratch_dir, 

69 'test_mlt_lc_file.npz') 

70 

71 lc_files = {} 

72 amp = 1.0e42 

73 lc_files['lc_1_time'] = np.arange(0.0, 3652.51, 0.1) 

74 lc_files['lc_1_u'] = amp*(1.0+np.power(np.sin(lc_files['lc_1_time']/100.0), 2)) 

75 lc_files['lc_1_g'] = amp*(1.0+np.power(np.cos(lc_files['lc_1_time']/100.0), 2)) 

76 

77 amp = 2.0e41 

78 lc_files['lc_2_time'] = np.arange(0.0, 365.251, 0.01) 

79 lc_files['lc_2_u'] = amp*(1.0+np.power(np.sin(lc_files['lc_2_time']/50.0), 2)) 

80 lc_files['lc_2_g'] = amp*(1.0+np.power(np.cos(lc_files['lc_2_time']/50.0), 2)) 

81 

82 with open(cls.mlt_lc_name, 'wb') as file_handle: 

83 np.savez(file_handle, **lc_files) 

84 

85 # Create a database of stars using these light curves 

86 cls.db_name = os.path.join(cls.scratch_dir, 'test_mlt_db.db') 

87 

88 conn = sqlite3.connect(cls.db_name) 

89 cursor = conn.cursor() 

90 cursor.execute('''CREATE TABLE mlt_test 

91 (simobjid int, ra real, decl real, sedfilename text, 

92 varParamStr text, parallax real, galacticAv real, 

93 magNorm real)''') 

94 conn.commit() 

95 

96 cursor.execute('''INSERT INTO mlt_test VALUES( 0, 25.0, 31.0, 

97 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

98 '{"m": "MLT", 

99 "p": {"lc": "lc_1.txt", "t0": 456.2}}', 

100 0.25, 2.432, 17.1)''') 

101 

102 cursor.execute('''INSERT INTO mlt_test VALUES( 1, 25.2, 32.0, 

103 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

104 '{"m": "MLT", 

105 "p": {"lc": "lc_1.txt", "t0": 41006.2}}', 

106 0.15, 1.876, 17.2)''') 

107 

108 cursor.execute('''INSERT INTO mlt_test VALUES( 2, 25.3, 10.0, 

109 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

110 '{"m": "MLT", 

111 "p": {"lc": "lc_2.txt", "t0": 117.2}}', 

112 0.3, 2.654, 17.3)''') 

113 

114 cursor.execute('''INSERT INTO mlt_test VALUES( 3, 25.4, 11.0, 

115 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

116 '{"m": "MLT", 

117 "p": {"lc": "lc_2.txt", "t0": 10456.2}}', 

118 0.22, 2.364, 17.4)''') 

119 conn.commit() 

120 conn.close() 

121 

122 

123 @classmethod 

124 def tearDownClass(cls): 

125 sims_clean_up() 

126 if os.path.exists(cls.mlt_lc_name): 

127 os.unlink(cls.mlt_lc_name) 

128 

129 if os.path.exists(cls.db_name): 

130 os.unlink(cls.db_name) 

131 

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

133 shutil.rmtree(cls.scratch_dir, ignore_errors=True) 

134 

135 def test_flare_lc_failure(self): 

136 """ 

137 Test that the correct exception is thrown when you try 

138 to interpolate from an MLT light curve cache that does not 

139 exist 

140 """ 

141 with getTempFilePath('.txt') as cat_name: 

142 db = MLT_test_DB(database=self.db_name, driver='sqlite') 

143 obs = ObservationMetaData(mjd=67432.1) 

144 flare_cat = FlaringCatalog(db, obs_metadata=obs) 

145 flare_cat._mlt_lc_file = 'a_nonexistent_cache' 

146 with self.assertRaises(RuntimeError) as context: 

147 flare_cat.write_catalog(cat_name) 

148 self.assertIn('get_mdwarf_flares.sh', 

149 context.exception.args[0]) 

150 

151 def test_flare_magnitudes(self): 

152 """ 

153 Test that we get the expected magnitudes out 

154 """ 

155 db = MLT_test_DB(database=self.db_name, driver='sqlite') 

156 

157 # load the quiescent SEDs of the objects in our catalog 

158 sed_list = SedList(['lte028-5.0+0.5a+0.0.BT-Settl.spec.gz']*4, 

159 [17.1, 17.2, 17.3, 17.4], 

160 galacticAvList = [2.432, 1.876, 2.654, 2.364], 

161 fileDir=getPackageDir('sims_sed_library'), 

162 specMap=defaultSpecMap) 

163 

164 bp_dict = BandpassDict.loadTotalBandpassesFromFiles() 

165 

166 # calculate the quiescent fluxes of the objects in our catalog 

167 baseline_fluxes = bp_dict.fluxListForSedList(sed_list) 

168 

169 bb_wavelen = np.arange(100.0, 1600.0, 0.1) 

170 bb = models.BlackBody(temperature=9000.0 * u.K, scale=1.0 * u.erg / (u.cm ** 2 * u.AA * u.s * u.sr)) 

171 bb_flambda = bb(bb_wavelen * u.nm).to_value() 

172 

173 # this data is taken from the setUpClass() classmethod above 

174 t0_list = [456.2, 41006.2, 117.2, 10456.2] 

175 av_list = [2.432, 1.876, 2.654, 2.364] 

176 parallax_list = np.array([0.25, 0.15, 0.3, 0.22]) 

177 distance_list = 1.0/(206265.0*radiansFromArcsec(0.001*parallax_list)) 

178 distance_list *= 3.0857e18 # convert to cm 

179 

180 dtype = np.dtype([('id', int), ('u', float), ('g', float)]) 

181 

182 photParams = PhotometricParameters() 

183 

184 ss = Sed() 

185 

186 quiet_cat_name = os.path.join(self.scratch_dir, 'mlt_quiet_cat.txt') 

187 flare_cat_name = os.path.join(self.scratch_dir, 'mlt_flaring_cat.txt') 

188 

189 # loop over several MJDs and verify that, to within a 

190 # milli-mag, our flaring model gives us the magnitudes 

191 # expected, given the light curves specified in 

192 # setUpClass() 

193 for mjd in (59580.0, 60000.0, 70000.0, 80000.0): 

194 

195 obs = ObservationMetaData(mjd=mjd) 

196 

197 quiet_cat = QuiescentCatalog(db, obs_metadata=obs) 

198 quiet_cat.write_catalog(quiet_cat_name) 

199 

200 flare_cat = FlaringCatalog(db, obs_metadata=obs) 

201 flare_cat._mlt_lc_file = self.mlt_lc_name 

202 flare_cat.write_catalog(flare_cat_name) 

203 

204 quiescent_data = np.genfromtxt(quiet_cat_name, dtype=dtype, delimiter=',') 

205 flaring_data = np.genfromtxt(flare_cat_name, dtype=dtype, delimiter=',') 

206 self.assertGreater(len(flaring_data), 3) 

207 

208 for ix in range(len(flaring_data)): 

209 obj_id = flaring_data['id'][ix] 

210 self.assertEqual(obj_id, ix) 

211 

212 # the models below are as specified in the 

213 # setUpClass() method 

214 if obj_id == 0 or obj_id == 1: 

215 amp = 1.0e42 

216 dt = 3652.5 

217 t_min = flare_cat._survey_start - t0_list[obj_id] 

218 

219 tt = mjd - t_min 

220 while tt > dt: 

221 tt -= dt 

222 

223 u_flux = amp*(1.0+np.power(np.sin(tt/100.0), 2)) 

224 g_flux = amp*(1.0+np.power(np.cos(tt/100.0), 2)) 

225 else: 

226 amp = 2.0e41 

227 dt = 365.25 

228 t_min = flare_cat._survey_start - t0_list[obj_id] 

229 

230 tt = mjd - t_min 

231 while tt > dt: 

232 tt -= dt 

233 u_flux = amp*(1.0+np.power(np.sin(tt/50.0), 2)) 

234 g_flux = amp*(1.0+np.power(np.cos(tt/50.0), 2)) 

235 

236 # calculate the multiplicative effect of dust on a 9000K 

237 # black body 

238 bb_sed = Sed(wavelen=bb_wavelen, flambda=bb_flambda) 

239 u_bb_flux = bb_sed.calcFlux(bp_dict['u']) 

240 g_bb_flux = bb_sed.calcFlux(bp_dict['g']) 

241 a_x, b_x = bb_sed.setupCCM_ab() 

242 bb_sed.addDust(a_x, b_x, A_v=av_list[obj_id]) 

243 u_bb_dusty_flux = bb_sed.calcFlux(bp_dict['u']) 

244 g_bb_dusty_flux = bb_sed.calcFlux(bp_dict['g']) 

245 

246 dust_u = u_bb_dusty_flux/u_bb_flux 

247 dust_g = g_bb_dusty_flux/g_bb_flux 

248 

249 area = 4.0*np.pi*np.power(distance_list[obj_id], 2) 

250 tot_u_flux = baseline_fluxes[obj_id][0] + u_flux*dust_u/area 

251 tot_g_flux = baseline_fluxes[obj_id][1] + g_flux*dust_g/area 

252 

253 msg = ('failed on object %d; mjd %.2f\n u_quiet %e u_flare %e\n g_quiet %e g_flare %e' % 

254 (obj_id, mjd, quiescent_data['u'][obj_id], flaring_data['u'][obj_id], 

255 quiescent_data['g'][obj_id], flaring_data['g'][obj_id])) 

256 

257 self.assertEqual(quiescent_data['id'][obj_id], flaring_data['id'][obj_id], msg=msg) 

258 self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][0]), 

259 quiescent_data['u'][obj_id], 3, msg=msg) 

260 self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][1]), 

261 quiescent_data['g'][obj_id], 3, msg=msg) 

262 self.assertAlmostEqual(ss.magFromFlux(tot_u_flux), flaring_data['u'][obj_id], 

263 3, msg=msg) 

264 self.assertAlmostEqual(ss.magFromFlux(tot_g_flux), flaring_data['g'][obj_id], 

265 3, msg=msg) 

266 self.assertGreater(np.abs(flaring_data['g'][obj_id]-quiescent_data['g'][obj_id]), 

267 0.001, msg=msg) 

268 self.assertGreater(np.abs(flaring_data['u'][obj_id]-quiescent_data['u'][obj_id]), 

269 0.001, msg=msg) 

270 

271 if os.path.exists(quiet_cat_name): 

272 os.unlink(quiet_cat_name) 

273 if os.path.exists(flare_cat_name): 

274 os.unlink(flare_cat_name) 

275 

276 def test_MLT_many_mjd(self): 

277 """ 

278 This test will verify that applyMLTflaring responds properly when given 

279 an array/vector of MJD values. 

280 """ 

281 db = MLT_test_DB(database=self.db_name, driver='sqlite') 

282 rng = np.random.RandomState(16) 

283 mjd_arr = rng.random_sample(17)*3653.3+59580.0 

284 objid = [] 

285 parallax = [] 

286 ebv = [] 

287 quiescent_u = [] 

288 quiescent_g = [] 

289 delta_u = [] 

290 delta_g = [] 

291 varparams = [] 

292 for mjd in mjd_arr: 

293 obs = ObservationMetaData(mjd=mjd) 

294 cat = FlaringCatalog(db, obs_metadata=obs, 

295 column_outputs=['parallax', 'ebv', 

296 'quiescent_lsst_u', 

297 'quiescent_lsst_g', 

298 'varParamStr', 

299 'delta_lsst_u', 

300 'delta_lsst_g']) 

301 

302 cat._mlt_lc_file = self.mlt_lc_name 

303 n_obj = 0 

304 for line in cat.iter_catalog(): 

305 n_obj += 1 

306 objid.append(line[0]) 

307 parallax.append(line[3]) 

308 ebv.append(line[4]) 

309 quiescent_u.append(line[5]) 

310 quiescent_g.append(line[6]) 

311 varparams.append(line[7]) 

312 delta_u.append(line[8]) 

313 delta_g.append(line[9]) 

314 

315 objid = np.array(objid) 

316 parallax = np.array(parallax) 

317 ebv = np.array(ebv) 

318 quiescent_u = np.array(quiescent_u) 

319 quiescent_g = np.array(quiescent_g) 

320 delta_u = np.array(delta_u) 

321 delta_g = np.array(delta_g) 

322 

323 self.assertEqual(len(parallax), n_obj*len(mjd_arr)) 

324 np.testing.assert_array_equal(objid, np.array([0,1,2,3]*len(mjd_arr))) 

325 

326 quiescent_mags = {} 

327 quiescent_mags['u'] = quiescent_u 

328 quiescent_mags['g'] = quiescent_g 

329 

330 params = {} 

331 params['lc'] = [] 

332 params['t0'] = [] 

333 for ix in range(4): 

334 local_dict = json.loads(varparams[ix]) 

335 params['lc'].append(local_dict['p']['lc']) 

336 params['t0'].append(local_dict['p']['t0']) 

337 params['lc'] = np.array(params['lc']) 

338 params['t0'] = np.array(params['t0']) 

339 

340 mlt_obj = MLTflaringMixin() 

341 mlt_obj.photParams = PhotometricParameters() 

342 mlt_obj.lsstBandpassDict = BandpassDict.loadTotalBandpassesFromFiles() 

343 mlt_obj._mlt_lc_file = cat._mlt_lc_file 

344 mlt_obj._actually_calculated_columns = ['delta_lsst_u', 'delta_lsst_g'] 

345 valid_dex = [np.arange(4, dtype=int)] 

346 delta_mag_vector = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr, 

347 parallax=parallax, 

348 ebv=ebv, 

349 quiescent_mags=quiescent_mags) 

350 n_time = len(mjd_arr) 

351 n_obj = 4 

352 self.assertEqual(delta_mag_vector.shape, (6, n_obj, n_time)) 

353 

354 for i_time, mjd in enumerate(mjd_arr): 

355 for i_obj in range(n_obj): 

356 for i_band in range(6): 

357 if i_band==0: 

358 self.assertEqual(delta_mag_vector[i_band][i_obj][i_time], 

359 delta_u[i_time*n_obj + i_obj]) 

360 elif i_band==1: 

361 self.assertEqual(delta_mag_vector[i_band][i_obj][i_time], 

362 delta_g[i_time*n_obj + i_obj]) 

363 else: 

364 self.assertEqual(delta_mag_vector[i_band][i_obj][i_time], 0.0) 

365 

366 # test that delta_flux is correctly calculated 

367 delta_flux_vector = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr, 

368 parallax=parallax, 

369 ebv=ebv, 

370 quiescent_mags=quiescent_mags, 

371 do_mags=False) 

372 

373 self.assertEqual(delta_flux_vector.shape, delta_mag_vector.shape) 

374 

375 dummy_sed = Sed() 

376 for i_band in range(6): 

377 if i_band>=2: 

378 # because we only implemented models of variability for u, g 

379 np.testing.assert_array_equal(delta_flux_vector[i_band], 

380 np.zeros(delta_flux_vector[i_band].shape, dtype=float)) 

381 continue 

382 for i_obj in range(n_obj): 

383 mag0 = quiescent_mags['ug'[i_band]][i_obj] 

384 flux0 = dummy_sed.fluxFromMag(mag0) 

385 delta_flux_control = dummy_sed.fluxFromMag(mag0 + delta_mag_vector[i_band][i_obj])-flux0 

386 err = np.abs(delta_flux_vector[i_band][i_obj]-delta_flux_control)/np.abs(delta_flux_control) 

387 self.assertLess(err.max(), 1.0e-10) 

388 

389 # test fluxes on just one mjd 

390 delta_flux_single_time = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr[3], 

391 parallax=parallax, 

392 ebv=ebv, 

393 quiescent_mags=quiescent_mags, 

394 do_mags=False) 

395 

396 self.assertEqual(delta_flux_single_time.shape, (6, n_obj)) 

397 np.testing.assert_array_equal(delta_flux_single_time, delta_flux_vector[:,:,3]) 

398 

399 def test_MLT_many_mjd_some_invalid(self): 

400 """ 

401 This test will verify that applyMLTflaring responds properly when given 

402 an array/vector of MJD values in the case where some stars are not 

403 marked as valid MLT stars. 

404 """ 

405 db = MLT_test_DB(database=self.db_name, driver='sqlite') 

406 rng = np.random.RandomState(16) 

407 mjd_arr = rng.random_sample(17)*3653.3+59580.0 

408 objid = [] 

409 parallax = [] 

410 ebv = [] 

411 quiescent_u = [] 

412 quiescent_g = [] 

413 delta_u = [] 

414 delta_g = [] 

415 varparams = [] 

416 for mjd in mjd_arr: 

417 obs = ObservationMetaData(mjd=mjd) 

418 cat = FlaringCatalog(db, obs_metadata=obs, 

419 column_outputs=['parallax', 'ebv', 

420 'quiescent_lsst_u', 

421 'quiescent_lsst_g', 

422 'varParamStr', 

423 'delta_lsst_u', 

424 'delta_lsst_g']) 

425 

426 cat._mlt_lc_file = self.mlt_lc_name 

427 n_obj = 0 

428 for line in cat.iter_catalog(): 

429 n_obj += 1 

430 objid.append(line[0]) 

431 parallax.append(line[3]) 

432 ebv.append(line[4]) 

433 quiescent_u.append(line[5]) 

434 quiescent_g.append(line[6]) 

435 varparams.append(line[7]) 

436 delta_u.append(line[8]) 

437 delta_g.append(line[9]) 

438 

439 objid = np.array(objid) 

440 parallax = np.array(parallax) 

441 ebv = np.array(ebv) 

442 quiescent_u = np.array(quiescent_u) 

443 quiescent_g = np.array(quiescent_g) 

444 delta_u = np.array(delta_u) 

445 delta_g = np.array(delta_g) 

446 

447 self.assertEqual(len(parallax), n_obj*len(mjd_arr)) 

448 np.testing.assert_array_equal(objid, np.array([0,1,2,3]*len(mjd_arr))) 

449 

450 quiescent_mags = {} 

451 quiescent_mags['u'] = quiescent_u 

452 quiescent_mags['g'] = quiescent_g 

453 

454 params = {} 

455 params['lc'] = [] 

456 params['t0'] = [] 

457 for ix in range(n_obj): 

458 local_dict = json.loads(varparams[ix]) 

459 params['lc'].append(local_dict['p']['lc']) 

460 params['t0'].append(local_dict['p']['t0']) 

461 params['lc'] = np.array(params['lc']) 

462 params['t0'] = np.array(params['t0']) 

463 

464 mlt_obj = MLTflaringMixin() 

465 mlt_obj.photParams = PhotometricParameters() 

466 mlt_obj.lsstBandpassDict = BandpassDict.loadTotalBandpassesFromFiles() 

467 mlt_obj._mlt_lc_file = cat._mlt_lc_file 

468 mlt_obj._actually_calculated_columns = ['delta_lsst_u', 'delta_lsst_g'] 

469 valid_dex = [] # applyMLT does not actually use valid_dex; it looks for non-None params['lc'] 

470 for ix in range(n_obj): 

471 if ix not in (1,2): 

472 params['lc'][ix] = None 

473 delta_mag_vector = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr, 

474 parallax=parallax, 

475 ebv=ebv, 

476 quiescent_mags=quiescent_mags) 

477 n_time = len(mjd_arr) 

478 self.assertEqual(delta_mag_vector.shape, (6, n_obj, n_time)) 

479 

480 for i_time, mjd in enumerate(mjd_arr): 

481 for i_obj in range(n_obj): 

482 if i_obj not in (1,2): 

483 for i_band in range(6): 

484 self.assertEqual(delta_mag_vector[i_band][i_obj][i_time], 0.0) 

485 continue 

486 

487 for i_band in range(6): 

488 if i_band==0: 

489 self.assertEqual(delta_mag_vector[i_band][i_obj][i_time], 

490 delta_u[i_time*n_obj + i_obj]) 

491 elif i_band==1: 

492 self.assertEqual(delta_mag_vector[i_band][i_obj][i_time], 

493 delta_g[i_time*n_obj + i_obj]) 

494 else: 

495 self.assertEqual(delta_mag_vector[i_band][i_obj][i_time], 0.0) 

496 

497 # test that delta_flux is correctly calculated 

498 delta_flux_vector = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr, 

499 parallax=parallax, 

500 ebv=ebv, 

501 quiescent_mags=quiescent_mags, 

502 do_mags=False) 

503 

504 self.assertEqual(delta_flux_vector.shape, delta_mag_vector.shape) 

505 

506 dummy_sed = Sed() 

507 for i_band in range(6): 

508 if i_band>=2: 

509 # because we only implemented models of variability for u, g 

510 np.testing.assert_array_equal(delta_flux_vector[i_band], 

511 np.zeros(delta_flux_vector[i_band].shape, dtype=float)) 

512 continue 

513 for i_obj in range(n_obj): 

514 mag0 = quiescent_mags['ug'[i_band]][i_obj] 

515 flux0 = dummy_sed.fluxFromMag(mag0) 

516 delta_flux_control = dummy_sed.fluxFromMag(mag0 + delta_mag_vector[i_band][i_obj])-flux0 

517 denom = np.abs(delta_flux_control) 

518 denom = np.where(denom>0.0, denom, 1.0e-20) 

519 err = np.abs(delta_flux_vector[i_band][i_obj]-delta_flux_control)/denom 

520 self.assertLess(err.max(), 1.0e-10) 

521 

522 def test_selective_MLT_magnitudes(self): 

523 """ 

524 This test will verify that applyMLTflaring responds correctly 

525 when mag_name_tuple is set to simulate only a subset of bandpasses 

526 """ 

527 rng =np.random.RandomState(87124) 

528 n_stars = 1000 

529 n_time = 5 

530 quiescent_mags = {} 

531 quiescent_mags['u'] = rng.random_sample(n_stars)*5.0+17.0 

532 quiescent_mags['g'] = rng.random_sample(n_stars)*5.0+17.0 

533 ebv = rng.random_sample(n_stars)*4.0 

534 parallax = rng.random_sample(n_stars)*np.radians(0.001/3600.0) 

535 

536 available_lc = np.array(['lc_1', 'lc_2']) 

537 

538 params = {} 

539 params['lc'] = rng.choice(available_lc, size=n_stars) 

540 params['t0'] = rng.random_sample(n_stars)*1000.0 

541 mjd_arr = rng.random_sample(n_time)*500.0*59580.0 

542 

543 mlt_obj = MLTflaringMixin() 

544 mlt_obj.photParams = PhotometricParameters() 

545 mlt_obj.lsstBandpassDict = BandpassDict.loadTotalBandpassesFromFiles() 

546 mlt_obj._mlt_lc_file = self.mlt_lc_name 

547 mlt_obj._actually_calculated_columns = ['delta_lsst_u', 'delta_lsst_g'] 

548 valid_dex = [] # applyMLT does not actually use valid_dex; it looks for non-None params['lc'] 

549 valid_obj = rng.choice(np.arange(n_stars, dtype=int), size=50) 

550 for ix in range(n_stars): 

551 if ix not in valid_obj: 

552 params['lc'][ix] = None 

553 delta_mag_vector = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr, 

554 parallax=parallax, 

555 ebv=ebv, 

556 quiescent_mags=quiescent_mags) 

557 n_time = len(mjd_arr) 

558 self.assertEqual(delta_mag_vector.shape, (6, n_stars, n_time)) 

559 

560 # test that delta_flux is correctly calculated 

561 delta_flux_vector = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr, 

562 parallax=parallax, 

563 ebv=ebv, 

564 quiescent_mags=quiescent_mags, 

565 do_mags=False) 

566 

567 self.assertEqual(delta_flux_vector.shape, delta_mag_vector.shape) 

568 

569 dummy_sed = Sed() 

570 for i_band in range(6): 

571 if i_band>=2: 

572 # because we only implemented models of variability for u, g 

573 np.testing.assert_array_equal(delta_flux_vector[i_band], 

574 np.zeros(delta_flux_vector[i_band].shape, dtype=float)) 

575 continue 

576 for i_obj in range(n_stars): 

577 mag0 = quiescent_mags['ug'[i_band]][i_obj] 

578 flux0 = dummy_sed.fluxFromMag(mag0) 

579 delta_flux_control = dummy_sed.fluxFromMag(mag0 + delta_mag_vector[i_band][i_obj])-flux0 

580 denom = np.abs(delta_flux_control) 

581 denom = np.where(denom>0.0, denom, 1.0e-20) 

582 err = np.abs(delta_flux_vector[i_band][i_obj]-delta_flux_control)/denom 

583 self.assertLess(err.max(), 1.0e-6) 

584 

585 # see that we get the same results as before when we request a subset 

586 # of magnitudes 

587 

588 test_mag_vector = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr, 

589 parallax=parallax, 

590 ebv=ebv, 

591 quiescent_mags=quiescent_mags, 

592 mag_name_tuple=('g','i')) 

593 

594 

595 non_zero = np.where(test_mag_vector[0]<0.0) 

596 self.assertGreater(len(non_zero[0]), 0) 

597 

598 np.testing.assert_array_equal(test_mag_vector[0], 

599 delta_mag_vector[1]) 

600 

601 np.testing.assert_array_equal(test_mag_vector[1], 

602 delta_mag_vector[3]) 

603 

604 

605 test_flux_vector = mlt_obj.applyMLTflaring(valid_dex, params, mjd_arr, 

606 parallax=parallax, 

607 ebv=ebv, 

608 quiescent_mags=quiescent_mags, 

609 do_mags=False, 

610 mag_name_tuple=('u','z','g')) 

611 

612 non_zero = np.where(test_flux_vector[2]>0.0) 

613 self.assertGreater(len(non_zero[0]), 0) 

614 

615 np.testing.assert_array_equal(test_flux_vector[0], 

616 delta_flux_vector[0]) 

617 

618 np.testing.assert_array_equal(test_flux_vector[1], 

619 delta_flux_vector[4]) 

620 

621 np.testing.assert_array_equal(test_flux_vector[2], 

622 delta_flux_vector[1]) 

623 

624 def test_mlt_clean_up(self): 

625 """ 

626 Test that the MLT cache is correctly loaded after sims_clean_up is 

627 called. 

628 """ 

629 db = MLT_test_DB(database=self.db_name, driver='sqlite') 

630 obs = ObservationMetaData(mjd=60000.0) 

631 cat = FlaringCatalog(db, obs_metadata=obs) 

632 cat._mlt_lc_file = self.mlt_lc_name 

633 cat_name_1 = os.path.join(self.scratch_dir,'mlt_clean_test_cat_1.txt') 

634 cat.write_catalog(cat_name_1) 

635 sims_clean_up() 

636 

637 # re-generate the same catalog and verify that its 

638 # contents are unchanged 

639 db = MLT_test_DB(database=self.db_name, driver='sqlite') 

640 obs = ObservationMetaData(mjd=60000.0) 

641 cat = FlaringCatalog(db, obs_metadata=obs) 

642 cat._mlt_lc_file = self.mlt_lc_name 

643 cat_name_2 = os.path.join(self.scratch_dir,'mlt_clean_test_cat_2.txt') 

644 cat.write_catalog(cat_name_2) 

645 with open(cat_name_1, 'r') as in_file_1: 

646 lines_1 = in_file_1.readlines() 

647 with open(cat_name_2, 'r') as in_file_2: 

648 lines_2 = in_file_2.readlines() 

649 self.assertGreater(len(lines_1), 1) 

650 self.assertEqual(len(lines_1), len(lines_2)) 

651 for line in lines_1: 

652 self.assertIn(line, lines_2) 

653 

654 if os.path.exists(cat_name_1): 

655 os.unlink(cat_name_1) 

656 if os.path.exists(cat_name_2): 

657 os.unlink(cat_name_2) 

658 

659 

660class MLT_flare_mixed_with_none_model_test_case(unittest.TestCase): 

661 """ 

662 This test class duplicates MLT_flare_model_test_case, except 

663 that some of the objects in the database have 'None' for their 

664 varParamStr. 

665 """ 

666 

667 longMessage = True 

668 

669 @classmethod 

670 def setUpClass(cls): 

671 cls.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix='MLT_flare_mixed_with_none_model_test_case-') 

672 

673 # Create a dummy mlt light curve file 

674 cls.mlt_lc_name = os.path.join(cls.scratch_dir, 

675 'test_mlt_mixed_with_none_lc_file.npz') 

676 

677 lc_files = {} 

678 amp = 1.0e42 

679 lc_files['lc_1_time'] = np.arange(0.0, 3652.51, 0.1) 

680 lc_files['lc_1_u'] = amp*(1.0+np.power(np.sin(lc_files['lc_1_time']/100.0), 2)) 

681 lc_files['lc_1_g'] = amp*(1.0+np.power(np.cos(lc_files['lc_1_time']/100.0), 2)) 

682 

683 amp = 2.0e41 

684 lc_files['lc_2_time'] = np.arange(0.0, 365.251, 0.01) 

685 lc_files['lc_2_u'] = amp*(1.0+np.power(np.sin(lc_files['lc_2_time']/50.0), 2)) 

686 lc_files['lc_2_g'] = amp*(1.0+np.power(np.cos(lc_files['lc_2_time']/50.0), 2)) 

687 

688 with open(cls.mlt_lc_name, 'wb') as file_handle: 

689 np.savez(file_handle, **lc_files) 

690 

691 # Create a database of stars using these light curves 

692 cls.db_name = os.path.join(cls.scratch_dir, 'test_mlt_mixed_with_none_db.db') 

693 

694 conn = sqlite3.connect(cls.db_name) 

695 cursor = conn.cursor() 

696 cursor.execute('''CREATE TABLE mlt_test 

697 (simobjid int, ra real, decl real, sedfilename text, 

698 varParamStr text, parallax real, galacticAv real, 

699 magNorm real)''') 

700 conn.commit() 

701 

702 cursor.execute('''INSERT INTO mlt_test VALUES( 0, 25.0, 31.0, 

703 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

704 '{"m": "MLT", 

705 "p": {"lc": "lc_1.txt", "t0": 456.2}}', 

706 0.25, 2.432, 17.1)''') 

707 

708 cursor.execute('''INSERT INTO mlt_test VALUES( 1, 25.2, 32.0, 

709 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

710 '{"m": "MLT", 

711 "p": {"lc": "lc_1.txt", "t0": 41006.2}}', 

712 0.15, 1.876, 17.2)''') 

713 

714 cursor.execute('''INSERT INTO mlt_test VALUES( 2, 25.3, 10.0, 

715 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

716 '{"m": "MLT", 

717 "p": {"lc": "lc_2.txt", "t0": 117.2}}', 

718 0.3, 2.654, 17.3)''') 

719 

720 cursor.execute('''INSERT INTO mlt_test VALUES( 3, 25.4, 11.0, 

721 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', NULL, 

722 0.22, 2.364, 17.4)''') 

723 conn.commit() 

724 conn.close() 

725 

726 

727 @classmethod 

728 def tearDownClass(cls): 

729 sims_clean_up() 

730 if os.path.exists(cls.mlt_lc_name): 

731 os.unlink(cls.mlt_lc_name) 

732 

733 if os.path.exists(cls.db_name): 

734 os.unlink(cls.db_name) 

735 

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

737 shutil.rmtree(cls.scratch_dir, ignore_errors=True) 

738 

739 def test_flare_magnitudes_mixed_with_none(self): 

740 """ 

741 Test that we get the expected magnitudes out 

742 """ 

743 db = MLT_test_DB(database=self.db_name, driver='sqlite') 

744 

745 # load the quiescent SEDs of the objects in our catalog 

746 sed_list = SedList(['lte028-5.0+0.5a+0.0.BT-Settl.spec.gz']*4, 

747 [17.1, 17.2, 17.3, 17.4], 

748 galacticAvList = [2.432, 1.876, 2.654, 2.364], 

749 fileDir=getPackageDir('sims_sed_library'), 

750 specMap=defaultSpecMap) 

751 

752 bp_dict = BandpassDict.loadTotalBandpassesFromFiles() 

753 

754 # calculate the quiescent fluxes of the objects in our catalog 

755 baseline_fluxes = bp_dict.fluxListForSedList(sed_list) 

756 

757 bb_wavelen = np.arange(100.0, 1600.0, 0.1) 

758 bb = models.BlackBody(temperature=9000.0 * u.K, scale=1.0 * u.erg / (u.cm ** 2 * u.AA * u.s * u.sr)) 

759 bb_flambda = bb(bb_wavelen * u.nm).to_value() 

760 

761 # this data is taken from the setUpClass() classmethod above 

762 t0_list = [456.2, 41006.2, 117.2, 10456.2] 

763 av_list = [2.432, 1.876, 2.654, 2.364] 

764 parallax_list = np.array([0.25, 0.15, 0.3, 0.22]) 

765 distance_list = 1.0/(206265.0*radiansFromArcsec(0.001*parallax_list)) 

766 distance_list *= 3.0857e18 # convert to cm 

767 

768 dtype = np.dtype([('id', int), ('u', float), ('g', float)]) 

769 

770 photParams = PhotometricParameters() 

771 

772 ss = Sed() 

773 

774 quiet_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_none_quiet_cat.txt') 

775 flare_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_none_flaring_cat.txt') 

776 

777 # loop over several MJDs and verify that, to within a 

778 # milli-mag, our flaring model gives us the magnitudes 

779 # expected, given the light curves specified in 

780 # setUpClass() 

781 for mjd in (59580.0, 60000.0, 70000.0, 80000.0): 

782 

783 obs = ObservationMetaData(mjd=mjd) 

784 

785 quiet_cat = QuiescentCatalog(db, obs_metadata=obs) 

786 quiet_cat.write_catalog(quiet_cat_name) 

787 

788 flare_cat = FlaringCatalog(db, obs_metadata=obs) 

789 flare_cat._mlt_lc_file = self.mlt_lc_name 

790 flare_cat.write_catalog(flare_cat_name) 

791 

792 quiescent_data = np.genfromtxt(quiet_cat_name, dtype=dtype, delimiter=',') 

793 flaring_data = np.genfromtxt(flare_cat_name, dtype=dtype, delimiter=',') 

794 self.assertGreater(len(flaring_data), 3) 

795 

796 for ix in range(len(flaring_data)): 

797 obj_id = flaring_data['id'][ix] 

798 self.assertEqual(obj_id, ix) 

799 

800 # the models below are as specified in the 

801 # setUpClass() method 

802 if obj_id == 0 or obj_id == 1: 

803 amp = 1.0e42 

804 dt = 3652.5 

805 t_min = flare_cat._survey_start - t0_list[obj_id] 

806 

807 tt = mjd - t_min 

808 while tt > dt: 

809 tt -= dt 

810 

811 u_flux = amp*(1.0+np.power(np.sin(tt/100.0), 2)) 

812 g_flux = amp*(1.0+np.power(np.cos(tt/100.0), 2)) 

813 elif obj_id==2: 

814 amp = 2.0e41 

815 dt = 365.25 

816 t_min = flare_cat._survey_start - t0_list[obj_id] 

817 

818 tt = mjd - t_min 

819 while tt > dt: 

820 tt -= dt 

821 u_flux = amp*(1.0+np.power(np.sin(tt/50.0), 2)) 

822 g_flux = amp*(1.0+np.power(np.cos(tt/50.0), 2)) 

823 else: 

824 u_flux = 0.0 

825 g_flux = 0.0 

826 

827 # calculate the multiplicative effect of dust on a 9000K 

828 # black body 

829 bb_sed = Sed(wavelen=bb_wavelen, flambda=bb_flambda) 

830 u_bb_flux = bb_sed.calcFlux(bp_dict['u']) 

831 g_bb_flux = bb_sed.calcFlux(bp_dict['g']) 

832 a_x, b_x = bb_sed.setupCCM_ab() 

833 bb_sed.addDust(a_x, b_x, A_v=av_list[obj_id]) 

834 u_bb_dusty_flux = bb_sed.calcFlux(bp_dict['u']) 

835 g_bb_dusty_flux = bb_sed.calcFlux(bp_dict['g']) 

836 

837 dust_u = u_bb_dusty_flux/u_bb_flux 

838 dust_g = g_bb_dusty_flux/g_bb_flux 

839 

840 area = 4.0*np.pi*np.power(distance_list[obj_id], 2) 

841 tot_u_flux = baseline_fluxes[obj_id][0] + u_flux*dust_u/area 

842 tot_g_flux = baseline_fluxes[obj_id][1] + g_flux*dust_g/area 

843 

844 msg = ('failed on object %d; mjd %.2f\n u_quiet %e u_flare %e\n g_quiet %e g_flare %e' % 

845 (obj_id, mjd, quiescent_data['u'][obj_id], flaring_data['u'][obj_id], 

846 quiescent_data['g'][obj_id], flaring_data['g'][obj_id])) 

847 

848 self.assertEqual(quiescent_data['id'][obj_id], flaring_data['id'][obj_id], msg=msg) 

849 self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][0]), 

850 quiescent_data['u'][obj_id], 3, msg=msg) 

851 self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][1]), 

852 quiescent_data['g'][obj_id], 3, msg=msg) 

853 self.assertAlmostEqual(ss.magFromFlux(tot_u_flux), flaring_data['u'][obj_id], 

854 3, msg=msg) 

855 self.assertAlmostEqual(ss.magFromFlux(tot_g_flux), flaring_data['g'][obj_id], 

856 3, msg=msg) 

857 if obj_id != 3: 

858 self.assertGreater(np.abs(flaring_data['g'][obj_id]-quiescent_data['g'][obj_id]), 

859 0.001, msg=msg) 

860 self.assertGreater(np.abs(flaring_data['u'][obj_id]-quiescent_data['u'][obj_id]), 

861 0.001, msg=msg) 

862 else: 

863 self.assertEqual(flaring_data['g'][obj_id]-quiescent_data['g'][obj_id], 0.0, msg=msg) 

864 self.assertEqual(flaring_data['u'][obj_id]-quiescent_data['u'][obj_id], 0.0, msg=msg) 

865 

866 if os.path.exists(quiet_cat_name): 

867 os.unlink(quiet_cat_name) 

868 if os.path.exists(flare_cat_name): 

869 os.unlink(flare_cat_name) 

870 

871 

872from lsst.sims.catUtils.mixins import Variability 

873from lsst.sims.catalogs.decorators import register_method 

874 

875 

876class DummyVariabilityMixin(Variability): 

877 

878 scratch_dir = None 

879 

880 @register_method('dummy') 

881 def applyDummy(self, valid_dexes, params, expmjd, 

882 variability_cache=None): 

883 if len(params) == 0: 

884 return np.array([[],[],[],[],[],[]]) 

885 dtype = np.dtype([('t', float), ('du', float), ('dg', float), 

886 ('dr', float), ('di', float), ('dz', float), 

887 ('dy', float)]) 

888 dmag = np.zeros((6, self.num_variable_obj(params))) 

889 for ix in valid_dexes[0]: 

890 lc_name = os.path.join(self.scratch_dir, params['lc'][ix]) 

891 lc_data = np.genfromtxt(lc_name, dtype=dtype) 

892 dmag[0][ix] = np.interp(expmjd, lc_data['t'], lc_data['du']) 

893 dmag[1][ix] = np.interp(expmjd, lc_data['t'], lc_data['dg']) 

894 dmag[2][ix] = np.interp(expmjd, lc_data['t'], lc_data['dr']) 

895 dmag[3][ix] = np.interp(expmjd, lc_data['t'], lc_data['di']) 

896 dmag[4][ix] = np.interp(expmjd, lc_data['t'], lc_data['dz']) 

897 dmag[5][ix] = np.interp(expmjd, lc_data['t'], lc_data['dy']) 

898 return dmag 

899 

900class FlaringCatalogDummy(PhotometryStars, VariabilityStars, 

901 MLTflaringMixin, DummyVariabilityMixin, 

902 InstanceCatalog): 

903 column_outputs = ['id', 'lsst_u', 'lsst_g'] 

904 

905 

906class MLT_flare_mixed_with_dummy_model_test_case(unittest.TestCase): 

907 """ 

908 This test class duplicates MLT_flare_model_test_case, except 

909 that one of the objects in the database has a different 

910 variability method applied to it to make sure that 

911 applyVariability properly handles cases where two variability 

912 models have identically named params ('lc' in this case). 

913 """ 

914 

915 longMessage = True 

916 

917 @classmethod 

918 def setUpClass(cls): 

919 cls.scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix='MLT_flare_mixed_with_dummy_model_test_case-') 

920 

921 # Create a dummy mlt light curve file 

922 cls.mlt_lc_name = os.path.join(cls.scratch_dir, 

923 'test_mlt_mixed_with_dummy_lc_file.npz') 

924 

925 lc_files = {} 

926 amp = 1.0e42 

927 lc_files['lc_1_time'] = np.arange(0.0, 3652.51, 0.1) 

928 lc_files['lc_1_u'] = amp*(1.0+np.power(np.sin(lc_files['lc_1_time']/100.0), 2)) 

929 lc_files['lc_1_g'] = amp*(1.0+np.power(np.cos(lc_files['lc_1_time']/100.0), 2)) 

930 

931 amp = 2.0e41 

932 lc_files['lc_2_time'] = np.arange(0.0, 365.251, 0.01) 

933 lc_files['lc_2_u'] = amp*(1.0+np.power(np.sin(lc_files['lc_2_time']/50.0), 2)) 

934 lc_files['lc_2_g'] = amp*(1.0+np.power(np.cos(lc_files['lc_2_time']/50.0), 2)) 

935 

936 with open(cls.mlt_lc_name, 'wb') as file_handle: 

937 np.savez(file_handle, **lc_files) 

938 

939 # Create a database of stars using these light curves 

940 cls.db_name = os.path.join(cls.scratch_dir, 'test_mlt_mixed_with_dummy_db.db') 

941 

942 conn = sqlite3.connect(cls.db_name) 

943 cursor = conn.cursor() 

944 cursor.execute('''CREATE TABLE mlt_test 

945 (simobjid int, ra real, decl real, sedfilename text, 

946 varParamStr text, parallax real, galacticAv real, 

947 magNorm real)''') 

948 conn.commit() 

949 

950 cursor.execute('''INSERT INTO mlt_test VALUES( 0, 25.0, 31.0, 

951 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

952 '{"m": "MLT", 

953 "p": {"lc": "lc_1.txt", "t0": 456.2}}', 

954 0.25, 2.432, 17.1)''') 

955 

956 cursor.execute('''INSERT INTO mlt_test VALUES( 1, 25.2, 32.0, 

957 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

958 '{"m": "MLT", 

959 "p": {"lc": "lc_1.txt", "t0": 41006.2}}', 

960 0.15, 1.876, 17.2)''') 

961 

962 cursor.execute('''INSERT INTO mlt_test VALUES( 2, 25.3, 10.0, 

963 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

964 '{"m": "MLT", 

965 "p": {"lc": "lc_2.txt", "t0": 117.2}}', 

966 0.3, 2.654, 17.3)''') 

967 

968 cursor.execute('''INSERT INTO mlt_test VALUES( 3, 25.4, 11.0, 

969 'lte028-5.0+0.5a+0.0.BT-Settl.spec.gz', 

970 '{"m": "dummy", 

971 "p": {"lc": "dummy_lc.txt"}}', 

972 0.22, 2.364, 17.4)''') 

973 conn.commit() 

974 conn.close() 

975 

976 cls.dummy_lc_name = os.path.join(cls.scratch_dir, 'dummy_lc.txt') 

977 

978 with open(cls.dummy_lc_name, 'w') as output_file: 

979 for tt in np.arange(59580.0, 82000.0, 1000.0): 

980 output_file.write('%e %e %e %e %e %e %e\n' % 

981 (tt, 2*(tt-59580.0)/10000.0, 

982 3*(tt-59580.0)/10000.0, 

983 4*(tt-59580.0)/10000.0, 

984 5*(tt-59580.0)/10000.0, 

985 6*(tt-59580.0)/10000.0, 

986 7*(tt-59580.0)/10000.0)) 

987 

988 @classmethod 

989 def tearDownClass(cls): 

990 sims_clean_up() 

991 if os.path.exists(cls.mlt_lc_name): 

992 os.unlink(cls.mlt_lc_name) 

993 

994 if os.path.exists(cls.db_name): 

995 os.unlink(cls.db_name) 

996 

997 if os.path.exists(cls.dummy_lc_name): 

998 os.unlink(cls.dummy_lc_name) 

999 

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

1001 shutil.rmtree(cls.scratch_dir, ignore_errors=True) 

1002 

1003 def test_flare_magnitudes_mixed_with_dummy(self): 

1004 """ 

1005 Test that we get the expected magnitudes out 

1006 """ 

1007 db = MLT_test_DB(database=self.db_name, driver='sqlite') 

1008 

1009 # load the quiescent SEDs of the objects in our catalog 

1010 sed_list = SedList(['lte028-5.0+0.5a+0.0.BT-Settl.spec.gz']*4, 

1011 [17.1, 17.2, 17.3, 17.4], 

1012 galacticAvList = [2.432, 1.876, 2.654, 2.364], 

1013 fileDir=getPackageDir('sims_sed_library'), 

1014 specMap=defaultSpecMap) 

1015 

1016 bp_dict = BandpassDict.loadTotalBandpassesFromFiles() 

1017 

1018 # calculate the quiescent fluxes of the objects in our catalog 

1019 baseline_fluxes = bp_dict.fluxListForSedList(sed_list) 

1020 

1021 bb_wavelen = np.arange(100.0, 1600.0, 0.1) 

1022 bb = models.BlackBody(temperature=9000.0 * u.K, scale=1.0 * u.erg / (u.cm ** 2 * u.AA * u.s * u.sr)) 

1023 bb_flambda = bb(bb_wavelen * u.nm).to_value() 

1024 

1025 # this data is taken from the setUpClass() classmethod above 

1026 t0_list = [456.2, 41006.2, 117.2, 10456.2] 

1027 av_list = [2.432, 1.876, 2.654, 2.364] 

1028 parallax_list = np.array([0.25, 0.15, 0.3, 0.22]) 

1029 distance_list = 1.0/(206265.0*radiansFromArcsec(0.001*parallax_list)) 

1030 distance_list *= 3.0857e18 # convert to cm 

1031 

1032 dtype = np.dtype([('id', int), ('u', float), ('g', float)]) 

1033 

1034 photParams = PhotometricParameters() 

1035 

1036 ss = Sed() 

1037 

1038 quiet_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_dummy_quiet_cat.txt') 

1039 flare_cat_name = os.path.join(self.scratch_dir, 'mlt_mixed_with_dummy_flaring_cat.txt') 

1040 

1041 # loop over several MJDs and verify that, to within a 

1042 # milli-mag, our flaring model gives us the magnitudes 

1043 # expected, given the light curves specified in 

1044 # setUpClass() 

1045 for mjd in (59580.0, 60000.0, 70000.0, 80000.0): 

1046 

1047 obs = ObservationMetaData(mjd=mjd) 

1048 

1049 quiet_cat = QuiescentCatalog(db, obs_metadata=obs) 

1050 quiet_cat.write_catalog(quiet_cat_name) 

1051 

1052 flare_cat = FlaringCatalogDummy(db, obs_metadata=obs) 

1053 flare_cat.scratch_dir = self.scratch_dir 

1054 flare_cat._mlt_lc_file = self.mlt_lc_name 

1055 flare_cat.write_catalog(flare_cat_name) 

1056 

1057 quiescent_data = np.genfromtxt(quiet_cat_name, dtype=dtype, delimiter=',') 

1058 flaring_data = np.genfromtxt(flare_cat_name, dtype=dtype, delimiter=',') 

1059 

1060 self.assertGreater(len(quiescent_data), 2) 

1061 self.assertEqual(len(quiescent_data), len(flaring_data)) 

1062 self.assertIn(3, flaring_data['id']) 

1063 

1064 for ix in range(len(flaring_data)): 

1065 obj_id = flaring_data['id'][ix] 

1066 self.assertEqual(obj_id, ix) 

1067 

1068 

1069 msg = ('failed on object %d; mjd %.2f\n u_quiet %e u_flare %e\n g_quiet %e g_flare %e' % 

1070 (obj_id, mjd, quiescent_data['u'][obj_id], flaring_data['u'][obj_id], 

1071 quiescent_data['g'][obj_id], flaring_data['g'][obj_id])) 

1072 

1073 self.assertEqual(quiescent_data['id'][obj_id], flaring_data['id'][obj_id], msg=msg) 

1074 self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][0]), 

1075 quiescent_data['u'][obj_id], 3, msg=msg) 

1076 self.assertAlmostEqual(ss.magFromFlux(baseline_fluxes[obj_id][1]), 

1077 quiescent_data['g'][obj_id], 3, msg=msg) 

1078 if obj_id != 3: 

1079 

1080 # the models below are as specified in the 

1081 # setUpClass() method 

1082 if obj_id == 0 or obj_id == 1: 

1083 amp = 1.0e42 

1084 dt = 3652.5 

1085 t_min = flare_cat._survey_start - t0_list[obj_id] 

1086 

1087 tt = mjd - t_min 

1088 while tt > dt: 

1089 tt -= dt 

1090 

1091 u_flux = amp*(1.0+np.power(np.sin(tt/100.0), 2)) 

1092 g_flux = amp*(1.0+np.power(np.cos(tt/100.0), 2)) 

1093 elif obj_id==2: 

1094 amp = 2.0e41 

1095 dt = 365.25 

1096 t_min = flare_cat._survey_start - t0_list[obj_id] 

1097 

1098 tt = mjd - t_min 

1099 while tt > dt: 

1100 tt -= dt 

1101 u_flux = amp*(1.0+np.power(np.sin(tt/50.0), 2)) 

1102 g_flux = amp*(1.0+np.power(np.cos(tt/50.0), 2)) 

1103 

1104 # calculate the multiplicative effect of dust on a 9000K 

1105 # black body 

1106 bb_sed = Sed(wavelen=bb_wavelen, flambda=bb_flambda) 

1107 u_bb_flux = bb_sed.calcFlux(bp_dict['u']) 

1108 g_bb_flux = bb_sed.calcFlux(bp_dict['g']) 

1109 a_x, b_x = bb_sed.setupCCM_ab() 

1110 bb_sed.addDust(a_x, b_x, A_v=av_list[obj_id]) 

1111 u_bb_dusty_flux = bb_sed.calcFlux(bp_dict['u']) 

1112 g_bb_dusty_flux = bb_sed.calcFlux(bp_dict['g']) 

1113 

1114 dust_u = u_bb_dusty_flux/u_bb_flux 

1115 dust_g = g_bb_dusty_flux/g_bb_flux 

1116 

1117 area = 4.0*np.pi*np.power(distance_list[obj_id], 2) 

1118 tot_u_flux = baseline_fluxes[obj_id][0] + u_flux*dust_u/area 

1119 tot_g_flux = baseline_fluxes[obj_id][1] + g_flux*dust_g/area 

1120 

1121 self.assertAlmostEqual(ss.magFromFlux(tot_u_flux), flaring_data['u'][obj_id], 

1122 3, msg=msg) 

1123 self.assertAlmostEqual(ss.magFromFlux(tot_g_flux), flaring_data['g'][obj_id], 

1124 3, msg=msg) 

1125 

1126 self.assertGreater(np.abs(flaring_data['g'][obj_id]-quiescent_data['g'][obj_id]), 

1127 0.001, msg=msg) 

1128 self.assertGreater(np.abs(flaring_data['u'][obj_id]-quiescent_data['u'][obj_id]), 

1129 0.001, msg=msg) 

1130 else: 

1131 self.assertAlmostEqual(flaring_data['g'][obj_id], 

1132 quiescent_data['g'][obj_id]+3*(mjd-59580.0)/10000.0, 

1133 3, msg=msg) 

1134 self.assertAlmostEqual(flaring_data['u'][obj_id], 

1135 quiescent_data['u'][obj_id]+2*(mjd-59580.0)/10000.0, 

1136 3, msg=msg) 

1137 

1138 if os.path.exists(quiet_cat_name): 

1139 os.unlink(quiet_cat_name) 

1140 if os.path.exists(flare_cat_name): 

1141 os.unlink(flare_cat_name) 

1142 

1143 

1144 

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

1146 pass 

1147 

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

1149 lsst.utils.tests.init() 

1150 unittest.main()