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 __call__(self, ra, dec, stack=True): """ similar to utils.hp_in_lsst_fov, but can take a arrays of ra,dec. Parameters ---------- ra : array_like RA in radians dec : array_like Dec in radians Returns ------- result : healpy map The number of times each healpxel is observed by the given pointings """ xs, ys, zs = _xyz_from_ra_dec(ra, dec) coords = np.array((xs, ys, zs)).T indx = self.tree.query_ball_point(coords, self.rad) # Convert array of lists to single array if stack: indx = np.hstack(indx) result, bins = np.histogram(indx, bins=self.bins) else: result = indx return result
def _sliceSimData(islice): """Return indexes for relevant opsim data at slicepoint (slicepoint=lonCol/latCol value .. usually ra/dec).""" # Build dict for slicePoint info slicePoint = {} if self.useCamera: indices = self.sliceLookup[islice] slicePoint['chipNames'] = self.chipNames[islice] else: sx, sy, sz = simsUtils._xyz_from_ra_dec(self.slicePoints['ra'][islice], self.slicePoints['dec'][islice]) # Query against tree. indices = self.opsimtree.query_ball_point((sx, sy, sz), self.rad) # Loop through all the slicePoint keys. If the first dimension of slicepoint[key] has # the same shape as the slicer, assume it is information per slicepoint. # Otherwise, pass the whole slicePoint[key] information. Useful for stellar LF maps # where we want to pass only the relevant LF and the bins that go with it. for key in self.slicePoints: if len(np.shape(self.slicePoints[key])) == 0: keyShape = 0 else: keyShape = np.shape(self.slicePoints[key])[0] if (keyShape == self.nslice): slicePoint[key] = self.slicePoints[key][islice] else: slicePoint[key] = self.slicePoints[key] return {'idxs': indices, 'slicePoint': slicePoint}
def fields_hit(self, mjd, fraction=False): """ Return an array that lists the number of hits in each field pointing """ mjds = mjd + self.tsteps result = self.fields_empty.copy() # convert the satellites above the limits to x,y,z and get the neighbors within the fov. for mjd in mjds: self.update_mjd(mjd) x, y, z = _xyz_from_ra_dec( self.azimuth_rad[self.above_alt_limit], self.altitudes_rad[self.above_alt_limit]) if np.size(x) > 0: indices = self.tree.query_ball_point( np.array([x, y, z]).T, self.radius) final_indices = [] for indx in indices: final_indices.extend(indx) result[final_indices] += 1 if fraction: n_hit = np.size(np.where(result > 0)[0]) result = n_hit / self.fields_empty.size return result
def _presliceFootprint(self, simData): """Loop over each pointing and find which sky points are observed """ # Now to make a list of lists for looking up the relevant observations at each slicepoint self.sliceLookup = [[] for dummy in range(self.nslice)] self.chipNames = [[] for dummy in range(self.nslice)] # Make a kdtree for the _slicepoints_ # Using scipy 0.16 or later self._buildTree(self.slicePoints['ra'], self.slicePoints['dec'], leafsize=self.leafsize) # Loop over each unique pointing position if self.latLonDeg: lat = np.radians(simData[self.latCol]) lon = np.radians(simData[self.lonCol]) else: lat = simData[self.latCol] lon = simData[self.lonCol] for ind, ra, dec, rotSkyPos, mjd in zip(np.arange(simData.size), lon, lat, simData[self.rotSkyPosColName], simData[self.mjdColName]): dx, dy, dz = simsUtils._xyz_from_ra_dec(ra, dec) # Find healpixels inside the FoV hpIndices = np.array( self.opsimtree.query_ball_point((dx, dy, dz), self.rad)) if hpIndices.size > 0: obs_metadata = simsUtils.ObservationMetaData( pointingRA=np.degrees(ra), pointingDec=np.degrees(dec), rotSkyPos=np.degrees(rotSkyPos), mjd=mjd) chipNames = _chipNameFromRaDec( self.slicePoints['ra'][hpIndices], self.slicePoints['dec'][hpIndices], epoch=self.epoch, camera=self.camera, obs_metadata=obs_metadata) # If we are using only a subset of chips if self.chipsToUse != 'all': checkedChipNames = [ chipName in self.chipsToUse for chipName in chipNames ] good = np.where(checkedChipNames)[0] chipNames = chipNames[good] hpIndices = hpIndices[good] # Find the healpixels that fell on a chip for this pointing good = np.where(chipNames != [None])[0] hpOnChip = hpIndices[good] for i, chipName in zip(hpOnChip, chipNames[good]): self.sliceLookup[i].append(ind) self.chipNames[i].append(chipName) if self.verbose: "Created lookup table after checking for chip gaps."
def run(self, slicePoints): self._readMap() x, y, z = _xyz_from_ra_dec(slicePoints['ra'], slicePoints['dec']) dist, indices = self.tree.query(list(zip(x, y, z))) slicePoints['starLumFunc_%s' % self.filtername] = self.starMap[indices, :] slicePoints['starMapBins_%s' % self.filtername] = self.starMapBins return slicePoints
def rotate_ra_dec(ra, dec, ra_target, dec_target, init_rotate=0.): """ Rotate ra and dec coordinates to be centered on a new dec. Rotates around the x-axis 1st, then to the dec, then ra. Inputs ------ ra : float or np.array RA coordinate(s) to be rotated in radians dec : float or np.array Dec coordinate(s) to be rotated in radians ra_rotation : float RA distance to rotate in radians dec_target : float Dec distance to rotate in radians init_rotate : float (0.) The amount to rotate the points around the x-axis first (radians). """ # point (ra,dec) = (0,0) is at x,y,z = 1,0,0 x, y, z = _xyz_from_ra_dec(ra, dec) # Rotate around the x axis to start xp = x if init_rotate != 0.: c_i = np.cos(init_rotate) s_i = np.sin(init_rotate) yp = c_i * y - s_i * z zp = s_i * y + c_i * z else: yp = y zp = z theta_y = dec_target c_ty = np.cos(theta_y) s_ty = np.sin(theta_y) # Rotate about y xp2 = c_ty * xp + s_ty * zp zp2 = -s_ty * xp + c_ty * zp # Convert back to RA, Dec ra_p = np.arctan2(yp, xp2) dec_p = -np.arcsin(zp2) # Rotate to the correct RA ra_p += ra_target ra_p, dec_p = wrapRADec(ra_p, dec_p) return ra_p, dec_p
def testKDTreeAPI(self): """ Make sure the API provided by scipy to the kdTree algorithm is functional. """ _ra = np.linspace(0., 2.*np.pi) _dec = np.linspace(-np.pi, np.pi) Ra, Dec = np.meshgrid(_ra, _dec) tree = utils._buildTree(Ra.flatten(), Dec.flatten()) x, y, z = utils._xyz_from_ra_dec(_ra, _dec) indx = tree.query_ball_point(list(zip(x, y, z)), utils.xyz_angular_radius()) self.assertEqual(indx.shape, _ra.shape)
def testKDTreeAPI(self): """ Make sure the API provided by scipy to the kdTree algorithm is functional. """ _ra = np.linspace(0., 2. * np.pi) _dec = np.linspace(-np.pi, np.pi) Ra, Dec = np.meshgrid(_ra, _dec) tree = utils._buildTree(Ra.flatten(), Dec.flatten()) x, y, z = utils._xyz_from_ra_dec(_ra, _dec) indx = tree.query_ball_point(list(zip(x, y, z)), utils.xyz_angular_radius()) self.assertEqual(indx.shape, _ra.shape)
def __call__(self, ra, dec, *args): """ Parameters ---------- ra : float RA in radians dec : float Dec in radians Returns ------- indx : numpy array The healpixels that are within the FoV """ x, y, z = _xyz_from_ra_dec(np.max(ra), np.max(dec)) indices = self.tree.query_ball_point((x, y, z), self.radius) return np.array(indices)
def _presliceFootprint(self, simData): """Loop over each pointing and find which sky points are observed """ # Now to make a list of lists for looking up the relevant observations at each slicepoint self.sliceLookup = [[] for dummy in range(self.nslice)] self.chipNames = [[] for dummy in range(self.nslice)] # Make a kdtree for the _slicepoints_ # Using scipy 0.16 or later self._buildTree(self.slicePoints['ra'], self.slicePoints['dec'], leafsize=self.leafsize) # Loop over each unique pointing position if self.latLonDeg: lat = np.radians(simData[self.latCol]) lon = np.radians(simData[self.lonCol]) else: lat = simData[self.latCol] lon = simData[self.lonCol] for ind, ra, dec, rotSkyPos, mjd in zip(np.arange(simData.size), lon, lat, simData[self.rotSkyPosColName], simData[self.mjdColName]): dx, dy, dz = simsUtils._xyz_from_ra_dec(ra, dec) # Find healpixels inside the FoV hpIndices = np.array(self.opsimtree.query_ball_point((dx, dy, dz), self.rad)) if hpIndices.size > 0: obs_metadata = simsUtils.ObservationMetaData(pointingRA=np.degrees(ra), pointingDec=np.degrees(dec), rotSkyPos=np.degrees(rotSkyPos), mjd=mjd) chipNames = _chipNameFromRaDec(self.slicePoints['ra'][hpIndices], self.slicePoints['dec'][hpIndices], epoch=self.epoch, camera=self.camera, obs_metadata=obs_metadata) # If we are using only a subset of chips if self.chipsToUse != 'all': checkedChipNames = [chipName in self.chipsToUse for chipName in chipNames] good = np.where(checkedChipNames)[0] chipNames = chipNames[good] hpIndices = hpIndices[good] # Find the healpixels that fell on a chip for this pointing good = np.where(chipNames != [None])[0] hpOnChip = hpIndices[good] for i, chipName in zip(hpOnChip, chipNames[good]): self.sliceLookup[i].append(ind) self.chipNames[i].append(chipName) if self.verbose: "Created lookup table after checking for chip gaps."
def __call__(self, ra, dec, rotSkyPos): """ Parameters ---------- ra : float RA in radians dec : float Dec in radians rotSkyPos : float The rotation angle of the camera in radians Returns ------- indx : numpy array The healpixels that are within the FoV """ x, y, z = _xyz_from_ra_dec(np.max(ra), np.max(dec)) # Healpixels within the inner circle indices = self.tree.query_ball_point((x, y, z), self.inner_radius) # Healpixels withing the outer circle indices_all = np.array(self.tree.query_ball_point((x, y, z), self.outter_radius)) indices_to_check = indices_all[np.in1d(indices_all, indices, invert=True)] cos_rot = np.cos(rotSkyPos) sin_rot = np.sin(rotSkyPos) x_rotated = self.corners_x*cos_rot - self.corners_y*sin_rot y_rotated = self.corners_x*sin_rot + self.corners_y*cos_rot # Draw the square that we want to check if points are in. bbPath = mplPath.Path(np.array([[x_rotated[0], y_rotated[0]], [x_rotated[1], y_rotated[1]], [x_rotated[2], y_rotated[2]], [x_rotated[3], y_rotated[3]], [x_rotated[0], y_rotated[0]]])) ra_to_check, dec_to_check = _hpid2RaDec(self.nside, indices_to_check) # Project the indices to check to the tangent plane, see if they fall inside the polygon x, y = gnomonic_project_toxy(ra_to_check, dec_to_check, ra, dec) for i, xcheck in enumerate(x): # I wonder if I can do this all at once rather than a loop? if bbPath.contains_point((x[i], y[i])): indices.append(indices_to_check[i]) return np.array(indices)
def _run(self, simData, cols_present=False): if cols_present: # Column already present in data; assume it is correct and does not need recalculating. return simData if self.degrees: coord_x, coord_y, coord_z = xyz_from_ra_dec(simData[self.raCol], simData[self.decCol]) field_ids = self.tree.query_ball_point(list(zip(coord_x, coord_y, coord_z)), xyz_angular_radius()) else: # use _xyz private method (sending radians) coord_x, coord_y, coord_z = _xyz_from_ra_dec(simData[self.raCol], simData[self.decCol]) field_ids = self.tree.query_ball_point(list(zip(coord_x, coord_y, coord_z)), xyz_angular_radius()) simData['opsimFieldId'] = np.array([ids[0] for ids in field_ids]) + 1 return simData
def _sliceSimData(islice): """Return indexes for relevant opsim data at slicepoint (slicepoint=lonCol/latCol value .. usually ra/dec).""" # Build dict for slicePoint info slicePoint = {} if self.useCamera: indices = self.sliceLookup[islice] slicePoint['chipNames'] = self.chipNames[islice] else: sx, sy, sz = simsUtils._xyz_from_ra_dec(self.slicePoints['ra'][islice], self.slicePoints['dec'][islice]) # Anything within half the side length is good no matter what rotation angle # the camera is at indices = self.opsimtree.query_ball_point((sx, sy, sz), self.side_radius) # Now the larger radius. Need to make it an array for easy subscripting initial_indices = np.array(self.opsimtree.query_ball_point((sx, sy, sz), self.rad), dtype=int) # remove the indices we already know about initial_indices = initial_indices[np.in1d(initial_indices, indices, invert=True)] if self.latLonDeg: lat = np.radians(simData[self.latCol][initial_indices]) lon = np.radians(simData[self.lonCol][initial_indices]) cos_rot = np.cos(np.radians(simData[self.rotSkyPosColName][initial_indices])) sin_rot = np.cos(np.radians(simData[self.rotSkyPosColName][initial_indices])) else: lat = simData[self.latCol][initial_indices] lon = simData[self.lonCol][initial_indices] cos_rot = np.cos(simData[self.rotSkyPosColName][initial_indices]) sin_rot = np.sin(simData[self.rotSkyPosColName][initial_indices]) # loop over the observations that might be overlapping the healpix, check each for i, ind in enumerate(initial_indices): # Rotate the camera x_rotated = self.corners_x*cos_rot[i] - self.corners_y*sin_rot[i] y_rotated = self.corners_x*sin_rot[i] + self.corners_y*cos_rot[i] # How far is the pointing center from the healpix center xshift, yshift = gnomonic_project_toxy(lon[i], lat[i], self.slicePoints['ra'][islice], self.slicePoints['dec'][islice]) x_rotated += xshift y_rotated += yshift # Use matplotlib to make a polygon bbPath = mplPath.Path(np.array([[x_rotated[0], y_rotated[0]], [x_rotated[1], y_rotated[1]], [x_rotated[2], y_rotated[2]], [x_rotated[3], y_rotated[3]], [x_rotated[0], y_rotated[0]]])) # Check if the slicepoint is inside the image corners and append to list if bbPath.contains_point((0., 0.)): indices.append(ind) # Loop through all the slicePoint keys. If the first dimension of slicepoint[key] has # the same shape as the slicer, assume it is information per slicepoint. # Otherwise, pass the whole slicePoint[key] information. Useful for stellar LF maps # where we want to pass only the relevant LF and the bins that go with it. for key in self.slicePoints: if len(np.shape(self.slicePoints[key])) == 0: keyShape = 0 else: keyShape = np.shape(self.slicePoints[key])[0] if (keyShape == self.nslice): slicePoint[key] = self.slicePoints[key][islice] else: slicePoint[key] = self.slicePoints[key] return {'idxs': indices, 'slicePoint': slicePoint}
def _sliceSimData(islice): """Return indexes for relevant opsim data at slicepoint (slicepoint=lonCol/latCol value .. usually ra/dec).""" # Build dict for slicePoint info slicePoint = {} if self.useCamera: indices = self.sliceLookup[islice] slicePoint['chipNames'] = self.chipNames[islice] else: sx, sy, sz = simsUtils._xyz_from_ra_dec( self.slicePoints['ra'][islice], self.slicePoints['dec'][islice]) # Anything within half the side length is good no matter what rotation angle # the camera is at indices = self.opsimtree.query_ball_point((sx, sy, sz), self.side_radius) # Now the larger radius. Need to make it an array for easy subscripting initial_indices = np.array(self.opsimtree.query_ball_point( (sx, sy, sz), self.rad), dtype=int) # remove the indices we already know about initial_indices = initial_indices[np.in1d(initial_indices, indices, invert=True)] if self.latLonDeg: lat = np.radians(simData[self.latCol][initial_indices]) lon = np.radians(simData[self.lonCol][initial_indices]) cos_rot = np.cos( np.radians( simData[self.rotSkyPosColName][initial_indices])) sin_rot = np.cos( np.radians( simData[self.rotSkyPosColName][initial_indices])) else: lat = simData[self.latCol][initial_indices] lon = simData[self.lonCol][initial_indices] cos_rot = np.cos( simData[self.rotSkyPosColName][initial_indices]) sin_rot = np.sin( simData[self.rotSkyPosColName][initial_indices]) # loop over the observations that might be overlapping the healpix, check each for i, ind in enumerate(initial_indices): # Rotate the camera x_rotated = self.corners_x * cos_rot[ i] - self.corners_y * sin_rot[i] y_rotated = self.corners_x * sin_rot[ i] + self.corners_y * cos_rot[i] # How far is the pointing center from the healpix center xshift, yshift = gnomonic_project_toxy( lon[i], lat[i], self.slicePoints['ra'][islice], self.slicePoints['dec'][islice]) x_rotated += xshift y_rotated += yshift # Use matplotlib to make a polygon bbPath = mplPath.Path( np.array([[x_rotated[0], y_rotated[0]], [x_rotated[1], y_rotated[1]], [x_rotated[2], y_rotated[2]], [x_rotated[3], y_rotated[3]], [x_rotated[0], y_rotated[0]]])) # Check if the slicepoint is inside the image corners and append to list if bbPath.contains_point((0., 0.)): indices.append(ind) # Loop through all the slicePoint keys. If the first dimension of slicepoint[key] has # the same shape as the slicer, assume it is information per slicepoint. # Otherwise, pass the whole slicePoint[key] information. Useful for stellar LF maps # where we want to pass only the relevant LF and the bins that go with it. for key in self.slicePoints: if len(np.shape(self.slicePoints[key])) == 0: keyShape = 0 else: keyShape = np.shape(self.slicePoints[key])[0] if (keyShape == self.nslice): slicePoint[key] = self.slicePoints[key][islice] else: slicePoint[key] = self.slicePoints[key] return {'idxs': indices, 'slicePoint': slicePoint}