def halfSpaceFromPoints(pt1, pt2, pt3): """ Return a Half Space defined by two points on a Great Circle and a third point contained in the Half Space. Parameters ---------- pt1, pt2 -- two tuples containing (RA, Dec) in degrees of the points on the Great Circle defining the Half Space pt3 -- a tuple containing (RA, Dec) in degrees of a point contained in the Half Space Returns -------- A Half Space """ vv1 = cartesianFromSpherical(np.radians(pt1[0]), np.radians(pt1[1])) vv2 = cartesianFromSpherical(np.radians(pt2[0]), np.radians(pt2[1])) axis = np.array([vv1[1]*vv2[2]-vv1[2]*vv2[1], vv1[2]*vv2[0]-vv1[0]*vv2[2], vv1[0]*vv2[1]-vv1[1]*vv2[0]]) axis /= np.sqrt(np.sum(axis**2)) vv3 = cartesianFromSpherical(np.radians(pt3[0]), np.radians(pt3[1])) if np.dot(axis, vv3)<0.0: axis *= -1.0 return HalfSpace(axis, 0.0)
def test_halfSpaceFromPoints(self): rng = np.random.RandomState(88) for ii in range(10): pt1 = (rng.random_sample() * 360.0, rng.random_sample() * 180.0 - 90.0) pt2 = (rng.random_sample() * 360.0, rng.random_sample() * 180.0 - 90.0) pt3 = (rng.random_sample() * 360.0, rng.random_sample() * 180.0 - 90.0) hs = halfSpaceFromPoints(pt1, pt2, pt3) # check that the HalfSpace contains pt3 vv3 = cartesianFromSpherical(np.radians(pt3[0]), np.radians(pt3[1])) self.assertTrue(hs.contains_pt(vv3)) # check that the HalfSpace encompasses 1/2 of the unit sphere self.assertAlmostEqual(hs.phi, 0.5 * np.pi, 10) self.assertAlmostEqual(hs.dd, 0.0, 10) # check that pt1 and pt2 are 90 degrees away from the center # of the HalfSpace vv1 = cartesianFromSpherical(np.radians(pt1[0]), np.radians(pt1[1])) vv2 = cartesianFromSpherical(np.radians(pt2[0]), np.radians(pt2[1])) self.assertAlmostEqual(np.dot(vv1, hs.vector), 0.0, 10) self.assertAlmostEqual(np.dot(vv2, hs.vector), 0.0, 10)
def testCartesianFromSpherical(self): nsamples = 10 theta = self.rng.random_sample(nsamples) * np.pi - 0.5 * np.pi phi = self.rng.random_sample(nsamples) * 2.0 * np.pi points = [] for ix in range(nsamples): vv = [np.cos(theta[ix]) * np.cos(phi[ix]), np.cos(theta[ix]) * np.sin(phi[ix]), np.sin(theta[ix])] points.append(vv) points = np.array(points) lon, lat = utils.sphericalFromCartesian(points) outPoints = utils.cartesianFromSpherical(lon, lat) for pp, oo in zip(points, outPoints): np.testing.assert_array_almost_equal(pp, oo, decimal=6) # test passing in arguments as floats for ix, (ll, bb) in enumerate(zip(lon, lat)): xyz = utils.cartesianFromSpherical(ll, bb) self.assertIsInstance(xyz[0], np.float) self.assertIsInstance(xyz[1], np.float) self.assertIsInstance(xyz[2], np.float) self.assertAlmostEqual(xyz[0], outPoints[ix][0], 12) self.assertAlmostEqual(xyz[1], outPoints[ix][1], 12) self.assertAlmostEqual(xyz[2], outPoints[ix][2], 12) # test _xyz_from_ra_dec <-> testCartesianFromSpherical np.testing.assert_array_equal(utils.cartesianFromSpherical(lon, lat), utils._xyz_from_ra_dec(lon, lat).transpose())
def _dePrecess(self, ra_in, dec_in, obs_metadata): """ 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_metadata 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([[], []]) # Calculate the rotation matrix to go from the precessed bore site # to the ICRS bore site xyz_bore = cartesianFromSpherical(np.array([obs_metadata._pointingRA]), np.array([obs_metadata._pointingDec])) precessedRA, precessedDec = _observedFromICRS(np.array([obs_metadata._pointingRA]), np.array([obs_metadata._pointingDec]), obs_metadata=obs_metadata, epoch=2000.0, includeRefraction=False) xyz_precessed = cartesianFromSpherical(precessedRA, precessedDec) rotMat = rotationMatrixFromVectors(xyz_precessed[0], xyz_bore[0]) xyz_list = cartesianFromSpherical(ra_in, dec_in) xyz_de_precessed = np.array([np.dot(rotMat, xx) for xx in xyz_list]) ra_deprecessed, dec_deprecessed = sphericalFromCartesian(xyz_de_precessed) return np.array([ra_deprecessed, dec_deprecessed])
def test_trixel_contains_many(self): """ Test that trixel.contains_pt and trixel.contains can work with numpy arrays of input """ htmid = (15 << 6) + 45 trixel = trixelFromHtmid(htmid) ra_0, dec_0 = trixel.get_center() radius = trixel.get_radius() rng = np.random.RandomState(44) n_pts = 100 rr = radius*rng.random_sample(n_pts)*1.1 theta = rng.random_sample(n_pts)*2.0*np.pi ra_list = ra_0 + rr*np.cos(theta) dec_list = dec_0 + rr*np.sin(theta) contains_arr = trixel.contains(ra_list, dec_list) n_in = 0 n_out = 0 for i_pt in range(n_pts): single_contains = trixel.contains(ra_list[i_pt], dec_list[i_pt]) self.assertEqual(single_contains, contains_arr[i_pt]) if single_contains: n_in += 1 else: n_out += 1 self.assertGreater(n_in, 0) self.assertGreater(n_out, 0) xyz_list = cartesianFromSpherical(np.radians(ra_list), np.radians(dec_list)) contains_xyz_arr = trixel.contains_pt(xyz_list) np.testing.assert_array_equal(contains_xyz_arr, contains_arr)
def test_trixel_contains_many(self): """ Test that trixel.contains_pt and trixel.contains can work with numpy arrays of input """ htmid = (15 << 6) + 45 trixel = trixelFromHtmid(htmid) ra_0, dec_0 = trixel.get_center() radius = trixel.get_radius() rng = np.random.RandomState(44) n_pts = 100 rr = radius * rng.random_sample(n_pts) * 1.1 theta = rng.random_sample(n_pts) * 2.0 * np.pi ra_list = ra_0 + rr * np.cos(theta) dec_list = dec_0 + rr * np.sin(theta) contains_arr = trixel.contains(ra_list, dec_list) n_in = 0 n_out = 0 for i_pt in range(n_pts): single_contains = trixel.contains(ra_list[i_pt], dec_list[i_pt]) self.assertEqual(single_contains, contains_arr[i_pt]) if single_contains: n_in += 1 else: n_out += 1 self.assertGreater(n_in, 0) self.assertGreater(n_out, 0) xyz_list = cartesianFromSpherical(np.radians(ra_list), np.radians(dec_list)) contains_xyz_arr = trixel.contains_pt(xyz_list) np.testing.assert_array_equal(contains_xyz_arr, contains_arr)
def contains(self, ra, dec): """ Returns True if the specified RA, Dec are inside this trixel; False if not. RA and Dec are in degrees. """ xyz = cartesianFromSpherical(np.radians(ra), np.radians(dec)) return self.contains_pt(xyz)
def transform(self, ra, dec): """ ra, dec are in degrees; return the RA, Dec coordinates of the point about the new field center """ xyz = cartesianFromSpherical(np.radians(ra), np.radians(dec)).transpose() xyz = np.dot(self._transformation, xyz).transpose() ra_out, dec_out = sphericalFromCartesian(xyz) return np.degrees(ra_out), np.degrees(dec_out)
def transform(self, ra, dec): """ ra, dec are in radians; return the RA, Dec coordinates of the point about the new field center """ xyz = cartesianFromSpherical(ra, dec).transpose() xyz = np.dot(self._transformation, xyz).transpose() ra_out, dec_out = sphericalFromCartesian(xyz) return ra_out, dec_out
def _icrsFromPhoSim(self, raPhoSim, decPhoSim, obs_metadata): """ This method will convert from the 'deprecessed' coordinates expected by PhoSim to ICRS coordinates Parameters ---------- raPhoSim is the PhoSim RA-like coordinate (in radians) decPhoSim is the PhoSim Dec-like coordinate (in radians) obs_metadata is an ObservationMetaData characterizing the telescope pointing Returns ------- raICRS in radians decICRS in radians """ # Calculate the rotation matrix to go from the ICRS bore site to the # precessed bore site xyz_bore = cartesianFromSpherical(np.array([obs_metadata._pointingRA]), np.array([obs_metadata._pointingDec])) precessedRA, precessedDec = _observedFromICRS(np.array([obs_metadata._pointingRA]), np.array([obs_metadata._pointingDec]), obs_metadata=obs_metadata, epoch=2000.0, includeRefraction=False) xyz_precessed = cartesianFromSpherical(precessedRA, precessedDec) rotMat = rotationMatrixFromVectors(xyz_bore[0], xyz_precessed[0]) # apply this rotation matrix to the PhoSim RA, Dec-like coordinates, # transforming back to "Observed" RA and Dec xyz_list = cartesianFromSpherical(raPhoSim, decPhoSim) xyz_obs = np.array([np.dot(rotMat, xx) for xx in xyz_list]) ra_obs, dec_obs = sphericalFromCartesian(xyz_obs) # convert to ICRS coordinates return _icrsFromObserved(ra_obs, dec_obs, obs_metadata=obs_metadata, epoch=2000.0, includeRefraction=False)
def _init_from_corners(self, box_corners): ra_range = [c[0] for c in box_corners] ra_min = min(ra_range) ra_max = max(ra_range) dec_range = [c[1] for c in box_corners] dec_min = min(dec_range) dec_max = max(dec_range) tol = 1.0e-10 for i_c1 in range(len(box_corners)): c1 = box_corners[i_c1] pt1 = cartesianFromSpherical(np.degrees(c1[0]), np.degrees(c1[1])) for i_c2 in range(i_c1+1, len(box_corners), 1): hs = None c2 = box_corners[i_c2] pt2 = cartesianFromSpherical(np.degrees(c2[0]), np.degrees(c2[1])) if np.abs(1.0-np.dot(pt1, pt2))<tol: continue dra = np.abs(c1[0]-c2[0]) ddec = np.abs(c1[1]-c2[1]) if dra<tol and ddec>tol: # The RAs of the two corners is identical, but the Decs are # different; this Half Space is defined by a Great Circle if np.abs(c1[0]-ra_min)<tol: inner_pt = (ra_min+0.001, dec_min+0.001) else: inner_pt = (ra_max-0.001, dec_min+0.001) hs = halfSpaceFromPoints(c1, c2, inner_pt) elif ddec<tol and dra>tol: # The Decs of the two corners is identical, bu the RAs are # different; this Half Space is defined by a line of constant # Dec and should be centered at one of the poles if np.abs(c1[1]-dec_min)<tol: hs = halfSpaceFromRaDec(0.0, 90.0, 90.0-dec_min) else: hs = halfSpaceFromRaDec(0.0, -90.0, 90.0+dec_max) else: continue if hs is None: raise RuntimeError("Somehow Half Space == None") self._hs_list.append(hs)
def fovCorners(obs, side_length): """ obs is an ObservationMetaData side_length in arcminutes """ # find the center of the field of view and convert it into "Observed RA, Dec" pointing_lon, pointing_lat = _observedFromICRS(np.array([obs._pointingRA]), np.array([obs._pointingDec ]), obs_metadata=obs, epoch=2000.0) # figure out the length of the diagonal of your square field of view hypotenuse = np.sqrt(2.0 * (side_length / 60.0)**2) half_length = np.radians(0.5 * hypotenuse) # Create a fiducial field of view cetnered on the north pole. # We will take this field of viewand rotate it so that it has # the correct orientation, then translate it down the celestial # sphere to the actual position of your telescope pointing. native_lon_list = np.array([0.0, np.pi / 2.0, np.pi, 1.5 * np.pi]) native_lat_list = np.array([0.5 * np.pi - half_length] * 4) # rotate your field of view to account for the rotation of the sky rot_angle = -1.0 * obs._rotSkyPos + 0.25 * np.pi # the extra 0.25 pi is to align our field # of view so that rotSkyPos=0 puts the # northern edge vertically up (when we # created the field of view, one of the # corners was vertically up) cosRot = np.cos(rot_angle) sinRot = np.sin(rot_angle) rotz = np.array([[cosRot, sinRot, 0.0], [-sinRot, cosRot, 0.0], [0.0, 0.0, 1.0]]) xyz = cartesianFromSpherical(native_lon_list, native_lat_list) rot_xyz = [] for vec in xyz: new_xyz = np.dot(rotz, vec) rot_xyz.append(new_xyz) rot_xyz = np.array(rot_xyz) rot_lon, rot_lat = sphericalFromCartesian(rot_xyz) # translate the field of view down to the actual telescope pointing ra_obs, dec_obs = _lonLatFromNativeLonLat(rot_lon, rot_lat, pointing_lon[0], pointing_lat[0]) return np.degrees( _icrsFromObserved(ra_obs, dec_obs, obs_metadata=obs, epoch=2000.0))
def testCartesianFromSpherical(self): arg1=2.19911485751 arg2=5.96902604182 output=utils.cartesianFromSpherical(arg1,arg2) vv=numpy.zeros((3),dtype=float) vv[0]=numpy.cos(arg2)*numpy.cos(arg1) vv[1]=numpy.cos(arg2)*numpy.sin(arg1) vv[2]=numpy.sin(arg2) self.assertAlmostEqual(output[0],vv[0],7) self.assertAlmostEqual(output[1],vv[1],7) self.assertAlmostEqual(output[2],vv[2],7)
def _applyPrecession(ra, dec, epoch=2000.0, mjd=None): """ _applyPrecession() applies precesion and nutation to coordinates between two epochs. Accepts RA and dec as inputs. Returns corrected RA and dec (in radians). Assumes FK5 as the coordinate system units: ra_in (radians), dec_in (radians) The precession-nutation matrix is calculated by the palpy.prenut method which uses the IAU 2006/2000A model @param [in] ra in radians @param [in] dec in radians @param [in] epoch is the epoch of the mean equinox (in years; default 2000) @param [in] mjd is an instantiation of the ModifiedJulianDate class representing the date of the observation @param [out] a 2-D numpy array in which the first row is the RA corrected for precession and nutation and the second row is the Dec corrected for precession and nutation (both in radians) """ if hasattr(ra, '__len__'): if len(ra) != len(dec): raise RuntimeError( "You supplied %d RAs but %d Decs to applyPrecession" % (len(ra), len(dec))) if mjd is None: raise RuntimeError("You need to supply applyPrecession with an mjd") # Determine the precession and nutation # palpy.prenut takes the julian epoch for the mean coordinates # and the MJD for the the true coordinates # # TODO it is not specified what this MJD should be (i.e. in which # time system it should be reckoned) rmat = palpy.prenut(epoch, mjd.TT) # Apply rotation matrix xyz = cartesianFromSpherical(ra, dec) xyz = np.dot(rmat, xyz.transpose()).transpose() raOut, decOut = sphericalFromCartesian(xyz) return np.array([raOut, decOut])
def find_all_tiles(self, ra, dec, radius): """ ra, dec, radius are all in degrees returns a numpy array of tile IDs that intersect the circle """ valid_id = [] radius_rad = np.radians(radius) center_pt = cartesianFromSpherical(np.radians(ra), np.radians(dec)) for tile_id in self._tile_dict: tile = self._tile_dict[tile_id] is_contained = tile.intersects_circle(center_pt, radius_rad) if is_contained: valid_id.append(tile_id) return np.array(valid_id)
def _findHtmid_slow(ra, dec, max_level): """ Find the htmid (the unique integer identifying each trixel) of the trixel containing a given RA, Dec pair. Parameters ---------- ra in degrees dec in degrees max_level is an integer denoting the mesh level of the trixel you want found Note: This method only works one point at a time. It cannot take arrays of RA and Dec. Returns ------- An int (the htmid) """ ra_rad = np.radians(ra) dec_rad = np.radians(dec) pt = cartesianFromSpherical(ra_rad, dec_rad) if _S0_trixel.contains_pt(pt): parent = _S0_trixel elif _S1_trixel.contains_pt(pt): parent = _S1_trixel elif _S2_trixel.contains_pt(pt): parent = _S2_trixel elif _S3_trixel.contains_pt(pt): parent = _S3_trixel elif _N0_trixel.contains_pt(pt): parent = _N0_trixel elif _N1_trixel.contains_pt(pt): parent = _N1_trixel elif _N2_trixel.contains_pt(pt): parent = _N2_trixel elif _N3_trixel.contains_pt(pt): parent = _N3_trixel else: raise RuntimeError("could not find parent Trixel") return _iterateTrixelFinder(pt, parent, max_level)
def _applyPrecession(ra, dec, epoch=2000.0, mjd=None): """ _applyPrecession() applies precesion and nutation to coordinates between two epochs. Accepts RA and dec as inputs. Returns corrected RA and dec (in radians). Assumes FK5 as the coordinate system units: ra_in (radians), dec_in (radians) The precession-nutation matrix is calculated by the palpy.prenut method which uses the IAU 2006/2000A model @param [in] ra in radians @param [in] dec in radians @param [in] epoch is the epoch of the mean equinox (in years; default 2000) @param [in] mjd is an instantiation of the ModifiedJulianDate class representing the date of the observation @param [out] a 2-D numpy array in which the first row is the RA corrected for precession and nutation and the second row is the Dec corrected for precession and nutation (both in radians) """ if hasattr(ra, '__len__'): if len(ra) != len(dec): raise RuntimeError("You supplied %d RAs but %d Decs to applyPrecession" % (len(ra), len(dec))) if mjd is None: raise RuntimeError("You need to supply applyPrecession with an mjd") # Determine the precession and nutation #palpy.prenut takes the julian epoch for the mean coordinates #and the MJD for the the true coordinates # #TODO it is not specified what this MJD should be (i.e. in which #time system it should be reckoned) rmat=palpy.prenut(epoch, mjd.TT) # Apply rotation matrix xyz = cartesianFromSpherical(ra,dec) xyz = numpy.dot(rmat,xyz.transpose()).transpose() raOut,decOut = sphericalFromCartesian(xyz) return numpy.array([raOut,decOut])
def smear_ra_dec(ra_deg, dec_deg, delta_ast, rng): xyz = cartesianFromSpherical(np.radians(ra_deg), np.radians(dec_deg)) ra_out = np.zeros(len(ra_deg), dtype=float) dec_out = np.zeros(len(dec_deg), dtype=float) for ii in range(len(ra_deg)): random_vec = rng.normal(0.0, 1.0, 3) parallel = np.dot(random_vec, xyz[ii]) random_vec -= parallel * xyz[ii] random_vec /= np.sqrt(np.dot(random_vec, random_vec)) cos_d = np.cos(delta_ast[ii]) sin_d = np.sin(delta_ast[ii]) new_xyz = cos_d * xyz[ii] + sin_d * random_vec new_xyz /= np.sqrt(np.dot(new_xyz, new_xyz)) new_ra, new_dec = sphericalFromCartesian(new_xyz) ra_out[ii] = np.degrees(new_ra) dec_out[ii] = np.degrees(new_dec) return ra_out, dec_out
def halfSpaceFromRaDec(ra, dec, radius): """ Take an RA, Dec and radius of a circular field of view and return a HalfSpace Parameters ---------- ra in degrees dec in degrees radius in degrees Returns ------- HalfSpace corresponding to the circular field of view """ dd = np.cos(np.radians(radius)) xyz = cartesianFromSpherical(np.radians(ra), np.radians(dec)) return HalfSpace(xyz, dd)
def testCartesianFromSpherical(self): numpy.random.seed(42) nsamples = 10 theta = numpy.random.random_sample(nsamples)*numpy.pi-0.5*numpy.pi phi = numpy.random.random_sample(nsamples)*2.0*numpy.pi points = [] for ix in range(nsamples): vv = [numpy.cos(theta[ix])*numpy.cos(phi[ix]), numpy.cos(theta[ix])*numpy.sin(phi[ix]), numpy.sin(theta[ix])] points.append(vv) points = numpy.array(points) lon, lat = utils.sphericalFromCartesian(points) outPoints = utils.cartesianFromSpherical(numpy.array(lon), numpy.array(lat)) for pp, oo in zip(points, outPoints): numpy.testing.assert_array_almost_equal(pp, oo, decimal=6)
def test_half_space_contains_pt(self): hs = HalfSpace(np.array([0.0, 0.0, 1.0]), 0.1) nhs = HalfSpace(np.array([0.0, 0.0, -1.0]), -0.1) theta = np.arcsin(0.1) rng = np.random.RandomState(88) n_tests = 200 ra_list = rng.random_sample(n_tests)*2.0*np.pi dec_list = rng.random_sample(n_tests)*(0.5*np.pi-theta)+theta for ra, dec, in zip(ra_list, dec_list): xyz = cartesianFromSpherical(ra, dec) self.assertTrue(hs.contains_pt(xyz)) self.assertFalse(nhs.contains_pt(xyz)) ra_list = rng.random_sample(n_tests)*2.0*np.pi dec_list = theta - rng.random_sample(n_tests)*(0.5*np.pi+theta) for ra, dec, in zip(ra_list, dec_list): xyz = cartesianFromSpherical(ra, dec) self.assertFalse(hs.contains_pt(xyz)) self.assertTrue(nhs.contains_pt(xyz)) hs = HalfSpace(np.array([1.0, 0.0, 0.0]), 0.2) nhs = HalfSpace(np.array([-1.0, 0.0, 0.0]), -0.2) theta = np.arcsin(0.2) ra_list = rng.random_sample(n_tests)*2.0*np.pi dec_list = rng.random_sample(n_tests)*(0.5*np.pi-theta)+theta for ra, dec in zip(ra_list, dec_list): xyz_rot = cartesianFromSpherical(ra, dec) xyz = rotAboutY(xyz_rot, 0.5*np.pi) self.assertTrue(hs.contains_pt(xyz)) self.assertFalse(nhs.contains_pt(xyz)) ra_list = rng.random_sample(n_tests)*2.0*np.pi dec_list = theta - rng.random_sample(n_tests)*(0.5*np.pi+theta) for ra, dec, in zip(ra_list, dec_list): xyz_rot = cartesianFromSpherical(ra, dec) xyz = rotAboutY(xyz_rot, 0.5*np.pi) self.assertFalse(hs.contains_pt(xyz)) self.assertTrue(nhs.contains_pt(xyz)) vv = np.array([0.5*np.sqrt(2), -0.5*np.sqrt(2), 0.0]) hs = HalfSpace(vv, 0.3) nhs = HalfSpace(-1.0*vv, -0.3) theta = np.arcsin(0.3) ra_list = rng.random_sample(n_tests)*2.0*np.pi dec_list = rng.random_sample(n_tests)*(0.5*np.pi-theta)+theta for ra, dec in zip(ra_list, dec_list): xyz_rot = cartesianFromSpherical(ra, dec) xyz_rot = rotAboutX(xyz_rot, 0.5*np.pi) xyz = rotAboutZ(xyz_rot, 0.25*np.pi) self.assertTrue(hs.contains_pt(xyz)) self.assertFalse(nhs.contains_pt(xyz)) ra_list = rng.random_sample(n_tests)*2.0*np.pi dec_list = theta - rng.random_sample(n_tests)*(0.5*np.pi+theta) for ra, dec, in zip(ra_list, dec_list): xyz_rot = cartesianFromSpherical(ra, dec) xyz_rot = rotAboutX(xyz_rot, 0.5*np.pi) xyz = rotAboutZ(xyz_rot, 0.25*np.pi) self.assertFalse(hs.contains_pt(xyz)) self.assertTrue(nhs.contains_pt(xyz))
def __init__(self, ra0, dec0, ra1, dec1): """ Parameters ---------- ra0, dec0 are the coordinates of the original field center in degrees ra1, dec1 are the coordinates of the new field center in degrees The transform() method of this class operates by first applying a rotation that carries the original field center into the new field center. Points are then transformed into a basis in which the unit vector defining the new field center is the x-axis. A rotation about the x-axis is applied so that a point that was due north of the original field center is still due north of the field center at the new location. Finally, points are transformed back into the original x,y,z bases. """ # find the rotation that carries the original field center # to the new field center xyz = cartesianFromSpherical(np.radians(ra0), np.radians(dec0)) xyz1 = cartesianFromSpherical(np.radians(ra1), np.radians(dec1)) if np.abs(1.0-np.dot(xyz, xyz1))<1.0e-10: self._transformation = np.identity(3, dtype=float) return first_rotation = rotationMatrixFromVectors(xyz, xyz1) # create a basis set in which the unit vector # defining the new field center is the x axis xx = np.dot(first_rotation, xyz) rng = np.random.RandomState(99) mag = np.NaN while np.abs(mag)<1.0e-20 or np.isnan(mag): random_vec = rng.random_sample(3) comp = np.dot(random_vec, xx) yy = random_vec - comp*xx mag = np.sqrt((yy**2).sum()) yy /= mag zz = np.cross(xx, yy) to_self_bases = np.array([xx, yy, zz]) out_of_self_bases =to_self_bases.transpose() # Take a point due north of the original field # center. Apply first_rotation to carry it to # the new field. Transform it to the [xx, yy, zz] # bases and find the rotation about xx that will # make it due north of the new field center. # Finally, transform back to the original bases. d_dec = 0.1 north = cartesianFromSpherical(np.radians(ra0), np.radians(dec0+d_dec)) north = np.dot(first_rotation, north) #print(np.degrees(sphericalFromCartesian(north))) north_true = cartesianFromSpherical(np.radians(ra1), np.radians(dec1+d_dec)) north = np.dot(to_self_bases, north) north_true = np.dot(to_self_bases, north_true) north = np.array([north[1], north[2]]) north /= np.sqrt((north**2).sum()) north_true = np.array([north_true[1], north_true[2]]) north_true /= np.sqrt((north_true**2).sum()) c = north_true[0]*north[0]+north_true[1]*north[1] s = north[0]*north_true[1]-north[1]*north_true[0] norm = np.sqrt(c*c+s*s) c = c/norm s = s/norm nprime = np.array([c*north[0]-s*north[1], s*north[0]+c*north[1]]) yz_rotation = np.array([[1.0, 0.0, 0.0], [0.0, c, -s], [0.0, s, c]]) second_rotation = np.dot(out_of_self_bases, np.dot(yz_rotation, to_self_bases)) self._transformation = np.dot(second_rotation, first_rotation)
def _findHtmid_fast(ra, dec, max_level): """ Find the htmid (the unique integer identifying each trixel) of the trixels containing arrays of RA, Dec pairs Parameters ---------- ra in degrees (a numpy array) dec in degrees (a numpy array) max_level is an integer denoting the mesh level of the trixel you want found Returns ------- A numpy array of ints (the htmids) Note: this method works by caching all of the trixels up to a given level. Do not call it on max_level>10 """ if max_level>10: raise RuntimeError("Do not call _findHtmid_fast with max_level>10; " "the cache of trixels generated will be too large. " "Call findHtmid or _findHtmid_slow (findHtmid will " "redirect to _findHtmid_slow for large max_level).") if (not hasattr(_findHtmid_fast, '_trixel_dict') or _findHtmid_fast._level < max_level): _findHtmid_fast._trixel_dict = getAllTrixels(max_level) _findHtmid_fast._level = max_level ra_rad = np.radians(ra) dec_rad = np.radians(dec) pt_arr = cartesianFromSpherical(ra_rad, dec_rad) base_trixels = [_S0_trixel, _S1_trixel, _S2_trixel, _S3_trixel, _N0_trixel, _N1_trixel, _N2_trixel, _N3_trixel] htmid_arr = np.zeros(len(pt_arr), dtype=int) parent_dict = {} for parent in base_trixels: is_contained = parent.contains_pt(pt_arr) valid_dexes = np.where(is_contained) if len(valid_dexes[0]) == 0: continue htmid_arr[valid_dexes] = parent.htmid parent_dict[parent.htmid] = valid_dexes[0] for level in range(1, max_level): new_parent_dict = {} for parent_htmid in parent_dict.keys(): considered_raw = parent_dict[parent_htmid] next_htmid = parent_htmid << 2 children_htmid = [next_htmid, next_htmid+1, next_htmid+2, next_htmid+3] is_found = np.zeros(len(considered_raw), dtype=int) for child in children_htmid: un_found = np.where(is_found==0)[0] considered = considered_raw[un_found] if len(considered) == 0: break child_trixel = _findHtmid_fast._trixel_dict[child] contains = child_trixel.contains_pt(pt_arr[considered]) valid = np.where(contains) if len(valid[0]) == 0: continue valid_dexes = considered[valid] is_found[un_found[valid[0]]] = 1 htmid_arr[valid_dexes] = child new_parent_dict[child] = valid_dexes parent_dict = new_parent_dict return htmid_arr
def __next__(self): if self._tile_to_do == 0: self._valid_tiles = 0 self._n_chunks += 1 if self.chunk_size is None: results = self._galaxy_query.fetchall() elif self.chunk_size is not None: results = self._galaxy_query.fetchmany(self.chunk_size) else: raise StopIteration self._galaxy_cache = self.dbobj._convert_results_to_numpy_recarray_catalogDBObj(results) self._n_rows += len(self._galaxy_cache) if len(self._galaxy_cache) == 0: raise StopIteration current_chunk = copy.deepcopy(self._galaxy_cache) rot_mat = self._rotate_to_sky[self._tile_to_do] bounds = self._00_bounds[self._tile_to_do] sky_tile = self._sky_tile[self._tile_to_do] tile_idx = self._tile_idx[self._tile_to_do] make_the_cut = None for bb in bounds: htmid_min = bb[0] << 2*(21-self._trixel_search_level) htmid_max = (bb[1]+1) << 2*(21-self._trixel_search_level) valid = ((current_chunk['htmid']>=htmid_min) & (current_chunk['htmid']<=htmid_max)) if make_the_cut is None: make_the_cut = valid else: make_the_cut |= valid good_dexes = np.where(make_the_cut)[0] if len(good_dexes) < len(current_chunk): current_chunk = current_chunk[good_dexes] self._tile_to_do += 1 if self._tile_to_do >= len(self._rotate_to_sky): self._tile_to_do = 0 if len(current_chunk) == 0: return self.__next__() xyz = cartesianFromSpherical(np.radians(current_chunk['ra']), np.radians(current_chunk['dec'])) xyz_sky = np.dot(rot_mat, xyz.transpose()).transpose() final_cut = sky_tile.contains_many_pts(xyz_sky) final_cut &= self.obs_hs.contains_many_pts(xyz_sky) final_cut = np.where(final_cut) xyz_sky = xyz_sky[final_cut] current_chunk = current_chunk[final_cut] if len(current_chunk) == 0: return self.__next__() ra_dec_sky = sphericalFromCartesian(xyz_sky) current_chunk['ra'] = np.degrees(ra_dec_sky[0]) % 360.0 current_chunk['dec'] = np.degrees(ra_dec_sky[1]) % 360.0 current_chunk['dec'] = np.where(current_chunk['dec']<270.0, current_chunk['dec'], current_chunk['dec']-360.0) current_chunk['dec'] = np.where(np.abs(current_chunk['dec'])<=90.0, current_chunk['dec'], 180.0-current_chunk['dec']) if self._has_J2000: current_chunk['raJ2000'] = ra_dec_sky[0] % (2.0*np.pi) _dec = ra_dec_sky[1] % (2.0*np.pi) current_chunk['decJ2000'] = np.where(_dec<1.5*np.pi, _dec, _dec-2.0*np.pi) current_chunk['decJ2000'] = np.where(np.abs(current_chunk['decJ2000'])<=0.5*np.pi, current_chunk['decJ2000'], np.pi-current_chunk['decJ2000']) #>>> r2 = recfunc.append_fields(r,['d','e'],d,dtypes=[float, int], usemask=False, asrecarray=True) galtileid = tile_idx*100000000+current_chunk['id'] current_chunk = np_recfn.append_fields(current_chunk, ['galtileid'], [galtileid], dtypes=[int], usemask=False, asrecarray=True) self._valid_tiles += 1 self._rows_kept += len(current_chunk) return self._postprocess_results(current_chunk)
def test_half_space_contains_pt(self): hs = HalfSpace(np.array([0.0, 0.0, 1.0]), 0.1) nhs = HalfSpace(np.array([0.0, 0.0, -1.0]), -0.1) theta = np.arcsin(0.1) rng = np.random.RandomState(88) n_tests = 200 ra_list = rng.random_sample(n_tests) * 2.0 * np.pi dec_list = rng.random_sample(n_tests) * (0.5 * np.pi - theta) + theta for ra, dec, in zip(ra_list, dec_list): xyz = cartesianFromSpherical(ra, dec) self.assertTrue(hs.contains_pt(xyz)) self.assertFalse(nhs.contains_pt(xyz)) ra_list = rng.random_sample(n_tests) * 2.0 * np.pi dec_list = theta - rng.random_sample(n_tests) * (0.5 * np.pi + theta) for ra, dec, in zip(ra_list, dec_list): xyz = cartesianFromSpherical(ra, dec) self.assertFalse(hs.contains_pt(xyz)) self.assertTrue(nhs.contains_pt(xyz)) hs = HalfSpace(np.array([1.0, 0.0, 0.0]), 0.2) nhs = HalfSpace(np.array([-1.0, 0.0, 0.0]), -0.2) theta = np.arcsin(0.2) ra_list = rng.random_sample(n_tests) * 2.0 * np.pi dec_list = rng.random_sample(n_tests) * (0.5 * np.pi - theta) + theta for ra, dec in zip(ra_list, dec_list): xyz_rot = cartesianFromSpherical(ra, dec) xyz = rotAboutY(xyz_rot, 0.5 * np.pi) self.assertTrue(hs.contains_pt(xyz)) self.assertFalse(nhs.contains_pt(xyz)) ra_list = rng.random_sample(n_tests) * 2.0 * np.pi dec_list = theta - rng.random_sample(n_tests) * (0.5 * np.pi + theta) for ra, dec, in zip(ra_list, dec_list): xyz_rot = cartesianFromSpherical(ra, dec) xyz = rotAboutY(xyz_rot, 0.5 * np.pi) self.assertFalse(hs.contains_pt(xyz)) self.assertTrue(nhs.contains_pt(xyz)) vv = np.array([0.5 * np.sqrt(2), -0.5 * np.sqrt(2), 0.0]) hs = HalfSpace(vv, 0.3) nhs = HalfSpace(-1.0 * vv, -0.3) theta = np.arcsin(0.3) ra_list = rng.random_sample(n_tests) * 2.0 * np.pi dec_list = rng.random_sample(n_tests) * (0.5 * np.pi - theta) + theta for ra, dec in zip(ra_list, dec_list): xyz_rot = cartesianFromSpherical(ra, dec) xyz_rot = rotAboutX(xyz_rot, 0.5 * np.pi) xyz = rotAboutZ(xyz_rot, 0.25 * np.pi) self.assertTrue(hs.contains_pt(xyz)) self.assertFalse(nhs.contains_pt(xyz)) ra_list = rng.random_sample(n_tests) * 2.0 * np.pi dec_list = theta - rng.random_sample(n_tests) * (0.5 * np.pi + theta) for ra, dec, in zip(ra_list, dec_list): xyz_rot = cartesianFromSpherical(ra, dec) xyz_rot = rotAboutX(xyz_rot, 0.5 * np.pi) xyz = rotAboutZ(xyz_rot, 0.25 * np.pi) self.assertFalse(hs.contains_pt(xyz)) self.assertTrue(nhs.contains_pt(xyz))
def __init__(self, ra0, dec0, ra1, dec1): """ Parameters ---------- ra0, dec0 are the coordinates of the original field center in radians ra1, dec1 are the coordinates of the new field center in radians The transform() method of this class operates by first applying a rotation that carries the original field center into the new field center. Points are then transformed into a basis in which the unit vector defining the new field center is the x-axis. A rotation about the x-axis is applied so that a point that was due north of the original field center is still due north of the field center at the new location. Finally, points are transformed back into the original x,y,z bases. """ self._ra0 = ra0 self._dec0 = dec0 self._ra1 = ra1 self._dec1 = dec1 # find the rotation that carries the original field center # to the new field center xyz = cartesianFromSpherical(ra0, dec0) xyz1 = cartesianFromSpherical(ra1, dec1) if np.abs(1.0-np.dot(xyz, xyz1))<1.0e-10: self._transformation = np.identity(3, dtype=float) return first_rotation = rotationMatrixFromVectors(xyz, xyz1) # create a basis set in which the unit vector # defining the new field center is the x axis xx = np.dot(first_rotation, xyz) rng = np.random.RandomState(99) mag = np.NaN while np.abs(mag)<1.0e-20 or np.isnan(mag): random_vec = rng.random_sample(3) comp = np.dot(random_vec, xx) yy = random_vec - comp*xx mag = np.sqrt((yy**2).sum()) yy /= mag zz = np.cross(xx, yy) to_self_bases = np.array([xx, yy, zz]) out_of_self_bases =to_self_bases.transpose() # Take a point due north of the original field # center. Apply first_rotation to carry it to # the new field. Transform it to the [xx, yy, zz] # bases and find the rotation about xx that will # make it due north of the new field center. # Finally, transform back to the original bases. d_dec = np.radians(0.1) north = cartesianFromSpherical(ra0,dec0+d_dec) north = np.dot(first_rotation, north) #print(np.degrees(sphericalFromCartesian(north))) north_true = cartesianFromSpherical(ra1, dec1+d_dec) north = np.dot(to_self_bases, north) north_true = np.dot(to_self_bases, north_true) north = np.array([north[1], north[2]]) north /= np.sqrt((north**2).sum()) north_true = np.array([north_true[1], north_true[2]]) north_true /= np.sqrt((north_true**2).sum()) c = north_true[0]*north[0]+north_true[1]*north[1] s = north[0]*north_true[1]-north[1]*north_true[0] norm = np.sqrt(c*c+s*s) c = c/norm s = s/norm nprime = np.array([c*north[0]-s*north[1], s*north[0]+c*north[1]]) yz_rotation = np.array([[1.0, 0.0, 0.0], [0.0, c, -s], [0.0, s, c]]) second_rotation = np.dot(out_of_self_bases, np.dot(yz_rotation, to_self_bases)) self._transformation = np.dot(second_rotation, first_rotation)