LSST Applications g034a557a3c+dd8dd8f11d,g0afe43252f+b86e4b8053,g11f7dcd041+017865fdd3,g1cd03abf6b+8446defddb,g1ce3e0751c+f991eae79d,g28da252d5a+ca8a1a9fb3,g2bbee38e9b+b6588ad223,g2bc492864f+b6588ad223,g2cdde0e794+8523d0dbb4,g347aa1857d+b6588ad223,g35bb328faa+b86e4b8053,g3a166c0a6a+b6588ad223,g461a3dce89+b86e4b8053,g52b1c1532d+b86e4b8053,g7f3b0d46df+ad13c1b82d,g80478fca09+f29c5d6c70,g858d7b2824+293f439f82,g8cd86fa7b1+af721d2595,g965a9036f2+293f439f82,g979bb04a14+51ed57f74c,g9ddcbc5298+f24b38b85a,gae0086650b+b86e4b8053,gbb886bcc26+b97e247655,gc28159a63d+b6588ad223,gc30aee3386+a2f0f6cab9,gcaf7e4fdec+293f439f82,gcd45df26be+293f439f82,gcdd4ae20e8+70b5def7e6,gce08ada175+da9c58a417,gcf0d15dbbd+70b5def7e6,gdaeeff99f8+006e14e809,gdbce86181e+6a170ce272,ge3d4d395c2+224150c836,ge5f7162a3a+bb2241c923,ge6cb8fbbf7+d119aed356,ge79ae78c31+b6588ad223,gf048a9a2f4+40ffced2b8,gf0baf85859+b4cca3d10f,w.2024.30
LSST Data Management Base Package
Loading...
Searching...
No Matches
Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | Static Protected Attributes | List of all members
lsst.skymap.ringsSkyMap.RingsSkyMap Class Reference
Inheritance diagram for lsst.skymap.ringsSkyMap.RingsSkyMap:
lsst.skymap.cachingSkyMap.CachingSkyMap lsst.skymap.baseSkyMap.BaseSkyMap

Public Member Functions

 __init__ (self, config, version=1)
 
 getRingIndices (self, index)
 
 generateTract (self, index)
 
 getRaDecRange (self, index)
 
 findTract (self, coord)
 
 findTractIdArray (self, ra, dec, degrees=False)
 
 findAllTracts (self, coord)
 
 findTractPatchList (self, coordList)
 
 updateSha1 (self, sha1)
 

Static Public Attributes

 ConfigClass = RingsSkyMapConfig
 

Protected Member Functions

 _decToRingNum (self, dec)
 
 _raToTractNum (self, ra, ringNum)
 

Protected Attributes

 _ringSize
 
 _ringNums
 
 _raStart
 
 _version
 
 _tractBuilder
 

Static Protected Attributes

tuple _version = (1, 0)
 

Detailed Description

Rings sky map pixelization.

We divide the sphere into N rings of Declination, plus the two polar
caps, which sets the size of the individual tracts.  The rings are
divided in RA into an integral number of tracts of this size; this
division is made at the Declination closest to zero so as to ensure
full overlap.

Rings are numbered in the rings from south to north. The south pole cap is
``tract=0``, then the tract at ``raStart`` in the southernmost ring is
``tract=1``. Numbering continues (in the positive RA direction) around that
ring and then continues in the same fashion with the next ring north, and
so on until all reaching the north pole cap, which is
``tract=len(skymap) - 1``.

However, ``version=0`` had a bug in the numbering of the tracts: the first
and last tracts in the first (southernmost) ring were identical, and the
first tract in the last (northernmost) ring was missing. When using
``version=0``, these tracts remain missing in order to preserve the
numbering scheme.

Parameters
----------
config : `lsst.skymap.RingsSkyMapConfig`
    The configuration for this SkyMap.
