def test_rad(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_rad, obs.site.longitude_rad, mjd) # Check that the fast is similar to the more precice transform tol = np.radians(2) tol_mean = np.radians(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_rad, obs.site.longitude_rad, mjd) separations = utils._angularSeparation(ra, dec, ra_back, dec_back) self.assertLess(np.max(separations), tol) self.assertLess(np.mean(separations), tol_mean)
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 add_mag_clouds(inmap=None, nside=32): if inmap is None: result = standard_goals(nside=nside) else: result = inmap ra, dec = utils.ra_dec_hp_map(nside=nside) lmc_ra = np.radians(80.893860) lmc_dec = np.radians(-69.756126) lmc_radius = np.radians(10.) smc_ra = np.radians(13.186588) smc_dec = np.radians(-72.828599) smc_radius = np.radians(5.) dist_to_lmc = _angularSeparation(lmc_ra, lmc_dec, ra, dec) lmc_pix = np.where(dist_to_lmc < lmc_radius) dist_to_smc = _angularSeparation(smc_ra, lmc_dec, ra, dec) smc_pix = np.where(dist_to_smc < smc_radius) for key in result: result[key][lmc_pix] = np.max(result[key]) result[key][smc_pix] = np.max(result[key]) return result
def magellanic_clouds_healpixels(nside=None, lmc_radius=10, smc_radius=5): """ Define the Galactic Plane region. Return a healpix map with GP pixels as 1. """ if nside is None: nside = set_default_nside() ra, dec = ra_dec_hp_map(nside=nside) result = np.zeros(hp.nside2npix(nside)) lmc_ra = np.radians(80.893860) lmc_dec = np.radians(-69.756126) lmc_radius = np.radians(lmc_radius) smc_ra = np.radians(13.186588) smc_dec = np.radians(-72.828599) smc_radius = np.radians(smc_radius) dist_to_lmc = _angularSeparation(lmc_ra, lmc_dec, ra, dec) lmc_pix = np.where(int_rounded(dist_to_lmc) < int_rounded(lmc_radius)) result[lmc_pix] = 1 dist_to_smc = _angularSeparation(smc_ra, smc_dec, ra, dec) smc_pix = np.where(int_rounded(dist_to_smc) < int_rounded(smc_radius)) result[smc_pix] = 1 return result
def observation_add_data(self, observation): """ Fill in the metadata for a completed observation """ current_time = Time(self.mjd, format='mjd') observation['clouds'] = self.cloud_data(current_time) observation['airmass'] = 1. / np.cos(np.pi / 2. - observation['alt']) # Seeing fwhm_500 = self.seeing_data(current_time) seeing_dict = self.seeing_model(fwhm_500, observation['airmass']) observation['FWHMeff'] = seeing_dict['fwhmEff'][self.seeing_indx_dict[ observation['filter'][0]]] observation['FWHM_geometric'] = seeing_dict['fwhmGeom'][ self.seeing_indx_dict[observation['filter'][0]]] observation['FWHM_500'] = fwhm_500 observation['night'] = self.night observation['mjd'] = self.mjd hpid = _raDec2Hpid(self.sky_model.nside, observation['RA'], observation['dec']) observation['skybrightness'] = self.sky_model.returnMags( self.mjd, indx=[hpid], extrapolate=True)[observation['filter'][0]] observation['fivesigmadepth'] = m5_flat_sed( observation['filter'][0], observation['skybrightness'], observation['FWHMeff'], observation['exptime'] / observation['nexp'], observation['airmass'], nexp=observation['nexp']) lmst, last = calcLmstLast(self.mjd, self.site.longitude_rad) observation['lmst'] = lmst sun_moon_info = self.almanac.get_sun_moon_positions(self.mjd) observation['sunAlt'] = sun_moon_info['sun_alt'] observation['sunAz'] = sun_moon_info['sun_az'] observation['sunRA'] = sun_moon_info['sun_RA'] observation['sunDec'] = sun_moon_info['sun_dec'] observation['moonAlt'] = sun_moon_info['moon_alt'] observation['moonAz'] = sun_moon_info['moon_az'] observation['moonRA'] = sun_moon_info['moon_RA'] observation['moonDec'] = sun_moon_info['moon_dec'] observation['moonDist'] = _angularSeparation(observation['RA'], observation['dec'], observation['moonRA'], observation['moonDec']) observation['solarElong'] = _angularSeparation(observation['RA'], observation['dec'], observation['sunRA'], observation['sunDec']) observation['moonPhase'] = sun_moon_info['moon_phase'] observation['ID'] = self.obsID_counter self.obsID_counter += 1 return observation
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 _dePrecess(self, ra_in, dec_in, obs): """ Transform a set of RA, Dec pairs by subtracting out a rotation which represents the effects of precession, nutation, and aberration. Specifically: Calculate the displacement between the boresite and the boresite corrected for precession, nutation, and aberration (not refraction). Convert boresite and corrected boresite to Cartesian coordinates. Calculate the rotation matrix to go between those Cartesian vectors. Convert [ra_in, dec_in] into Cartesian coordinates. Apply the rotation vector to those Cartesian coordinates. Convert back to ra, dec-like coordinates @param [in] ra_in is a numpy array of RA in radians @param [in] dec_in is a numpy array of Dec in radians @param [in] obs is an ObservationMetaData @param [out] ra_out is a numpy array of de-precessed RA in radians @param [out] dec_out is a numpy array of de-precessed Dec in radians """ if len(ra_in) == 0: return np.array([[], []]) precessedRA, precessedDec = _observedFromICRS(obs._pointingRA, obs._pointingDec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) if (not hasattr(self, '_icrs_to_phosim_rotator') or arcsecFromRadians( _angularSeparation(obs._pointingRA, obs._pointingDec, self._icrs_to_phosim_rotator._ra1, self._icrs_to_phosim_rotator._dec1)) > 1.0e-6 or arcsecFromRadians( _angularSeparation(precessedRA, precessedDec, self._icrs_to_phosim_rotator._ra0, self._icrs_to_phosim_rotator._dec0)) > 1.0e-6): self._icrs_to_phosim_rotator = _FieldRotator( precessedRA, precessedDec, obs._pointingRA, obs._pointingDec) ra_deprecessed, dec_deprecessed = self._icrs_to_phosim_rotator.transform( ra_in, dec_in) return np.array([ra_deprecessed, dec_deprecessed])
def _dePrecess(self, ra_in, dec_in, obs): """ Transform a set of RA, Dec pairs by subtracting out a rotation which represents the effects of precession, nutation, and aberration. Specifically: Calculate the displacement between the boresite and the boresite corrected for precession, nutation, and aberration (not refraction). Convert boresite and corrected boresite to Cartesian coordinates. Calculate the rotation matrix to go between those Cartesian vectors. Convert [ra_in, dec_in] into Cartesian coordinates. Apply the rotation vector to those Cartesian coordinates. Convert back to ra, dec-like coordinates @param [in] ra_in is a numpy array of RA in radians @param [in] dec_in is a numpy array of Dec in radians @param [in] obs is an ObservationMetaData @param [out] ra_out is a numpy array of de-precessed RA in radians @param [out] dec_out is a numpy array of de-precessed Dec in radians """ if len(ra_in) == 0: return np.array([[], []]) precessedRA, precessedDec = _observedFromICRS(obs._pointingRA,obs._pointingDec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) if (not hasattr(self, '_icrs_to_phosim_rotator') or arcsecFromRadians(_angularSeparation(obs._pointingRA, obs._pointingDec, self._icrs_to_phosim_rotator._ra1, self._icrs_to_phosim_rotator._dec1))>1.0e-6 or arcsecFromRadians(_angularSeparation(precessedRA, precessedDec, self._icrs_to_phosim_rotator._ra0, self._icrs_to_phosim_rotator._dec0))>1.0e-6): self._icrs_to_phosim_rotator = _FieldRotator(precessedRA, precessedDec, obs._pointingRA, obs._pointingDec) ra_deprecessed, dec_deprecessed = self._icrs_to_phosim_rotator.transform(ra_in, dec_in) return np.array([ra_deprecessed, dec_deprecessed])
def add_observation(self, observation, indx=None, **kwargs): """Check if observation matches a scripted observation """ # From base class checks = [io not in str(observation['note']) for io in self.ignore_obs] if all(checks): for feature in self.extra_features: self.extra_features[feature].add_observation( observation, **kwargs) for bf in self.basis_functions: bf.add_observation(observation, **kwargs) for detailer in self.detailers: detailer.add_observation(observation, **kwargs) self.reward_checked = False # was it taken in the right time window, and hasn't already been marked as observed. time_matches = np.where( (observation['mjd'] > self.mjd_start) & (observation['mjd'] < self.obs_wanted['flush_by_mjd']) & (~self.obs_wanted['observed']) & (observation['note'] == self.obs_wanted['note']))[0] for match in time_matches: distances = _angularSeparation(self.obs_wanted[match]['RA'], self.obs_wanted[match]['dec'], observation['RA'], observation['dec']) if (distances < self.obs_wanted[match]['dist_tol']) & \ (self.obs_wanted[match]['filter'] == observation['filter']): # Log it as observed. self.obs_wanted['observed'][match] = True self.scheduled_obs = self.obs_wanted['mjd'][ ~self.obs_wanted['observed']] break
def test_trixel_bounding_circle(self): """ Verify that the trixel's bounding_circle method returns a circle that contains all of the corners of the trixel """ rng = np.random.RandomState(142) n_test_cases = 5 for i_test in range(n_test_cases): htmid = (13 << 6)+rng.randint(1, 2**6-1) trixel = trixelFromHtmid(htmid) bounding_circle = trixel.bounding_circle ra_0, dec_0 = sphericalFromCartesian(bounding_circle[0]) ra_list = [] dec_list = [] for cc in trixel.corners: ra, dec = sphericalFromCartesian(cc) ra_list.append(ra) dec_list.append(dec) ra_list = np.array(ra_list) dec_list = np.array(dec_list) distance = _angularSeparation(ra_0, dec_0, ra_list, dec_list) distance = arcsecFromRadians(distance) radius = arcsecFromRadians(bounding_circle[2]) self.assertLessEqual(distance.max()-radius, 1.0e-8) self.assertLess(np.abs(distance.max()-radius), 1.0e-8)
def check_pointing(self, pointing_alt, pointing_az, mjd): """ See if a pointing has a satellite in it pointing_alt : float Altitude of pointing (degrees) pointing_az : float Azimuth of pointing (degrees) mjd : float Modified Julian Date at the start of the exposure Returns ------- in_fov : float Returns the fraction of time there is a satellite in the field of view. Values >1 mean there were on average more than one satellite in the FoV. Zero means there was no satllite in the image the entire exposure. """ mjds = mjd + self.tsteps in_fov = 0 for mjd in mjds: self.update_mjd(mjd) ang_distances = _angularSeparation( self.azimuth_rad[self.above_alt_limit], self.altitudes_rad[self.above_alt_limit], np.radians(pointing_az), np.radians(pointing_alt)) in_fov += np.size(np.where(ang_distances <= self.fov_rad)[0]) in_fov = in_fov / mjds.size return in_fov
def test_trixel_bounding_circle(self): """ Verify that the trixel's bounding_circle method returns a circle that contains all of the corners of the trixel """ rng = np.random.RandomState(142) n_test_cases = 5 for i_test in range(n_test_cases): htmid = (13 << 6) + rng.randint(1, 2**6 - 1) trixel = trixelFromHtmid(htmid) bounding_circle = trixel.bounding_circle ra_0, dec_0 = sphericalFromCartesian(bounding_circle[0]) ra_list = [] dec_list = [] for cc in trixel.corners: ra, dec = sphericalFromCartesian(cc) ra_list.append(ra) dec_list.append(dec) ra_list = np.array(ra_list) dec_list = np.array(dec_list) distance = _angularSeparation(ra_0, dec_0, ra_list, dec_list) distance = arcsecFromRadians(distance) radius = arcsecFromRadians(bounding_circle[2]) self.assertLessEqual(distance.max() - radius, 1.0e-8) self.assertLess(np.abs(distance.max() - radius), 1.0e-8)
def _init_data_indices(self): """ Do the spatial filtering of extragalactic catalog data. """ self._native_filters = None descqa_catalog = self._descqa_obj._catalog if self._obs_metadata is None or self._obs_metadata._boundLength is None: self._data_indices = np.arange( self._descqa_obj._catalog['raJ2000'].size) else: try: radius_rad = max(self._obs_metadata._boundLength[0], self._obs_metadata._boundLength[1]) except (TypeError, IndexError): radius_rad = self._obs_metadata._boundLength if 'healpix_pixel' in descqa_catalog._native_filter_quantities: ra_rad = self._obs_metadata._pointingRA dec_rad = self._obs_metadata._pointingDec vv = np.array([ np.cos(dec_rad) * np.cos(ra_rad), np.cos(dec_rad) * np.sin(ra_rad), np.sin(dec_rad) ]) healpix_list = healpy.query_disc(8, vv, radius_rad, inclusive=True, nest=False) healpix_filter = None for hh in healpix_list: local_filter = GCRQuery('healpix_pixel==%d' % hh) if healpix_filter is None: healpix_filter = local_filter else: healpix_filter |= local_filter if healpix_filter is not None: if self._native_filters is None: self._native_filters = [healpix_filter] else: self._native_filters.append(healpix_filter) ra_dec = descqa_catalog.get_quantities( ['raJ2000', 'decJ2000'], native_filters=self._native_filters) ra = ra_dec['raJ2000'] dec = ra_dec['decJ2000'] self._data_indices = np.where(_angularSeparation(ra, dec, \ self._obs_metadata._pointingRA, \ self._obs_metadata._pointingDec) < radius_rad)[0] if self._chunk_size is None: self._chunk_size = self._data_indices.size
def _appGeoFromPhoSim(self, raPhoSim, decPhoSim, obs): """ This method will convert from the 'deprecessed' coordinates expected by PhoSim to apparent geocentric coordinates Parameters ---------- raPhoSim is the PhoSim RA-like coordinate (in radians) decPhoSim is the PhoSim Dec-like coordinate (in radians) obs is an ObservationMetaData characterizing the telescope pointing Returns ------- apparent geocentric RA in radians apparent geocentric Dec in radians """ precessedRA, precessedDec = _observedFromICRS(obs._pointingRA, obs._pointingDec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) if (not hasattr(self, '_phosim_to_icrs_rotator') or arcsecFromRadians( _angularSeparation(obs._pointingRA, obs._pointingDec, self._phosim_to_icrs_rotator._ra0, self._phosim_to_icrs_rotator._dec0)) > 1.0e-6 or arcsecFromRadians( _angularSeparation(precessedRA, precessedDec, self._phosim_to_icrs_rotator._ra1, self._phosim_to_icrs_rotator._dec1)) > 1.0e-6): self._phosim_to_icrs_rotator = _FieldRotator( obs._pointingRA, obs._pointingDec, precessedRA, precessedDec) ra_obs, dec_obs = self._phosim_to_icrs_rotator.transform( raPhoSim, decPhoSim) return _appGeoFromObserved(ra_obs, dec_obs, includeRefraction=False, obs_metadata=obs)
def test_stellar_astrometry_radians(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of stars (in radians) """ cat_name = os.path.join(self.scratch_dir, 'phosim_ast_star_cat_rad.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) ra_pho_rad = np.radians(data['raPhoSim']) dec_pho_rad = np.radians(data['decPhoSim']) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase._icrsFromPhoSim( ra_pho_rad, dec_pho_rad, self.obs) dist = _angularSeparation(np.radians(data['raICRS']), np.radians(data['decICRS']), ra_icrs, dec_icrs) dist = arcsecFromRadians(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(ra_pho_rad, dec_pho_rad, np.radians(data['raICRS']), np.radians(data['decICRS'])) dist_bad = arcsecFromRadians(dist_bad) self.assertGreater(dist_bad.min(), dist.max()) if os.path.exists(cat_name): os.unlink(cat_name) del db
def _calc_value(self, conditions, indx=None): result = self.result.copy() angular_distance = _angularSeparation(conditions.az, conditions.alt, conditions.moonAz, conditions.moonAlt) result[int_rounded(angular_distance) < self.moon_distance] = np.nan return result
def test_stellar_astrometry_radians(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of stars (in radians) """ 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_pho_rad = np.radians(data['raPhoSim']) dec_pho_rad = np.radians(data['decPhoSim']) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase._icrsFromPhoSim(ra_pho_rad, dec_pho_rad, self.obs) dist = _angularSeparation(np.radians(data['raICRS']), np.radians(data['decICRS']), ra_icrs, dec_icrs) dist = arcsecFromRadians(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(ra_pho_rad, dec_pho_rad, np.radians(data['raICRS']), np.radians(data['decICRS'])) dist_bad = arcsecFromRadians(dist_bad) self.assertGreater(dist_bad.min(), dist.max()) del db
def calc_reward_function(self, conditions): """ """ # Set the number of observations we are going to try and take self._set_block_size(conditions) # Computing reward like usual with basis functions and weights if self._check_feasibility(conditions): self.reward = 0 indx = np.arange(hp.nside2npix(self.nside)) for bf, weight in zip(self.basis_functions, self.basis_weights): basis_value = bf(conditions, indx=indx) self.reward += basis_value * weight # might be faster to pull this out into the feasabiliity check? if self.smoothing_kernel is not None: self.smooth_reward() # Apply max altitude cut too_high = np.where( int_rounded(conditions.alt) > int_rounded(self.alt_max)) self.reward[too_high] = np.nan # Select healpixels within some radius of the max # This is probably faster with a kd-tree. max_hp = np.where(self.reward == np.nanmax(self.reward))[0] if np.size(max_hp) > 0: peak_reward = np.min(max_hp) else: # Everything is masked, so get out return -np.inf # Apply radius selection dists = _angularSeparation(self.ra[peak_reward], self.dec[peak_reward], self.ra, self.dec) out_hp = np.where( int_rounded(dists) > int_rounded(self.search_radius)) self.reward[out_hp] = np.nan # Apply az cut az_centered = conditions.az - conditions.az[peak_reward] az_centered[np.where(az_centered < 0)] += 2. * np.pi az_out = np.where( (int_rounded(az_centered) > int_rounded(self.az_range / 2.)) & (int_rounded(az_centered) < int_rounded(2. * np.pi - self.az_range / 2.))) self.reward[az_out] = np.nan else: self.reward = -np.inf self.reward_checked = True return self.reward
def test_galaxy_astrometry_radians(self): """ Test that we can go from raPhoSim, decPhoSim to ICRS coordinates in the case of galaxies (in radians) """ 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) ra_pho_rad = np.radians(data['raPhoSim']) dec_pho_rad = np.radians(data['decPhoSim']) # verify that, when transforming back to ICRS, we are within # 10^-3 arcsec ra_icrs, dec_icrs = PhoSimAstrometryBase._icrsFromPhoSim( ra_pho_rad, dec_pho_rad, self.obs) dist = _angularSeparation(np.radians(data['raICRS']), np.radians(data['decICRS']), ra_icrs, dec_icrs) dist = arcsecFromRadians(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(ra_pho_rad, dec_pho_rad, np.radians(data['raICRS']), np.radians(data['decICRS'])) dist_bad = arcsecFromRadians(dist_bad) self.assertGreater(dist_bad.min(), dist.max()) del db
def testSunMoon(self): """ Test that the sun moon interpolation is good enough """ if self.data_present: sm = self.sm telescope = utils.Site('LSST') Observatory = ephem.Observer() Observatory.lat = telescope.latitude_rad Observatory.lon = telescope.longitude_rad Observatory.elevation = telescope.height sun = ephem.Sun() moon = ephem.Moon() mjd1 = sm.info['mjds'][0] mjd2 = sm.info['mjds'][3] mjds = np.linspace(mjd1, mjd2, 20) # Demand Moon and Sun Positions match to within 3 arcmin arcmin_places = np.abs(np.floor(np.log10(3/60./180.*np.pi))).astype(int) for mjd in mjds: Observatory.date = mjd2djd(mjd) sun.compute(Observatory) moon.compute(Observatory) pre_calced = sm.returnSunMoon(mjd) self.assertLess(np.abs(pre_calced['sunAlt']-sun.alt), arcmin_places) sun_dist = _angularSeparation(sun.ra, sun.dec, pre_calced['sunRA'], pre_calced['sunDec']) self.assertAlmostEqual(sun_dist, 0., places=arcmin_places) self.assertLess(np.abs(pre_calced['moonAlt']-moon.alt), arcmin_places) moon_dist = _angularSeparation(moon.ra, moon.dec, pre_calced['moonRA'], pre_calced['moonDec']) self.assertAlmostEqual(moon_dist, 0., places=arcmin_places) self.assertAlmostEqual(np.radians(pre_calced['moonSunSep']), np.radians(moon.phase/100.*180.), places=arcmin_places)
def _final_pass(self, chunk): """ Only keep objects that are inside the field of view """ if len(chunk) == 0: return chunk dd = _angularSeparation(self._obs_metadata._pointingRA, self._obs_metadata._pointingDec, chunk['raJ2000'], chunk['decJ2000']) valid = np.where(dd <= self._obs_metadata._boundLength) return chunk[valid]
def _appGeoFromPhoSim(self, raPhoSim, decPhoSim, obs): """ This method will convert from the 'deprecessed' coordinates expected by PhoSim to apparent geocentric coordinates Parameters ---------- raPhoSim is the PhoSim RA-like coordinate (in radians) decPhoSim is the PhoSim Dec-like coordinate (in radians) obs is an ObservationMetaData characterizing the telescope pointing Returns ------- apparent geocentric RA in radians apparent geocentric Dec in radians """ precessedRA, precessedDec = _observedFromICRS(obs._pointingRA,obs._pointingDec, obs_metadata=obs, epoch=2000.0, includeRefraction=False) if (not hasattr(self, '_phosim_to_icrs_rotator') or arcsecFromRadians(_angularSeparation(obs._pointingRA, obs._pointingDec, self._phosim_to_icrs_rotator._ra0, self._phosim_to_icrs_rotator._dec0))>1.0e-6 or arcsecFromRadians(_angularSeparation(precessedRA, precessedDec, self._phosim_to_icrs_rotator._ra1, self._phosim_to_icrs_rotator._dec1))>1.0e-6): self._phosim_to_icrs_rotator = _FieldRotator(obs._pointingRA, obs._pointingDec, precessedRA, precessedDec) ra_obs, dec_obs = self._phosim_to_icrs_rotator.transform(raPhoSim, decPhoSim) return _appGeoFromObserved(ra_obs, dec_obs, includeRefraction=False, obs_metadata=obs)
def look_ahead(self, pointing_alt, pointing_az, mjds): """ Return 1 if satellite in FoV, 0 if clear """ result = [] for mjd in mjds: self.update_mjd(mjd) ang_distances = _angularSeparation(self.azimuth_rad[self.above_alt_limit], self.altitudes_rad[self.above_alt_limit], np.radians(pointing_az), np.radians(pointing_alt)) if np.size(np.where(ang_distances <= self.fov_rad)[0]) > 0: result.append(1) else: result.append(0) return result
def ang_potential(x0): """ If distance is computed along sphere rather than through 3-space. """ theta = x0[0:x0.size / 2] phi = np.pi / 2 - x0[x0.size / 2:] indices = np.triu_indices(theta.size, k=1) theta_i = np.tile(theta, (theta.size, 1)) theta_j = theta_i.T phi_i = np.tile(phi, (phi.size, 1)) phi_j = phi_i.T d = _angularSeparation(theta_i[indices], phi_i[indices], theta_j[indices], phi_j[indices]) U = np.sum(1. / d) return U
def __call__(self, observation_list, conditions): obs_array = np.concatenate(observation_list) alt, az = _approx_RaDec2AltAz(obs_array['RA'], obs_array['dec'], conditions.site.latitude_rad, conditions.site.longitude_rad, conditions.mjd) alt_diff = np.abs(alt - conditions.telAlt) in_band = np.where(int_rounded(alt_diff) <= self.alt_band)[0] if in_band.size == 0: in_band = np.arange(alt.size) # Find the closest in angular distance of the points that are in band ang_dist = _angularSeparation(az[in_band], alt[in_band], conditions.telAz, conditions.telAlt) good = np.min(np.where(ang_dist == ang_dist.min())[0]) indx = in_band[good] result = observation_list[indx:] + observation_list[:indx] return result
def degrees_separation(ra0, dec0, ra, dec): """ Compute angular separation in degrees. Parameters ---------- ra0: float Right ascension of reference location in degrees. dec0: float Declination of reference location in degrees. ra: float or numpy.array Right ascension of object(s) in degrees dec: float or numpy.array Declination of object(s) in degrees. """ return np.degrees( _angularSeparation(np.radians(ra0), np.radians(dec0), np.radians(ra), np.radians(dec)))
def generate_events(nside=32, mjd0=59853.5, radius=15., survey_length=365.25 * 10, rate=10., expires=3., seed=42): """ Parameters ---------- """ np.random.seed(seed=seed) ra, dec = _hpid2RaDec(nside, np.arange(hp.nside2npix(nside))) radius = np.radians(radius) # Use a ceil here so we get at least 1 event even if doing a short run. n_events = np.int(np.ceil(survey_length / 365.25 * rate)) names = ['mjd_start', 'ra', 'dec', 'expires'] types = [float] * 4 event_table = np.zeros(n_events, dtype=list(zip(names, types))) event_table['mjd_start'] = np.sort( np.random.random(n_events)) * survey_length + mjd0 event_table['expires'] = event_table['mjd_start'] + expires # Make sure latitude points spread correctly # http://mathworld.wolfram.com/SpherePointPicking.html event_table['ra'] = np.random.rand(n_events) * np.pi * 2 event_table['dec'] = np.arccos(2. * np.random.rand(n_events) - 1.) - np.pi / 2. events = [] for i, event_time in enumerate(event_table['mjd_start']): dist = _angularSeparation(ra, dec, event_table['ra'][i], event_table['dec'][i]) good = np.where(dist <= radius) footprint = np.zeros(ra.size, dtype=float) footprint[good] = 1 events.append(TargetoO(i, footprint, event_time, expires)) events = Sim_targetoO_server(events) return events, event_table
def test_stellar_observed_radians(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(data['raJ2000'], data['decJ2000'], obs_metadata=self.obs, pm_ra=data['pmRA'], pm_dec=data['pmDec'], parallax=data['parallax'], v_rad=data['vRad'], includeRefraction=True, epoch=2000.0) (ra_appGeo, dec_appGeo) = PhoSimAstrometryBase._appGeoFromPhoSim(np.radians(data['raPhoSim']), np.radians(data['decPhoSim']), self.obs) (ra_obs_2, dec_obs_2) = _observedFromAppGeo(ra_appGeo, dec_appGeo, obs_metadata=self.obs, includeRefraction=True) dd = arcsecFromRadians(_angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2)) self.assertLess(dd.max(), 1.0e-5)
def generate_events_simple(nside=32, mjd0=59853.5, radius=15.): """ Generate 3 simple ToO events """ ra, dec = _hpid2RaDec(nside, np.arange(hp.nside2npix(nside))) radius = np.radians(radius) nights = [1, 3, 6] expires = 3 event_ra = np.radians([0, 10, 350]) event_dec = np.radians(-40.) events = [] for i, nignt in enumerate(nights): dist = _angularSeparation(ra, dec, event_ra[i], event_dec) good = np.where(dist <= radius) footprint = np.zeros(ra.size, dtype=float) footprint[good] = 1 events.append(TargetoO(i, footprint, mjd0 + nights[i], expires)) events = Sim_targetoO_server(events) return events
def _init_data_indices(self): if self._obs_metadata is None or self._obs_metadata._boundLength is None: self._data_indices = np.arange(self._descqa_obj['raJ2000'].size) else: try: radius_rad = max(self._obs_metadata._boundLength[0], self._obs_metadata._boundLength[1]) except (TypeError, IndexError): radius_rad = self._obs_metadata._boundLength ra = self._descqa_obj['raJ2000'] dec = self._descqa_obj['decJ2000'] self._data_indices = np.where(_angularSeparation(ra, dec, \ self._obs_metadata._pointingRA, \ self._obs_metadata._pointingDec) < radius_rad)[0] if self._chunk_size is None: self._chunk_size = self._data_indices.size
def test_stellar_observed_radians(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(data['raJ2000'], data['decJ2000'], obs_metadata=self.obs, pm_ra=data['pmRA'], pm_dec=data['pmDec'], parallax=data['parallax'], v_rad=data['vRad'], includeRefraction=True, epoch=2000.0) (ra_appGeo, dec_appGeo) = PhoSimAstrometryBase._appGeoFromPhoSim( np.radians(data['raPhoSim']), np.radians(data['decPhoSim']), self.obs) (ra_obs_2, dec_obs_2) = _observedFromAppGeo(ra_appGeo, dec_appGeo, obs_metadata=self.obs, includeRefraction=True) dd = arcsecFromRadians( _angularSeparation(ra_obs, dec_obs, ra_obs_2, dec_obs_2)) self.assertLess(dd.max(), 1.0e-5)
def testHaversine(self): """ Test that haversine() returns the same thing as _angularSeparation """ ra1 = 0.2 dec1 = 1.3 ra2 = 2.1 dec2 = -0.5 ra3 = np.array([1.9, 2.1, 0.3]) dec3 = np.array([-1.1, 0.34, 0.01]) control = utils._angularSeparation(ra1, dec1, ra2, dec2) test = utils.haversine(ra1, dec1, ra2, dec2) self.assertIsInstance(test, float) self.assertEqual(test, control) control = utils._angularSeparation(ra1, dec1, ra3, dec3) test = utils.haversine(ra1, dec1, ra3, dec3) np.testing.assert_array_equal(test, control) control = utils._angularSeparation(np.array([ra1]), np.array([dec1]), ra3, dec3) test = utils.haversine(np.array([ra1]), np.array([dec1]), ra3, dec3) np.testing.assert_array_equal(test, control) control = utils._angularSeparation(ra3, dec3, np.array([ra1]), np.array([dec1])) test = utils.haversine(ra3, dec3, np.array([ra1]), np.array([dec1])) np.testing.assert_array_equal(test, control) control = utils._angularSeparation(ra2, dec2, np.array([ra1]), np.array([dec1])) test = utils.haversine(ra2, dec2, np.array([ra1]), np.array([dec1])) self.assertIsInstance(test, float) self.assertEqual(test, control) control = utils._angularSeparation(np.array([ra1]), np.array([dec1]), ra2, dec2) test = utils.haversine(np.array([ra1]), np.array([dec1]), ra2, dec2) self.assertIsInstance(test, float) self.assertEqual(test, control)
def __next__(self): if self._data is None and self._continue: avail_qties = self._descqa_obj.list_all_quantities() avail_native_qties = self._descqa_obj.list_all_native_quantities() # find the list of names that need to be passed to self._descqa_obj.get_quantities() gcr_col_names = np.array([self._column_map[catsim_name][0] for catsim_name in self._catsim_colnames if self._column_map[catsim_name][0] in avail_qties or self._column_map[catsim_name][0] in avail_native_qties]) gcr_col_names = np.unique(gcr_col_names) gcr_cat_data = self._descqa_obj.get_quantities(gcr_col_names) n_rows = len(gcr_cat_data[gcr_col_names[0]]) # now build a dict keyed to the row names in self._catsim_colnames # whose values are the numpy arrays of data corresponding to those # column names catsim_data = {} dtype_list = [] for catsim_name in self._catsim_colnames: gcr_name = self._column_map[catsim_name][0] if gcr_name in avail_qties or gcr_name in avail_native_qties: catsim_data[catsim_name] = gcr_cat_data[gcr_name] else: catsim_data[catsim_name] = np.array([self._default_values[gcr_name]]*n_rows) if len(self._column_map[catsim_name])>1: catsim_data[catsim_name] = self._column_map[catsim_name][1](catsim_data[catsim_name]) dtype_list.append((catsim_name, catsim_data[catsim_name].dtype)) dtype = np.dtype(dtype_list) del gcr_cat_data gc.collect() # if an ObservationMetaData has been specified, cull # the data to be within the field of view if self._obs_metadata is not None: if self._obs_metadata._boundLength is not None: if not isinstance(self._obs_metadata._boundLength, numbers.Number): radius_rad = max(self._obs_metadata._boundLength[0], self._obs_metadata._boundLength[1]) else: radius_rad = self._obs_metadata._boundLength valid = np.where(_angularSeparation(catsim_data['raJ2000'], catsim_data['decJ2000'], self._obs_metadata._pointingRA, self._obs_metadata._pointingDec) < radius_rad) for name in catsim_data: catsim_data[name] = catsim_data[name][valid] # convert catsim_data into a numpy recarray, which is what # CatSim ultimately expects the ChunkIterator to deliver records = [] for i_rec in range(len(catsim_data[self._catsim_colnames[0]])): rec = (tuple([catsim_data[name][i_rec] for name in self._catsim_colnames])) records.append(rec) if len(records) == 0: self._data = np.recarray(shape=(0,len(catsim_data)), dtype=dtype) else: self._data = np.rec.array(records, dtype=dtype) self._start_row = 0 # iterate over the chunks of the recarray stored in self._data if self._chunk_size is None and self._continue and len(self._data)>0: output = self._data self._data = None self._continue = False return output elif self._continue: if self._start_row<len(self._data): old_start = self._start_row self._start_row += self._chunk_size return self._data[old_start:self._start_row] else: self._data = None self._continue = False raise StopIteration raise StopIteration
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])
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 trixel_intersects_half_space(trix, hspace): """ This is a brute force method to determine whether a trixel is inside, or at least intersects, a halfspace. """ if hspace.phi > 0.25*np.pi: raise RuntimeError("trixel_intersects_half_space is not safe for " "large HalfSpaces") # if any of the trixel's corners are within the # HalfSpace, return True raRad, decRad = sphericalFromCartesian(hspace.vector) for corner in trix.corners: raRad1, decRad1 = sphericalFromCartesian(corner) if _angularSeparation(raRad, decRad, raRad1, decRad1) < hspace.phi: return True # if the trixel contains the HalfSpace's center, # return True if trix.contains_pt(hspace.vector): return True sinphi = np.abs(np.sin(hspace.phi)) # Iterate over each pair of corners (c1, c2). For each pair, # construct a coordinate basis in which +z is in the # direction of c3, and +x is along the # unit vector defining c_i such that the angle # phi of c_j in the x,y plane is positive. This coordinate # system is such that the trixel edge defined by c1, c2 is # now along the equator of the unit sphere. Find the point # of closest approach of the HalfSpace's center to the equator. # If that point is between c1 and c2, return True. for i_c_1 in range(3): c1 = trix.corners[i_c_1] for i_c_2 in range(3): if i_c_2 <= i_c_1: continue c2 = trix.corners[i_c_2] i_c_3 = 3 - (i_c_1+i_c_2) c3 = trix.corners[i_c_3] assert i_c_3 != i_c_2 assert i_c_3 != i_c_1 assert i_c_1 != i_c_2 z_axis = np.array([c1[1]*c2[2]-c1[2]*c2[1], c2[0]*c1[2]-c1[0]*c2[2], c1[0]*c2[1]-c2[0]*c1[1]]) z_axis = z_axis/np.sqrt((z_axis**2).sum()) if np.dot(z_axis, c3) < 0.0: z_axis *= -1.0 assert np.abs(1.0-np.dot(z_axis, z_axis)) < 1.0e-10 assert np.abs(1.0-np.dot(c1, c1)) < 1.0e-10 assert np.abs(1.0-np.dot(c2, c2)) < 1.0e-10 assert np.abs(np.dot(z_axis, c1)) < 1.0e-10 assert np.abs(np.dot(z_axis, c2)) < 1.0e-10 # if the dot product of the center of the HalfSpace # with the z axis of the new coordinate system is # greater than the sine of the radius of the # halfspace, then there is no way that the halfspace # intersects the equator of the unit sphere in this # coordinate system if np.abs(np.dot(z_axis, hspace.vector)) > sinphi: continue x_axis = c1 y_axis = -1.0*np.array([x_axis[1]*z_axis[2]-x_axis[2]*z_axis[1], z_axis[0]*x_axis[2]-x_axis[0]*z_axis[2], x_axis[0]*z_axis[1]-z_axis[0]*x_axis[1]]) cos_a = np.dot(x_axis, c2) sin_a = np.dot(y_axis, c2) if sin_a < 0.0: x_axis = c2 y_axis = -1.0*np.array([x_axis[1]*z_axis[2]-x_axis[2]*z_axis[1], z_axis[0]*x_axis[2]-x_axis[0]*z_axis[2], x_axis[0]*z_axis[1]-z_axis[0]*x_axis[1]]) cos_a = np.dot(x_axis, c1) sin_a = np.dot(y_axis, c1) assert cos_a >= 0.0 assert sin_a >= 0.0 assert np.abs(1.0-cos_a**2-sin_a**2) < 1.0e-10 assert np.abs(np.dot(x_axis, z_axis)) < 1.0e-10 assert np.abs(np.dot(x_axis, y_axis)) < 1.0e-10 assert np.abs(np.dot(y_axis, z_axis)) < 1.0e-10 x_center = np.dot(x_axis, hspace.vector) # if the x-coordinate of the HalfSpace's center is # negative, the HalfSpace is on the opposite side # of the unit sphere; ignore this pair c1, c2 if x_center < 0.0: continue y_center = np.dot(y_axis, hspace.vector) # tan_a is the tangent of the angle between # the x_axis and the other trixel corner in # the x, y plane tan_a = sin_a/cos_a # tan_extreme is the tangent of the angle in # the x, y plane defining the point of closest # approach of the HalfSpace's center to the # equator. If this point is between c1, c2, # return True. tan_extreme = y_center/x_center if tan_extreme > 0.0 and tan_extreme < tan_a: return True return False