lsst.skymap  13.0-5-g2a40766+40
baseSkyMap.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010 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 @todo
24 - Consider tweaking pixel scale so the average scale is as specified, rather than the scale at the center
25 """
26 from builtins import object
27 import lsst.pex.config as pexConfig
28 import lsst.afw.geom as afwGeom
29 from . import detail
30 
31 __all__ = ["BaseSkyMap"]
32 
33 
34 class BaseSkyMapConfig(pexConfig.Config):
35  patchInnerDimensions = pexConfig.ListField(
36  doc="dimensions of inner region of patches (x,y pixels)",
37  dtype=int,
38  length=2,
39  default=(4000, 4000),
40  )
41  patchBorder = pexConfig.Field(
42  doc="border between patch inner and outer bbox (pixels)",
43  dtype=int,
44  default=100,
45  )
46  tractOverlap = pexConfig.Field(
47  doc="minimum overlap between adjacent sky tracts, on the sky (deg)",
48  dtype=float,
49  default=1.0,
50  )
51  pixelScale = pexConfig.Field(
52  doc="nominal pixel scale (arcsec/pixel)",
53  dtype=float,
54  default=0.333
55  )
56  projection = pexConfig.Field(
57  doc="""one of the FITS WCS projection codes, such as:
58  - STG: stereographic projection
59  - MOL: Molleweide's projection
60  - TAN: tangent-plane projection
61  """,
62  dtype=str,
63  default="STG",
64  )
65  rotation = pexConfig.Field(
66  doc="Rotation for WCS (deg)",
67  dtype=float,
68  default=0,
69  )
70 
71 
72 class BaseSkyMap(object):
73  """A collection of overlapping Tracts that map part or all of the sky.
74 
75  See TractInfo for more information.
76 
77  BaseSkyMap is an abstract base class. Subclasses must do the following:
78  @li define __init__ and have it construct the TractInfo objects and put them in _tractInfoList
79  @li define __getstate__ and __setstate__ to allow pickling (the butler saves sky maps using pickle);
80  see DodecaSkyMap for an example of how to do this. (Most of that code could be moved
81  into this base class, but that would make it harder to handle older versions of pickle data.)
82  """
83  ConfigClass = BaseSkyMapConfig
84 
85  def __init__(self, config=None):
86  """Construct a BaseSkyMap
87 
88  @param[in] config: an instance of self.ConfigClass; if None the default config is used
89  """
90  if config is None:
91  config = self.ConfigClass()
92  config.freeze() # just to be sure, e.g. for pickling
93  self.config = config
94  self._tractInfoList = []
96  pixelScale=afwGeom.Angle(self.config.pixelScale, afwGeom.arcseconds),
97  projection=self.config.projection,
98  rotation=afwGeom.Angle(self.config.rotation, afwGeom.degrees),
99  )
100 
101  def findTract(self, coord):
102  """Find the tract whose center is nearest the specified coord.
103 
104  @param[in] coord: sky coordinate (afwCoord.Coord)
105  @return TractInfo of tract whose center is nearest the specified coord
106 
107  @warning:
108  - if tracts do not cover the whole sky then the returned tract may not include the coord
109 
110  @note
111  - This routine will be more efficient if coord is ICRS.
112  - If coord is equidistant between multiple sky tract centers then one is arbitrarily chosen.
113  - The default implementation is not very efficient; subclasses may wish to override.
114  """
115  icrsCoord = coord.toIcrs()
116  distTractInfoList = []
117  for tractInfo in self:
118  angSep = icrsCoord.angularSeparation(tractInfo.getCtrCoord()).asDegrees()
119  distTractInfoList.append((angSep, tractInfo))
120  distTractInfoList.sort()
121  return distTractInfoList[0][1]
122 
123  def findTractPatchList(self, coordList):
124  """Find tracts and patches that overlap a region
125 
126  @param[in] coordList: list of sky coordinates (afwCoord.Coord)
127  @return list of (TractInfo, list of PatchInfo) for tracts and patches that contain,
128  or may contain, the specified region. The list will be empty if there is no overlap.
129 
130  @warning this uses a naive algorithm that may find some tracts and patches that do not overlap
131  the region (especially if the region is not a rectangle aligned along patch x,y).
132  """
133  retList = []
134  for tractInfo in self:
135  patchList = tractInfo.findPatchList(coordList)
136  if patchList:
137  retList.append((tractInfo, patchList))
138  return retList
139 
140  def findClosestTractPatchList(self, coordList):
141  """Find closest tract and patches that overlap coordinates
142 
143  @param[in] coordList: list of sky coordinates (afwCoord.Coord)
144  @return list of (TractInfo, list of PatchInfo) for tracts and patches that contain,
145  or may contain, the specified region. The list will be empty if there is no overlap.
146  """
147  retList = []
148  for coord in coordList:
149  tractInfo = self.findTract(coord)
150  patchList = tractInfo.findPatchList(coordList)
151  if patchList and not (tractInfo, patchList) in retList:
152  retList.append((tractInfo, patchList))
153  return retList
154 
155  def __getitem__(self, ind):
156  return self._tractInfoList[ind]
157 
158  def __iter__(self):
159  return iter(self._tractInfoList)
160 
161  def __len__(self):
162  return len(self._tractInfoList)
def findTractPatchList(self, coordList)
Definition: baseSkyMap.py:123
def findClosestTractPatchList(self, coordList)
Definition: baseSkyMap.py:140
def __init__(self, config=None)
Definition: baseSkyMap.py:85