version : `int`, optional
    Software version of this class, to retain compatibility with old
    verisons. ``version=0`` covers the period from first implementation
    until DM-14809, at which point bugs were identified in the numbering
    of tracts (affecting only tracts at RA=0). ``version=1`` uses the
    post-DM-14809 tract numbering.

Definition at line 43 of file ringsSkyMap.py.

Constructor & Destructor Documentation

◆ __init__()

lsst.skymap.ringsSkyMap.RingsSkyMap.__init__ ( self,
config,
version = 1 )

Reimplemented from lsst.skymap.cachingSkyMap.CachingSkyMap.

Definition at line 79 of file ringsSkyMap.py.

79 def __init__(self, config, version=1):
80 assert version in (0, 1), "Unrecognised version: %s" % (version,)
81 # We count rings from south to north
82 # Note: pole caps together count for one additional ring when
83 # calculating the ring size.
84 self._ringSize = math.pi / (config.numRings + 1) # Size of a ring in Declination (radians)
85 self._ringNums = [] # Number of tracts for each ring
86 for i in range(config.numRings):
87 startDec = self._ringSize*(i + 0.5) - 0.5*math.pi
88 stopDec = startDec + self._ringSize
89 dec = min(math.fabs(startDec), math.fabs(stopDec)) # Declination for determining division in RA
90 self._ringNums.append(int(2*math.pi*math.cos(dec)/self._ringSize) + 1)
91 numTracts = sum(self._ringNums) + 2
92 super(RingsSkyMap, self).__init__(numTracts, config, version)
93 self._raStart = self.config.raStart*geom.degrees
94
int min

Member Function Documentation

◆ _decToRingNum()

lsst.skymap.ringsSkyMap.RingsSkyMap._decToRingNum ( self,
dec )
protected
Calculate ring number from Declination.

Parameters
----------
dec : `lsst.geom.Angle`
    Declination.

Returns
-------
ringNum : `int`
    Ring number: -1 for the south polar cap, and increasing to the
    north, ending with ``numRings`` for the north polar cap.

Definition at line 198 of file ringsSkyMap.py.

198 def _decToRingNum(self, dec):
199 """Calculate ring number from Declination.
200
201 Parameters
202 ----------
203 dec : `lsst.geom.Angle`
204 Declination.
205
206 Returns
207 -------
208 ringNum : `int`
209 Ring number: -1 for the south polar cap, and increasing to the
210 north, ending with ``numRings`` for the north polar cap.
211 """
212 firstRingStart = self._ringSize*0.5 - 0.5*math.pi
213 if dec < firstRingStart:
214 # Southern cap
215 return -1
216 elif dec > firstRingStart*-1:
217 # Northern cap
218 return self.config.numRings
219 return int((dec.asRadians() - firstRingStart)/self._ringSize)
220

◆ _raToTractNum()

lsst.skymap.ringsSkyMap.RingsSkyMap._raToTractNum ( self,
ra,
ringNum )
protected
Calculate tract number from the Right Ascension.

Parameters
----------
ra : `lsst.geom.Angle`
    Right Ascension.
ringNum : `int`
    Ring number (from ``_decToRingNum``).

Returns
-------
tractNum : `int`
    Tract number within the ring (starts at 0 for the tract at
    ``raStart``).

Definition at line 221 of file ringsSkyMap.py.

221 def _raToTractNum(self, ra, ringNum):
222 """Calculate tract number from the Right Ascension.
223
224 Parameters
225 ----------
226 ra : `lsst.geom.Angle`
227 Right Ascension.
228 ringNum : `int`
229 Ring number (from ``_decToRingNum``).
230
231 Returns
232 -------
233 tractNum : `int`
234 Tract number within the ring (starts at 0 for the tract at
235 ``raStart``).
236 """
237 if ringNum in (-1, self.config.numRings):
238 return 0
239 assert ringNum in range(self.config.numRings)
240 tractNum = int((ra - self._raStart).wrap().asRadians()
241 / (2*math.pi/self._ringNums[ringNum]) + 0.5)
242 return 0 if tractNum == self._ringNums[ringNum] else tractNum # Allow wraparound
243

