LSSTApplications  21.0.0+1b62c9342b,21.0.0+45a059f35e,21.0.0-1-ga51b5d4+ceb9cf20a3,21.0.0-2-g103fe59+4d13aff7ba,21.0.0-2-g1367e85+571a348718,21.0.0-2-g2909d54+45a059f35e,21.0.0-2-g45278ab+1b62c9342b,21.0.0-2-g4bc9b9f+ebfe466dad,21.0.0-2-g5242d73+571a348718,21.0.0-2-g54e2caa+07cebfb09d,21.0.0-2-g66bcc37+0b2c5d3971,21.0.0-2-g7f82c8f+08f1f55c36,21.0.0-2-g8dde007+5d1b9cb3f5,21.0.0-2-g8f08a60+73884b2cf5,21.0.0-2-ga326454+08f1f55c36,21.0.0-2-ga63a54e+458e82fbcd,21.0.0-2-gc738bc1+8c4731df06,21.0.0-2-gde069b7+5a8f2956b8,21.0.0-2-ge17e5af+571a348718,21.0.0-2-ge712728+cfa36ee5f9,21.0.0-2-gecfae73+e597808034,21.0.0-2-gfc62afb+571a348718,21.0.0-20-g4449a12+6d1341e0f3,21.0.0-22-gf0532904+1cd928f0c5,21.0.0-3-g4c5b185+c3794955c6,21.0.0-3-g6d51c4a+0b2c5d3971,21.0.0-3-g8076721+5adeb471db,21.0.0-3-gaa929c8+01f4b7cfca,21.0.0-3-gd222c45+afc8332dbe,21.0.0-4-g1383c07+0b2c5d3971,21.0.0-4-g3300ddd+1b62c9342b,21.0.0-4-g5873dc9+9a92674037,21.0.0-4-g8a80011+bd904b6426,21.0.0-5-gcff38f6+844b7f7b93,21.0.0-6-g463d161+18af5fb57b,21.0.0-6-gd3283ba+01f4b7cfca,21.0.0-8-g19111d86+8234efb485,21.0.0-9-g7bed000b9+c7d3cce47e,w.2021.04
LSSTDataManagementBasePackage
utils.py
Go to the documentation of this file.
1 # This file is part of obs_base.
2 #
3 # Developed for the LSST Data Management System.
4 # This product includes software developed by the LSST Project
5 # (https://www.lsst.org).
6 # See the COPYRIGHT file at the top-level directory of this distribution
7 # for details of code ownership.
8 #
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <https://www.gnu.org/licenses/>.
21 
22 __all__ = ('InitialSkyWcsError', 'createInitialSkyWcs', 'createInitialSkyWcsFromBoresight', 'bboxFromIraf')
23 
24 import re
25 import lsst.geom as geom
26 
27 from . import Instrument
28 from lsst.afw.cameraGeom import PIXELS, FIELD_ANGLE
29 from lsst.afw.image import RotType
30 from lsst.afw.geom.skyWcs import makeSkyWcs
32 from lsst.utils import doImport
33 
34 
35 class InitialSkyWcsError(Exception):
36  """For handling failures when creating a SkyWcs from a camera geometry and
37  boresight.
38 
39  Typically used as a chained exception from a lower level exception.
40  """
41  pass
42 
43 
44 def createInitialSkyWcs(visitInfo, detector, flipX=False):
45  """Create a SkyWcs from the visit information and detector geometry.
46 
47  A typical usecase for this is to create the initial WCS for a newly-read
48  raw exposure.
49 
50 
51  Parameters
52  ----------
53  visitInfo : `lsst.afw.image.VisitInfo`
54  Where to get the telescope boresight and rotator angle from.
55  detector : `lsst.afw.cameraGeom.Detector`
56  Where to get the camera geomtry from.
57  flipX : `bool`, optional
58  If False, +X is along W, if True +X is along E.
59 
60  Returns
61  -------
62  skyWcs : `lsst.afw.geom.SkyWcs`
63  The new composed WCS.
64 
65  Raises
66  ------
67  InitialSkyWcsError
68  Raised if there is an error generating the SkyWcs, chained from the
69  lower-level exception if available.
70  """
71  if visitInfo.getRotType() != RotType.SKY:
72  msg = (f"Cannot create SkyWcs from camera geometry: rotator angle defined using "
73  f"RotType={visitInfo.getRotType()} instead of SKY.")
74  raise InitialSkyWcsError(msg)
75  orientation = visitInfo.getBoresightRotAngle()
76  boresight = visitInfo.getBoresightRaDec()
77  return createInitialSkyWcsFromBoresight(boresight, orientation, detector, flipX)
78 
79 
80 def createInitialSkyWcsFromBoresight(boresight, orientation, detector, flipX=False):
81  """Create a SkyWcs from the telescope boresight and detector geometry.
82 
83  A typical usecase for this is to create the initial WCS for a newly-read
84  raw exposure.
85 
86  Parameters
87  ----------
88  boresight : `lsst.geom.SpherePoint`
89  The ICRS boresight RA/Dec
90  orientation : `lsst.geom.Angle`
91  The rotation angle of the focal plane on the sky.
92  detector : `lsst.afw.cameraGeom.Detector`
93  Where to get the camera geomtry from.
94  flipX : `bool`, optional
95  If False, +X is along W, if True +X is along E.
96 
97  Returns
98  -------
99  skyWcs : `lsst.afw.geom.SkyWcs`
100  The new composed WCS.
101 
102  Raises
103  ------
104  InitialSkyWcsError
105  Raised if there is an error generating the SkyWcs, chained from the
106  lower-level exception if available.
107  """
108  try:
109  pixelsToFieldAngle = detector.getTransform(detector.makeCameraSys(PIXELS),
110  detector.makeCameraSys(FIELD_ANGLE))
112  raise InitialSkyWcsError("Cannot compute PIXELS to FIELD_ANGLE Transform.") from e
113  return makeSkyWcs(pixelsToFieldAngle, orientation, flipX, boresight)
114 
115 
116 def bboxFromIraf(irafBBoxStr):
117  """Return a Box2I corresponding to an IRAF-style BBOX
118 
119  [x0:x1,y0:y1] where x0 and x1 are the one-indexed start and end columns,
120  and correspondingly y0 and y1 are the start and end rows.
121  """
122 
123  mat = re.search(r"^\[([-\d]+):([-\d]+),([-\d]+):([-\d]+)\]$", irafBBoxStr)
124  if not mat:
125  raise RuntimeError("Unable to parse IRAF-style bbox \"%s\"" % irafBBoxStr)
126  x0, x1, y0, y1 = [int(_) for _ in mat.groups()]
127 
128  return geom.BoxI(geom.PointI(x0 - 1, y0 - 1), geom.PointI(x1 - 1, y1 - 1))
129 
130 
131 def getInstrument(instrumentName, registry=None):
132  """Return an instance of a named instrument.
133 
134  If the instrument name not is qualified (does not contain a '.') and a
135  butler registry is provided, this will attempt to load the instrument using
136  Instrument.fromName. Otherwise the instrument will be imported and
137  instantiated.
138 
139  Parameters
140  ----------
141  instrumentName : string
142  The name or fully-qualified class name of an instrument.
143  registry : `lsst.daf.butler.Registry`, optional
144  Butler registry to query to find information about the instrument, by
145  default None
146 
147  Returns
148  -------
149  Instrument subclass instance
150  The instantiated instrument.
151 
152  Raises
153  ------
154  RuntimeError
155  If the instrument can not be imported, instantiated, or obtained from
156  the registry.
157  TypeError
158  If the instrument is not a subclass of lsst.obs.base.Instrument.
159  """
160  if "." not in instrumentName and registry is not None:
161  try:
162  instr = Instrument.fromName(instrumentName, registry)
163  except Exception as err:
164  raise RuntimeError(
165  f"Could not get instrument from name: {instrumentName}. Failed with exception: {err}")
166  else:
167  try:
168  instr = doImport(instrumentName)
169  except Exception as err:
170  raise RuntimeError(f"Could not import instrument: {instrumentName}. Failed with exception: {err}")
171  instr = instr()
172  if not isinstance(instr, Instrument):
173  raise TypeError(f"{instrumentName} is not an Instrument subclass.")
174  return instr
175 
176 
177 # TODO remove the impl in pipe_base? (NB this combines setDottedAtr AND the
178 # handling in ConfigValueAction.__call__)
179 def setDottedAttr(item, name, value):
180  """Set an instance attribute (like `setattr` but accepting hierarchical
181  names such as ``foo.bar.baz``) If the attribute can not be set as a string,
182  will attempt to set the attribute with the result of eval'ing the value.
183 
184  Parameters
185  ----------
186  item : obj
187  Object whose attribute is to be set.
188  name : `str`
189  Name of attribute to set.
190  value : obj
191  New value for the attribute.
192 
193  Notes
194  -----
195  For example if name is ``foo.bar.baz`` then ``item.foo.bar.baz``
196  is set to the specified value.
197 
198  Raises
199  ------
200  AttributeError
201  If the item does not have a field specified by name that can be set.
202  RuntimeError
203  If the value can not be set as a string or rendered by eval, or if
204  there is an error setting the attribute with the rendered value.
205  """
206  subitem = item
207  subnameList = name.split(".")
208  for subname in subnameList[:-1]:
209  subitem = getattr(subitem, subname)
210  try:
211  setattr(subitem, subnameList[-1], value)
212  except AttributeError:
213  raise AttributeError(f"No field: {name!r}")
214  except Exception:
215  try:
216  v = eval(value, {})
217  except Exception:
218  raise RuntimeError(f"Cannot render {value!r} as a value for {name!r}")
219  try:
220  setattr(subitem, subnameList[-1], v)
221  except Exception as e:
222  raise RuntimeError(f"Cannot set config. {name}={value!r}: {e}")
223 
224 
225 def setDottedAttrs(item, attrs):
226  for name, value in attrs:
227  setDottedAttr(item, name, value)
lsst::afw::image
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
Definition: imageAlgorithm.dox:1
lsst.obs.base.utils.createInitialSkyWcsFromBoresight
def createInitialSkyWcsFromBoresight(boresight, orientation, detector, flipX=False)
Definition: utils.py:80
lsst.obs.base.utils.getInstrument
def getInstrument(instrumentName, registry=None)
Definition: utils.py:131
lsst.obs.base.utils.setDottedAttrs
def setDottedAttrs(item, attrs)
Definition: utils.py:225
lsst::daf::persistence.utils.doImport
def doImport(pythonType)
Definition: utils.py:104
lsst.obs.base.utils.bboxFromIraf
def bboxFromIraf(irafBBoxStr)
Definition: utils.py:116
lsst::utils
Definition: Backtrace.h:29
lsst::geom
Definition: AffineTransform.h:36
lsst::afw::cameraGeom
Definition: Amplifier.h:33
lsst.pex::exceptions::InvalidParameterError
Reports invalid arguments.
Definition: Runtime.h:66
lsst.obs.base.utils.InitialSkyWcsError
Definition: utils.py:35
lsst::geom::Point< int, 2 >
lsst::afw::geom.skyWcs
Definition: __init__.py:1
lsst::geom::Box2I
An integer coordinate rectangle.
Definition: Box.h:55
lsst::afw::geom::makeSkyWcs
std::shared_ptr< SkyWcs > makeSkyWcs(daf::base::PropertySet &metadata, bool strip=false)
Construct a SkyWcs from FITS keywords.
Definition: SkyWcs.cc:526
lsst.obs.base.utils.createInitialSkyWcs
def createInitialSkyWcs(visitInfo, detector, flipX=False)
Definition: utils.py:44
lsst.pex::exceptions
Definition: Exception.h:37
lsst.obs.base.utils.setDottedAttr
def setDottedAttr(item, name, value)
Definition: utils.py:179