def test_degrees(self): nside = 64 hpids = np.arange(hp.nside2npix(nside)) ra, dec = utils.hpid2RaDec(nside, hpids) mjd = 59852. obs = utils.ObservationMetaData(mjd=mjd) alt1, az1, pa1 = utils.altAzPaFromRaDec(ra, dec, obs) alt2, az2 = utils.approx_RaDec2AltAz(ra, dec, obs.site.latitude, obs.site.longitude, mjd) # Check that the fast is similar to the more precice transform tol = 2 # Degrees tol_mean = 1. separations = utils.angularSeparation(az1, alt1, az2, alt2) self.assertLess(np.max(separations), tol) self.assertLess(np.mean(separations), tol_mean) # Check that the fast can nearly round-trip ra_back, dec_back = utils.approx_altAz2RaDec(alt2, az2, obs.site.latitude, obs.site.longitude, mjd) separations = utils.angularSeparation(ra, dec, ra_back, dec_back) self.assertLess(np.max(separations), tol) self.assertLess(np.mean(separations), tol_mean)
def test_findAllTrixels_radius(self): """ Test the method that attempts to find all of the trixels inside a given half space by approximating the angular scale of the trixels and verifying that all returned trixels are within radius+angular scale of the center of the half space. """ level = 5 # approximate the linear angular scale (in degrees) # of a trixel grid using the fact that there are # 8*4**(level-1) trixels in the grid as per equation 2.5 of # # https://www.microsoft.com/en-us/research/wp-content/uploads/2005/09/tr-2005-123.pdf angular_scale = np.sqrt(4.0*np.pi*(180.0/np.pi)**2/(8.0*4.0**(level-1))) ra = 43.0 dec = 22.0 radius = 20.0 half_space = halfSpaceFromRaDec(ra, dec, radius) trixel_list = half_space.findAllTrixels(level) self.assertGreater(len(trixel_list), 2) # first, check that all of the returned trixels are # inside the HalfSpace good_htmid_list = [] for i_limit, limits in enumerate(trixel_list): # verify that the tuples have been sorted by # htmid_min if i_limit > 0: self.assertGreater(limits[0], trixel_list[i_limit-1][1]) for htmid in range(limits[0], limits[1]+1): test_trixel = trixelFromHtmid(htmid) ra_trix, dec_trix = test_trixel.get_center() good_htmid_list.append(htmid) self.assertNotEqual(half_space.contains_trixel(test_trixel), 'outside') # check that the returned trixels are within # radius+angular_scale of the center of the HalfSpace self.assertLess(angularSeparation(ra, dec, ra_trix, dec_trix), radius+angular_scale) # next, verify that all of the possible trixels that # were not returned are outside the HalfSpace for base_htmid in range(8, 16): htmid_0 = base_htmid << 2*(level-1) self.assertEqual(levelFromHtmid(htmid_0), level) for ii in range(2**(2*level-2)): htmid = htmid_0 + ii self.assertEqual(levelFromHtmid(htmid), level) if htmid not in good_htmid_list: test_trixel = trixelFromHtmid(htmid) self.assertEqual(half_space.contains_trixel(test_trixel), 'outside') ra_trix, dec_trix = test_trixel.get_center() self.assertGreater(angularSeparation(ra, dec, ra_trix, dec_trix), radius)
def test_galaxy_astrometry_degrees(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of galaxies (in degrees) """ db = testGalaxyDiskDBObj(driver='sqlite', database=self.db_name) cat = GalaxyTestCatalog(db, obs_metadata=self.obs) with lsst.utils.tests.getTempFilePath('.txt') as cat_name: cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase.icrsFromPhoSim( data['raPhoSim'], data['decPhoSim'], self.obs) dist = angularSeparation(data['raICRS'], data['decICRS'], ra_icrs, dec_icrs) dist = 3600.0 * dist self.assertLess(dist.max(), 0.001) # verify that the distance between raPhoSim, decPhoSim and # raICRS, decICRS is greater than the distance between # the original raICRS, decICRS and the newly-calculated # raICRS, decICRS dist_bad = angularSeparation(data['raPhoSim'], data['decPhoSim'], data['raICRS'], data['decICRS']) dist_bad = 3600.0 * dist_bad self.assertGreater(dist_bad.min(), dist.max()) del db
def testAngSepResultsArr(self): """ Test that angularSeparation gives the correct answer by comparing results with the dot products of Cartesian vectors. Pass in arrays of arguments. """ rng = np.random.RandomState(99421) n_obj = 100 ra1 = rng.random_sample(n_obj)*2.0*np.pi dec1 = rng.random_sample(n_obj)*np.pi - 0.5*np.pi ra2 = rng.random_sample(n_obj)*2.0*np.pi dec2 = rng.random_sample(n_obj)*np.pi - 0.5*np.pi x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) x2 = np.cos(dec2)*np.cos(ra2) y2 = np.cos(dec2)*np.sin(ra2) z2 = np.sin(dec2) test = utils._angularSeparation(ra1, dec1, ra2, dec2) test = np.cos(test) control = x1*x2 + y1*y2 + z1*z2 np.testing.assert_array_almost_equal(test, control, decimal=15) test = utils.angularSeparation(np.degrees(ra1), np.degrees(dec1), np.degrees(ra2), np.degrees(dec2)) test = np.cos(np.radians(test)) np.testing.assert_array_almost_equal(test, control, decimal=15) # specifically test at the north pole dec1 = np.ones(n_obj)*np.pi x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) control = x1*x2 + y1*y2 + z1*z2 test = utils._angularSeparation(ra1, dec1, ra2, dec2) test = np.cos(test) np.testing.assert_array_almost_equal(test, control, decimal=15) test = utils.angularSeparation(np.degrees(ra1), np.degrees(dec1), np.degrees(ra2), np.degrees(dec2)) test = np.cos(np.radians(test)) np.testing.assert_array_almost_equal(test, control, decimal=15) # specifically test at the south pole dec1 = -1.0*np.ones(n_obj)*np.pi x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) control = x1*x2 + y1*y2 + z1*z2 test = utils._angularSeparation(ra1, dec1, ra2, dec2) test = np.cos(test) np.testing.assert_array_almost_equal(test, control, decimal=15) test = utils.angularSeparation(np.degrees(ra1), np.degrees(dec1), np.degrees(ra2), np.degrees(dec2)) test = np.cos(np.radians(test)) np.testing.assert_array_almost_equal(test, control, decimal=15)
def testAngSepResultsMixed(self): """ Test that angularSeparation gives the correct answer by comparing results with the dot products of Cartesian vectors. Pass in mixtures of floats and arrays as arguments. """ rng = np.random.RandomState(8131) n_obj = 100 ra1 = rng.random_sample(n_obj)*2.0*np.pi dec1 = rng.random_sample(n_obj)*np.pi - 0.5*np.pi ra2 = rng.random_sample()*2.0*np.pi dec2 = rng.random_sample()*np.pi - 0.5*np.pi self.assertIsInstance(ra1, np.ndarray) self.assertIsInstance(dec1, np.ndarray) self.assertIsInstance(ra2, float) self.assertIsInstance(dec2, float) x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) x2 = np.cos(dec2)*np.cos(ra2) y2 = np.cos(dec2)*np.sin(ra2) z2 = np.sin(dec2) control = x1*x2 + y1*y2 + z1*z2 test = utils._angularSeparation(ra1, dec1, ra2, dec2) test = np.cos(test) np.testing.assert_array_almost_equal(test, control, decimal=15) test = utils._angularSeparation(ra2, dec2, ra1, dec1) test = np.cos(test) np.testing.assert_array_almost_equal(test, control, decimal=15) # now do it in degrees ra1 = rng.random_sample(n_obj)*360.0 dec1 = rng.random_sample(n_obj)*180.0 - 90.0 ra2 = rng.random_sample()*360.0 dec2 = rng.random_sample()*180.0 - 90.0 self.assertIsInstance(ra1, np.ndarray) self.assertIsInstance(dec1, np.ndarray) self.assertIsInstance(ra2, float) self.assertIsInstance(dec2, float) x1 = np.cos(np.radians(dec1))*np.cos(np.radians(ra1)) y1 = np.cos(np.radians(dec1))*np.sin(np.radians(ra1)) z1 = np.sin(np.radians(dec1)) x2 = np.cos(np.radians(dec2))*np.cos(np.radians(ra2)) y2 = np.cos(np.radians(dec2))*np.sin(np.radians(ra2)) z2 = np.sin(np.radians(dec2)) control = x1*x2 + y1*y2 + z1*z2 test = utils.angularSeparation(ra1, dec1, ra2, dec2) test = np.cos(np.radians(test)) np.testing.assert_array_almost_equal(test, control, decimal=15) test = utils.angularSeparation(ra2, dec2, ra1, dec1) test = np.cos(np.radians(test)) np.testing.assert_array_almost_equal(test, control, decimal=15)
def _ssoInCircleFov(self, ephems, obsData, rFov): if not self.obsDegrees: sep = angularSeparation(ephems['ra'], ephems['dec'], np.degrees(obsData[self.obsRA]), np.degrees(obsData[self.obsDec])) else: sep = angularSeparation(ephems['ra'], ephems['dec'], obsData[self.obsRA], obsData[self.obsDec]) idxObs = np.where(sep <= rFov)[0] return idxObs
def fov_overlaps_protoDC2(x, y, half_size=2.5, radius=1.77): if x > half_size and y > half_size: return angularSeparation(x, y, half_size, half_size) < radius elif x < -half_size and y > half_size: return angularSeparation(x, y, -half_size, half_size) < radius elif x < -half_size and y < -half_size: return angularSeparation(x, y, -half_size, -half_size) < radius elif x > half_size and y < -half_size: return angularSeparation(x, y, half_size, -half_size) < radius outer_box_size = half_size + radius return (-outer_box_size < x and x < outer_box_size and -outer_box_size < y and y < outer_box_size)
def test_HalfSpaceIntersection(self): # Test that the two roots of an intersection are the # correct angular distance from the centers of the # half spaces ra1 = 22.0 dec1 = 45.0 rad1 = 10.0 ra2 = 23.5 dec2 = 37.9 rad2 = 9.2 hs1 = halfSpaceFromRaDec(ra1, dec1, rad1) hs2 = halfSpaceFromRaDec(ra2, dec2, rad2) roots = intersectHalfSpaces(hs1, hs2) self.assertEqual(len(roots), 2) self.assertAlmostEqual(np.sqrt(np.sum(roots[0]**2)), 1.0, 10) self.assertAlmostEqual(np.sqrt(np.sum(roots[1]**2)), 1.0, 10) ra_r1, dec_r1 = np.degrees(sphericalFromCartesian(roots[0])) ra_r2, dec_r2 = np.degrees(sphericalFromCartesian(roots[1])) dd = angularSeparation(ra1, dec1, ra_r1, dec_r1) self.assertAlmostEqual(dd, rad1, 10) dd = angularSeparation(ra1, dec1, ra_r2, dec_r2) self.assertAlmostEqual(dd, rad1, 10) dd = angularSeparation(ra2, dec2, ra_r1, dec_r1) self.assertAlmostEqual(dd, rad2, 10) dd = angularSeparation(ra2, dec2, ra_r2, dec_r2) self.assertAlmostEqual(dd, rad2, 10) # test that two non-intersecting HalfSpaces return no roots hs1 = halfSpaceFromRaDec(0.0, 90.0, 1.0) hs2 = halfSpaceFromRaDec(20.0, -75.0, 5.0) roots = intersectHalfSpaces(hs1, hs2) self.assertEqual(len(roots), 0) # test that two half spaces that are inside each other # return no roots hs1 = halfSpaceFromRaDec(77.0, 10.0, 20.0) hs2 = halfSpaceFromRaDec(75.0, 8.0, 0.2) roots = intersectHalfSpaces(hs1, hs2) self.assertEqual(len(roots), 0) # test that two half spaces with identical centers # return no roots hs1 = halfSpaceFromRaDec(11.0, -23.0, 1.0) hs2 = halfSpaceFromRaDec(11.0, -23.0, 0.2) roots = intersectHalfSpaces(hs1, hs2) self.assertEqual(len(roots), 0) roots = intersectHalfSpaces(hs1, hs1) self.assertEqual(len(roots), 0)
def prune(self, verbose=True, magG_max=19.5, magG_min=15., poleClip=True): """ Remove the variable and multiple systems from the catalog """ start_size = np.size(self.catalog) singles = [] for i, starID in enumerate(self.catalog['sourceExtendedId']): if (starID[-1] == 'A') | (starID[-1] == 'B') | (starID[-1] == '+'): singles.append(False) else: singles.append(True) singles = np.array(singles) self.catalog = self.catalog[np.where(singles == True)] nonvariables = np.where(self.catalog['variabilityAmplitude'] == 0)[0] self.catalog = self.catalog[nonvariables] self.catalog = self.catalog[np.where((self.catalog['magG'] < magG_max) & (self.catalog['magG'] > magG_min))] if poleClip: ra_pole = np.median(self.catalog['raj2000']) dec_pole = np.median(self.catalog['dej2000']) dist_to_center = angularSeparation(ra_pole, dec_pole, self.catalog['raj2000'], self.catalog['dej2000']) clip_dist=3.6/2. # Degrees good = np.where(dist_to_center < clip_dist) self.catalog = self.catalog[good] if verbose: end_size = np.size(self.catalog) print 'clipped %i entries. %i remain.' % (start_size - end_size, end_size)
def testFieldsMatch(self): """Test that the field based maps match the healpix maps """ if self.data_present: decs = [-60., -40., -20.] mjds = [] ra = 280 # Load up the fields selection = sf.FieldSelection() all_fields = selection.get_all_fields() fdb = sf.FieldsDatabase() field_ras, field_decs = fdb.get_ra_dec_arrays(all_fields) for mjd in self.sm.info['mjds'][10:12]: mjds.append(mjd) mjds.append(mjd+.0002) for dec in decs: healID = raDec2Hpid(self.sm.nside, ra, dec) # do the slow brute force lookup since I'm too lazy to import kdtree dist = angularSeparation(field_ras, field_decs, ra, dec) fieldID = np.max(np.where(dist == dist.min())) for mjd in mjds: field_mag = self.sm_fields.returnMags(mjd, indx=[fieldID]) heal_mag = self.sm.returnMags(mjd, indx=[healID]) for key in field_mag: np.testing.assert_almost_equal(field_mag[key], heal_mag[key], decimal=3)
def test_outside_radius(self): """ Test that methods can gracefully handle points outside of the focal plane """ rng = np.random.RandomState(7123) ra = 145.0 dec = -25.0 obs = ObservationMetaData(pointingRA=ra, pointingDec=dec, mjd=59580.0, rotSkyPos=113.0) rr = rng.random_sample(100) * 5.0 self.assertGreater(rr.max(), 4.5) theta = rng.random_sample(100) * 2.0 * np.pi ra_vec = ra + rr * np.cos(theta) dec_vec = dec + rr * np.sin(theta) chip_name_list = chipNameFromRaDecLSST(ra_vec, dec_vec, obs_metadata=obs, band='u') rr = angularSeparation(ra, dec, ra_vec, dec_vec) ct_none = 0 for rr, name in zip(rr, chip_name_list): if rr > 2.0: self.assertIsNone(name) ct_none += 1 self.assertGreater(ct_none, 0)
def potential_obscond(self, t, fieldRA, fieldDec, nightOffset=59579.6): """ Calculate the observing Conditions at a sequence of mjd values `t` for a location with ra and dec `fieldRA` and `fieldDec` in `degrees`. Parameters ---------- t : times at which observations are being made fieldRA : RA, degree fieldDec : Dec, degree nightOffset : mjd value, defaults to 59579.6 mjd value for night = 0 of the survey. """ alt, az = self.field_coords(fieldRA, fieldDec, mjd=t) moonra, moondec, moonalt = self.moonCoords(mjd=t) sunAlt = self.sunAlt(mjd=t) df = pd.DataFrame( dict(mjd=t, alt=alt, az=az, sunAlt=sunAlt, moonRA=moonra, moonDec=moondec, moonAlt=moonalt, night=np.floor(t - 59579.6).astype(np.int))) df['moonDist'] = angularSeparation(moonra, moondec, np.degrees(self.ra), np.degrees(self.dec)) return df
def test_outside_radius(self): """ Test that methods can gracefully handle points outside of the focal plane """ rng = np.random.RandomState(7123) ra = 145.0 dec = -25.0 obs = ObservationMetaData(pointingRA=ra, pointingDec=dec, mjd=59580.0, rotSkyPos=113.0) rr = rng.random_sample(100)*5.0 self.assertGreater(rr.max(), 4.5) theta = rng.random_sample(100)*2.0*np.pi ra_vec = ra + rr*np.cos(theta) dec_vec = dec + rr*np.sin(theta) chip_name_list = chipNameFromRaDecLSST(ra_vec, dec_vec, obs_metadata=obs, band='u') rr = angularSeparation(ra, dec, ra_vec, dec_vec) ct_none = 0 for rr, name in zip(rr, chip_name_list): if rr > 2.0: self.assertIsNone(name) ct_none += 1 self.assertGreater(ct_none, 0)
def write_host_cat(self, image_dir, host_df, output_cat, append=False): """Adds entries for each lensed host FITS stamp to output instance catalog Parameters: ----------- image_dir: string the location of the FITS stamps host_df: pandas dataframe the agn/sne host truth catalog in pandas dataframe format output_cat: string the location of the output instance catalogs """ ang_sep_list = [] image_list = os.listdir(image_dir) image_ids = np.array( ['_'.join(image_name.split('_')[:4]) for image_name in image_list], dtype=str) for sys_ra, sys_dec in zip(host_df['ra_lens'], host_df['dec_lens']): ang_sep_list.append( angularSeparation(sys_ra, sys_dec, self.ra, self.dec)) ang_sep = np.array(ang_sep_list) keep_idx = np.where(ang_sep < self.radius) host_image_df = host_df.iloc[keep_idx].reset_index(drop=True) unique_id_list = [] if append: write_status = 'a' else: write_status = 'w' phosim_coords = self.get_phosim_coords( np.radians(host_image_df['ra_lens'].values), np.radians(host_image_df['dec_lens'].values), self.obs_md) phosim_ra, phosim_dec = np.degrees(phosim_coords) host_image_df['ra_lens'] = phosim_ra host_image_df['dec_lens'] = phosim_dec with open(output_cat, write_status) as f: for df_row_num in range(len(host_image_df)): df_line = host_image_df.iloc[df_row_num] line_uID = df_line['unique_id'] if line_uID in unique_id_list: continue line_idx = np.where(image_ids == line_uID)[0] if len(line_idx) > 1: print(line_idx, line_uID) raise ValueError( 'Multiple images have same unique lens id') if len(line_idx) > 0: line_name = image_list[line_idx[0]] f.write(self.format_catalog(df_line, line_name, image_dir)) unique_id_list.append(line_uID)
def test_stellar_astrometry_degrees(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of stars (in degrees) """ cat_name = os.path.join(self.scratch_dir, 'phosim_ast_star_cat_deg.txt') if os.path.exists(cat_name): os.unlink(cat_name) db = testStarsDBObj(driver='sqlite', database=self.db_name) cat = StarTestCatalog(db, obs_metadata=self.obs) cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase.icrsFromPhoSim( data['raPhoSim'], data['decPhoSim'], self.obs) dist = angularSeparation(data['raICRS'], data['decICRS'], ra_icrs, dec_icrs) dist = 3600.0 * dist self.assertLess(dist.max(), 0.001) # verify that the distance between raPhoSim, decPhoSim and # raICRS, decICRS is greater than the distance between # the original raICRS, decICRS and the newly-calculated # raICRS, decICRS dist_bad = angularSeparation(data['raPhoSim'], data['decPhoSim'], data['raICRS'], data['decICRS']) dist_bad = 3600.0 * dist_bad self.assertGreater(dist_bad.min(), dist.max()) if os.path.exists(cat_name): os.unlink(cat_name) del db
def test_stellar_astrometry_degrees(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of stars (in degrees) """ db = testStarsDBObj(driver='sqlite', database=self.db_name) cat = StarTestCatalog(db, obs_metadata=self.obs) with lsst.utils.tests.getTempFilePath('.txt') as cat_name: cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float), ('raJ2000', float), ('decJ2000', float), ('pmRA', float), ('pmDec', float), ('parallax', float), ('vRad', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase.icrsFromPhoSim(data['raPhoSim'], data['decPhoSim'], self.obs) dist = angularSeparation(data['raICRS'], data['decICRS'], ra_icrs, dec_icrs) dist = 3600.0*dist self.assertLess(dist.max(), 0.001) # verify that the distance between raPhoSim, decPhoSim and # raICRS, decICRS is greater than the distance between # the original raICRS, decICRS and the newly-calculated # raICRS, decICRS dist_bad = angularSeparation(data['raPhoSim'], data['decPhoSim'], data['raICRS'], data['decICRS']) dist_bad = 3600.0*dist_bad self.assertGreater(dist_bad.min(), dist.max()) del db
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 write_lensed_sn_light_curves(row, output, opsim_df, fp_radius, table_name, start_mjd=59580., end_mjd=61405): """ Write the light curve values to the variability table. """ unique_id, ra, dec, z, t_delay, magnification, t0, x0, x1, c = row sp_factory = SNSynthPhotFactory(z=z, t0=t0, x0=x0, x1=x1, c=c, snra=ra, sndec=dec) # Find the opsim db entries corresponding to the time span # when the SN is active and which are within fp_radius # degrees of the SN position. tmin, tmax = sp_factory.mintime() + t_delay, sp_factory.maxtime() + t_delay tmin = max(start_mjd, tmin) tmax = min(end_mjd, tmax) dmin, dmax = dec - fp_radius, dec + fp_radius df = pd.DataFrame( opsim_df.query(f'{tmin} <= expMJD <= {tmax} and ' f'{dmin} <= dec <= {dmax}')) if len(df) == 0: return df['ang_sep'] = angularSeparation(df['ra'].to_numpy(), df['dec'].to_numpy(), ra, dec) df = df.query(f'ang_sep <= {fp_radius}') # Insert the rows into the variability truth table. values = [] for visit, band, mjd in zip(df['obsHistID'], df['filter'], df['expMJD']): phot_params = PhotometricParameters(nexp=1, exptime=30, gain=1, bandpass=band) synth_phot = sp_factory.create(mjd - t_delay) flux = magnification * synth_phot.calcFlux(band) bp = synth_phot.bp_dict[band] num_photons = magnification * synth_phot.sed.calcADU(bp, phot_params) values.append((unique_id, visit, mjd, band, flux, num_photons)) output.cursor().executemany( f'''insert into {table_name} values (?,?,?,?,?,?)''', values) output.commit()
def _actually_on_chip(ra, dec, obs_md): """ Take a numpy array of RA in degrees, a numpy array of Decin degrees and an ObservationMetaData and return a boolean array indicating which of the objects are actually on a chip and which are not """ out_arr = np.array([False]*len(ra)) d_ang = 2.11 good_radii = np.where(angularSeparation(ra, dec, obs_md.pointingRA, obs_md.pointingDec)<d_ang) if len(good_radii[0]) > 0: chip_names = chipNameFromRaDecLSST(ra[good_radii], dec[good_radii], obs_metadata=obs_md).astype(str) vals = np.where(np.char.find(chip_names, 'None')==0, False, True) out_arr[good_radii] = vals return out_arr
def convert_schema(filename, fileout): remap_dict = { 'RA': 'fieldRA', 'dec': 'fieldDec', 'mjd': 'observationStartMJD', 'exptime': 'visitExposureTime', 'filter': 'filter', 'rotSkyPos': 'rotSkyPos', 'nexp': 'numExposures', 'airmass': 'airmass', 'FWHMeff': 'seeingFwhmEff', 'FWHM_geometric': 'seeingFwhmGeom', 'skybrightness': 'skyBrightness', 'night': 'night', 'slewtime': 'slewTime', 'fivesigmadepth': 'fiveSigmaDepth', 'alt': 'altitude', 'az': 'azimuth', 'clouds': 'clouds', 'moonAlt': 'moonAlt', 'sunAlt': 'sunAlt', 'note': 'note', 'field_id': 'fieldId', 'survey_id': 'proposalId', 'block_id': 'block_id' } conn = db.connect(filename) df = pd.read_sql('select * from observations;', conn) df = df.rename(index=str, columns=remap_dict) # Kludge on the visitTime df['visitTime'] = 2. * df['numExposures'].values + df[ 'visitExposureTime'].values # Dummy column df['slewDistance'] = 0. * df['numExposures'].values # Add the solar elongation in there times = Time(df['observationStartMJD'].values, format='mjd') suns = get_sun(times) solarElong = angularSeparation(suns.ra.value, suns.dec.value, df['fieldRA'].values, df['fieldDec'].values) df['solarElong'] = solarElong conn.close() conn = db.connect(fileout) df.to_sql('SummaryAllProps', conn, index=False, if_exists='replace')
def test_local_instance_catalog(self): """ Test that the local galaxy obj can interface with the InstanceCatalog as expected """ class LocalGalDummyICat(InstanceCatalog): column_outputs = [ 'raJ2000', 'decJ2000', 'ra', 'dec', 'galtag', 'someFloat' ] delimiter = ' ' default_formats = {'f': '%.9g'} @cached def get_someFloat(self): t = self.column_by_name('galtag') r = self.column_by_name('ra') d = self.column_by_name('dec') return r**2 + d + 0.5 * t obs = ObservationMetaData(pointingRA=34.0, pointingDec=44.0, boundType='circle', boundLength=3.0) dbobj = UWGal.UWGalaxyTileObj(database=self._temp_gal_db, driver='sqlite') cat = LocalGalDummyICat(dbobj, obs_metadata=obs) scratch_dir = tempfile.mkdtemp(dir=ROOT, prefix='local_gal') cat_name = tempfile.mktemp(dir=scratch_dir, prefix='local_gal', suffix='.txt') cat.write_catalog(cat_name) dt = np.dtype([('raJ2000', float), ('decJ2000', float), ('ra', float), ('dec', float), ('galtag', int), ('someFloat', float)]) data = np.genfromtxt(cat_name, dtype=dt) dd = angularSeparation(data['ra'], data['dec'], np.degrees(data['raJ2000']), np.degrees(data['decJ2000'])) self.assertLess(dd.max(), 0.001 / 3600.0) ff = data['ra']**2 + data['dec'] + 0.5 * data['galtag'] np.testing.assert_array_almost_equal(ff, data['someFloat'], decimal=5) if os.path.exists(cat_name): os.unlink(cat_name) shutil.rmtree(scratch_dir, ignore_errors=True)
def main(ramax=58, ramin=56, decmin=-32, decmax=-31, t0=59215, tm=59945): res = ObsMetaData.getObservationMetaData(boundLength=2, boundType='circle', fieldRA=(ramin-3, ramax+3), fieldDec=(decmin-3, decmax+3), expMJD=(t0, tm)) parsed = [Odict(obsmd.summary['OpsimMetaData']) for obsmd in res \ if obsmd.bandpass in ("g", "r", "i", "z", "y")] df = pd.DataFrame(parsed) X = df[['obsHistID', 'filter', 'FWHMeff', 'descDitheredRA', 'descDitheredDec', 'airmass', 'fiveSigmaDepth', 'expMJD']].copy() X.descDitheredRA = np.degrees(X.descDitheredRA) X.descDitheredDec = np.degrees(X.descDitheredDec) X['d1'] = angularSeparation(ramin, decmax, X.descDitheredRA.values, X.descDitheredDec.values) X['d2'] = angularSeparation(ramin, decmin, X.descDitheredRA.values, X.descDitheredDec.values) X['d3'] = angularSeparation(ramax, decmax, X.descDitheredRA.values, X.descDitheredDec.values) X['d4'] = angularSeparation(ramax, decmin, X.descDitheredRA.values, X.descDitheredDec.values) Y = X.query('d1 < 1.75 | d2 < 1.75 | d3 < 1.75 |d4 < 1.75')#.obsHistID.size for afilter in np.unique(Y['filter']): sub = Y[Y['filter']==afilter] print(afilter, sub[['airmass', 'FWHMeff', 'fiveSigmaDepth']].describe()) print('\n') Y.to_csv('./catalogs+tables/visits_from_minion.csv')
def write_host_cat(self, image_dir, input_cat, output_cat, append=False): """Adds entries for each lensed host FITS stamp to output instance catalog Parameters: ----------- image_dir: string the location of the FITS stamps input_cat: string the list of FITS stamps to be read in output_cat: string the location of the output instance catalogs """ host_df = pd.read_csv(input_cat) ang_sep_list = [] image_list = os.listdir(image_dir) image_ids = np.array( [image_name.split('_')[0] for image_name in image_list], dtype=np.int) for sys_ra, sys_dec in zip(host_df['raPhoSim_lens'], host_df['decPhoSim_lens']): ang_sep_list.append( angularSeparation(sys_ra, sys_dec, self.ra, self.dec)) ang_sep = np.array(ang_sep_list) keep_idx = np.where(ang_sep < self.radius) host_image_df = host_df.iloc[keep_idx] unique_id_list = [] if append: write_status = 'a' else: write_status = 'w' with open(output_cat, write_status) as f: for df_line in host_image_df.iterrows(): line_uID = df_line[1]['uniqueId_lens'] if line_uID in unique_id_list: continue line_idx = np.where(image_ids == line_uID)[0] if len(line_idx) > 1: raise ValueError( 'Multiple images have same unique lens id') if len(line_idx) > 0: line_name = image_list[line_idx[0]] f.write( self.format_catalog(df_line[1], line_name, image_dir)) unique_id_list.append(line_uID)
def setUpClass(cls): cls._tile_radius = angularSeparation(0.0, 0.0, 2.0, 2.0) dir_name = os.path.join(getPackageDir('sims_catUtils'), 'tests') cls._tmpdir = tempfile.mkdtemp(dir=dir_name) cls._temp_gal_db = os.path.join(cls._tmpdir, 'test_galaxies.db') ra_min = -2.25 cls._ra_min = ra_min ra_max = 2.251 cls._d_ra = 0.05 ra_grid = np.arange(ra_min, ra_max, cls._d_ra) dec_grid = np.arange(ra_min, ra_max, cls._d_ra) print('raw grid %d' % len(ra_grid)) ra_dec_mesh = np.meshgrid(ra_grid, dec_grid) ra_grid = ra_dec_mesh[0].flatten() dec_grid = ra_dec_mesh[1].flatten() # add a very small offset so that numerical precision # does not foul things up on the tile boundaries rng = np.random.RandomState(7163) ra_grid += 1.0e-5 * (rng.random_sample(len(ra_grid)) - 0.5) dec_grid += 1.0e-5 * (rng.random_sample(len(dec_grid)) - 0.5) galtag = (100 * np.round(45 + ra_grid / cls._d_ra) + np.round(45 + dec_grid / cls._d_ra)).astype(int) assert len(galtag) == len(np.unique(galtag)) htmid_grid = htm.findHtmid(ra_grid, dec_grid, 21) print('got htmid %d' % len(htmid_grid)) print(htm.levelFromHtmid(htmid_grid.min())) print(htm.levelFromHtmid(htmid_grid.max())) assert htm.levelFromHtmid(htmid_grid.min()) == 21 assert htm.levelFromHtmid(htmid_grid.max()) == 21 gid = np.arange(len(ra_grid), dtype=int) assert len(galtag) == len(np.unique(galtag)) print(ra_grid.max(), ra_grid.min()) with sqlite3.connect(cls._temp_gal_db) as conn: c = conn.cursor() query = '''CREATE TABLE galaxy(htmid int, id int, galid text, ra real, dec real, galtag int, redshift)''' c.execute(query).fetchall() values = ((int(hh), int(ii), str(ii), r, d, int(g), 0.5) for hh, ii, r, d, g in zip(htmid_grid, gid, ra_grid, dec_grid, galtag)) c.executemany('INSERT INTO galaxy VALUES (?,?,?,?,?,?,?)', values)
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_stellar_observed_degrees(self): """ Test ability to go all the way to observed RA, Dec from PhoSim (this is necessary for the ImSim software that DESC is working on) """ db = testStarsDBObj(driver='sqlite', database=self.db_name) cat = StarTestCatalog(db, obs_metadata=self.obs) with lsst.utils.tests.getTempFilePath('.txt') as cat_name: cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float), ('raJ2000', float), ('decJ2000', float), ('pmRA', float), ('pmDec', float), ('parallax', float), ('vRad', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) (ra_obs, dec_obs) = observedFromICRS(np.degrees(data['raJ2000']), np.degrees(data['decJ2000']), obs_metadata=self.obs, pm_ra=arcsecFromRadians(data['pmRA']), pm_dec=arcsecFromRadians(data['pmDec']), parallax=arcsecFromRadians(data['parallax']), v_rad=data['vRad'], includeRefraction=True, epoch=2000.0) (ra_appGeo, dec_appGeo) = PhoSimAstrometryBase.appGeoFromPhoSim(data['raPhoSim'], data['decPhoSim'], self.obs) (ra_obs_2, dec_obs_2) = observedFromAppGeo(ra_appGeo, dec_appGeo, obs_metadata=self.obs, includeRefraction=True) dd = 3600.0*angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2) self.assertLess(dd.max(), 1.0e-5)
def test_stellar_observed_degrees(self): """ Test ability to go all the way to observed RA, Dec from PhoSim (this is necessary for the ImSim software that DESC is working on) """ db = testStarsDBObj(driver='sqlite', database=self.db_name) cat = StarTestCatalog(db, obs_metadata=self.obs) with lsst.utils.tests.getTempFilePath('.txt') as cat_name: cat.write_catalog(cat_name) dtype = np.dtype([('raICRS', float), ('decICRS', float), ('raPhoSim', float), ('decPhoSim', float), ('raJ2000', float), ('decJ2000', float), ('pmRA', float), ('pmDec', float), ('parallax', float), ('vRad', float)]) data = np.genfromtxt(cat_name, dtype=dtype) self.assertGreater(len(data), 100) (ra_obs, dec_obs) = observedFromICRS( np.degrees(data['raJ2000']), np.degrees(data['decJ2000']), obs_metadata=self.obs, pm_ra=arcsecFromRadians(data['pmRA']), pm_dec=arcsecFromRadians(data['pmDec']), parallax=arcsecFromRadians(data['parallax']), v_rad=data['vRad'], includeRefraction=True, epoch=2000.0) (ra_appGeo, dec_appGeo) = PhoSimAstrometryBase.appGeoFromPhoSim( data['raPhoSim'], data['decPhoSim'], self.obs) (ra_obs_2, dec_obs_2) = observedFromAppGeo(ra_appGeo, dec_appGeo, obs_metadata=self.obs, includeRefraction=True) dd = 3600.0 * angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2) self.assertLess(dd.max(), 1.0e-5)
def test_against_catalog(self): """ Compare deprecession results to a catalog that was validated with PhoSim. """ obs = ObservationMetaData(pointingRA=53.00913847303155535, pointingDec=-27.43894880881512321, rotSkyPos=256.75075318193080420, mjd=59580.13955500000156462, site=Site(name="LSST", pressure=0.0, humidity=0.0)) dtype = np.dtype([('id', int), ('ra', float), ('dec', float), ('ra_deprecessed', float), ('dec_deprecessed', float), ('x_dm', float), ('y_dm', float), ('x_focal', float), ('y_focal', float), ('x_cam', float), ('y_cam', float)]) data = np.genfromtxt(os.path.join(getPackageDir('sims_catUtils'), 'tests', 'testData', 'pixel_prediction_catalog.txt'), dtype=dtype) ra_obs, dec_obs = observedFromICRS(data['ra'], data['dec'], obs_metadata=obs, includeRefraction=False, epoch=2000.0) phosim_mixin = PhoSimAstrometryBase() ra_dep, dec_dep = phosim_mixin._dePrecess(np.radians(ra_obs), np.radians(dec_obs), obs) dd = 3600.0 * angularSeparation( data['ra_deprecessed'], data['dec_deprecessed'], np.degrees(ra_dep), np.degrees(dec_dep)) self.assertLess(dd.max(), 1.0e-5)
def ssoInCircleFov(self, ephems, obsData, rFov=2.1): """Determine which observations are within a circular fov 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 The observation pointings, with RA and Dec as 'ra' and 'dec' columns (in degrees). rFov : float, opt The radius of the field of view, in degrees. Default 2.1 is appropriate for LSST fov if later applying camera footprint. A value of 1.75 would be appropriate for simple circular LSST FOV assumption. Returns ------- np.ndarray Returns the indexes of the numpy array of the object observations which are inside the fov. """ sep = angularSeparation(ephems['ra'], ephems['dec'], obsData['ra'], obsData['dec']) idxObs = np.where(sep <= rFov)[0] return idxObs
def test_against_catalog(self): """ Compare deprecession results to a catalog that was validated with PhoSim. """ obs = ObservationMetaData(pointingRA=53.00913847303155535, pointingDec=-27.43894880881512321, rotSkyPos=256.75075318193080420, mjd=59580.13955500000156462, site=Site(name="LSST", pressure=0.0, humidity=0.0)) dtype = np.dtype([('id', int), ('ra', float), ('dec', float), ('ra_deprecessed', float), ('dec_deprecessed', float), ('x_dm', float), ('y_dm', float), ('x_focal', float), ('y_focal', float), ('x_cam', float), ('y_cam', float)]) data = np.genfromtxt(os.path.join(getPackageDir('sims_catUtils'), 'tests', 'testData', 'pixel_prediction_catalog.txt'), dtype=dtype) ra_obs, dec_obs = observedFromICRS(data['ra'], data['dec'], obs_metadata=obs, includeRefraction=False, epoch=2000.0) phosim_mixin = PhoSimAstrometryBase() ra_dep, dec_dep = phosim_mixin._dePrecess(np.radians(ra_obs), np.radians(dec_obs), obs) dd = 3600.0*angularSeparation(data['ra_deprecessed'], data['dec_deprecessed'], np.degrees(ra_dep), np.degrees(dec_dep)) self.assertLess(dd.max(), 1.0e-5)
def apply_focal_plane(ra, dec, photometry_mask_1d, obs_md_list, filter_obs, proper_chip): fov_radius = 1.75 n_obj = len(ra) n_t = len(filter_obs) if not proper_chip: seed = int(np.round(ra[0]*1000.0+ dec[0]*1000.0+ obs_md_list[0].mjd.TAI)) rng = np.random.RandomState(seed) chip_mask = np.zeros((n_obj, n_t), dtype=bool) for i_t, (obs, i_bp) in enumerate(zip(obs_md_list, filter_obs)): if proper_chip: chip_name= chipNameFromRaDecLSST(ra[photometry_mask_1d], dec[photometry_mask_1d], obs_metadata=obs, band='ugrizy'[i_bp]) valid_chip = (np.char.find(chip_name.astype(str), 'None') == -1) else: ra_valid = ra[photometry_mask_1d] dec_valid = dec[photometry_mask_1d] dd = angularSeparation(ra_valid, dec_valid, obs.pointingRA, obs.pointingDec) #focal_plane_roll = rng.random_sample(len(ra_valid)) #valid_chip = (dd<=fov_radius)&(focal_plane_roll<0.9) valid_chip = (dd<=fov_radius) chip_mask[photometry_mask_1d, i_t] = valid_chip return chip_mask
def testAngSepExceptions(self): """ Test that an exception is raised when you pass mismatched inputs to angularSeparation. """ ra1 = 23.0 dec1 = -12.0 ra2 = 45.0 dec2 = 33.1 ra1_arr = np.array([11.0, 21.0, 33.1]) dec1_arr = np.array([-11.1, 34.1, 86.2]) ra2_arr = np.array([45.2, 112.0, 89.3]) dec2_arr = np.array([11.1, -45.0, -71.0]) # test that everything runs utils._angularSeparation(np.radians(ra1), np.radians(dec1), np.radians(ra2), np.radians(dec2)) utils.angularSeparation(ra1, dec1, ra2, dec2) ans = utils._angularSeparation(np.radians(ra1_arr), np.radians(dec1_arr), np.radians(ra2_arr), np.radians(dec2_arr)) self.assertEqual(len(ans), 3) ans = utils.angularSeparation(ra1_arr, dec1_arr, ra2_arr, dec2_arr) self.assertEqual(len(ans), 3) ans = utils.angularSeparation(ra1_arr, dec1_arr, ra2, dec2) self.assertEqual(len(ans), 3) ans = utils._angularSeparation(ra1_arr, ra2_arr, ra2, dec2) self.assertEqual(len(ans), 3) ans = utils.angularSeparation(ra1, dec1, ra2_arr, dec2_arr) self.assertEqual(len(ans), 3) ans = utils._angularSeparation(dec1, ra1, ra2_arr, dec2_arr) self.assertEqual(len(ans), 3) # test with lists # Note: these exceptions will not get raised if you call # angularSeparation() with lists instead of numpy arrays # because the conversion from degrees to radians with # np.radians will automatically convert the lists into arrays with self.assertRaises(RuntimeError) as context: utils._angularSeparation(list(ra1_arr), dec1_arr, ra2_arr, dec2_arr) self.assertIn("number", context.exception.args[0]) self.assertIn("numpy array", context.exception.args[0]) self.assertIn("long1", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr, list(dec1_arr), ra2_arr, dec2_arr) self.assertIn("number", context.exception.args[0]) self.assertIn("numpy array", context.exception.args[0]) self.assertIn("lat1", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr, dec1_arr, list(ra2_arr), dec2_arr) self.assertIn("number", context.exception.args[0]) self.assertIn("numpy array", context.exception.args[0]) self.assertIn("long2", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr, dec1_arr, ra2_arr, list(dec2_arr)) self.assertIn("number", context.exception.args[0]) self.assertIn("numpy array", context.exception.args[0]) self.assertIn("lat2", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) # test with numbers and arrays with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr, dec1, ra2, dec2) self.assertIn("the same type", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1, dec1_arr, ra2, dec2) self.assertIn("the same type", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1, dec1, ra2_arr, dec2) self.assertIn("the same type", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1, dec1, ra2, dec2_arr) self.assertIn("the same type", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1_arr, dec1, ra2, dec2) self.assertIn("the same type", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1, dec1_arr, ra2, dec2) self.assertIn("the same type", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1, dec1, ra2_arr, dec2) self.assertIn("the same type", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1, dec1, ra2, dec2_arr) self.assertIn("the same type", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) # test with mismatched arrays with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr[:2], dec1_arr, ra2_arr, dec2_arr) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr, dec1_arr[:2], ra2_arr, dec2_arr) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr, dec1_arr, ra2_arr[:2], dec2_arr) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr, dec1_arr, ra2_arr, dec2_arr[:2]) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1_arr[:2], dec1_arr, ra2_arr, dec2_arr) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1_arr, dec1_arr[:2], ra2_arr, dec2_arr) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1_arr, dec1_arr, ra2_arr[:2], dec2_arr) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1_arr, dec1_arr, ra2_arr, dec2_arr[:2]) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr[:2], dec1_arr[:2], ra2_arr, dec2_arr) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1_arr, dec1_arr, ra2_arr[:2], dec2_arr[:2]) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1_arr[:2], dec1_arr[:2], ra2_arr, dec2_arr) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils.angularSeparation(ra1_arr, dec1_arr, ra2_arr[:2], dec2_arr[:2]) self.assertIn("same length", context.exception.args[0]) self.assertIn("angularSeparation", context.exception.args[0]) # test that a sensible error is raised if you pass a string # into angularSeparation # Note: a different error will be raised if you pass these # bad inputs into angularSeparation(). The exception will come # from trying to convert a str with np.radians with self.assertRaises(RuntimeError) as context: utils._angularSeparation('a', dec1, ra2, dec2) self.assertIn("angularSeparation", context.exception.args[0]) self.assertIn("number", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1, 'a', ra2, dec2) self.assertIn("angularSeparation", context.exception.args[0]) self.assertIn("number", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1, dec1, 'a', dec2) self.assertIn("angularSeparation", context.exception.args[0]) self.assertIn("number", context.exception.args[0]) with self.assertRaises(RuntimeError) as context: utils._angularSeparation(ra1, dec1, ra2, 'a') self.assertIn("angularSeparation", context.exception.args[0]) self.assertIn("number", context.exception.args[0])
query += 'FROM gaia_2016 ' query += 'WHERE ' for i_pair, pair in enumerate(tx_list): min_tx = int(pair[0]<<n_bits_off) max_tx = int((pair[1]+1)<<n_bits_off) query += '(htmid>=%d AND htmid<=%d)' % (min_tx, max_tx) if i_pair<len(tx_list)-1: query += ' OR ' dtype = np.dtype([('ra', float), ('dec', float), ('mag', float)]) results = gaia_db.get_arbitrary_chunk_iterator(query, dtype=dtype, chunk_size=10000) result = list(results)[0] distances = angularSeparation(result['ra'], result['dec'], ra[i], dec[i]) # Degrees result = result[np.where(distances < radius)] import pdb ; pdb.set_trace() # I could think of setting the chunksize to something really large, then only doing one chunk? # Or maybe setting up a way to break out of the loop if everything gets really dense? tempHist = np.zeros(np.size(bins)-1, dtype=float) counter = 0 for chunk in results: chunkHist, bins = np.histogram(chunk[colName], bins) tempHist += chunkHist counter += chunk_size if counter >= breakLimit: overMaxMask[i] = True break
def testAngSepResultsFloat(self): """ Test that angularSeparation gives the correct answer by comparing results with the dot products of Cartesian vectors. Pass in floats as arguments. """ rng = np.random.RandomState(831) ra1 = rng.random_sample()*2.0*np.pi dec1 = rng.random_sample()*np.pi-0.5*np.pi ra2 = rng.random_sample()*2.0*np.pi dec2 = rng.random_sample()*np.pi-0.5*np.pi x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) x2 = np.cos(dec2)*np.cos(ra2) y2 = np.cos(dec2)*np.sin(ra2) z2 = np.sin(dec2) control = x1*x2 + y1*y2 + z1*z2 test = utils._angularSeparation(ra1, dec1, ra2, dec2) self.assertIsInstance(test, float) test = np.cos(test) self.assertAlmostEqual(control, test, 15) test = utils._angularSeparation(np.array([ra1]), np.array([dec1]), ra2, dec2) self.assertIsInstance(test, float) test = np.cos(test) self.assertAlmostEqual(control, test, 15) test = utils._angularSeparation(ra1, dec1, np.array([ra2]), np.array([dec2])) self.assertIsInstance(test, float) test = np.cos(test) self.assertAlmostEqual(control, test, 15) # try north pole ra1 = 0.5*np.pi x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) control = x1*x2 + y1*y2 + z1*z2 test = utils._angularSeparation(ra1, dec1, ra2, dec2) self.assertIsInstance(test, float) test = np.cos(test) self.assertAlmostEqual(control, test, 15) test = utils._angularSeparation(np.array([ra1]), np.array([dec1]), ra2, dec2) self.assertIsInstance(test, float) test = np.cos(test) self.assertAlmostEqual(control, test, 15) test = utils._angularSeparation(ra1, dec1, np.array([ra2]), np.array([dec2])) self.assertIsInstance(test, float) test = np.cos(test) self.assertAlmostEqual(control, test, 15) # do all of that in degrees ra1 = rng.random_sample()*360.0 dec1 = rng.random_sample()*180.0-90.0 ra2 = rng.random_sample()*360.0 dec2 = rng.random_sample()*180.0-90.0 x1 = np.cos(np.radians(dec1))*np.cos(np.radians(ra1)) y1 = np.cos(np.radians(dec1))*np.sin(np.radians(ra1)) z1 = np.sin(np.radians(dec1)) x2 = np.cos(np.radians(dec2))*np.cos(np.radians(ra2)) y2 = np.cos(np.radians(dec2))*np.sin(np.radians(ra2)) z2 = np.sin(np.radians(dec2)) control = x1*x2 + y1*y2 + z1*z2 test = utils.angularSeparation(ra1, dec1, ra2, dec2) self.assertIsInstance(test, float) test = np.cos(np.radians(test)) self.assertAlmostEqual(control, test, 15) test = utils.angularSeparation(np.array([ra1]), np.array([dec1]), ra2, dec2) self.assertIsInstance(test, float) test = np.cos(np.radians(test)) self.assertAlmostEqual(control, test, 15) test = utils.angularSeparation(ra1, dec1, np.array([ra2]), np.array([dec2])) self.assertIsInstance(test, float) test = np.cos(np.radians(test)) self.assertAlmostEqual(control, test, 15) # try north pole ra1 = 90.0 x1 = np.cos(np.radians(dec1))*np.cos(np.radians(ra1)) y1 = np.cos(np.radians(dec1))*np.sin(np.radians(ra1)) z1 = np.sin(np.radians(dec1)) control = x1*x2 + y1*y2 + z1*z2 test = utils.angularSeparation(ra1, dec1, ra2, dec2) self.assertIsInstance(test, float) test = np.cos(np.radians(test)) self.assertAlmostEqual(control, test, 15) test = utils.angularSeparation(np.array([ra1]), np.array([dec1]), ra2, dec2) self.assertIsInstance(test, float) test = np.cos(np.radians(test)) self.assertAlmostEqual(control, test, 15) test = utils.angularSeparation(ra1, dec1, np.array([ra2]), np.array([dec2])) self.assertIsInstance(test, float) test = np.cos(np.radians(test)) self.assertAlmostEqual(control, test, 15)
def testAngSepResultsExtreme(self): """ Test that angularSeparation gives the correct answer by comparing results with the dot products of Cartesian vectors. Test on extremal values (i.e. longitudes that go beyond 360.0 and latitudes that go beyond 90.0) """ rng = np.random.RandomState(99421) n_obj = 100 for sgn in (-1.0, 1.0): ra1 = sgn*(rng.random_sample(n_obj)*2.0*np.pi + 2.0*np.pi) dec1 = sgn*(rng.random_sample(n_obj)*4.0*np.pi + 2.0*np.pi) ra2 = sgn*(rng.random_sample(n_obj)*2.0*np.pi + 2.0*np.pi) dec2 = sgn*(rng.random_sample(n_obj)*2.0*np.pi + 2.0*np.pi) x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) x2 = np.cos(dec2)*np.cos(ra2) y2 = np.cos(dec2)*np.sin(ra2) z2 = np.sin(dec2) test = utils._angularSeparation(ra1, dec1, ra2, dec2) test = np.cos(test) control = x1*x2 + y1*y2 + z1*z2 np.testing.assert_array_almost_equal(test, control, decimal=14) test = utils.angularSeparation(np.degrees(ra1), np.degrees(dec1), np.degrees(ra2), np.degrees(dec2)) test = np.cos(np.radians(test)) np.testing.assert_array_almost_equal(test, control, decimal=14) # specifically test at the north pole dec1 = np.ones(n_obj)*np.pi x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) control = x1*x2 + y1*y2 + z1*z2 test = utils._angularSeparation(ra1, dec1, ra2, dec2) test = np.cos(test) np.testing.assert_array_almost_equal(test, control, decimal=14) test = utils.angularSeparation(np.degrees(ra1), np.degrees(dec1), np.degrees(ra2), np.degrees(dec2)) test = np.cos(np.radians(test)) dd = np.abs(test-control) np.testing.assert_array_almost_equal(test, control, decimal=14) # specifically test at the south pole dec1 = -1.0*np.ones(n_obj)*np.pi x1 = np.cos(dec1)*np.cos(ra1) y1 = np.cos(dec1)*np.sin(ra1) z1 = np.sin(dec1) control = x1*x2 + y1*y2 + z1*z2 test = utils._angularSeparation(ra1, dec1, ra2, dec2) test = np.cos(test) np.testing.assert_array_almost_equal(test, control, decimal=14) test = utils.angularSeparation(np.degrees(ra1), np.degrees(dec1), np.degrees(ra2), np.degrees(dec2)) test = np.cos(np.radians(test)) np.testing.assert_array_almost_equal(test, control, decimal=14)
def test_very_positive_RA(self): """ Test that spatial queries behave correctly around RA=0 (when RA>350) """ rng = np.random.RandomState(81234122) db_name = os.path.join(self.scratch_dir, 'very_pos_ra.db') with sqlite3.connect(db_name) as connection: cursor = connection.cursor() cursor.execute('''CREATE TABLE neg_ra_table (cat_id int, ra real, dec real)''') connection.commit() n_samples = 1000 id_val = np.arange(n_samples, dtype=int) + 1 ra = 10.0*(rng.random_sample(n_samples)-0.5) neg_dex = np.where(ra<0.0) ra[neg_dex] += 360.0 dec = rng.random_sample(n_samples)-0.5 values = ((int(ii), rr, dd) for ii, rr, dd in zip(id_val, ra, dec)) cursor.executemany('''INSERT INTO neg_ra_table VALUES (?, ?, ?)''', values) connection.commit() class veryPositiveRaCatalogDBClass(CatalogDBObject): tableid = 'neg_ra_table' idColKey = 'cat_id' raColName = 'ra' decColName = 'dec' objectTypeId = 126 class veryPositiveRaCatalogClass(InstanceCatalog): column_outputs = ['cat_id', 'ra', 'dec'] delimiter = ' ' db = veryPositiveRaCatalogDBClass(database=db_name, driver='sqlite') boundLength=0.2 pra = 359.9 pdec = 0.0 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, boundType='circle', boundLength=boundLength) cat = veryPositiveRaCatalogClass(db, obs_metadata=obs) cat_name = os.path.join(self.scratch_dir, 'very_pos_ra_cat.txt') cat.write_catalog(cat_name) valid = np.where(angularSeparation(pra, pdec, ra, dec)<boundLength) self.assertGreater(len(valid[0]), 0) self.assertLess(len(valid[0]), n_samples) valid_pos = np.where(np.logical_and(angularSeparation(pra, pdec, ra, dec)<boundLength, ra<350.0)) valid_neg = np.where(np.logical_and(angularSeparation(pra, pdec, ra, dec)<boundLength, ra>350.0)) self.assertGreater(len(valid_pos[0]), 0) self.assertGreater(len(valid_neg[0]), 0) self.assertLess(len(valid_pos[0]), len(valid[0])) valid_id = id_val[valid] valid_ra = ra[valid] valid_dec = dec[valid] cat_dtype = np.dtype([('cat_id', int), ('ra', float), ('dec', float)]) cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) np.testing.assert_array_equal(cat_data['cat_id'], valid_id) np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) # now try it when RA is specified as negative pra = -0.1 pdec = 0.0 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, boundType='circle', boundLength=boundLength) cat = veryPositiveRaCatalogClass(db, obs_metadata=obs) cat.write_catalog(cat_name) cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) np.testing.assert_array_equal(cat_data['cat_id'], valid_id) np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) # test it on a box pra = 359.9 pdec = 0.0 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, boundType='box', boundLength=boundLength) cat = veryPositiveRaCatalogClass(db, obs_metadata=obs) dec_min = pdec-boundLength dec_max = pdec+boundLength valid_id = [] valid_ra = [] valid_dec = [] for rr, dd, ii in zip(ra, dec, id_val): if dd>dec_max or dd<dec_min: continue if np.abs(rr-359.9)<boundLength or (rr+0.1)<boundLength: valid_id.append(ii) valid_ra.append(rr) valid_dec.append(dd) valid_id = np.array(valid_id) valid_ra = np.array(valid_ra) valid_dec = np.array(valid_dec) cat.write_catalog(cat_name) cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) np.testing.assert_array_equal(cat_data['cat_id'], valid_id) np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) # try when defined at negative pra = -0.1 pdec = 0.0 obs = ObservationMetaData(pointingRA=pra, pointingDec=pdec, boundType='box', boundLength=boundLength) cat = veryPositiveRaCatalogClass(db, obs_metadata=obs) cat.write_catalog(cat_name) cat_data = np.genfromtxt(cat_name, dtype=cat_dtype) np.testing.assert_array_equal(cat_data['cat_id'], valid_id) np.testing.assert_array_almost_equal(cat_data['ra'], valid_ra, decimal=3) np.testing.assert_array_almost_equal(cat_data['dec'], valid_dec, decimal=3) del db if os.path.exists(db_name): os.unlink(db_name)
def scienceRadarBatch(colmap=None, runName='opsim', extraSql=None, extraMetadata=None, nside=64, benchmarkArea=18000, benchmarkNvisits=825, DDF=True): """A batch of metrics for looking at survey performance relative to the SRD and the main science drivers of LSST. Parameters ---------- """ # Hide dependencies from mafContrib.LSSObsStrategy.galaxyCountsMetric_extended import GalaxyCountsMetric_extended from mafContrib import Plasticc_metric, plasticc_slicer, load_plasticc_lc, TDEsAsciiMetric if colmap is None: colmap = ColMapDict('fbs') if extraSql is None: extraSql = '' if extraSql == '': joiner = '' else: joiner = ' and ' bundleList = [] # Get some standard per-filter coloring and sql constraints filterlist, colors, filterorders, filtersqls, filtermetadata = filterList( all=False, extraSql=extraSql, extraMetadata=extraMetadata) standardStats = standardSummary(withCount=False) healslicer = slicers.HealpixSlicer(nside=nside) subsetPlots = [plots.HealpixSkyMap(), plots.HealpixHistogram()] # Load up the plastic light curves models = ['SNIa-normal', 'KN'] plasticc_models_dict = {} for model in models: plasticc_models_dict[model] = list( load_plasticc_lc(model=model).values()) ######################### # SRD, DM, etc ######################### fOb = fOBatch(runName=runName, colmap=colmap, extraSql=extraSql, extraMetadata=extraMetadata, benchmarkArea=benchmarkArea, benchmarkNvisits=benchmarkNvisits) astromb = astrometryBatch(runName=runName, colmap=colmap, extraSql=extraSql, extraMetadata=extraMetadata) rapidb = rapidRevisitBatch(runName=runName, colmap=colmap, extraSql=extraSql, extraMetadata=extraMetadata) # loop through and modify the display dicts - set SRD as group and their previous 'group' as the subgroup temp_list = [] for key in fOb: temp_list.append(fOb[key]) for key in astromb: temp_list.append(astromb[key]) for key in rapidb: temp_list.append(rapidb[key]) for metricb in temp_list: metricb.displayDict['subgroup'] = metricb.displayDict['group'].replace( 'SRD', '').lstrip(' ') metricb.displayDict['group'] = 'SRD' bundleList.extend(temp_list) displayDict = { 'group': 'SRD', 'subgroup': 'Year Coverage', 'order': 0, 'caption': 'Number of years with observations.' } slicer = slicers.HealpixSlicer(nside=nside) metric = metrics.YearCoverageMetric() for f in filterlist: plotDict = {'colorMin': 7, 'colorMax': 10, 'color': colors[f]} summary = [ metrics.AreaSummaryMetric(area=18000, reduce_func=np.mean, decreasing=True, metricName='N Seasons (18k) %s' % f) ] bundleList.append( mb.MetricBundle(metric, slicer, filtersqls[f], plotDict=plotDict, metadata=filtermetadata[f], displayDict=displayDict, summaryMetrics=summary)) ######################### # Solar System ######################### # Generally, we need to run Solar System metrics separately; they're a multi-step process. ######################### # Cosmology ######################### displayDict = { 'group': 'Cosmology', 'subgroup': 'Galaxy Counts', 'order': 0, 'caption': None } plotDict = {'percentileClip': 95., 'nTicks': 5} sql = extraSql + joiner + 'filter="i"' metadata = combineMetadata(extraMetadata, 'i band') metric = GalaxyCountsMetric_extended(filterBand='i', redshiftBin='all', nside=nside) summary = [ metrics.AreaSummaryMetric(area=18000, reduce_func=np.sum, decreasing=True, metricName='N Galaxies (18k)') ] summary.append(metrics.SumMetric(metricName='N Galaxies (all)')) # make sure slicer has cache off slicer = slicers.HealpixSlicer(nside=nside, useCache=False) bundle = mb.MetricBundle(metric, slicer, sql, plotDict=plotDict, metadata=metadata, displayDict=displayDict, summaryMetrics=summary, plotFuncs=subsetPlots) bundleList.append(bundle) displayDict['order'] += 1 # let's put Type Ia SN in here displayDict['subgroup'] = 'SNe Ia' # XXX-- use the light curves from PLASTICC here displayDict['caption'] = 'Fraction of normal SNe Ia' sql = extraSql slicer = plasticc_slicer(plcs=plasticc_models_dict['SNIa-normal'], seed=42, badval=0) metric = Plasticc_metric(metricName='SNIa') # Set the maskval so that we count missing objects as zero. summary_stats = [metrics.MeanMetric(maskVal=0)] plotFuncs = [plots.HealpixSkyMap()] bundle = mb.MetricBundle(metric, slicer, sql, runName=runName, summaryMetrics=summary_stats, plotFuncs=plotFuncs, metadata=extraMetadata, displayDict=displayDict) bundleList.append(bundle) displayDict['order'] += 1 displayDict['subgroup'] = 'Camera Rotator' displayDict[ 'caption'] = 'Kuiper statistic (0 is uniform, 1 is delta function) of the ' slicer = slicers.HealpixSlicer(nside=nside) metric1 = metrics.KuiperMetric('rotSkyPos') metric2 = metrics.KuiperMetric('rotTelPos') for f in filterlist: for m in [metric1, metric2]: plotDict = {'color': colors[f]} displayDict['order'] = filterorders[f] displayDict['caption'] += f"{m.colname} for visits in {f} band." bundleList.append( mb.MetricBundle(m, slicer, filtersqls[f], plotDict=plotDict, displayDict=displayDict, summaryMetrics=standardStats, plotFuncs=subsetPlots)) # XXX--need some sort of metric for weak lensing ######################### # Variables and Transients ######################### displayDict = { 'group': 'Variables/Transients', 'subgroup': 'Periodic Stars', 'order': 0, 'caption': None } for period in [ 0.5, 1, 2, ]: for magnitude in [21., 24.]: amplitudes = [0.05, 0.1, 1.0] periods = [period] * len(amplitudes) starMags = [magnitude] * len(amplitudes) plotDict = { 'nTicks': 3, 'colorMin': 0, 'colorMax': 3, 'xMin': 0, 'xMax': 3 } metadata = combineMetadata( 'P_%.1f_Mag_%.0f_Amp_0.05-0.1-1' % (period, magnitude), extraMetadata) sql = None displayDict['caption'] = 'Metric evaluates if a periodic signal of period %.1f days could ' \ 'be detected for an r=%i star. A variety of amplitudes of periodicity ' \ 'are tested: [1, 0.1, and 0.05] mag amplitudes, which correspond to ' \ 'metric values of [1, 2, or 3]. ' % (period, magnitude) metric = metrics.PeriodicDetectMetric(periods=periods, starMags=starMags, amplitudes=amplitudes, metricName='PeriodDetection') bundle = mb.MetricBundle(metric, healslicer, sql, metadata=metadata, displayDict=displayDict, plotDict=plotDict, plotFuncs=subsetPlots, summaryMetrics=standardStats) bundleList.append(bundle) displayDict['order'] += 1 # XXX add some PLASTICC metrics for kilovnova and tidal disruption events. displayDict['subgroup'] = 'KN' displayDict['caption'] = 'Fraction of Kilonova (from PLASTICC)' displayDict['order'] = 0 slicer = plasticc_slicer(plcs=plasticc_models_dict['KN'], seed=43, badval=0) metric = Plasticc_metric(metricName='KN') plotFuncs = [plots.HealpixSkyMap()] summary_stats = [metrics.MeanMetric(maskVal=0)] bundle = mb.MetricBundle(metric, slicer, extraSql, runName=runName, summaryMetrics=summary_stats, plotFuncs=plotFuncs, metadata=extraMetadata, displayDict=displayDict) bundleList.append(bundle) # Tidal Disruption Events displayDict['subgroup'] = 'TDE' displayDict[ 'caption'] = 'Fraction of TDE lightcurves that could be identified, outside of DD fields' detectSNR = {'u': 5, 'g': 5, 'r': 5, 'i': 5, 'z': 5, 'y': 5} # light curve parameters epochStart = -22 peakEpoch = 0 nearPeakT = 10 postPeakT = 14 # two weeks nPhaseCheck = 1 # condition parameters nObsTotal = {'u': 0, 'g': 0, 'r': 0, 'i': 0, 'z': 0, 'y': 0} nObsPrePeak = 1 nObsNearPeak = {'u': 0, 'g': 0, 'r': 0, 'i': 0, 'z': 0, 'y': 0} nFiltersNearPeak = 3 nObsPostPeak = 0 nFiltersPostPeak = 2 metric = TDEsAsciiMetric(asciifile=None, detectSNR=detectSNR, epochStart=epochStart, peakEpoch=peakEpoch, nearPeakT=nearPeakT, postPeakT=postPeakT, nPhaseCheck=nPhaseCheck, nObsTotal=nObsTotal, nObsPrePeak=nObsPrePeak, nObsNearPeak=nObsNearPeak, nFiltersNearPeak=nFiltersNearPeak, nObsPostPeak=nObsPostPeak, nFiltersPostPeak=nFiltersPostPeak) slicer = slicers.HealpixSlicer(nside=32) sql = extraSql + joiner + "note not like '%DD%'" md = extraMetadata if md is None: md = " NonDD" else: md += 'NonDD' bundle = mb.MetricBundle(metric, slicer, sql, runName=runName, summaryMetrics=standardStats, plotFuncs=plotFuncs, metadata=md, displayDict=displayDict) bundleList.append(bundle) # XXX -- would be good to add some microlensing events, for both MW and LMC/SMC. ######################### # Milky Way ######################### displayDict = {'group': 'Milky Way', 'subgroup': ''} displayDict['subgroup'] = 'N stars' slicer = slicers.HealpixSlicer(nside=nside, useCache=False) sum_stats = [metrics.SumMetric(metricName='Total N Stars')] for f in filterlist: displayDict['order'] = filterorders[f] displayDict['caption'] = 'Number of stars in %s band with an measurement error due to crowding ' \ 'of less than 0.1 mag' % f # Configure the NstarsMetric - note 'filtername' refers to the filter in which to evaluate crowding metric = metrics.NstarsMetric(crowding_error=0.1, filtername='r', seeingCol=colmap['seeingGeom'], m5Col=colmap['fiveSigmaDepth']) plotDict = {'nTicks': 5, 'logScale': True, 'colorMin': 100} bundle = mb.MetricBundle(metric, slicer, filtersqls[f], runName=runName, summaryMetrics=sum_stats, plotFuncs=subsetPlots, plotDict=plotDict, displayDict=displayDict) bundleList.append(bundle) ######################### # DDF ######################### if DDF: # Hide this import to avoid adding a dependency. from lsst.sims.featureScheduler.surveys import generate_dd_surveys, Deep_drilling_survey ddf_surveys = generate_dd_surveys() # Add on the Euclid fields # XXX--to update. Should have a spot where all the DDF locations are stored. ddf_surveys.append( Deep_drilling_survey([], 58.97, -49.28, survey_name='DD:EDFSa')) ddf_surveys.append( Deep_drilling_survey([], 63.6, -47.60, survey_name='DD:EDFSb')) # For doing a high-res sampling of the DDF for co-adds ddf_radius = 1.8 # Degrees ddf_nside = 512 ra, dec = hpid2RaDec(ddf_nside, np.arange(hp.nside2npix(ddf_nside))) displayDict = {'group': 'DDF depths', 'subgroup': None} for survey in ddf_surveys: displayDict['subgroup'] = survey.survey_name # Crop off the u-band only DDF if survey.survey_name[0:4] != 'DD:u': dist_to_ddf = angularSeparation(ra, dec, np.degrees(survey.ra), np.degrees(survey.dec)) goodhp = np.where(dist_to_ddf <= ddf_radius) slicer = slicers.UserPointsSlicer(ra=ra[goodhp], dec=dec[goodhp], useCamera=False) for f in filterlist: metric = metrics.Coaddm5Metric( metricName=survey.survey_name + ', ' + f) summary = [ metrics.MedianMetric(metricName='Median depth ' + survey.survey_name + ', ' + f) ] plotDict = {'color': colors[f]} sql = filtersqls[f] displayDict['order'] = filterorders[f] displayDict['caption'] = 'Coadded m5 depth in %s band.' % ( f) bundle = mb.MetricBundle(metric, slicer, sql, metadata=filtermetadata[f], displayDict=displayDict, summaryMetrics=summary, plotFuncs=[], plotDict=plotDict) bundleList.append(bundle) displayDict = {'group': 'DDF Transients', 'subgroup': None} for survey in ddf_surveys: displayDict['subgroup'] = survey.survey_name if survey.survey_name[0:4] != 'DD:u': slicer = plasticc_slicer( plcs=plasticc_models_dict['SNIa-normal'], seed=42, ra_cen=survey.ra, dec_cen=survey.dec, radius=np.radians(3.), useCamera=False) metric = Plasticc_metric(metricName=survey.survey_name + ' SNIa') sql = extraSql summary_stats = [metrics.MeanMetric(maskVal=0)] plotFuncs = [plots.HealpixSkyMap()] bundle = mb.MetricBundle(metric, slicer, sql, runName=runName, summaryMetrics=summary_stats, plotFuncs=plotFuncs, metadata=extraMetadata, displayDict=displayDict) bundleList.append(bundle) displayDict['order'] = 10 # Set the runName for all bundles and return the bundleDict. for b in bundleList: b.setRunName(runName) bundleDict = mb.makeBundlesDictFromList(bundleList) return bundleDict
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 validate_instance_catalog_magnitudes(cat_dir, obsid, seed=99, nrows=-1): """ Parameters ---------- cat_dir is the parent dir of $obsid obsid is the obsHistID of the pointing seed is the seed for a random number generator nrows is the number of galaxies to test (if <0, test all of them) """ agn_dtype = np.dtype([('galaxy_id', int), ('twinkles_id', int)]) agn_cache = np.genfromtxt(os.path.join(os.environ['TWINKLES_DIR'], 'data', 'cosmoDC2_v1.1.4_agn_cache.csv'), dtype=agn_dtype, delimiter=',', skip_header=1) sne_cache = np.genfromtxt(os.path.join(os.environ['TWINKLES_DIR'], 'data', 'cosmoDC2_v1.1.4_sne_cache.csv'), dtype=agn_dtype, delimiter=',', skip_header=1) sprinkled_gid = np.append(agn_cache['galaxy_id'], sne_cache['galaxy_id']) colnames = [ 'obj', 'uniqueID', 'ra', 'dec', 'magnorm', 'sed', 'redshift', 'g1', 'g2', 'kappa', 'dra', 'ddec', 'src_type', 'major', 'minor', 'positionAngle', 'sindex', 'dust_rest', 'rest_av', 'rest_rv', 'dust_obs', 'obs_av', 'obs_rv' ] to_drop = [ 'obj', 'g1', 'g2', 'kappa', 'dra', 'ddec', 'src_type', 'major', 'minor', 'positionAngle', 'sindex', 'dust_rest', 'dust_obs' ] col_types = { 'magnorm': float, 'redshift': float, 'rest_av': float, 'rest_rv': float, 'sed': bytes, 'uniqueID': int } assert os.path.isdir(cat_dir) data_dir = os.path.join(cat_dir, '%.8d' % obsid) if not os.path.isdir(data_dir): raise RuntimeError('\n\n%s\nis not a dir\n\n' % data_dir) phosim_file = os.path.join(data_dir, 'phosim_cat_%d.txt' % obsid) assert os.path.isfile(phosim_file) bandpass_name = None bandpass_name_list = 'ugrizy' with open(phosim_file, 'r') as in_file: for line in in_file: params = line.strip().split() if params[0] == 'filter': bandpass_name = bandpass_name_list[int(params[1])] assert bandpass_name is not None (tot_dict, hw_dict) = BandpassDict.loadBandpassesFromFiles() bandpass = hw_dict[bandpass_name] disk_file = os.path.join(data_dir, 'disk_gal_cat_%d.txt.gz' % obsid) if not os.path.isfile(disk_file): raise RuntimeError("%s is not a file" % disk_file) bulge_file = os.path.join(data_dir, 'bulge_gal_cat_%d.txt.gz' % obsid) assert os.path.isfile(bulge_file) knots_file = os.path.join(data_dir, 'knots_cat_%d.txt.gz' % obsid) assert os.path.isfile(knots_file) print('reading disks') disk_df = pd.read_csv(disk_file, delimiter=' ', compression='gzip', names=colnames, dtype=col_types, nrows=None) disk_df.drop(labels=to_drop, axis='columns', inplace=True) print('read disks') disk_df['galaxy_id'] = pd.Series(disk_df['uniqueID'] // 1024, index=disk_df.index) disk_df = disk_df.set_index('galaxy_id') print('reading bulges') bulge_df = pd.read_csv(bulge_file, delimiter=' ', compression='gzip', names=colnames, dtype=col_types, nrows=None) bulge_df.drop(labels=to_drop, axis='columns', inplace=True) print('read bulges') bulge_df['galaxy_id'] = pd.Series(bulge_df['uniqueID'] // 1024, index=bulge_df.index) bulge_df = bulge_df.set_index('galaxy_id') for ii in range(len(colnames)): colnames[ii] = colnames[ii] + '_knots' for ii in range(len(to_drop)): to_drop[ii] = to_drop[ii] + '_knots' print('reading knots') knots_df = pd.read_csv(knots_file, delimiter=' ', compression='gzip', names=colnames, dtype=col_types, nrows=None) knots_df.drop(labels=to_drop, axis='columns', inplace=True) print('read knots') knots_df['galaxy_id'] = pd.Series(knots_df['uniqueID_knots'] // 1024, index=knots_df.index) knots_df = knots_df.set_index('galaxy_id') wanted_col = [ 'sed', 'magnorm', 'redshift', 'rest_av', 'rest_rv', 'ra', 'dec' ] galaxy_df = disk_df[wanted_col].join(bulge_df[wanted_col], how='outer', lsuffix='_disk', rsuffix='_bulge') for ii in range(len(wanted_col)): wanted_col[ii] = wanted_col[ii] + '_knots' galaxy_df = galaxy_df.join(knots_df[wanted_col], how='outer', rsuffix='_knots') valid_galaxies = np.where( np.logical_not(np.in1d(galaxy_df.index, sprinkled_gid))) galaxy_df = galaxy_df.iloc[valid_galaxies] ra_center = np.nanmedian(galaxy_df['ra_disk'].values) dec_center = np.nanmedian(galaxy_df['dec_disk'].values) dd = angularSeparation(ra_center, dec_center, galaxy_df['ra_disk'].values, galaxy_df['dec_disk'].values) radius_deg = np.nanmax(dd) ra_rad = np.radians(ra_center) dec_rad = np.radians(dec_center) vv = np.array([ np.cos(ra_rad) * np.cos(dec_rad), np.sin(ra_rad) * np.cos(dec_rad), np.sin(dec_rad) ]) healpix_list = healpy.query_disc(32, vv, np.radians(radius_deg), nest=False, inclusive=True) gal_id_values = galaxy_df.index.values cat = GCRCatalogs.load_catalog('cosmoDC2_v1.1.4_image') cat_qties = {} cat_qties['galaxy_id'] = [] cat_qties['ra'] = [] cat_qties['dec'] = [] for hp in healpix_list: hp_query = GCRQuery('healpix_pixel==%d' % hp) local_qties = cat.get_quantities(['galaxy_id', 'ra', 'dec'], native_filters=[hp_query]) valid = np.in1d(local_qties['galaxy_id'], gal_id_values) if valid.any(): for k in local_qties: cat_qties[k].append(local_qties[k][valid]) for k in cat_qties: cat_qties[k] = np.concatenate(cat_qties[k]) cat_dexes = np.arange(len(cat_qties['galaxy_id']), dtype=int) if nrows > 0: rng = np.random.RandomState(seed) dexes = rng.choice(galaxy_df.index.values, size=nrows, replace=False) galaxy_df = galaxy_df.loc[dexes] galaxy_df = galaxy_df.sort_index() invalid_knots = np.where( np.logical_not( np.isfinite(galaxy_df['magnorm_knots'].values.astype(np.float)))) dd = angularSeparation(ra_center, dec_center, cat_qties['ra'], cat_qties['dec']) dd_cut = np.where(dd < (radius_deg + 0.05)) gid = cat_qties['galaxy_id'][dd_cut] cat_dexes = cat_dexes[dd_cut] in1d_valid_dexes = np.where( np.in1d(gid, galaxy_df.index.values, assume_unique=True)) valid_dexes = cat_dexes[in1d_valid_dexes] gid = gid[in1d_valid_dexes] sorted_dex = np.argsort(gid) valid_dexes = valid_dexes[sorted_dex] assert len(gid) == len(galaxy_df.index.values) np.testing.assert_array_equal(gid[sorted_dex], galaxy_df.index.values) mag_name = 'mag_true_%s_lsst' % bandpass_name qties = {} qties['galaxy_id'] = [] qties[mag_name] = [] for hp in healpix_list: hp_query = GCRQuery('healpix_pixel==%d' % hp) local_qties = cat.get_quantities(['galaxy_id', mag_name], native_filters=[hp_query]) valid = np.in1d(local_qties['galaxy_id'], gal_id_values) if valid.any(): for k in local_qties: qties[k].append(local_qties[k][valid]) for k in qties: qties[k] = np.concatenate(qties[k]) np.testing.assert_array_equal(qties['galaxy_id'], cat_qties['galaxy_id']) mags = qties[mag_name][valid_dexes] gid = qties['galaxy_id'][valid_dexes] assert len(gid) == len(mags) assert len(mags) > 0 if nrows > 0: assert len(mags) == nrows t_start = time.time() n_proc = 3 d_proc = len(gid) // n_proc mgr = multiprocessing.Manager() out_dict = mgr.dict() p_list = [] for i_start in range(0, len(gid), d_proc): mag_true = mags[i_start:i_start + d_proc] galaxy_arr = galaxy_df.iloc[i_start:i_start + d_proc] p = multiprocessing.Process(target=validate_batch, args=(mag_true, galaxy_arr, bandpass, out_dict)) p.start() p_list.append(p) for p in p_list: p.join() assert len(list(out_dict.keys())) > 0 d_mag_max = 0.0 for k in out_dict.keys(): if out_dict[k] > d_mag_max: d_mag_max = out_dict[k] if d_mag_max > 1.0e-5: raise RuntimeError("\nobsHistID failed magnitud validation\n" "d_mag_max %e" % d_mag_max)
obs_pointing = ObservationMetaData(mjd=59580.0) alt_pointing = 66.0 az_pointing = 11.0 (ra_pointing, dec_pointing) = raDecFromAltAz(alt_pointing, az_pointing, obs_pointing) (alt_check, az_check, pa_pointing) = altAzPaFromRaDec(ra_pointing, dec_pointing, obs_pointing) from lsst.sims.utils import angularSeparation dd = angularSeparation(alt_pointing, az_pointing, alt_check, az_check) assert dd < 1.0e-6 import numpy as np from lsst.sims.utils import getRotTelPos def write_header(file_handle, rot_sky, obshistid): file_handle.write('rightascension %.7f\n' % ra_pointing) file_handle.write('declination %.7f\n' % dec_pointing) file_handle.write('mjd %.5f\n' % obs_pointing.mjd.TAI) file_handle.write('altitude %.7f\n' % alt_pointing) file_handle.write('azimuth %.7f\n' % az_pointing) file_handle.write('filter 2\n') file_handle.write('moonalt -10.0\n') file_handle.write('nsnap 1\n')
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_InstanceCatalog_against_catalog_chunks(self): """ Test that we can reproduce the validated data using the InstanceCatalog framework when the catalog must be written in multiple chunks """ obs = ObservationMetaData(pointingRA=53.00913847303155535, pointingDec=-27.43894880881512321, rotSkyPos=256.75075318193080420, mjd=59580.13955500000156462, bandpassName='r', site=Site(name="LSST", pressure=0.0, humidity=0.0)) data_dir = os.path.join(getPackageDir('sims_catUtils'),'tests', 'testData') dtype = np.dtype([('id', int), ('ra', float), ('dec', float), ('ra_deprecessed', float), ('dec_deprecessed', float), ('x_dm', float), ('y_dm', float), ('x_focal', float), ('y_focal', float), ('x_cam', float), ('y_cam', float)]) data = np.genfromtxt(os.path.join(data_dir, 'pixel_prediction_catalog.txt'), dtype=dtype) data_txt_file = tempfile.mktemp(dir=data_dir, prefix='ic_validation_cat', suffix='.txt') cat_dtype = np.dtype([('id', int), ('raJ2000', float), ('decJ2000', float)]) with open(data_txt_file, 'w') as out_file: out_file.write('# a header\n') for ii, rr, dd in zip(data['id'], np.radians(data['ra']), np.radians(data['dec'])): out_file.write('%d %.17f %.17f\n' % (ii, rr, dd)) db = fileDBObject(data_txt_file, idColKey='id', dtype=cat_dtype, delimiter=' ') class DeprecessionTestCatalog_chunks(PhoSimCatalogPoint): def get_uniqueId(self): return self.column_by_name('id') def get_properMotionRa(self): return np.zeros(len(self.column_by_name('raJ2000'))) def get_properMotionDec(self): return np.zeros(len(self.column_by_name('raJ2000'))) def get_radialVelocity(self): return np.zeros(len(self.column_by_name('raJ2000'))) def get_parallax(self): return np.zeros(len(self.column_by_name('raJ2000'))) def get_galacticAv(self): return np.zeros(len(self.column_by_name('raJ2000'))) def get_galacticRv(self): return 3.1*np.ones(len(self.column_by_name('raJ2000'))) def get_sedFilepath(self): return np.array(['sed_flat.txt.gz']*len(self.column_by_name('raJ2000'))) def get_phoSimMagNorm(self): return np.ones(len(self.column_by_name('raJ2000'))) cat = DeprecessionTestCatalog_chunks(db, obs_metadata=obs) cat.phoSimHeaderMap = DefaultPhoSimHeaderMap id_list = [] ra_dep_list = [] dec_dep_list= [] phosim_cat_name = tempfile.mktemp(dir=data_dir, prefix='phosim_dep', suffix='.txt') cat.write_catalog(phosim_cat_name, chunk_size=10) with open(phosim_cat_name, 'r') as input_file: for line in input_file: params = line.strip().split() if len(params) < 3: continue id_list.append(int(params[1])) ra_dep_list.append(float(params[2])) dec_dep_list.append(float(params[3])) id_list = np.array(id_list) np.testing.assert_array_equal(id_list, data['id']) ra_dep_list = np.array(ra_dep_list) dec_dep_list = np.array(dec_dep_list) dd = 3600.0*angularSeparation(data['ra_deprecessed'], data['dec_deprecessed'], ra_dep_list, dec_dep_list) self.assertLess(dd.max(), 1.0e-5) if os.path.exists(data_txt_file): os.unlink(data_txt_file) if os.path.exists(phosim_cat_name): os.unlink(phosim_cat_name)