◆ findAllTracts()

lsst.skymap.ringsSkyMap.RingsSkyMap.findAllTracts ( self,
coord )
Find all tracts which include the specified coord.

Parameters
----------
coord : `lsst.geom.SpherePoint`
    ICRS sky coordinate to search for.

Returns
-------
tractList : `list` of `TractInfo`
    The tracts which include the specified coord.

Definition at line 310 of file ringsSkyMap.py.

310 def findAllTracts(self, coord):
311 """Find all tracts which include the specified coord.
312
313 Parameters
314 ----------
315 coord : `lsst.geom.SpherePoint`
316 ICRS sky coordinate to search for.
317
318 Returns
319 -------
320 tractList : `list` of `TractInfo`
321 The tracts which include the specified coord.
322 """
323 ringNum = self._decToRingNum(coord.getLatitude())
324
325 tractList = list()
326 # ringNum denotes the closest ring to the specified coord
327 # I will check adjacent rings which may include the specified coord
328 for r in [ringNum - 1, ringNum, ringNum + 1]:
329 if r < 0 or r >= self.config.numRings:
330 # Poles will be checked explicitly outside this loop
331 continue
332 tractNum = self._raToTractNum(coord.getLongitude(), r)
333 # Adjacent tracts will also be checked.
334 for t in [tractNum - 1, tractNum, tractNum + 1]:
335 # Wrap over raStart
336 if t < 0:
337 t = t + self._ringNums[r]
338 elif t > self._ringNums[r] - 1:
339 t = t - self._ringNums[r]
340
341 extra = 0
342 if self._version == 0 and t == 0 and r != 0:
343 # Account for off-by-one error in getRingIndices
344 # Note that this means that tract 1 gets duplicated.
345 extra = 1
346
347 index = sum(self._ringNums[:r + extra], t + 1) # Allow 1 for south pole
348 tract = self[index]
349 if tract.contains(coord):
350 tractList.append(tract)
351
352 # Always check tracts at poles
353 # Southern cap is 0, Northern cap is the last entry in self
354 for entry in [0, len(self)-1]:
355 tract = self[entry]
356 if tract.contains(coord):
357 tractList.append(tract)
358
359 return tractList
360

◆ findTract()

lsst.skymap.ringsSkyMap.RingsSkyMap.findTract ( self,
coord )
Find the tract whose center is nearest the specified coord.

Parameters
----------
coord : `lsst.geom.SpherePoint`
    ICRS sky coordinate to search for.

Returns
-------
result : `TractInfo`
    TractInfo of tract whose center is nearest the specified coord.

Notes
-----
- If coord is equidistant between multiple sky tract centers then one
  is arbitrarily chosen.

- The default implementation is not very efficient; subclasses may wish
  to override.

.. warning::

   If tracts do not cover the whole sky then the returned tract may not
   include the coord.

Reimplemented from lsst.skymap.baseSkyMap.BaseSkyMap.

Definition at line 244 of file ringsSkyMap.py.

244 def findTract(self, coord):
245 ringNum = self._decToRingNum(coord.getLatitude())
246 if ringNum == -1:
247 # Southern cap
248 return self[0]
249 if ringNum == self.config.numRings:
250 # Northern cap
251 return self[self._numTracts - 1]
252 tractNum = self._raToTractNum(coord.getLongitude(), ringNum)
253
254 if self._version == 0 and tractNum == 0 and ringNum != 0:
255 # Account for off-by-one error in getRingIndices
256 # Note that this means that tract 1 gets duplicated.
257 ringNum += 1
258
259 index = sum(self._ringNums[:ringNum], tractNum + 1) # Allow 1 for south pole
260 return self[index]
261

◆ findTractIdArray()

lsst.skymap.ringsSkyMap.RingsSkyMap.findTractIdArray ( self,
ra,
dec,
degrees = False )
Find array of tract IDs with vectorized operations (where
supported).

