1 from builtins
import range
26 from lsst.pex.config
import Field
27 from lsst.afw.coord
import IcrsCoord
28 import lsst.afw.geom
as afwGeom
29 from .cachingSkyMap
import CachingSkyMap
30 from .tractInfo
import ExplicitTractInfo
32 __all__ = [
"RingsSkyMap"]
36 """Configuration for the RingsSkyMap"""
37 numRings = Field(dtype=int, doc=
"Number of rings", check=
lambda x: x > 0)
38 raStart = Field(dtype=float, default=0.0, doc=
"Starting center RA for each ring (degrees)",
39 check=
lambda x: x >= 0.0
and x < 360.0)
43 """Rings sky map pixelization.
45 We divide the sphere into N rings of Declination, plus the two polar
46 caps, which sets the size of the individual tracts. The rings are
47 divided in RA into an integral number of tracts of this size; this
48 division is made at the Declination closest to zero so as to ensure
51 ConfigClass = RingsSkyMapConfig
57 @param[in] config: an instance of self.ConfigClass; if None the default config is used
58 @param[in] version: software version of this class, to retain compatibility with old instances
62 self.
_ringSize = math.pi / (config.numRings + 1)
64 for i
in range(config.numRings):
65 startDec = self.
_ringSize*(i + 0.5) - 0.5*math.pi
67 dec = min(math.fabs(startDec), math.fabs(stopDec))
68 self._ringNums.append(int(2*math.pi*math.cos(dec)/self.
_ringSize) + 1)
70 super(RingsSkyMap, self).
__init__(numTracts, config, version)
73 """Calculate ring indices given a numerical index of a tract
75 The ring indices are the ring number and the tract number within
78 The ring number is -1 for the south polar cap and increases to the
79 north. The north polar cap has ring number = numRings. The tract
80 number is zero for either of the polar caps.
84 if index == self._numTracts - 1:
85 return self.config.numRings, 0
88 while ring < self.config.numRings
and index > self.
_ringNums[ring]:
94 """Generate the TractInfo for this index"""
97 ra, dec = 0, -0.5*math.pi
98 elif ringNum == self.config.numRings:
99 ra, dec = 0, 0.5*math.pi
101 dec = self.
_ringSize*(ringNum + 1) - 0.5*math.pi
102 ra = math.fmod(self.config.raStart + 2*math.pi*tractNum/self.
_ringNums[ringNum], 2*math.pi)
104 center = IcrsCoord(ra*afwGeom.radians, dec*afwGeom.radians)
105 wcs = self._wcsFactory.makeWcs(crPixPos=afwGeom.Point2D(0, 0), crValCoord=center)
106 return ExplicitTractInfo(index, self.config.patchInnerDimensions, self.config.patchBorder, center,
107 0.5*self.
_ringSize*afwGeom.radians, self.config.tractOverlap*afwGeom.degrees,
111 """Find the tract whose center is nearest the specified coord.
113 @param[in] coord: sky coordinate (afwCoord.Coord)
114 @return TractInfo of tract whose center is nearest the specified coord
117 - if tracts do not cover the whole sky then the returned tract may not include the coord
120 - This routine will be more efficient if coord is ICRS.
121 - If coord is equidistant between multiple sky tract centers then one is arbitrarily chosen.
122 - The default implementation is not very efficient; subclasses may wish to override.
124 icrsCoord = coord.toIcrs()
125 ra = icrsCoord.getLongitude().asRadians()
126 dec = icrsCoord.getLatitude().asRadians()
128 firstRingStart = self.
_ringSize*0.5 - 0.5*math.pi
129 if dec < firstRingStart:
132 elif dec > firstRingStart*-1:
136 ringNum = int((dec - firstRingStart)/self.
_ringSize)
137 tractNum = int(math.fmod(ra - self.config.raStart, 2*math.pi) /
138 (2*math.pi/self.
_ringNums[ringNum]) + 0.5)
141 for i
in range(ringNum):
147 """Find all tracts which include the specified coord.
149 @param[in] coord: sky coordinate (afwCoord.Coord)
150 @return List of TractInfo of tracts which include the specified coord
153 - This routine will be more efficient if coord is ICRS.
155 icrsCoord = coord.toIcrs()
156 ra = icrsCoord.getLongitude().asRadians()
157 dec = icrsCoord.getLatitude().asRadians()
159 firstRingStart = self.
_ringSize*0.5 - 0.5*math.pi
161 if dec < firstRingStart:
164 elif dec > firstRingStart*-1:
168 ringNum = int((dec - firstRingStart)/self.
_ringSize)
173 for r
in [ringNum - 1, ringNum, ringNum + 1]:
174 if r < 0
or r > self.config.numRings - 1:
176 tractNum = int(math.fmod(ra - self.config.raStart, 2*math.pi) /
179 for t
in [tractNum - 1, tractNum, tractNum + 1]:
191 if tract.contains(icrsCoord):
192 tractList.append(tract)
196 for entry
in [0, len(self)-1]:
198 if tract.contains(icrsCoord):
199 tractList.append(tract)
204 """Find tracts and patches that overlap a region
206 @param[in] coordList: list of sky coordinates (afwCoord.Coord)
207 @return list of (TractInfo, list of PatchInfo) for tracts and patches that contain,
208 or may contain, the specified region. The list will be empty if there is no overlap.
210 @warning this uses a naive algorithm that may find some tracts and patches that do not overlap
211 the region (especially if the region is not a rectangle aligned along patch x,y).
214 for coord
in coordList:
216 patchList = tractInfo.findPatchList(coordList)
217 if patchList
and not (tractInfo, patchList)
in retList:
218 retList.append((tractInfo, patchList))