23__all__ = [
"RingsSkyMapConfig",
"RingsSkyMap"]
31from .cachingSkyMap
import CachingSkyMap
32from .tractInfo
import ExplicitTractInfo
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 Rings are numbered
in the rings
from south to north. The south pole cap
is
52 ``tract=0``, then the tract at ``raStart``
in the southernmost ring
is
53 ``tract=1``. Numbering continues (
in the positive RA direction) around that
54 ring
and then continues
in the same fashion
with the next ring north,
and
55 so on until all reaching the north pole cap, which
is
56 ``tract=len(skymap) - 1``.
58 However, ``version=0`` had a bug
in the numbering of the tracts: the first
59 and last tracts
in the first (southernmost) ring were identical,
and the
60 first tract
in the last (northernmost) ring was missing. When using
61 ``version=0``, these tracts remain missing
in order to preserve the
66 config : `lsst.skymap.RingsSkyMapConfig`
67 The configuration
for this SkyMap.
68 version : `int`, optional
69 Software version of this
class, to retain compatibility
with old
70 verisons. ``version=0`` covers the period
from first implementation
71 until DM-14809, at which point bugs were identified
in the numbering
72 of tracts (affecting only tracts at RA=0). ``version=1`` uses the
73 post-DM-14809 tract numbering.
75 ConfigClass = RingsSkyMapConfig
79 assert version
in (0, 1),
"Unrecognised version: %s" % (version,)
85 for i
in range(config.numRings):
86 startDec = self.
_ringSize*(i + 0.5) - 0.5*math.pi
88 dec =
min(math.fabs(startDec), math.fabs(stopDec))
91 super(RingsSkyMap, self).
__init__(numTracts, config, version)
95 """Calculate ring indices given a numerical index of a tract.
97 The ring indices are the ring number and the tract number within
100 The ring number
is -1
for the south polar cap
and increases to the
101 north. The north polar cap has ring number = numRings. The tract
102 number
is zero
for either of the polar caps.
109 raise IndexError(
"Tract index %d is out of range [0, %d]" % (index, len(self) - 1))
123 return ring, tractNum
126 """Generate TractInfo for the specified tract index."""
129 ra, dec = 0, -0.5*math.pi
131 ra, dec = 0, 0.5*math.pi
133 dec = self.
_ringSize*(ringNum + 1) - 0.5*math.pi
134 ra = ((2*math.pi*tractNum/self.
_ringNums[ringNum])*geom.radians
144 """Calculate ring number from Declination.
154 Ring number: -1 for the south polar cap,
and increasing to the
155 north, ending
with ``numRings``
for the north polar cap.
157 firstRingStart = self._ringSize*0.5 - 0.5*math.pi
158 if dec < firstRingStart:
161 elif dec > firstRingStart*-1:
164 return int((dec.asRadians() - firstRingStart)/self.
_ringSize)
167 """Calculate tract number from the Right Ascension.
174 Ring number (from ``_decToRingNum``).
179 Tract number within the ring (starts at 0
for the tract at
185 tractNum = int((ra - self.
_raStart).wrap().asRadians()
186 / (2*math.pi/self.
_ringNums[ringNum]) + 0.5)
187 return 0
if tractNum == self.
_ringNums[ringNum]
else tractNum
204 index = sum(self.
_ringNums[:ringNum], tractNum + 1)
210 _dec = np.deg2rad(dec)
212 _ra = np.atleast_1d(ra)
213 _dec = np.atleast_1d(dec)
216 indexes = np.full(_ra.size, -1, dtype=np.int32)
219 firstRingStart = self.
_ringSize*0.5 - 0.5*np.pi
220 ringNums = np.zeros(len(_dec), dtype=np.int32)
222 ringNums[_dec < firstRingStart] = -1
223 ringNums[_dec > -1*firstRingStart] = self.
configconfig.numRings
225 mid = (_dec >= firstRingStart) & (_dec <= -1*firstRingStart)
226 ringNums[mid] = ((_dec[mid] - firstRingStart)/self.
_ringSize).astype(np.int32)
228 indexes[ringNums == -1] = 0
233 inRange, = np.where(indexes < 0)
237 _ringCumulative = np.cumsum(np.insert(_ringNumArray, 0, 0))
239 deltaWrap = (_ra[inRange] - self.
_raStart.asRadians()) % (2.*np.pi)
240 tractNum = (deltaWrap/(2.*np.pi/_ringNumArray[ringNums[inRange]]) + 0.5).astype(np.int32)
242 tractNum[tractNum == _ringNumArray[ringNums[inRange]]] = 0
247 offByOne, = np.where((tractNum == 0)
248 & (ringNums[inRange] != 0))
249 ringNums[inRange[offByOne]] += 1
251 indexes[inRange] = _ringCumulative[ringNums[inRange]] + tractNum + 1
256 """Find all tracts which include the specified coord.
261 ICRS sky coordinate to search for.
265 tractList : `list` of `TractInfo`
266 The tracts which include the specified coord.
273 for r
in [ringNum - 1, ringNum, ringNum + 1]:
279 for t
in [tractNum - 1, tractNum, tractNum + 1]:
292 index = sum(self.
_ringNums[:r + extra], t + 1)
294 if tract.contains(coord):
295 tractList.append(tract)
299 for entry
in [0, len(self)-1]:
301 if tract.contains(coord):
302 tractList.append(tract)
308 for coord
in coordList:
310 patchList = tractInfo.findPatchList(coordList)
311 if patchList
and not (tractInfo, patchList)
in retList:
312 retList.append((tractInfo, patchList))
316 """Add subclass-specific state or configuration options to the SHA1."""
A class representing an angle.
Point in an unspecified spherical coordinate system.
generateTract(self, index)
findAllTracts(self, coord)
__init__(self, config, version=1)
findTractPatchList(self, coordList)
_raToTractNum(self, ra, ringNum)
getRingIndices(self, index)
findTractIdArray(self, ra, dec, degrees=False)
daf::base::PropertyList * list