If a given sky map does not support vectorized operations, then a loop
over findTract will be called.

Parameters
----------
ra : `numpy.ndarray`
    Array of Right Ascension.  Units are radians unless
    degrees=True.
dec : `numpy.ndarray`
    Array of Declination.  Units are radians unless
    degrees=True.
degrees : `bool`, optional
    Input ra, dec arrays are degrees if `True`.

Returns
-------
tractId : `numpy.ndarray`
    Array of tract IDs

Notes
-----
- If coord is equidistant between multiple sky tract centers then one
  is arbitrarily chosen.

.. warning::

   If tracts do not cover the whole sky then the returned tract may not
   include the given ra/dec.

Reimplemented from lsst.skymap.baseSkyMap.BaseSkyMap.

Definition at line 262 of file ringsSkyMap.py.

262 def findTractIdArray(self, ra, dec, degrees=False):
263 if degrees:
264 _ra = np.deg2rad(ra)
265 _dec = np.deg2rad(dec)
266 else:
267 _ra = np.atleast_1d(ra)
268 _dec = np.atleast_1d(dec)
269
270 # Set default to -1 to distinguish from polar tracts
271 indexes = np.full(_ra.size, -1, dtype=np.int32)
272
273 # Do the dec search
274 firstRingStart = self._ringSize*0.5 - 0.5*np.pi
275 ringNums = np.zeros(len(_dec), dtype=np.int32)
276
277 ringNums[_dec < firstRingStart] = -1
278 ringNums[_dec > -1*firstRingStart] = self.config.numRings
279
280 mid = (_dec >= firstRingStart) & (_dec <= -1*firstRingStart)
281 ringNums[mid] = ((_dec[mid] - firstRingStart)/self._ringSize).astype(np.int32)
282
283 indexes[ringNums == -1] = 0
284 indexes[ringNums == self.config.numRings] = self._numTracts - 1
285
286 # We now do the full lookup for all non-polar tracts that have not
287 # been set.
288 inRange, = np.where(indexes < 0)
289
290 # Do the ra search
291 _ringNumArray = np.array(self._ringNums)
292 _ringCumulative = np.cumsum(np.insert(_ringNumArray, 0, 0))
293
294 deltaWrap = (_ra[inRange] - self._raStart.asRadians()) % (2.*np.pi)
295 tractNum = (deltaWrap/(2.*np.pi/_ringNumArray[ringNums[inRange]]) + 0.5).astype(np.int32)
296 # Allow wraparound
297 tractNum[tractNum == _ringNumArray[ringNums[inRange]]] = 0
298
299 if self._version == 0:
300 # Account for off-by-one error in getRingIndices
301 # Note that this means tract 1 gets duplicated
302 offByOne, = np.where((tractNum == 0)
303 & (ringNums[inRange] != 0))
304 ringNums[inRange[offByOne]] += 1
305
306 indexes[inRange] = _ringCumulative[ringNums[inRange]] + tractNum + 1
307
308 return indexes
309

◆ findTractPatchList()

lsst.skymap.ringsSkyMap.RingsSkyMap.findTractPatchList ( self,
coordList )
Find tracts and patches that overlap a region.

Parameters
----------
coordList : `list` of `lsst.geom.SpherePoint`
    List of ICRS sky coordinates to search for.

Returns
-------
reList : `list` of (`TractInfo`, `list` of `PatchInfo`)
    For tracts and patches that contain, or may contain, the specified
    region. The list will be empty if there is no overlap.

Notes
-----
.. warning::

    This uses a naive algorithm that may find some tracts and patches
    that do not overlap the region (especially if the region is not a
    rectangle aligned along patch x, y).

Reimplemented from lsst.skymap.baseSkyMap.BaseSkyMap.

Definition at line 361 of file ringsSkyMap.py.

