Coverage for python/lsst/sims/maf/slicers/healpixComCamSlicer.py : 14%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import numpy as np
2import healpy as hp
3from .healpixSlicer import HealpixSlicer
4import warnings
5from functools import wraps
6import lsst.sims.utils as simsUtils
7import matplotlib.path as mplPath
8from lsst.sims.maf.utils.mafUtils import gnomonic_project_toxy
11__all__ = ['HealpixComCamSlicer']
14# The names of the chips in the central raft, aka, ComCam
15center_raft_chips = ['R:2,2 S:0,0', 'R:2,2 S:0,1', 'R:2,2 S:0,2',
16 'R:2,2 S:1,0', 'R:2,2 S:1,1', 'R:2,2 S:1,2',
17 'R:2,2 S:2,0', 'R:2,2 S:2,1', 'R:2,2 S:2,2']
20class HealpixComCamSlicer(HealpixSlicer):
21 """Slicer that uses the ComCam footprint to decide if observations overlap a healpixel center
22 """
24 def __init__(self, nside=128, lonCol='fieldRA',
25 latCol='fieldDec', latLonDeg=True, verbose=True, badval=hp.UNSEEN,
26 useCache=True, leafsize=100,
27 useCamera=False, rotSkyPosColName='rotSkyPos',
28 mjdColName='observationStartMJD', chipNames=center_raft_chips, side_length=0.7):
29 """
30 Parameters
31 ----------
32 side_length : float (0.7)
33 How large is a side of the raft (degrees)
34 """
35 radius = side_length/2.*np.sqrt(2.)
36 super(HealpixComCamSlicer, self).__init__(nside=nside, lonCol=lonCol, latCol=latCol,
37 latLonDeg=latLonDeg,
38 verbose=verbose, badval=badval, useCache=useCache,
39 leafsize=leafsize, radius=radius, useCamera=useCamera,
40 rotSkyPosColName=rotSkyPosColName,
41 mjdColName=mjdColName, chipNames=chipNames)
42 self.side_length = np.radians(side_length)
43 self.corners_x = np.array([-self.side_length/2., -self.side_length/2., self.side_length/2.,
44 self.side_length/2.])
45 self.corners_y = np.array([self.side_length/2., -self.side_length/2., -self.side_length/2.,
46 self.side_length/2.])
47 # Need the rotation even if not using the camera
48 self.columnsNeeded.append(rotSkyPosColName)
49 self.columnsNeeded = list(set(self.columnsNeeded))
51 # The 3D search radius for things inside the raft
52 self.side_radius = simsUtils.xyz_angular_radius(side_length/2.)
54 def setupSlicer(self, simData, maps=None):
55 """Use simData[self.lonCol] and simData[self.latCol] (in radians) to set up KDTree.
57 Parameters
58 -----------
59 simData : numpy.recarray
60 The simulated data, including the location of each pointing.
61 maps : list of lsst.sims.maf.maps objects, optional
62 List of maps (such as dust extinction) that will run to build up additional metadata at each
63 slicePoint. This additional metadata is available to metrics via the slicePoint dictionary.
64 Default None.
65 """
66 if maps is not None:
67 if self.cacheSize != 0 and len(maps) > 0:
68 warnings.warn('Warning: Loading maps but cache on.'
69 'Should probably set useCache=False in slicer.')
70 self._runMaps(maps)
71 self._setRad(self.radius)
72 if self.useCamera:
73 self._setupLSSTCamera()
74 self._presliceFootprint(simData)
75 else:
76 if self.latLonDeg:
77 self._buildTree(np.radians(simData[self.lonCol]),
78 np.radians(simData[self.latCol]), self.leafsize)
79 else:
80 self._buildTree(simData[self.lonCol], simData[self.latCol], self.leafsize)
82 @wraps(self._sliceSimData)
83 def _sliceSimData(islice):
84 """Return indexes for relevant opsim data at slicepoint
85 (slicepoint=lonCol/latCol value .. usually ra/dec)."""
87 # Build dict for slicePoint info
88 slicePoint = {}
89 if self.useCamera:
90 indices = self.sliceLookup[islice]
91 slicePoint['chipNames'] = self.chipNames[islice]
92 else:
93 sx, sy, sz = simsUtils._xyz_from_ra_dec(self.slicePoints['ra'][islice],
94 self.slicePoints['dec'][islice])
95 # Anything within half the side length is good no matter what rotation angle
96 # the camera is at
97 indices = self.opsimtree.query_ball_point((sx, sy, sz), self.side_radius)
98 # Now the larger radius. Need to make it an array for easy subscripting
99 initial_indices = np.array(self.opsimtree.query_ball_point((sx, sy, sz), self.rad), dtype=int)
100 # remove the indices we already know about
101 initial_indices = initial_indices[np.in1d(initial_indices, indices, invert=True)]
103 if self.latLonDeg:
104 lat = np.radians(simData[self.latCol][initial_indices])
105 lon = np.radians(simData[self.lonCol][initial_indices])
106 cos_rot = np.cos(np.radians(simData[self.rotSkyPosColName][initial_indices]))
107 sin_rot = np.cos(np.radians(simData[self.rotSkyPosColName][initial_indices]))
108 else:
109 lat = simData[self.latCol][initial_indices]
110 lon = simData[self.lonCol][initial_indices]
111 cos_rot = np.cos(simData[self.rotSkyPosColName][initial_indices])
112 sin_rot = np.sin(simData[self.rotSkyPosColName][initial_indices])
113 # loop over the observations that might be overlapping the healpix, check each
114 for i, ind in enumerate(initial_indices):
115 # Rotate the camera
116 x_rotated = self.corners_x*cos_rot[i] - self.corners_y*sin_rot[i]
117 y_rotated = self.corners_x*sin_rot[i] + self.corners_y*cos_rot[i]
118 # How far is the pointing center from the healpix center
119 xshift, yshift = gnomonic_project_toxy(lon[i], lat[i], self.slicePoints['ra'][islice],
120 self.slicePoints['dec'][islice])
122 x_rotated += xshift
123 y_rotated += yshift
124 # Use matplotlib to make a polygon
125 bbPath = mplPath.Path(np.array([[x_rotated[0], y_rotated[0]],
126 [x_rotated[1], y_rotated[1]],
127 [x_rotated[2], y_rotated[2]],
128 [x_rotated[3], y_rotated[3]],
129 [x_rotated[0], y_rotated[0]]]))
130 # Check if the slicepoint is inside the image corners and append to list
131 if bbPath.contains_point((0., 0.)):
132 indices.append(ind)
134 # Loop through all the slicePoint keys. If the first dimension of slicepoint[key] has
135 # the same shape as the slicer, assume it is information per slicepoint.
136 # Otherwise, pass the whole slicePoint[key] information. Useful for stellar LF maps
137 # where we want to pass only the relevant LF and the bins that go with it.
139 for key in self.slicePoints:
140 if len(np.shape(self.slicePoints[key])) == 0:
141 keyShape = 0
142 else:
143 keyShape = np.shape(self.slicePoints[key])[0]
144 if (keyShape == self.nslice):
145 slicePoint[key] = self.slicePoints[key][islice]
146 else:
147 slicePoint[key] = self.slicePoints[key]
149 return {'idxs': indices, 'slicePoint': slicePoint}
150 setattr(self, '_sliceSimData', _sliceSimData)