def testAppGeoFromICRS(self): mjd = 42350.0 for pmRaList in [self.pm_raList, None]: for pmDecList in [self.pm_decList, None]: for pxList in [self.pxList, None]: for vRadList in [self.v_radList, None]: raRad, decRad = utils._appGeoFromICRS( self.raList, self.decList, pmRaList, pmDecList, pxList, vRadList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.appGeoFromICRS( np.degrees(self.raList), np.degrees(self.decList), utils.arcsecFromRadians(pmRaList), utils.arcsecFromRadians(pmDecList), utils.arcsecFromRadians(pxList), vRadList, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal( dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal( dDec, np.zeros(self.nStars), 9)
def ssoInCameraFov(self, ephems, obsData): """Determine which observations are within the actual camera footprint for a series of observations. Note that ephems and obsData must be the same length. Parameters ---------- ephems : np.recarray Ephemerides for the objects. obsData : np.recarray Observation pointings. Returns ------- np.ndarray Returns the indexes of the numpy array of the object observations which are inside the fov. """ if not hasattr(self, 'camera'): self._setupCamera() epoch = 2000.0 # See if the object is within 'rFov' of the center of the boresight. idxObsRough = self._ssoInCircleFov(ephems, obsData, rFov=2.1) # Then test for the camera footprint exactly. idxObs = [] for idx in idxObsRough: mjd_date = obsData[idx][self.obsTimeCol] if self.obsTimeScale == 'TAI': mjd = ModifiedJulianDate(TAI=mjd_date) elif self.obsTimeScale == 'UTC': mjd = ModifiedJulianDate(UTC=mjd_date) else: warnings.warn( 'Expected timescale of TAI or UTC, but did not match. Using TAI.' ) mjd = ModifiedJulianDate(TAI=mjd_date) if not self.obsDegrees: obs_metadata = ObservationMetaData( pointingRA=np.degrees(obsData[idx][self.obsRA]), pointingDec=np.degrees(obsData[idx][self.obsDec]), rotSkyPos=np.degrees(obsData[idx][self.obsRotSkyPos]), mjd=mjd) else: obs_metadata = ObservationMetaData( pointingRA=obsData[idx][self.obsRA], pointingDec=obsData[idx][self.obsDec], rotSkyPos=obsData[idx][self.obsRotSkyPos], mjd=mjd) # Catch the warnings from astropy about the time being in the future. with warnings.catch_warnings(record=False): warnings.simplefilter('ignore') chipName = chipNameFromRaDec(ra=ephems['ra'][idx], dec=ephems['dec'][idx], epoch=epoch, obs_metadata=obs_metadata, camera=self.camera) if chipName is not None: tt = self.ccd_type_dict[self.camera[chipName].getType()] if tt == 'science': idxObs.append(idx) idxObs = np.array(idxObs, int) return idxObs
def test_tai_from_utc(self): """ Load a table of UTC vs. TAI (as JD) generated directly with ERFA. Verify our ModifiedJulianDate wrapper against this data. This is mostly so that we can catch any major API changes in astropy. """ file_name = os.path.join(getPackageDir('sims_utils'), 'tests') file_name = os.path.join(file_name, 'testData', 'utc_tai_comparison_data.txt') dtype = np.dtype([('utc', np.float), ('tai', np.float)]) data = np.genfromtxt(file_name, dtype=dtype) msg = "\n\nIt is possible you are using an out-of-date astropy.\n" + \ "Try running 'conda update astropy' and restarting the build." for uu, tt in zip(data['utc']-2400000.5, data['tai']-2400000.5): mjd = ModifiedJulianDate(UTC=uu) dd_sec = np.abs(mjd.TAI-tt)*86400.0 self.assertLess(dd_sec, 5.0e-5, msg=msg) self.assertAlmostEqual(mjd.UTC, uu, 15, msg=msg) mjd = ModifiedJulianDate(TAI=tt) dd_sec = np.abs(mjd.UTC-uu)*86400.0 self.assertLess(dd_sec, 5.0e-5, msg=msg) self.assertAlmostEqual(mjd.TAI, tt, 15, msg=msg)
def test_eq(self): mjd1 = ModifiedJulianDate(TAI=43000.0) mjd2 = ModifiedJulianDate(TAI=43000.0) self.assertEqual(mjd1, mjd2) self.assertTrue(mjd1 == mjd2) self.assertFalse(mjd1 != mjd2) mjd3 = ModifiedJulianDate(TAI=43000.01) self.assertNotEqual(mjd1, mjd3) self.assertFalse(mjd1 == mjd3) self.assertTrue(mjd1 != mjd3)
def testApplyProperMotion(self): for mjd in self.mjdList: raRad, decRad = utils._applyProperMotion( self.raList, self.decList, self.pm_raList, self.pm_decList, self.pxList, self.v_radList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.applyProperMotion( np.degrees(self.raList), np.degrees(self.decList), utils.arcsecFromRadians(self.pm_raList), utils.arcsecFromRadians(self.pm_decList), utils.arcsecFromRadians(self.pxList), self.v_radList, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9) for ra, dec, pm_ra, pm_dec, px, v_rad in \ zip(self.raList, self.decList, self.pm_raList, self.pm_decList, self.pxList, self.v_radList): raRad, decRad = utils._applyProperMotion( ra, dec, pm_ra, pm_dec, px, v_rad, mjd=ModifiedJulianDate(TAI=self.mjdList[0])) raDeg, decDeg = utils.applyProperMotion( np.degrees(ra), np.degrees(dec), utils.arcsecFromRadians(pm_ra), utils.arcsecFromRadians(pm_dec), utils.arcsecFromRadians(px), v_rad, mjd=ModifiedJulianDate(TAI=self.mjdList[0])) self.assertAlmostEqual( utils.arcsecFromRadians(raRad - np.radians(raDeg)), 0.0, 9) self.assertAlmostEqual( utils.arcsecFromRadians(decRad - np.radians(decDeg)), 0.0, 9)
def test_fast_agn_light_curves(self): raRange = (78.0, 85.0) decRange = (-69.0, -65.0) bandpass = ('g', 'r') slow_lc_gen = AgnLightCurveGenerator(self.agn_db, self.opsimDb) pointings = slow_lc_gen.get_pointings(raRange, decRange, bandpass=bandpass) for row in pointings: for obs in row: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd slow_lc, slow_truth = slow_lc_gen.light_curves_from_pointings( pointings) self.assertGreater(len(slow_lc), 2) # make sure we got some light curves fast_lc_gen = FastAgnLightCurveGenerator(self.agn_db, self.opsimDb) pointings = fast_lc_gen.get_pointings(raRange, decRange, bandpass=bandpass) for row in pointings: for obs in row: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd fast_lc, fast_truth = fast_lc_gen.light_curves_from_pointings( pointings) self.assertEqual(len(slow_lc), len(fast_lc)) self.assertEqual(len(slow_truth), len(fast_truth)) for obj_id in slow_lc: self.assertEqual(len(fast_lc[obj_id]), len(slow_lc[obj_id])) for bp in fast_lc[obj_id]: self.assertEqual(len(fast_lc[obj_id][bp]), len(slow_lc[obj_id][bp])) for data_key in fast_lc[obj_id][bp]: self.assertEqual(fast_lc[obj_id][bp][data_key].shape, slow_lc[obj_id][bp][data_key].shape) self.assertLess( np.abs(fast_lc[obj_id][bp][data_key] - slow_lc[obj_id][bp][data_key]).max(), 2.0e-10, msg='failed on %d, %s, %s' % (obj_id, bp, data_key))
def test_dut1(self): """ Test that UT1 is within 0.9 seconds of UTC and that dut1 is equal to UT1-UTC to within a microsecond. (Because calculating UT1-UTC requires loading a lookup table, we will just do this somewhat gross unit test to make sure that the astropy.time API doesn't change out from under us in some weird way... for instance, returning dut in units of days rather than seconds, etc.) """ rng = np.random.RandomState(117) utc_list = rng.random_sample(1000) * 10000.0 + 43000.0 for utc in utc_list: mjd = ModifiedJulianDate(UTC=utc) # first, test the self-consistency of ModifiedJulianData.dut1 # and ModifiedJulianData.UT1-ModifiedJulianData.UTC # # this only works for days on which a leap second is not applied dt = (mjd.UT1-mjd.UTC) * 86400.0 self.assertLess(np.abs(dt - mjd.dut1), 1.0e-5, msg='failed on UTC: %.12f' % mjd.UTC) self.assertLess(np.abs(mjd.dut1), 0.9)
def testApplyPrecession(self): for mjd in self.mjdList: raRad, decRad = utils._applyPrecession( self.raList, self.decList, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.applyPrecession( np.degrees(self.raList), np.degrees(self.decList), mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dRa, np.zeros(self.nStars), 9) dDec = utils.arcsecFromRadians(raRad - np.radians(raDeg)) np.testing.assert_array_almost_equal(dDec, np.zeros(self.nStars), 9)
def test_limited_agn_light_curves(self): """ Test that we can select only a limited number of agn light curves per field of view """ lc_limit = 2 raRange = (78.0, 82.0) decRange = (-69.0, -65.0) bandpass = '******' lc_gen = AgnLightCurveGenerator(self.agn_db, self.opsimDb) pointings = lc_gen.get_pointings(raRange, decRange, bandpass=bandpass) for row in pointings: for obs in row: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd self.assertEqual(len(pointings), 1) control_lc, truth = lc_gen.light_curves_from_pointings(pointings) self.assertGreater(len(control_lc), 2) test_lc, truth = lc_gen.light_curves_from_pointings( pointings, lc_per_field=lc_limit) self.assertGreater(len(control_lc), len(test_lc)) self.assertEqual(len(test_lc), lc_limit)
def __init__(self, boundType=None, boundLength=None, mjd=None, pointingRA=None, pointingDec=None, rotSkyPos=None, bandpassName=None, site=Site(name='LSST'), m5=None, skyBrightness=None, seeing=None): self._bounds = None self._boundType = boundType self._bandpass = bandpassName self._skyBrightness = skyBrightness self._site = site self._OpsimMetaData = None if mjd is not None: if isinstance(mjd, numbers.Number): self._mjd = ModifiedJulianDate(TAI=mjd) elif isinstance(mjd, ModifiedJulianDate): self._mjd = mjd else: raise RuntimeError( "You must pass either a float or a ModifiedJulianDate " "as the kwarg mjd to ObservationMetaData") else: self._mjd = None if rotSkyPos is not None: self._rotSkyPos = np.radians(rotSkyPos) else: self._rotSkyPos = None if pointingRA is not None: self._pointingRA = np.radians(pointingRA) else: self._pointingRA = None if pointingDec is not None: self._pointingDec = np.radians(pointingDec) else: self._pointingDec = None if boundLength is not None: self._boundLength = np.radians(boundLength) else: self._boundLength = None self._m5 = self._assignDictKeyedToBandpass(m5, 'm5') self._seeing = self._assignDictKeyedToBandpass(seeing, 'seeing') if self._bounds is None: self._buildBounds()
def testRaDecFromPupil(self): """ Test conversion from pupil coordinates back to Ra, Dec """ mjd = ModifiedJulianDate(TAI=52000.0) solarRA, solarDec = solarRaDec(mjd) # to make sure that we are more than 45 degrees from the Sun as required # for _icrsFromObserved to be at all accurate raCenter = solarRA + 100.0 decCenter = solarDec - 30.0 obs = ObservationMetaData(pointingRA=raCenter, pointingDec=decCenter, boundType='circle', boundLength=0.1, rotSkyPos=23.0, mjd=mjd) nSamples = 1000 rng = np.random.RandomState(42) ra = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(raCenter) dec = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(decCenter) xp, yp = _pupilCoordsFromRaDec(ra, dec, obs_metadata=obs, epoch=2000.0) raTest, decTest = _raDecFromPupilCoords(xp, yp, obs_metadata=obs, epoch=2000.0) distance = arcsecFromRadians(haversine(ra, dec, raTest, decTest)) dex = np.argmax(distance) worstSolarDistance = distanceToSun(np.degrees(ra[dex]), np.degrees(dec[dex]), mjd) msg = "_raDecFromPupilCoords off by %e arcsec at distance to Sun of %e degrees" % \ (distance.max(), worstSolarDistance) self.assertLess(distance.max(), 1.0e-6, msg=msg) # now check that passing in the xp, yp values one at a time still gives # the right answer for ix in range(len(ra)): ra_f, dec_f = _raDecFromPupilCoords(xp[ix], yp[ix], obs_metadata=obs, epoch=2000.0) self.assertIsInstance(ra_f, np.float) self.assertIsInstance(dec_f, np.float) dist_f = arcsecFromRadians( haversine(ra_f, dec_f, raTest[ix], decTest[ix])) self.assertLess(dist_f, 1.0e-9)
def mjd(self, value): """ Either a float or a ModifiedJulianDate. If a float, this setter assumes that you are passing in International Atomic Time """ if isinstance(value, float): self._mjd = ModifiedJulianDate(TAI=value) elif isinstance(value, ModifiedJulianDate): self._mjd = value else: raise RuntimeError( "You can only set mjd to either a float or a ModifiedJulianDate" )
def test_warnings(self): """ Test that warnings raised when trying to interpolate UT1-UTC for UTC too far in the future are of the type UTCtoUT1Warning """ with warnings.catch_warnings(record=True) as w_list: mjd = ModifiedJulianDate(1000000.0) # clear the warning registry, in case a previous test raised the warnings # we are looking for if '__warningregistry__' in mjd._warn_utc_out_of_bounds.__globals__: mjd._warn_utc_out_of_bounds.__globals__['__warningregistry__'].clear() warnings.simplefilter("always") # Trigger a warning. # Note that this may also trigger astropy warnings, # depending on the order in which tests are run. mjd.UT1 expected_MJD_warnings = 1 MJD_warnings = 0 for w in w_list: # Count the number of warnings and test we can filter by category. if w.category == UTCtoUT1Warning: MJD_warnings += 1 # Test that the string "ModifiedJulianDate.UT1" actually showed up in the message. # This indicates what method the warning occured from (UT1 vs dut). self.assertIn("ModifiedJulianDate.UT1", str(w.message)) self.assertEqual(expected_MJD_warnings, MJD_warnings, msg="UT1 did not emit a UTCtoUT1Warning") expected_MJD_warnings = 1 MJD_warnings = 0 with warnings.catch_warnings(record=True) as w_list: warnings.simplefilter('always') mjd = ModifiedJulianDate(1000000.0) mjd.dut1 for w in w_list: if w.category == UTCtoUT1Warning: MJD_warnings += 1 self.assertIn("ModifiedJulianDate.dut1", str(w.message)) self.assertEqual(expected_MJD_warnings, MJD_warnings, msg="dut1 did not emit a UTCtoUT1Warning")
def inCameraFov(self, ephems, obsData, epoch=2000.0, timeCol='observationStartMJD'): """Determine which observations are within the actual camera footprint for a series of observations. Parameters ---------- ephems : np.recarray Ephemerides for the objects, with RA and Dec as 'ra' and 'dec' columns (in degrees). obsData : np.recarray Observation pointings, with RA and Dec as 'ra' and 'dec' columns (in degrees). The telescope rotation angle should be in 'rotSkyPos' (in degrees), and the time of each pointing should be in the 'expMJD' column. epoch: float, opt The epoch of the ephemerides and pointing data. Default 2000.0. Returns ------- np.ndarray Returns the indexes of the numpy array of the object observations which are inside the fov. """ # See if the object is within 'rFov' of the center of the boresight. sep = angularSeparation(ephems['ra'], ephems['dec'], obsData['ra'], obsData['dec']) idxObsRough = np.where(sep <= 2.1)[0] # Or go on and use the camera footprint. idxObs = [] for idx in idxObsRough: mjd_date = obsData[idx][timeCol] mjd = ModifiedJulianDate(TAI=mjd_date) obs_metadata = ObservationMetaData( pointingRA=obsData[idx]['ra'], pointingDec=obsData[idx]['dec'], rotSkyPos=obsData[idx]['rotSkyPos'], mjd=mjd) # Catch the warnings from astropy about the time being in the future. with warnings.catch_warnings(record=False): warnings.simplefilter('ignore') chipName = chipNameFromRaDecLSST(ra=ephems['ra'][idx], dec=ephems['dec'][idx], epoch=epoch, obs_metadata=obs_metadata) if chipName != None: tt = self.ccd_type_dict[self.camera[chipName].getType()] if tt == 'science': idxObs.append(idx) idxObs = np.array(idxObs, int) return idxObs
def testIcrsFromAppGeo(self): for mjd in (53525.0, 54316.3, 58463.7): for epoch in (2000.0, 1950.0, 2010.0): raRad, decRad = utils._icrsFromAppGeo( self.raList, self.decList, epoch=epoch, mjd=ModifiedJulianDate(TAI=mjd)) raDeg, decDeg = utils.icrsFromAppGeo( np.degrees(self.raList), np.degrees(self.decList), epoch=epoch, mjd=ModifiedJulianDate(TAI=mjd)) dRa = utils.arcsecFromRadians(np.abs(raRad - np.radians(raDeg))) self.assertLess(dRa.max(), 1.0e-9) dDec = utils.arcsecFromRadians( np.abs(decRad - np.radians(decDeg))) self.assertLess(dDec.max(), 1.0e-9)
def ssoInFov(self, interpfuncs, simdata, rFov=1.75, useCamera=True, simdataRaCol='fieldRA', simdataDecCol='fieldDec', simdataExpMJDCol='expMJD'): """ Return the indexes of the simdata observations where the object was inside the fov. """ # See if the object is within 'rFov' of the center of the boresight. raSso = interpfuncs['ra'](simdata[simdataExpMJDCol]) decSso = interpfuncs['dec'](simdata[simdataExpMJDCol]) sep = angularSeparation(raSso, decSso, np.degrees(simdata[simdataRaCol]), np.degrees(simdata[simdataDecCol])) if not useCamera: idxObsRough = np.where(sep < rFov)[0] return idxObsRough # Or go on and use the camera footprint. idxObs = [] idxObsRough = np.where(sep < self.cameraFov)[0] for idx in idxObsRough: mjd_date = simdata[idx][simdataExpMJDCol] mjd = ModifiedJulianDate(TAI=mjd_date) obs_metadata = ObservationMetaData( pointingRA=np.degrees(simdata[idx][simdataRaCol]), pointingDec=np.degrees(simdata[idx][simdataDecCol]), rotSkyPos=np.degrees(simdata[idx]['rotSkyPos']), mjd=mjd) raObj = np.array( [interpfuncs['ra'](simdata[idx][simdataExpMJDCol])]) decObj = np.array( [interpfuncs['dec'](simdata[idx][simdataExpMJDCol])]) # Catch the warnings from astropy about the time being in the future. with warnings.catch_warnings(record=False): warnings.simplefilter('ignore') chipNames = chipNameFromRaDecLSST(ra=raObj, dec=decObj, epoch=self.epoch, obs_metadata=obs_metadata) if chipNames != [None]: idxObs.append(idx) idxObs = np.array(idxObs) return idxObs
def test_tt(self): """ Verify that Terrestrial Time is TAI + 32.184 seconds as in equation 2.223-6 of Explanatory Supplement to the Astrnomical Almanac ed. Seidelmann, Kenneth P. 1992, University Science Books Mostly, this test exists to catch any major API changes in astropy.time """ rng = np.random.RandomState(115) tai_list = rng.random_sample(1000)*7000.0+50000.0 for tai in tai_list: mjd = ModifiedJulianDate(TAI=tai) self.assertAlmostEqual(mjd.TT, tai + 32.184 / 86400.0, 15)
def test_list(self): """ Test that ModifiedJulianDate.get_list() gets results that are consistent with creating a list of ModifiedJulianDates by hand. """ rng = np.random.RandomState(88) tol = 10 # decimal place tolerance tai_list = 40000.0 + 10000.0 * rng.random_sample(20) tai_list = np.append(tai_list, 59580.0 + 10000.0 * rng.random_sample(20)) mjd_list = ModifiedJulianDate.get_list(TAI=tai_list) for tai, mjd in zip(tai_list, mjd_list): msg = "Offending TAI: %f" % tai control = ModifiedJulianDate(TAI=tai) self.assertAlmostEqual(mjd.TAI, tai, 11, msg=msg) self.assertAlmostEqual(mjd.TAI, control.TAI, tol, msg=msg) self.assertAlmostEqual(mjd.UTC, control.UTC, tol, msg=msg) self.assertAlmostEqual(mjd.UT1, control.UT1, tol, msg=msg) self.assertAlmostEqual(mjd.TT, control.TT, tol, msg=msg) self.assertAlmostEqual(mjd.TDB, control.TDB, tol, msg=msg) self.assertAlmostEqual(mjd.dut1, control.dut1, tol, msg=msg) utc_list = 40000.0 + 10000.0 * rng.random_sample(20) utc_list = np.append(utc_list, 59580.0 + 10000.0 * rng.random_sample(20)) mjd_list = ModifiedJulianDate.get_list(UTC=utc_list) for utc, mjd in zip(utc_list, mjd_list): msg = "Offending UTC: %f" % utc control = ModifiedJulianDate(UTC=utc) self.assertAlmostEqual(mjd.UTC, utc, tol, msg=msg) self.assertAlmostEqual(mjd.TAI, control.TAI, tol, msg=msg) self.assertAlmostEqual(mjd.UTC, control.UTC, tol, msg=msg) self.assertAlmostEqual(mjd.UT1, control.UT1, tol, msg=msg) self.assertAlmostEqual(mjd.TT, control.TT, tol, msg=msg) self.assertAlmostEqual(mjd.TDB, control.TDB, tol, msg=msg) self.assertAlmostEqual(mjd.dut1, control.dut1, tol, msg=msg) # Now test the case where we only have dates in the future (this # is an edge case since good_dexes in ModifiedJulianDate._get_ut1_from_utc # will have len = 0 tai_list = 60000.0 + 10000.0 * rng.random_sample(20) mjd_list = ModifiedJulianDate.get_list(TAI=tai_list) for tai, mjd in zip(tai_list, mjd_list): msg = "Offending TAI: %f" % tai control = ModifiedJulianDate(TAI=tai) self.assertAlmostEqual(mjd.TAI, tai, 11, msg=msg) self.assertAlmostEqual(mjd.TAI, control.TAI, tol, msg=msg) self.assertAlmostEqual(mjd.UTC, control.UTC, tol, msg=msg) self.assertAlmostEqual(mjd.UT1, control.UT1, tol, msg=msg) self.assertAlmostEqual(mjd.TT, control.TT, tol, msg=msg) self.assertAlmostEqual(mjd.TDB, control.TDB, tol, msg=msg) self.assertAlmostEqual(mjd.dut1, control.dut1, tol, msg=msg)
def test_tdb(self): """ Verify that TDB is within a few tens of microseconds of the value given by the approximation given by equation 2.222-1 of Explanatory Supplement to the Astrnomical Almanac ed. Seidelmann, Kenneth P. 1992, University Science Books Mostly, this test exists to catch any major API changes in astropy.time """ rng = np.random.RandomState(117) tai_list = rng.random_sample(1000)*10000.0 + 46000.0 for tai in tai_list: mjd = ModifiedJulianDate(TAI=tai) g = np.radians(357.53 + 0.9856003 * (np.round(tai - 51544.5))) tdb_test = mjd.TT + (0.001658 * np.sin(g) + 0.000014 * np.sin(2.0*g)) / 86400.0 dt = np.abs(tdb_test-mjd.TDB) * 8.64 * 1.0e10 # convert to microseconds self.assertLess(dt, 50)
def test_force_values(self): """ Test that we can force the properties of a ModifiedJulianDate to have specific values """ tt = ModifiedJulianDate(TAI=59580.0) values = np.arange(6) tt._force_values(values) self.assertEqual(tt.TAI, 0.0) self.assertEqual(tt.UTC, 1.0) self.assertEqual(tt.TT, 2.0) self.assertEqual(tt.TDB, 3.0) self.assertEqual(tt.UT1, 4.0) self.assertEqual(tt.dut1, 5.0) tt = ModifiedJulianDate(UTC=59580.0) values = 2.0*np.arange(6) tt._force_values(values) self.assertEqual(tt.TAI, 0.0) self.assertEqual(tt.UTC, 2.0) self.assertEqual(tt.TT, 4.0) self.assertEqual(tt.TDB, 6.0) self.assertEqual(tt.UT1, 8.0) self.assertEqual(tt.dut1, 10.0)
def test_alert_data_generation(self): dmag_cutoff = 0.005 mag_name_to_int = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z' : 4, 'y': 5} _max_var_param_str = self.max_str_len class StarAlertTestDBObj(StellarAlertDBObjMixin, CatalogDBObject): objid = 'star_alert' tableid = 'stars' idColKey = 'simobjid' raColName = 'ra' decColName = 'dec' objectTypeId = 0 columns = [('raJ2000', 'ra*0.01745329252'), ('decJ2000', 'dec*0.01745329252'), ('parallax', 'px*0.01745329252/3600.0'), ('properMotionRa', 'pmra*0.01745329252/3600.0'), ('properMotionDec', 'pmdec*0.01745329252/3600.0'), ('radialVelocity', 'vrad'), ('variabilityParameters', 'varParamStr', str, _max_var_param_str)] class TestAlertsVarCatMixin(object): @register_method('alert_test') def applyAlertTest(self, valid_dexes, params, expmjd, variability_cache=None): if len(params) == 0: return np.array([[], [], [], [], [], []]) if isinstance(expmjd, numbers.Number): dmags_out = np.zeros((6, self.num_variable_obj(params))) else: dmags_out = np.zeros((6, self.num_variable_obj(params), len(expmjd))) for i_star in range(self.num_variable_obj(params)): if params['amp'][i_star] is not None: dmags = params['amp'][i_star]*np.cos(params['per'][i_star]*expmjd) for i_filter in range(6): dmags_out[i_filter][i_star] = dmags return dmags_out class TestAlertsVarCat(TestAlertsVarCatMixin, AlertStellarVariabilityCatalog): pass class TestAlertsTruthCat(TestAlertsVarCatMixin, CameraCoords, AstrometryStars, Variability, InstanceCatalog): column_outputs = ['uniqueId', 'chipName', 'dmagAlert', 'magAlert'] camera = obs_lsst_phosim.PhosimMapper().camera @compound('delta_umag', 'delta_gmag', 'delta_rmag', 'delta_imag', 'delta_zmag', 'delta_ymag') def get_TruthVariability(self): return self.applyVariability(self.column_by_name('varParamStr')) @cached def get_dmagAlert(self): return self.column_by_name('delta_%smag' % self.obs_metadata.bandpass) @cached def get_magAlert(self): return self.column_by_name('%smag' % self.obs_metadata.bandpass) + \ self.column_by_name('dmagAlert') star_db = StarAlertTestDBObj(database=self.star_db_name, driver='sqlite') # assemble the true light curves for each object; we need to figure out # if their np.max(dMag) ever goes over dmag_cutoff; then we will know if # we are supposed to simulate them true_lc_dict = {} true_lc_obshistid_dict = {} is_visible_dict = {} obs_dict = {} max_obshistid = -1 n_total_observations = 0 for obs in self.obs_list: obs_dict[obs.OpsimMetaData['obsHistID']] = obs obshistid = obs.OpsimMetaData['obsHistID'] if obshistid > max_obshistid: max_obshistid = obshistid cat = TestAlertsTruthCat(star_db, obs_metadata=obs) for line in cat.iter_catalog(): if line[1] is None: continue n_total_observations += 1 if line[0] not in true_lc_dict: true_lc_dict[line[0]] = {} true_lc_obshistid_dict[line[0]] = [] true_lc_dict[line[0]][obshistid] = line[2] true_lc_obshistid_dict[line[0]].append(obshistid) if line[0] not in is_visible_dict: is_visible_dict[line[0]] = False if line[3] <= self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]]: is_visible_dict[line[0]] = True obshistid_bits = int(np.ceil(np.log(max_obshistid)/np.log(2))) skipped_due_to_mag = 0 objects_to_simulate = [] obshistid_unqid_set = set() for obj_id in true_lc_dict: dmag_max = -1.0 for obshistid in true_lc_dict[obj_id]: if np.abs(true_lc_dict[obj_id][obshistid]) > dmag_max: dmag_max = np.abs(true_lc_dict[obj_id][obshistid]) if dmag_max >= dmag_cutoff: if not is_visible_dict[obj_id]: skipped_due_to_mag += 1 continue objects_to_simulate.append(obj_id) for obshistid in true_lc_obshistid_dict[obj_id]: obshistid_unqid_set.add((obj_id << obshistid_bits) + obshistid) self.assertGreater(len(objects_to_simulate), 10) self.assertGreater(skipped_due_to_mag, 0) log_file_name = tempfile.mktemp(dir=self.output_dir, suffix='log.txt') alert_gen = AlertDataGenerator(testing=True) alert_gen.subdivide_obs(self.obs_list, htmid_level=6) for htmid in alert_gen.htmid_list: alert_gen.alert_data_from_htmid(htmid, star_db, photometry_class=TestAlertsVarCat, output_prefix='alert_test', output_dir=self.output_dir, dmag_cutoff=dmag_cutoff, log_file_name=log_file_name) dummy_sed = Sed() bp_dict = BandpassDict.loadTotalBandpassesFromFiles() phot_params = PhotometricParameters() # First, verify that the contents of the sqlite files are all correct n_tot_simulated = 0 alert_query = 'SELECT alert.uniqueId, alert.obshistId, meta.TAI, ' alert_query += 'meta.band, quiescent.flux, alert.dflux, ' alert_query += 'quiescent.snr, alert.snr, ' alert_query += 'alert.ra, alert.dec, alert.chipNum, ' alert_query += 'alert.xPix, alert.yPix, ast.pmRA, ast.pmDec, ' alert_query += 'ast.parallax ' alert_query += 'FROM alert_data AS alert ' alert_query += 'INNER JOIN metadata AS meta ON meta.obshistId=alert.obshistId ' alert_query += 'INNER JOIN quiescent_flux AS quiescent ' alert_query += 'ON quiescent.uniqueId=alert.uniqueId ' alert_query += 'AND quiescent.band=meta.band ' alert_query += 'INNER JOIN baseline_astrometry AS ast ' alert_query += 'ON ast.uniqueId=alert.uniqueId' alert_dtype = np.dtype([('uniqueId', int), ('obshistId', int), ('TAI', float), ('band', int), ('q_flux', float), ('dflux', float), ('q_snr', float), ('tot_snr', float), ('ra', float), ('dec', float), ('chipNum', int), ('xPix', float), ('yPix', float), ('pmRA', float), ('pmDec', float), ('parallax', float)]) sqlite_file_list = os.listdir(self.output_dir) n_tot_simulated = 0 obshistid_unqid_simulated_set = set() for file_name in sqlite_file_list: if not file_name.endswith('db'): continue full_name = os.path.join(self.output_dir, file_name) self.assertTrue(os.path.exists(full_name)) alert_db = DBObject(full_name, driver='sqlite') alert_data = alert_db.execute_arbitrary(alert_query, dtype=alert_dtype) if len(alert_data) == 0: continue mjd_list = ModifiedJulianDate.get_list(TAI=alert_data['TAI']) for i_obj in range(len(alert_data)): n_tot_simulated += 1 obshistid_unqid_simulated_set.add((alert_data['uniqueId'][i_obj] << obshistid_bits) + alert_data['obshistId'][i_obj]) unq = alert_data['uniqueId'][i_obj] obj_dex = (unq//1024)-1 self.assertAlmostEqual(self.pmra_truth[obj_dex], 0.001*alert_data['pmRA'][i_obj], 4) self.assertAlmostEqual(self.pmdec_truth[obj_dex], 0.001*alert_data['pmDec'][i_obj], 4) self.assertAlmostEqual(self.px_truth[obj_dex], 0.001*alert_data['parallax'][i_obj], 4) ra_truth, dec_truth = applyProperMotion(self.ra_truth[obj_dex], self.dec_truth[obj_dex], self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex], self.px_truth[obj_dex], self.vrad_truth[obj_dex], mjd=mjd_list[i_obj]) distance = angularSeparation(ra_truth, dec_truth, alert_data['ra'][i_obj], alert_data['dec'][i_obj]) distance_arcsec = 3600.0*distance msg = '\ntruth: %e %e\nalert: %e %e\n' % (ra_truth, dec_truth, alert_data['ra'][i_obj], alert_data['dec'][i_obj]) self.assertLess(distance_arcsec, 0.0005, msg=msg) obs = obs_dict[alert_data['obshistId'][i_obj]] chipname = chipNameFromRaDec(self.ra_truth[obj_dex], self.dec_truth[obj_dex], pm_ra=self.pmra_truth[obj_dex], pm_dec=self.pmdec_truth[obj_dex], parallax=self.px_truth[obj_dex], v_rad=self.vrad_truth[obj_dex], obs_metadata=obs, camera=self.camera) chipnum = int(chipname.replace('R', '').replace('S', ''). replace(' ', '').replace(';', '').replace(',', ''). replace(':', '')) self.assertEqual(chipnum, alert_data['chipNum'][i_obj]) xpix, ypix = pixelCoordsFromRaDec(self.ra_truth[obj_dex], self.dec_truth[obj_dex], pm_ra=self.pmra_truth[obj_dex], pm_dec=self.pmdec_truth[obj_dex], parallax=self.px_truth[obj_dex], v_rad=self.vrad_truth[obj_dex], obs_metadata=obs, camera=self.camera) self.assertAlmostEqual(alert_data['xPix'][i_obj], xpix, 4) self.assertAlmostEqual(alert_data['yPix'][i_obj], ypix, 4) dmag_sim = -2.5*np.log10(1.0+alert_data['dflux'][i_obj]/alert_data['q_flux'][i_obj]) self.assertAlmostEqual(true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]], dmag_sim, 3) mag_name = ('u', 'g', 'r', 'i', 'z', 'y')[alert_data['band'][i_obj]] m5 = obs.m5[mag_name] q_mag = dummy_sed.magFromFlux(alert_data['q_flux'][i_obj]) self.assertAlmostEqual(self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex], q_mag, 4) snr, gamma = calcSNR_m5(self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex], bp_dict[mag_name], self.obs_mag_cutoff[alert_data['band'][i_obj]], phot_params) self.assertAlmostEqual(snr/alert_data['q_snr'][i_obj], 1.0, 4) tot_mag = self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex] + \ true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]] snr, gamma = calcSNR_m5(tot_mag, bp_dict[mag_name], m5, phot_params) self.assertAlmostEqual(snr/alert_data['tot_snr'][i_obj], 1.0, 4) for val in obshistid_unqid_set: self.assertIn(val, obshistid_unqid_simulated_set) self.assertEqual(len(obshistid_unqid_set), len(obshistid_unqid_simulated_set)) astrometry_query = 'SELECT uniqueId, ra, dec, TAI ' astrometry_query += 'FROM baseline_astrometry' astrometry_dtype = np.dtype([('uniqueId', int), ('ra', float), ('dec', float), ('TAI', float)]) tai_list = [] for obs in self.obs_list: tai_list.append(obs.mjd.TAI) tai_list = np.array(tai_list) n_tot_ast_simulated = 0 for file_name in sqlite_file_list: if not file_name.endswith('db'): continue full_name = os.path.join(self.output_dir, file_name) self.assertTrue(os.path.exists(full_name)) alert_db = DBObject(full_name, driver='sqlite') astrometry_data = alert_db.execute_arbitrary(astrometry_query, dtype=astrometry_dtype) if len(astrometry_data) == 0: continue mjd_list = ModifiedJulianDate.get_list(TAI=astrometry_data['TAI']) for i_obj in range(len(astrometry_data)): n_tot_ast_simulated += 1 obj_dex = (astrometry_data['uniqueId'][i_obj]//1024) - 1 ra_truth, dec_truth = applyProperMotion(self.ra_truth[obj_dex], self.dec_truth[obj_dex], self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex], self.px_truth[obj_dex], self.vrad_truth[obj_dex], mjd=mjd_list[i_obj]) distance = angularSeparation(ra_truth, dec_truth, astrometry_data['ra'][i_obj], astrometry_data['dec'][i_obj]) self.assertLess(3600.0*distance, 0.0005) del alert_gen gc.collect() self.assertGreater(n_tot_simulated, 10) self.assertGreater(len(obshistid_unqid_simulated_set), 10) self.assertLess(len(obshistid_unqid_simulated_set), n_total_observations) self.assertGreater(n_tot_ast_simulated, 0)
def testAssignment(self): """ Test that ObservationMetaData member variables get passed correctly """ mjd = 5120.0 RA = 1.5 Dec = -1.1 rotSkyPos = -10.0 skyBrightness = 25.0 testObsMD = ObservationMetaData() testObsMD.pointingRA = RA testObsMD.pointingDec = Dec testObsMD.rotSkyPos = rotSkyPos testObsMD.skyBrightness = skyBrightness testObsMD.mjd = mjd testObsMD.boundType = 'box' testObsMD.boundLength = [1.2, 3.0] self.assertAlmostEqual(testObsMD.pointingRA, RA, 10) self.assertAlmostEqual(testObsMD.pointingDec, Dec, 10) self.assertAlmostEqual(testObsMD.rotSkyPos, rotSkyPos, 10) self.assertAlmostEqual(testObsMD.skyBrightness, skyBrightness, 10) self.assertEqual(testObsMD.boundType, 'box') self.assertAlmostEqual(testObsMD.boundLength[0], 1.2, 10) self.assertAlmostEqual(testObsMD.boundLength[1], 3.0, 10) self.assertAlmostEqual(testObsMD.mjd.TAI, mjd, 10) # test reassignment testObsMD.pointingRA = RA + 1.0 testObsMD.pointingDec = Dec + 1.0 testObsMD.rotSkyPos = rotSkyPos + 1.0 testObsMD.skyBrightness = skyBrightness + 1.0 testObsMD.boundLength = 2.2 testObsMD.boundType = 'circle' testObsMD.mjd = mjd + 10.0 self.assertAlmostEqual(testObsMD.pointingRA, RA + 1.0, 10) self.assertAlmostEqual(testObsMD.pointingDec, Dec + 1.0, 10) self.assertAlmostEqual(testObsMD.rotSkyPos, rotSkyPos + 1.0, 10) self.assertAlmostEqual(testObsMD.skyBrightness, skyBrightness + 1.0, 10) self.assertEqual(testObsMD.boundType, 'circle') self.assertAlmostEqual(testObsMD.boundLength, 2.2, 10) self.assertAlmostEqual(testObsMD.mjd.TAI, mjd + 10.0, 10) testObsMD = ObservationMetaData(mjd=mjd, pointingRA=RA, pointingDec=Dec, rotSkyPos=rotSkyPos, bandpassName='z', skyBrightness=skyBrightness) self.assertAlmostEqual(testObsMD.mjd.TAI, 5120.0, 10) self.assertAlmostEqual(testObsMD.pointingRA, 1.5, 10) self.assertAlmostEqual(testObsMD.pointingDec, -1.1, 10) self.assertAlmostEqual(testObsMD.rotSkyPos, -10.0, 10) self.assertEqual(testObsMD.bandpass, 'z') self.assertAlmostEqual(testObsMD.skyBrightness, skyBrightness, 10) # test assigning ModifiedJulianDate obs = ObservationMetaData() mjd = ModifiedJulianDate(TAI=57388.0) obs.mjd = mjd self.assertEqual(obs.mjd, mjd) mjd2 = ModifiedJulianDate(TAI=45000.0) obs.mjd = mjd2 self.assertEqual(obs.mjd, mjd2) self.assertNotEqual(obs.mjd, mjd)
assert np.diff(obs_params['obsHistID']).min()>0 obsid_query = np.array(htmid_to_obs[htmid_query]) obs_dex = np.searchsorted(obs_params['obsHistID'].value, obsid_query) np.testing.assert_array_equal(obs_params['obsHistID'].value[obs_dex], obsid_query) ra_obs = obs_params['ra'].value[obs_dex] dec_obs = obs_params['dec'].value[obs_dex] mjd_obs = obs_params['mjd'].value[obs_dex] rotsky_obs = obs_params['rotSkyPos'].value[obs_dex] filter_obs = obs_params['filter'].value[obs_dex] m5_obs = obs_params['m5'].value[obs_dex] mjd_obj_list = ModifiedJulianDate.get_list(TAI=mjd_obs) obs_md_list = [] for ii in range(len(ra_obs)): obs = ObservationMetaData(pointingRA=ra_obs[ii], pointingDec=dec_obs[ii], mjd=mjd_obj_list[ii], rotSkyPos=rotsky_obs[ii], bandpassName='ugrizy'[filter_obs[ii]]) obs_md_list.append(obs) print('%d time steps' % len(filter_obs)) constraint = 'isvar=1 ' htmid_21_min = htmid_query<<2*(21-query_level) htmid_21_max = (htmid_query+1)<<2*(21-query_level) constraint += 'AND htmid>=%d AND htmid<%d' % (htmid_21_min, htmid_21_max)
def extract_objects(df, header): """ Extract the object information needed by the sims code and pack into a new dataframe. Parameters ---------- df : pandas.DataFrame DataFrame containing the instance catalog object data. header : dictionary dictionary containing the PhoSim header cards as output by extract_commands() (necessary for correctly applying proper motion to stars) Returns ------- pandas.DataFrame A DataFrame with the columns expected by the sims code. """ # Check for unhandled source types and emit warning if any are present. valid_types = dict(point='pointSource', sersic2d='sersic') invalid_types = set(df['SOURCE_TYPE']) - set(valid_types) if invalid_types: warnings.warn("Instance catalog contains unhandled source types:\n%s\nSkipping these." % '\n'.join(invalid_types)) columns = ('uniqueId', 'galSimType', 'magNorm', 'sedFilepath', 'redshift', 'raJ2000', 'decJ2000', 'halfLightRadius', 'minorAxis', 'majorAxis', 'positionAngle', 'sindex', 'properMotionRa', 'properMotionDec', 'parallax', 'radialVelocity') # Process point sources and galaxies separately. source_type = 'point' stars = df.query("SOURCE_TYPE=='%s'" % source_type) phosim_stars = pd.DataFrame(np.zeros((len(stars), len(columns))), index=stars.index, columns=columns) phosim_stars['uniqueId'] = pd.to_numeric(stars['VALUE']).tolist() phosim_stars['galSimType'] = valid_types[source_type] phosim_stars['magNorm'] = pd.to_numeric(stars['MAG_NORM']).tolist() phosim_stars['sedFilepath'] = stars['SED_NAME'].tolist() phosim_stars['redshift'] = pd.to_numeric(stars['REDSHIFT']).tolist() phosim_stars['raJ2000'] = pd.to_numeric(stars['RA']).tolist() phosim_stars['decJ2000'] = pd.to_numeric(stars['DEC']).tolist() phosim_stars['properMotionRa'] = pd.to_numeric(stars['PAR5']).tolist() phosim_stars['properMotionDec'] = pd.to_numeric(stars['PAR6']).tolist() phosim_stars['parallax'] = pd.to_numeric(stars['PAR7']).tolist() phosim_stars['radialVelocity'] = pd.to_numeric(stars['PAR8']).tolist() if len(phosim_stars) > 0: phosim_stars = extract_extinction(stars, phosim_stars, 1) mjd = ModifiedJulianDate(TAI=header['mjd']) raICRS, decICRS = applyProperMotion(phosim_stars.raJ2000.values, phosim_stars.decJ2000.values, phosim_stars.properMotionRa.values, phosim_stars.properMotionDec.values, phosim_stars.parallax.values, phosim_stars.radialVelocity.values, mjd=mjd) phosim_stars = phosim_stars.assign(raICRS=raICRS, decICRS=decICRS) source_type = 'sersic2d' galaxies = df.query("SOURCE_TYPE == '%s'" % source_type) phosim_galaxies = pd.DataFrame(np.zeros((len(galaxies), len(columns))), index=galaxies.index, columns=columns) phosim_galaxies['uniqueId'] = pd.to_numeric(galaxies['VALUE']).tolist() phosim_galaxies['galSimType'] = valid_types[source_type] phosim_galaxies['magNorm'] = pd.to_numeric(galaxies['MAG_NORM']).tolist() phosim_galaxies['sedFilepath'] = galaxies['SED_NAME'].tolist() phosim_galaxies['redshift'] = pd.to_numeric(galaxies['REDSHIFT']).tolist() phosim_galaxies['raJ2000'] = pd.to_numeric(galaxies['RA']).tolist() phosim_galaxies['decJ2000'] = pd.to_numeric(galaxies['DEC']).tolist() phosim_galaxies['majorAxis'] = \ radiansFromArcsec(pd.to_numeric(galaxies['PAR1'])).tolist() phosim_galaxies['minorAxis'] = \ radiansFromArcsec(pd.to_numeric(galaxies['PAR2'])).tolist() phosim_galaxies['halfLightRadius'] = phosim_galaxies['majorAxis'] phosim_galaxies['positionAngle'] = \ (np.pi/180.*pd.to_numeric(galaxies['PAR3'])).tolist() phosim_galaxies['sindex'] = pd.to_numeric(galaxies['PAR4']).tolist() n_gal = len(phosim_galaxies.raJ2000.values) phosim_galaxies = phosim_galaxies.assign(raICRS=phosim_galaxies.raJ2000, decICRS=phosim_galaxies.decJ2000, properMotionRa=np.zeros(n_gal), properMotionDec=np.zeros(n_gal), parallax=np.zeros(n_gal), radialVelocity=np.zeros(n_gal)) if len(phosim_galaxies) > 0: phosim_galaxies = extract_extinction(galaxies, phosim_galaxies, 5) return pd.concat((phosim_stars, phosim_galaxies), ignore_index=True)
def test_avro_alert_generation_diff_dmag(self): """ Make sure everything works properly when the AlertDataGenerator and the AvroAlertGenerator have different dmag thresholds """ dmag_cutoff_sqlite = 0.005 dmag_cutoff_avro = 0.2 mag_name_to_int = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z': 4, 'y': 5} star_db = StarAlertTestDBObj_avro(database=self.star_db_name, driver='sqlite') # assemble a dict of all of the alerts that need to be generated obshistid_list = [] for obs in self.obs_list: obshistid_list.append(obs.OpsimMetaData['obsHistID']) obshistid_max = max(obshistid_list) obshistid_bits = int(np.ceil(np.log(obshistid_max) / np.log(2.0))) true_alert_dict = {} obs_dict = {} ignored_sqlite = 0 # count number of alerts written to sqlite, but not avro for obs in self.obs_list: obs_dict[obs.OpsimMetaData['obsHistID']] = obs obshistid = obs.OpsimMetaData['obsHistID'] cat = TestAlertsTruthCat_avro(star_db, obs_metadata=obs) cat.camera = obs_lsst_phosim.PhosimMapper().camera for line in cat.iter_catalog(): if line[1] is None: continue dmag = line[2] mag = line[3] if (np.abs(dmag) > dmag_cutoff_avro and mag <= self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]]): alertId = (line[0] << obshistid_bits) + obshistid self.assertNotIn(alertId, true_alert_dict) true_alert_dict[alertId] = {} true_alert_dict[alertId]['chipName'] = line[1] true_alert_dict[alertId]['dmag'] = dmag true_alert_dict[alertId]['mag'] = mag true_alert_dict[alertId]['ra'] = np.degrees(line[4]) true_alert_dict[alertId]['decl'] = np.degrees(line[5]) true_alert_dict[alertId]['xPix'] = line[6] true_alert_dict[alertId]['yPix'] = line[7] elif np.abs(dmag) > dmag_cutoff_sqlite: ignored_sqlite += 1 self.assertGreater(len(true_alert_dict), 10) self.assertGreater(ignored_sqlite, 50) # just make sure that some sqlite # alerts were ignored by the more # stringent avro cut log_file_name = tempfile.mktemp(dir=self.alert_data_output_dir, suffix='log.txt') alert_gen = AlertDataGenerator(testing=True) alert_gen.subdivide_obs(self.obs_list, htmid_level=6) for htmid in alert_gen.htmid_list: alert_gen.alert_data_from_htmid( htmid, star_db, photometry_class=TestAlertsVarCat_avro, output_prefix='alert_test', output_dir=self.alert_data_output_dir, dmag_cutoff=dmag_cutoff_sqlite, log_file_name=log_file_name) obshistid_to_htmid = {} for htmid in alert_gen.htmid_list: for obs in alert_gen.obs_from_htmid(htmid): obshistid = obs.OpsimMetaData['obsHistID'] if obshistid not in obshistid_to_htmid: obshistid_to_htmid[obshistid] = [] obshistid_to_htmid[obshistid].append(htmid) avro_gen = AvroAlertGenerator() avro_gen.load_schema( os.path.join(getPackageDir('sims_catUtils'), 'tests', 'testData', 'avroSchema')) sql_prefix_list = ['alert_test'] out_prefix = 'test_avro' log_file_name = tempfile.mktemp(dir=self.avro_out_dir, prefix='test_avro', suffix='log.txt') for obshistid in obshistid_list: avro_gen.write_alerts(obshistid, self.alert_data_output_dir, sql_prefix_list, obshistid_to_htmid[obshistid], self.avro_out_dir, out_prefix, dmag_cutoff_avro, lock=None, log_file_name=log_file_name) list_of_avro_files = os.listdir(self.avro_out_dir) self.assertGreater(len(list_of_avro_files), 2) alert_ct = 0 dummy_sed = Sed() bp_dict = BandpassDict.loadTotalBandpassesFromFiles() photParams = PhotometricParameters() diasourceId_set = set() for avro_file_name in list_of_avro_files: if avro_file_name.endswith('log.txt'): continue full_name = os.path.join(self.avro_out_dir, avro_file_name) with DataFileReader(open(full_name, 'rb'), DatumReader()) as data_reader: for alert in data_reader: alert_ct += 1 obshistid = alert['alertId'] >> 20 obs = obs_dict[obshistid] uniqueId = alert['diaObject']['diaObjectId'] true_alert_id = (uniqueId << obshistid_bits) + obshistid self.assertIn(true_alert_id, true_alert_dict) self.assertEqual(alert['l1dbId'], uniqueId) true_alert = true_alert_dict[true_alert_id] diaSource = alert['diaSource'] self.assertAlmostEqual(diaSource['ra'], true_alert['ra'], 10) self.assertAlmostEqual(diaSource['decl'], true_alert['decl'], 10) self.assertAlmostEqual(diaSource['x'], true_alert['xPix'], 3) self.assertAlmostEqual(diaSource['y'], true_alert['yPix'], 3) self.assertAlmostEqual(diaSource['midPointTai'], obs.mjd.TAI, 4) true_tot_flux = dummy_sed.fluxFromMag(true_alert['mag']) true_q_mag = true_alert['mag'] - true_alert['dmag'] true_q_flux = dummy_sed.fluxFromMag(true_q_mag) true_dflux = true_tot_flux - true_q_flux self.assertAlmostEqual(diaSource['psFlux'] / true_dflux, 1.0, 6) self.assertAlmostEqual( diaSource['totFlux'] / true_tot_flux, 1.0, 6) self.assertAlmostEqual(diaSource['diffFlux'] / true_dflux, 1.0, 6) true_tot_snr, gamma = calcSNR_m5(true_alert['mag'], bp_dict[obs.bandpass], obs.m5[obs.bandpass], photParams) true_q_snr, gamma = calcSNR_m5( true_q_mag, bp_dict[obs.bandpass], self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]], photParams) true_tot_err = true_tot_flux / true_tot_snr true_q_err = true_q_flux / true_q_snr true_diff_err = np.sqrt(true_tot_err**2 + true_q_err**2) self.assertAlmostEqual( diaSource['snr'] / np.abs(true_dflux / true_diff_err), 1.0, 6) self.assertAlmostEqual( diaSource['totFluxErr'] / true_tot_err, 1.0, 6) self.assertAlmostEqual( diaSource['diffFluxErr'] / true_diff_err, 1.0, 6) chipnum = int(true_alert['chipName'].replace( 'R', '').replace('S', '').replace(',', '').replace( ':', '').replace(' ', '')) true_ccdid = (chipnum * 10**7) + obshistid self.assertEqual(true_ccdid, diaSource['ccdVisitId']) self.assertEqual(uniqueId, diaSource['diaObjectId']) self.assertNotIn(diaSource['diaSourceId'], diasourceId_set) diasourceId_set.add(diaSource['diaSourceId']) diaObject = alert['diaObject'] obj_dex = (uniqueId // 1024) - 1 self.assertAlmostEqual( 0.001 * diaObject['pmRa'] / self.pmra_truth[obj_dex], 1.0, 5) self.assertAlmostEqual( 0.001 * diaObject['pmDecl'] / self.pmdec_truth[obj_dex], 1.0, 5) self.assertAlmostEqual( 0.001 * diaObject['parallax'] / self.px_truth[obj_dex], 1.0, 5) (true_ra_base, true_dec_base) = applyProperMotion( self.ra_truth[obj_dex], self.dec_truth[obj_dex], self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex], self.px_truth[obj_dex], self.vrad_truth[obj_dex], mjd=ModifiedJulianDate(TAI=diaObject['radecTai'])) self.assertAlmostEqual(true_ra_base, diaObject['ra'], 7) self.assertAlmostEqual(true_dec_base, diaObject['decl'], 7) self.assertEqual(alert_ct, len(true_alert_dict))
def test_alert_data_generation(self): dmag_cutoff = 0.005 mag_name_to_int = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z' : 4, 'y': 5} _max_var_param_str = self.max_str_len class StarAlertTestDBObj(StellarAlertDBObjMixin, CatalogDBObject): objid = 'star_alert' tableid = 'stars' idColKey = 'simobjid' raColName = 'ra' decColName = 'dec' objectTypeId = 0 columns = [('raJ2000', 'ra*0.01745329252'), ('decJ2000', 'dec*0.01745329252'), ('parallax', 'px*0.01745329252/3600.0'), ('properMotionRa', 'pmra*0.01745329252/3600.0'), ('properMotionDec', 'pmdec*0.01745329252/3600.0'), ('radialVelocity', 'vrad'), ('variabilityParameters', 'varParamStr', str, _max_var_param_str)] class TestAlertsVarCatMixin(object): @register_method('alert_test') def applyAlertTest(self, valid_dexes, params, expmjd, variability_cache=None): if len(params) == 0: return np.array([[], [], [], [], [], []]) if isinstance(expmjd, numbers.Number): dmags_out = np.zeros((6, self.num_variable_obj(params))) else: dmags_out = np.zeros((6, self.num_variable_obj(params), len(expmjd))) for i_star in range(self.num_variable_obj(params)): if params['amp'][i_star] is not None: dmags = params['amp'][i_star]*np.cos(params['per'][i_star]*expmjd) for i_filter in range(6): dmags_out[i_filter][i_star] = dmags return dmags_out class TestAlertsVarCat(TestAlertsVarCatMixin, AlertStellarVariabilityCatalog): pass class TestAlertsTruthCat(TestAlertsVarCatMixin, CameraCoordsLSST, AstrometryStars, Variability, InstanceCatalog): column_outputs = ['uniqueId', 'chipName', 'dmagAlert', 'magAlert'] @compound('delta_umag', 'delta_gmag', 'delta_rmag', 'delta_imag', 'delta_zmag', 'delta_ymag') def get_TruthVariability(self): return self.applyVariability(self.column_by_name('varParamStr')) @cached def get_dmagAlert(self): return self.column_by_name('delta_%smag' % self.obs_metadata.bandpass) @cached def get_magAlert(self): return self.column_by_name('%smag' % self.obs_metadata.bandpass) + \ self.column_by_name('dmagAlert') star_db = StarAlertTestDBObj(database=self.star_db_name, driver='sqlite') # assemble the true light curves for each object; we need to figure out # if their np.max(dMag) ever goes over dmag_cutoff; then we will know if # we are supposed to simulate them true_lc_dict = {} true_lc_obshistid_dict = {} is_visible_dict = {} obs_dict = {} max_obshistid = -1 n_total_observations = 0 for obs in self.obs_list: obs_dict[obs.OpsimMetaData['obsHistID']] = obs obshistid = obs.OpsimMetaData['obsHistID'] if obshistid > max_obshistid: max_obshistid = obshistid cat = TestAlertsTruthCat(star_db, obs_metadata=obs) for line in cat.iter_catalog(): if line[1] is None: continue n_total_observations += 1 if line[0] not in true_lc_dict: true_lc_dict[line[0]] = {} true_lc_obshistid_dict[line[0]] = [] true_lc_dict[line[0]][obshistid] = line[2] true_lc_obshistid_dict[line[0]].append(obshistid) if line[0] not in is_visible_dict: is_visible_dict[line[0]] = False if line[3] <= self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]]: is_visible_dict[line[0]] = True obshistid_bits = int(np.ceil(np.log(max_obshistid)/np.log(2))) skipped_due_to_mag = 0 objects_to_simulate = [] obshistid_unqid_set = set() for obj_id in true_lc_dict: dmag_max = -1.0 for obshistid in true_lc_dict[obj_id]: if np.abs(true_lc_dict[obj_id][obshistid]) > dmag_max: dmag_max = np.abs(true_lc_dict[obj_id][obshistid]) if dmag_max >= dmag_cutoff: if not is_visible_dict[obj_id]: skipped_due_to_mag += 1 continue objects_to_simulate.append(obj_id) for obshistid in true_lc_obshistid_dict[obj_id]: obshistid_unqid_set.add((obj_id << obshistid_bits) + obshistid) self.assertGreater(len(objects_to_simulate), 10) self.assertGreater(skipped_due_to_mag, 0) log_file_name = tempfile.mktemp(dir=self.output_dir, suffix='log.txt') alert_gen = AlertDataGenerator(testing=True) alert_gen.subdivide_obs(self.obs_list, htmid_level=6) for htmid in alert_gen.htmid_list: alert_gen.alert_data_from_htmid(htmid, star_db, photometry_class=TestAlertsVarCat, output_prefix='alert_test', output_dir=self.output_dir, dmag_cutoff=dmag_cutoff, log_file_name=log_file_name) dummy_sed = Sed() bp_dict = BandpassDict.loadTotalBandpassesFromFiles() phot_params = PhotometricParameters() # First, verify that the contents of the sqlite files are all correct n_tot_simulated = 0 alert_query = 'SELECT alert.uniqueId, alert.obshistId, meta.TAI, ' alert_query += 'meta.band, quiescent.flux, alert.dflux, ' alert_query += 'quiescent.snr, alert.snr, ' alert_query += 'alert.ra, alert.dec, alert.chipNum, ' alert_query += 'alert.xPix, alert.yPix, ast.pmRA, ast.pmDec, ' alert_query += 'ast.parallax ' alert_query += 'FROM alert_data AS alert ' alert_query += 'INNER JOIN metadata AS meta ON meta.obshistId=alert.obshistId ' alert_query += 'INNER JOIN quiescent_flux AS quiescent ' alert_query += 'ON quiescent.uniqueId=alert.uniqueId ' alert_query += 'AND quiescent.band=meta.band ' alert_query += 'INNER JOIN baseline_astrometry AS ast ' alert_query += 'ON ast.uniqueId=alert.uniqueId' alert_dtype = np.dtype([('uniqueId', int), ('obshistId', int), ('TAI', float), ('band', int), ('q_flux', float), ('dflux', float), ('q_snr', float), ('tot_snr', float), ('ra', float), ('dec', float), ('chipNum', int), ('xPix', float), ('yPix', float), ('pmRA', float), ('pmDec', float), ('parallax', float)]) sqlite_file_list = os.listdir(self.output_dir) n_tot_simulated = 0 obshistid_unqid_simulated_set = set() for file_name in sqlite_file_list: if not file_name.endswith('db'): continue full_name = os.path.join(self.output_dir, file_name) self.assertTrue(os.path.exists(full_name)) alert_db = DBObject(full_name, driver='sqlite') alert_data = alert_db.execute_arbitrary(alert_query, dtype=alert_dtype) if len(alert_data) == 0: continue mjd_list = ModifiedJulianDate.get_list(TAI=alert_data['TAI']) for i_obj in range(len(alert_data)): n_tot_simulated += 1 obshistid_unqid_simulated_set.add((alert_data['uniqueId'][i_obj] << obshistid_bits) + alert_data['obshistId'][i_obj]) unq = alert_data['uniqueId'][i_obj] obj_dex = (unq//1024)-1 self.assertAlmostEqual(self.pmra_truth[obj_dex], 0.001*alert_data['pmRA'][i_obj], 4) self.assertAlmostEqual(self.pmdec_truth[obj_dex], 0.001*alert_data['pmDec'][i_obj], 4) self.assertAlmostEqual(self.px_truth[obj_dex], 0.001*alert_data['parallax'][i_obj], 4) ra_truth, dec_truth = applyProperMotion(self.ra_truth[obj_dex], self.dec_truth[obj_dex], self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex], self.px_truth[obj_dex], self.vrad_truth[obj_dex], mjd=mjd_list[i_obj]) distance = angularSeparation(ra_truth, dec_truth, alert_data['ra'][i_obj], alert_data['dec'][i_obj]) distance_arcsec = 3600.0*distance msg = '\ntruth: %e %e\nalert: %e %e\n' % (ra_truth, dec_truth, alert_data['ra'][i_obj], alert_data['dec'][i_obj]) self.assertLess(distance_arcsec, 0.0005, msg=msg) obs = obs_dict[alert_data['obshistId'][i_obj]] chipname = chipNameFromRaDecLSST(self.ra_truth[obj_dex], self.dec_truth[obj_dex], pm_ra=self.pmra_truth[obj_dex], pm_dec=self.pmdec_truth[obj_dex], parallax=self.px_truth[obj_dex], v_rad=self.vrad_truth[obj_dex], obs_metadata=obs, band=obs.bandpass) chipnum = int(chipname.replace('R', '').replace('S', ''). replace(' ', '').replace(';', '').replace(',', ''). replace(':', '')) self.assertEqual(chipnum, alert_data['chipNum'][i_obj]) xpix, ypix = pixelCoordsFromRaDecLSST(self.ra_truth[obj_dex], self.dec_truth[obj_dex], pm_ra=self.pmra_truth[obj_dex], pm_dec=self.pmdec_truth[obj_dex], parallax=self.px_truth[obj_dex], v_rad=self.vrad_truth[obj_dex], obs_metadata=obs, band=obs.bandpass) self.assertAlmostEqual(alert_data['xPix'][i_obj], xpix, 4) self.assertAlmostEqual(alert_data['yPix'][i_obj], ypix, 4) dmag_sim = -2.5*np.log10(1.0+alert_data['dflux'][i_obj]/alert_data['q_flux'][i_obj]) self.assertAlmostEqual(true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]], dmag_sim, 3) mag_name = ('u', 'g', 'r', 'i', 'z', 'y')[alert_data['band'][i_obj]] m5 = obs.m5[mag_name] q_mag = dummy_sed.magFromFlux(alert_data['q_flux'][i_obj]) self.assertAlmostEqual(self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex], q_mag, 4) snr, gamma = calcSNR_m5(self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex], bp_dict[mag_name], self.obs_mag_cutoff[alert_data['band'][i_obj]], phot_params) self.assertAlmostEqual(snr/alert_data['q_snr'][i_obj], 1.0, 4) tot_mag = self.mag0_truth_dict[alert_data['band'][i_obj]][obj_dex] + \ true_lc_dict[alert_data['uniqueId'][i_obj]][alert_data['obshistId'][i_obj]] snr, gamma = calcSNR_m5(tot_mag, bp_dict[mag_name], m5, phot_params) self.assertAlmostEqual(snr/alert_data['tot_snr'][i_obj], 1.0, 4) for val in obshistid_unqid_set: self.assertIn(val, obshistid_unqid_simulated_set) self.assertEqual(len(obshistid_unqid_set), len(obshistid_unqid_simulated_set)) astrometry_query = 'SELECT uniqueId, ra, dec, TAI ' astrometry_query += 'FROM baseline_astrometry' astrometry_dtype = np.dtype([('uniqueId', int), ('ra', float), ('dec', float), ('TAI', float)]) tai_list = [] for obs in self.obs_list: tai_list.append(obs.mjd.TAI) tai_list = np.array(tai_list) n_tot_ast_simulated = 0 for file_name in sqlite_file_list: if not file_name.endswith('db'): continue full_name = os.path.join(self.output_dir, file_name) self.assertTrue(os.path.exists(full_name)) alert_db = DBObject(full_name, driver='sqlite') astrometry_data = alert_db.execute_arbitrary(astrometry_query, dtype=astrometry_dtype) if len(astrometry_data) == 0: continue mjd_list = ModifiedJulianDate.get_list(TAI=astrometry_data['TAI']) for i_obj in range(len(astrometry_data)): n_tot_ast_simulated += 1 obj_dex = (astrometry_data['uniqueId'][i_obj]//1024) - 1 ra_truth, dec_truth = applyProperMotion(self.ra_truth[obj_dex], self.dec_truth[obj_dex], self.pmra_truth[obj_dex], self.pmdec_truth[obj_dex], self.px_truth[obj_dex], self.vrad_truth[obj_dex], mjd=mjd_list[i_obj]) distance = angularSeparation(ra_truth, dec_truth, astrometry_data['ra'][i_obj], astrometry_data['dec'][i_obj]) self.assertLess(3600.0*distance, 0.0005) del alert_gen gc.collect() self.assertGreater(n_tot_simulated, 10) self.assertGreater(len(obshistid_unqid_simulated_set), 10) self.assertLess(len(obshistid_unqid_simulated_set), n_total_observations) self.assertGreater(n_tot_ast_simulated, 0)
def test_agn_light_curves(self): """ Test the AgnLightCurveGenerator by generating some AGN light curves and comparing them to the results obtained by generating a series of InstanceCatalogs containing the same objects at the same MJDs """ raRange = (78.0, 85.0) decRange = (-69.0, -65.0) bandpass = '******' lc_gen = AgnLightCurveGenerator(self.agn_db, self.opsimDb) pointings = lc_gen.get_pointings(raRange, decRange, bandpass=bandpass) for row in pointings: for obs in row: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd test_light_curves, truth_info = lc_gen.light_curves_from_pointings( pointings) self.assertGreater(len(test_light_curves), 2) # make sure we got some light curves for unique_id in test_light_curves: # verify that the sources returned all do vary by making sure that the # np.diff run on the magnitudes reutrns something non-zero self.assertGreater( np.abs(np.diff( test_light_curves[unique_id][bandpass]['mag'])).max(), 0.0) self.assertGreater( len(test_light_curves[unique_id][bandpass]['mjd']), 0) # Now test that specifying a small chunk_size does not change the output # light curves chunk_light_curves, truth_info = lc_gen.light_curves_from_pointings( pointings, chunk_size=1) self.assertGreater(len(chunk_light_curves), 2) for unique_id in test_light_curves: self.assertEqual( len(test_light_curves[unique_id][bandpass]['mjd']), len(chunk_light_curves[unique_id][bandpass]['mjd'])) np.testing.assert_array_equal( test_light_curves[unique_id][bandpass]['mjd'], chunk_light_curves[unique_id][bandpass]['mjd']) np.testing.assert_array_equal( test_light_curves[unique_id][bandpass]['mag'], chunk_light_curves[unique_id][bandpass]['mag']) np.testing.assert_array_equal( test_light_curves[unique_id][bandpass]['error'], chunk_light_curves[unique_id][bandpass]['error']) # Now find all of the ObservationMetaData that were included in our # light curves, generate InstanceCatalogs from them separately, # and verify that the contents of the InstanceCatalogs agree with # the contents of the light curves. gen = ObservationMetaDataGenerator(database=self.opsimDb, driver='sqlite') obs_list = gen.getObservationMetaData(fieldRA=raRange, fieldDec=decRange, telescopeFilter=bandpass, boundLength=1.75) for obs in obs_list: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd ct = 0 for obs in obs_list: cat = agnControlCatalog(self.agn_db, obs_metadata=obs) for agn_obj in cat.iter_catalog(): ct += 1 lc = test_light_curves[agn_obj[0]][bandpass] dex = np.argmin(np.abs(lc['mjd'] - obs.mjd.TAI)) self.assertLess(np.abs(lc['mjd'][dex] - obs.mjd.TAI), 1.0e-7) self.assertLess(np.abs(lc['mag'][dex] - agn_obj[3]), 1.0e-7) self.assertLess(np.abs(lc['error'][dex] - agn_obj[4]), 1.0e-7) # Verify that the catalogs and LightCurveGenerator returned the # same number of observations total_ct = 0 for obj_name in test_light_curves: for band in test_light_curves[obj_name]: total_ct += len(test_light_curves[obj_name][band]['mjd']) self.assertEqual(ct, total_ct)
def test_multiband_light_curves(self): """ Check that multi-band light curves are returned correctly. """ raRange = (78.0, 82.0) decRange = (-69.0, -65.0) bandpass = ('r', 'g') gen = AgnLightCurveGenerator(self.agn_db, self.opsimDb) pointings = gen.get_pointings(raRange, decRange, bandpass=bandpass) for row in pointings: for obs in row: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd lc_dict, truth_info = gen.light_curves_from_pointings(pointings) self.assertGreater(len(lc_dict), 2) obs_gen = ObservationMetaDataGenerator(database=self.opsimDb, driver='sqlite') control_pointings_r = obs_gen.getObservationMetaData( fieldRA=raRange, fieldDec=decRange, telescopeFilter='r', boundLength=1.75) for obs in control_pointings_r: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd control_pointings_g = obs_gen.getObservationMetaData( fieldRA=raRange, fieldDec=decRange, telescopeFilter='g', boundLength=1.75) for obs in control_pointings_g: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd self.assertGreater(len(control_pointings_g), 0) self.assertGreater(len(control_pointings_r), 0) ct = 0 for obs in control_pointings_r: cat = agnControlCatalog(self.agn_db, obs_metadata=obs) for star_obj in cat.iter_catalog(): ct += 1 lc = lc_dict[star_obj[0]]['r'] dex = np.argmin(np.abs(lc['mjd'] - obs.mjd.TAI)) self.assertLess(np.abs(lc['mjd'][dex] - obs.mjd.TAI), 1.0e-7) self.assertLess(np.abs(lc['mag'][dex] - star_obj[3]), 1.0e-7) self.assertLess(np.abs(lc['error'][dex] - star_obj[4]), 1.0e-7) for obs in control_pointings_g: cat = agnControlCatalog(self.agn_db, obs_metadata=obs) for star_obj in cat.iter_catalog(): ct += 1 lc = lc_dict[star_obj[0]]['g'] dex = np.argmin(np.abs(lc['mjd'] - obs.mjd.TAI)) self.assertLess(np.abs(lc['mjd'][dex] - obs.mjd.TAI), 1.0e-7) self.assertLess(np.abs(lc['mag'][dex] - star_obj[3]), 1.0e-7) self.assertLess(np.abs(lc['error'][dex] - star_obj[4]), 1.0e-7) # Verify that the catalogs and LightCurveGenerator returned the # same number of observations total_ct = 0 for obj_name in lc_dict: for band in lc_dict[obj_name]: total_ct += len(lc_dict[obj_name][band]['mjd']) self.assertEqual(ct, total_ct)
def test_agn_constraint(self): """ Test that the light curve generator correctly ignores objects with varParamStr == None We do this by generating a database of two galaxies with AGN-like varParamStr and two stars with no varParamStr. We run this database through a LightCurveGenerator and an InstanceCatalog. We verify that the LightCurveGenerator finds 2 AGN while the InstanceCatalog finds 4 stars. """ rng = np.random.RandomState(83) raRange = (80.8, 83.8) decRange = (-71.0, -69.0) bandpass = '******' agn_sed_name = "agn.spec" sed_name = "Burst.10E10.1Z.spec.gz" varparams = { 'varMethodName': 'applyAgn', 'pars': { 'agn_tau': 20.0, 'agn_sfu': 11.0, 'agn_sfg': 12.0, 'agn_sfr': 13.0, 'agn_sfi': 14.0, 'agn_sfz': 15.0, 'agn_sfy': 16.0, 't0_mjd': 49330.0, 'seed': rng.randint(0, 200000) } } varParamStr = json.dumps(varparams) # create the dummy database db_name = tempfile.mktemp(prefix="agn_constraint_cat_sqlite", suffix=".db", dir=ROOT) conn = sqlite3.connect(db_name) c = conn.cursor() c.execute('''CREATE TABLE agn (id int, ra real, dec real, redshift real, sedFilenameDisk text, internalAvDisk real, magNormDisk real, sedFilenameBulge text, internalAvBulge real, magNormBulge real, sedFilenameAgn text, varParamStr text, magNormAgn real)''') conn.commit() for ix, (rr, dd, zz, avb, mnb, avd, mnd, mnagn) in \ enumerate(zip(rng.random_sample(4)*(raRange[1]-raRange[0])+raRange[0], rng.random_sample(4)*(decRange[1]-decRange[0])+decRange[0], rng.random_sample(4)*0.5+0.1, rng.random_sample(4)*0.5+0.1, rng.random_sample(4)*3.0+17.0, rng.random_sample(4)*0.5+0.1, rng.random_sample(4)*3.0+17.0, rng.random_sample(4)*3.0+17.0)): if ix < 2: cmd = '''INSERT INTO agn VALUES(%d, %e, %e, %e, '%s', %e, %e, '%s', %e, %e, '%s', '%s', %e)''' % \ (ix, rr, dd, zz, sed_name, avb, mnb, sed_name, avd, mnd, agn_sed_name, varParamStr, mnagn) else: cmd = '''INSERT INTO agn VALUES(%d, %e, %e, %e, '%s', %e, %e, '%s', %e, %e, '%s', NULL, %e)''' % \ (ix, rr, dd, zz, sed_name, avb, mnb, sed_name, avd, mnd, agn_sed_name, mnagn) c.execute(cmd) conn.commit() # create a CatalogDBObject class to interface with the dummy database class dummyAgnDBObject(CatalogDBObject): database = db_name host = None driver = 'sqlite' tableid = 'agn' raColName = 'ra' decColName = 'dec' idColKey = 'id' objid = 'dummyAgn' skipRegistration = True objectTypeId = 99 columns = [('raJ2000', 'ra*PI()/180.0', float), ('decJ2000', 'dec*PI()/180.0', float)] agn_db = dummyAgnDBObject() # verify that the LightCurveGenerator finds the two variable stars lc_gen = AgnLightCurveGenerator(agn_db, self.opsimDb) ptngs = lc_gen.get_pointings(raRange, decRange, bandpass=bandpass) for row in ptngs: for obs in row: mjd = ModifiedJulianDate(TAI=obs.mjd.TAI - 49000.0 + 59580.0) obs.mjd = mjd lc_dict, truth_dict = lc_gen.light_curves_from_pointings(ptngs) self.assertEqual(len(lc_dict), 2) if os.path.exists(db_name): os.unlink(db_name) # verify that an InstanceCatalog finds all 4 stars obs = ptngs[0][0] cat = agnControlCatalog(agn_db, obs_metadata=obs) with lsst.utils.tests.getTempFilePath('.txt') as dummy_cat_name: cat.write_catalog(dummy_cat_name) with open(dummy_cat_name, 'r') as input_file: lines = input_file.readlines() self.assertEqual(len(lines), 5)
def test_deepcopy(self): # make sure that deepcopy() creates identical # ModifiedJulianDates with different memory addresses mjd1 = ModifiedJulianDate(TAI=43590.0) mjd1.dut1 deep_mjd2 = copy.deepcopy(mjd1) self.assertEqual(mjd1, deep_mjd2) self.assertNotEqual(mjd1.__repr__(), deep_mjd2.__repr__()) self.assertEqual(mjd1.TAI, deep_mjd2.TAI) self.assertEqual(mjd1.dut1, deep_mjd2.dut1) equiv_mjd2 = mjd1 self.assertEqual(mjd1, equiv_mjd2) self.assertEqual(mjd1.__repr__(), equiv_mjd2.__repr__()) mjd1 = ModifiedJulianDate(UTC=43590.0) mjd1.dut1 deep_mjd2 = copy.deepcopy(mjd1) self.assertEqual(mjd1, deep_mjd2) self.assertEqual(mjd1.UTC, deep_mjd2.UTC) self.assertEqual(mjd1.dut1, deep_mjd2.dut1) self.assertNotEqual(mjd1.__repr__(), deep_mjd2.__repr__()) equiv_mjd2 = mjd1 self.assertEqual(mjd1, equiv_mjd2) self.assertEqual(mjd1.__repr__(), equiv_mjd2.__repr__()) # make sure that deepcopy() still works, even if you have called # all of the original ModifiedJulianDate's properties mjd1 = ModifiedJulianDate(TAI=42590.0) mjd1.UTC mjd1.dut1 mjd1.UT1 mjd1.TT mjd1.TDB mjd2 = copy.deepcopy(mjd1) self.assertEqual(mjd1.TAI, mjd2.TAI) self.assertEqual(mjd1.UTC, mjd2.UTC) self.assertEqual(mjd1.dut1, mjd2.dut1) self.assertEqual(mjd1.UT1, mjd2.UT1) self.assertEqual(mjd1.TT, mjd2.TT) self.assertEqual(mjd1.TDB, mjd2.TDB) self.assertEqual(mjd1, mjd2) self.assertNotEqual(mjd1.__repr__(), mjd2.__repr__())
def testObservedFromPupil_noRefraction(self): """ Test conversion from pupil coordinates to observed coordinates when includeRefraction=False """ mjd = ModifiedJulianDate(TAI=53000.0) solarRA, solarDec = solarRaDec(mjd) # to make sure that we are more than 45 degrees from the Sun as required # for _icrsFromObserved to be at all accurate raCenter = solarRA + 100.0 decCenter = solarDec - 30.0 obs = ObservationMetaData(pointingRA=raCenter, pointingDec=decCenter, boundType='circle', boundLength=0.1, rotSkyPos=23.0, mjd=mjd) nSamples = 1000 rng = np.random.RandomState(4453) ra = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(raCenter) dec = (rng.random_sample(nSamples) * 0.1 - 0.2) + np.radians(decCenter) xp, yp = _pupilCoordsFromRaDec(ra, dec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) raObs, decObs = _observedFromICRS(ra, dec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) raObs_test, decObs_test = _observedFromPupilCoords( xp, yp, obs_metadata=obs, epoch=2000.0, includeRefraction=False) dist = arcsecFromRadians( haversine(raObs, decObs, raObs_test, decObs_test)) self.assertLess(dist.max(), 1.0e-6) # test output in degrees raObs_deg, decObs_deg = observedFromPupilCoords( xp, yp, obs_metadata=obs, epoch=2000.0, includeRefraction=False) np.testing.assert_array_almost_equal(raObs_deg, np.degrees(raObs_test), decimal=16) np.testing.assert_array_almost_equal(decObs_deg, np.degrees(decObs_test), decimal=16) # test one-at-a-time input for ii in range(len(raObs)): rr, dd = _observedFromPupilCoords(xp[ii], yp[ii], obs_metadata=obs, epoch=2000.0, includeRefraction=False) self.assertAlmostEqual(rr, raObs_test[ii], 16) self.assertAlmostEqual(dd, decObs_test[ii], 16) rr, dd = observedFromPupilCoords(xp[ii], yp[ii], obs_metadata=obs, epoch=2000.0, includeRefraction=False) self.assertAlmostEqual(rr, raObs_deg[ii], 16) self.assertAlmostEqual(dd, decObs_deg[ii], 16)