361 def findTractPatchList(self, coordList):
362 retList = []
363 for coord in coordList:
364 for tractInfo in self.findAllTracts(coord):
365 patchList = tractInfo.findPatchList(coordList)
366 if patchList and not (tractInfo, patchList) in retList:
367 retList.append((tractInfo, patchList))
368 return retList
369

◆ generateTract()

lsst.skymap.ringsSkyMap.RingsSkyMap.generateTract ( self,
index )
Generate TractInfo for the specified tract index.

Reimplemented from lsst.skymap.cachingSkyMap.CachingSkyMap.

Definition at line 126 of file ringsSkyMap.py.

126 def generateTract(self, index):
127 """Generate TractInfo for the specified tract index."""
128 ringNum, tractNum = self.getRingIndices(index)
129 if ringNum == -1: # South polar cap
130 ra, dec = 0, -0.5*math.pi
131 elif ringNum == self.config.numRings: # North polar cap
132 ra, dec = 0, 0.5*math.pi
133 else:
134 dec = self._ringSize*(ringNum + 1) - 0.5*math.pi
135 ra = ((2*math.pi*tractNum/self._ringNums[ringNum])*geom.radians
136 + self._raStart).wrap().asRadians()
137
138 center = geom.SpherePoint(ra, dec, geom.radians)
139 wcs = self._wcsFactory.makeWcs(crPixPos=geom.Point2D(0, 0), crValCoord=center)
140
141 raMin, raMax, decMin, decMax = self.getRaDecRange(index)
142
143 innerBoxCorners = [
144 sphgeom.LonLat(lon=sphgeom.NormalizedAngle(raMin), lat=sphgeom.Angle(decMin)),
145 sphgeom.LonLat(lon=sphgeom.NormalizedAngle(raMax), lat=sphgeom.Angle(decMax)),
146 ]
147
148 return ExplicitTractInfo(
149 index,
150 self._tractBuilder,
151 center,
152 0.5*self._ringSize*geom.radians,
153 self.config.tractOverlap*geom.degrees,
154 wcs,
155 innerBoxCorners=innerBoxCorners,
156 )
157
Point in an unspecified spherical coordinate system.
Definition SpherePoint.h:57

◆ getRaDecRange()

lsst.skymap.ringsSkyMap.RingsSkyMap.getRaDecRange ( self,
index )
Get the ra and dec ranges for the inner region of a
specified tract index.

Parameters
----------
index : `int`
    Tract index number.

Returns
-------
raMin, raMax, decMin, decMax : `lsst.geom.Angle`
    RA/Dec boundaries of the inner region.

Definition at line 158 of file ringsSkyMap.py.

158 def getRaDecRange(self, index):
159 """Get the ra and dec ranges for the inner region of a
160 specified tract index.
161
162 Parameters
163 ----------
164 index : `int`
165 Tract index number.
166
167 Returns
168 -------
169 raMin, raMax, decMin, decMax : `lsst.geom.Angle`
170 RA/Dec boundaries of the inner region.
171 """
172 ringNum, tractNum = self.getRingIndices(index)
173
174 if ringNum == -1:
175 # South polar cap.
176 decMin = (-np.pi/2.)*geom.radians
177 decMax = (-np.pi/2. + (ringNum + 1.5)*self._ringSize)*geom.radians
178 raMin = 0.0*geom.radians
179 raMax = 2.*np.pi*geom.radians
180 elif ringNum == self.config.numRings:
181 # North polar cap.
182 decMin = (-np.pi/2. + (ringNum + 0.5)*self._ringSize)*geom.radians
183 decMax = (np.pi/2.)*geom.radians
184 raMin = 0.0*geom.radians
185 raMax = 2.*np.pi*geom.radians
186 else:
187 decMin = (-np.pi/2. + (ringNum + 0.5)*self._ringSize)*geom.radians
188 decMax = (-np.pi/2. + (ringNum + 1.5)*self._ringSize)*geom.radians
189
190 deltaStart = ((tractNum - 0.5)*2.*np.pi/self._ringNums[ringNum])*geom.radians
191 deltaStop = ((tractNum + 0.5)*2.*np.pi/self._ringNums[ringNum])*geom.radians
192
193 raMin = (self._raStart + deltaStart).wrap()
194 raMax = (self._raStart + deltaStop).wrap()
195
196 return raMin, raMax, decMin, decMax
197

