LSSTApplications  10.0-2-g4f67435,11.0.rc2+1,11.0.rc2+12,11.0.rc2+3,11.0.rc2+4,11.0.rc2+5,11.0.rc2+6,11.0.rc2+7,11.0.rc2+8
LSSTDataManagementBasePackage
ringsSkyMap.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010, 2012 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 import math
24 
25 from lsst.pex.config import Field
26 from lsst.afw.coord import IcrsCoord
27 import lsst.afw.geom as afwGeom
28 from .cachingSkyMap import CachingSkyMap
29 from .tractInfo import ExplicitTractInfo
30 
31 __all__ = ["RingsSkyMap"]
32 
33 class RingsSkyMapConfig(CachingSkyMap.ConfigClass):
34  """Configuration for the RingsSkyMap"""
35  numRings = Field(dtype=int, doc="Number of rings", check=lambda x: x > 0)
36  raStart = Field(dtype=float, default=0.0, doc="Starting center RA for each ring (degrees)",
37  check=lambda x: x >= 0.0 and x < 360.0)
38 
39 
40 class RingsSkyMap(CachingSkyMap):
41  """Rings sky map pixelization.
42 
43  We divide the sphere into N rings of Declination, plus the two polar
44  caps, which sets the size of the individual tracts. The rings are
45  divided in RA into an integral number of tracts of this size; this
46  division is made at the Declination closest to zero so as to ensure
47  full overlap.
48  """
49  ConfigClass = RingsSkyMapConfig
50  _version = (1, 0) # for pickle
51 
52  def __init__(self, config, version=0):
53  """Constructor
54 
55  @param[in] config: an instance of self.ConfigClass; if None the default config is used
56  @param[in] version: software version of this class, to retain compatibility with old instances
57  """
58  # We count rings from south to north
59  # Note: pole caps together count for one additional ring
60  self._ringSize = math.pi / (config.numRings + 1) # Size of a ring in Declination (radians)
61  self._ringNums = [] # Number of tracts for each ring
62  for i in range(config.numRings):
63  startDec = self._ringSize*(i + 0.5) - 0.5*math.pi
64  stopDec = startDec + self._ringSize
65  dec = min(math.fabs(startDec), math.fabs(stopDec)) # Declination for determining division in RA
66  self._ringNums.append(int(2*math.pi*math.cos(dec)/self._ringSize) + 1)
67  numTracts = sum(self._ringNums) + 2
68  super(RingsSkyMap, self).__init__(numTracts, config, version)
69 
70  def getRingIndices(self, index):
71  """Calculate ring indices given a numerical index of a tract
72 
73  The ring indices are the ring number and the tract number within
74  the ring.
75 
76  The ring number is -1 for the south polar cap and increases to the
77  north. The north polar cap has ring number = numRings. The tract
78  number is zero for either of the polar caps.
79  """
80  if index == 0: # South polar cap
81  return -1, 0
82  if index == self._numTracts - 1: # North polar cap
83  return self.config.numRings, 0
84  index -= 1
85  ring = 0
86  while ring < self.config.numRings and index > self._ringNums[ring]:
87  index -= self._ringNums[ring]
88  ring += 1
89  return ring, index
90 
91  def generateTract(self, index):
92  """Generate the TractInfo for this index"""
93  ringNum, tractNum = self.getRingIndices(index)
94  if ringNum == -1: # South polar cap
95  ra, dec = 0, -0.5*math.pi
96  elif ringNum == self.config.numRings: # North polar cap
97  ra, dec = 0, 0.5*math.pi
98  else:
99  dec = self._ringSize*(ringNum + 1) - 0.5*math.pi
100  ra = math.fmod(self.config.raStart + 2*math.pi*tractNum/self._ringNums[ringNum], 2*math.pi)
101 
102  center = IcrsCoord(ra*afwGeom.radians, dec*afwGeom.radians)
103  wcs = self._wcsFactory.makeWcs(crPixPos=afwGeom.Point2D(0,0), crValCoord=center)
104  return ExplicitTractInfo(index, self.config.patchInnerDimensions, self.config.patchBorder, center,
105  0.5*self._ringSize*afwGeom.radians, self.config.tractOverlap*afwGeom.degrees,
106  wcs)
boost::enable_if< typename ExpressionTraits< Scalar >::IsScalar, Scalar >::type sum(Scalar const &scalar)
Definition: operators.h:1250
A class to handle Icrs coordinates (inherits from Coord)
Definition: Coord.h:157