◆ getRingIndices()

lsst.skymap.ringsSkyMap.RingsSkyMap.getRingIndices ( self,
index )
Calculate ring indices given a numerical index of a tract.

The ring indices are the ring number and the tract number within
the ring.

The ring number is -1 for the south polar cap and increases to the
north.  The north polar cap has ring number = numRings.  The tract
number is zero for either of the polar caps.

Definition at line 95 of file ringsSkyMap.py.

95 def getRingIndices(self, index):
96 """Calculate ring indices given a numerical index of a tract.
97
98 The ring indices are the ring number and the tract number within
99 the ring.
100
101 The ring number is -1 for the south polar cap and increases to the
102 north. The north polar cap has ring number = numRings. The tract
103 number is zero for either of the polar caps.
104 """
105 if index == 0: # South polar cap
106 return -1, 0
107 if index == self._numTracts - 1: # North polar cap
108 return self.config.numRings, 0
109 if index < 0 or index >= self._numTracts:
110 raise IndexError("Tract index %d is out of range [0, %d]" % (index, len(self) - 1))
111 ring = 0 # Ring number
112 tractNum = index - 1 # Tract number within ring
113 if self._version == 0:
114 # Maintain the off-by-one bug in version=0 (DM-14809).
115 # This means that the first tract in the first ring is duplicated
116 # and the first tract in the last ring is missing.
117 while ring < self.config.numRings and tractNum > self._ringNums[ring]:
118 tractNum -= self._ringNums[ring]
119 ring += 1
120 else:
121 while ring < self.config.numRings and tractNum >= self._ringNums[ring]:
122 tractNum -= self._ringNums[ring]
123 ring += 1
124 return ring, tractNum
125

◆ updateSha1()

lsst.skymap.ringsSkyMap.RingsSkyMap.updateSha1 ( self,
sha1 )
Add subclass-specific state or configuration options to the SHA1.

Reimplemented from lsst.skymap.baseSkyMap.BaseSkyMap.

Definition at line 370 of file ringsSkyMap.py.

370 def updateSha1(self, sha1):
371 """Add subclass-specific state or configuration options to the SHA1."""
372 sha1.update(struct.pack("<id", self.config.numRings, self.config.raStart))

Member Data Documentation

◆ _raStart

lsst.skymap.ringsSkyMap.RingsSkyMap._raStart
protected

Definition at line 93 of file ringsSkyMap.py.

◆ _ringNums

lsst.skymap.ringsSkyMap.RingsSkyMap._ringNums
protected

Definition at line 85 of file ringsSkyMap.py.

◆ _ringSize

lsst.skymap.ringsSkyMap.RingsSkyMap._ringSize
protected

Definition at line 84 of file ringsSkyMap.py.

◆ _tractBuilder

lsst.skymap.ringsSkyMap.RingsSkyMap._tractBuilder
protected

Definition at line 150 of file ringsSkyMap.py.

◆ _version [1/2]

tuple lsst.skymap.ringsSkyMap.RingsSkyMap._version = (1, 0)
staticprotected

Definition at line 77 of file ringsSkyMap.py.

◆ _version [2/2]

lsst.skymap.ringsSkyMap.RingsSkyMap._version
protected

Definition at line 113 of file ringsSkyMap.py.

◆ ConfigClass

lsst.skymap.ringsSkyMap.RingsSkyMap.ConfigClass = RingsSkyMapConfig
static

Definition at line 76 of file ringsSkyMap.py.


The documentation for this class was generated from the following file: