LSST Applications  21.0.0+04719a4bac,21.0.0-1-ga51b5d4+f5e6047307,21.0.0-11-g2b59f77+a9c1acf22d,21.0.0-11-ga42c5b2+86977b0b17,21.0.0-12-gf4ce030+76814010d2,21.0.0-13-g1721dae+760e7a6536,21.0.0-13-g3a573fe+768d78a30a,21.0.0-15-g5a7caf0+f21cbc5713,21.0.0-16-g0fb55c1+b60e2d390c,21.0.0-19-g4cded4ca+71a93a33c0,21.0.0-2-g103fe59+bb20972958,21.0.0-2-g45278ab+04719a4bac,21.0.0-2-g5242d73+3ad5d60fb1,21.0.0-2-g7f82c8f+8babb168e8,21.0.0-2-g8f08a60+06509c8b61,21.0.0-2-g8faa9b5+616205b9df,21.0.0-2-ga326454+8babb168e8,21.0.0-2-gde069b7+5e4aea9c2f,21.0.0-2-gecfae73+1d3a86e577,21.0.0-2-gfc62afb+3ad5d60fb1,21.0.0-25-g1d57be3cd+e73869a214,21.0.0-3-g357aad2+ed88757d29,21.0.0-3-g4a4ce7f+3ad5d60fb1,21.0.0-3-g4be5c26+3ad5d60fb1,21.0.0-3-g65f322c+e0b24896a3,21.0.0-3-g7d9da8d+616205b9df,21.0.0-3-ge02ed75+a9c1acf22d,21.0.0-4-g591bb35+a9c1acf22d,21.0.0-4-g65b4814+b60e2d390c,21.0.0-4-gccdca77+0de219a2bc,21.0.0-4-ge8a399c+6c55c39e83,21.0.0-5-gd00fb1e+05fce91b99,21.0.0-6-gc675373+3ad5d60fb1,21.0.0-64-g1122c245+4fb2b8f86e,21.0.0-7-g04766d7+cd19d05db2,21.0.0-7-gdf92d54+04719a4bac,21.0.0-8-g5674e7b+d1bd76f71f,master-gac4afde19b+a9c1acf22d,w.2021.13
LSST Data Management Base Package
_assembleImage.py
Go to the documentation of this file.
1 # This file is part of afw.
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__ = ['assembleAmplifierImage', 'assembleAmplifierRawImage',
23  'makeUpdatedDetector']
24 
25 import lsst.geom
26 
27 # dict of doFlip: slice
28 _SliceDict = {
29  False: slice(None, None, 1),
30  True: slice(None, None, -1),
31 }
32 
33 
34 def _insertPixelChunk(outView, inView, amplifier, hasArrays):
35  # For the sake of simplicity and robustness, this code does not short-circuit the case flipX=flipY=False.
36  # However, it would save a bit of time, including the cost of making numpy array views.
37  # If short circuiting is wanted, do it here.
38 
39  xSlice = _SliceDict[amplifier.getRawFlipX()]
40  ySlice = _SliceDict[amplifier.getRawFlipY()]
41  if hasArrays:
42  # MaskedImage
43  inArrList = inView.getArrays()
44  outArrList = outView.getArrays()
45  else:
46  inArrList = [inView.getArray()]
47  outArrList = [outView.getArray()]
48 
49  for inArr, outArr in zip(inArrList, outArrList):
50  # y,x because numpy arrays are transposed w.r.t. afw Images
51  outArr[:] = inArr[ySlice, xSlice]
52 
53 
54 def assembleAmplifierImage(destImage, rawImage, amplifier):
55  """Assemble the amplifier region of an image from a raw image.
56 
57  Parameters
58  ----------
59  destImage : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage`
60  Assembled image; the region amplifier.getBBox() is overwritten with
61  the assembled amplifier image.
62  rawImage : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage`
63  Raw image (same type as destImage).
64  amplifier : `lsst.afw.cameraGeom.Amplifier`
65  Amplifier geometry, with raw amplifier info.
66 
67  Raises
68  ------
69  RuntimeError
70  Raised if image types do not match or amplifier has no raw amplifier info.
71  """
72  if type(destImage.Factory) != type(rawImage.Factory): # noqa: E721
73  raise RuntimeError(f"destImage type = {type(destImage.Factory).__name__} != "
74  f"{type(rawImage.Factory).__name__} = rawImage type")
75  inView = rawImage.Factory(rawImage, amplifier.getRawDataBBox())
76  outView = destImage.Factory(destImage, amplifier.getBBox())
77 
78  _insertPixelChunk(outView, inView, amplifier,
79  hasattr(rawImage, "getArrays"))
80 
81 
82 def assembleAmplifierRawImage(destImage, rawImage, amplifier):
83  """Assemble the amplifier region of a raw CCD image.
84 
85  For most cameras this is a no-op: the raw image already is an assembled
86  CCD image.
87  However, it is useful for camera such as LSST for which each amplifier
88  image is a separate image.
89 
90  Parameters
91  ----------
92  destImage : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage`
93  CCD Image; the region amplifier.getRawAmplifier().getBBox()
94  is overwritten with the raw amplifier image.
95  rawImage : `lsst.afw.image.Image` or `lsst.afw.image.MaskedImage`
96  Raw image (same type as destImage).
97  amplifier : `lsst.afw.cameraGeom.Amplifier`
98  Amplifier geometry with raw amplifier info
99 
100  Raises
101  ------
102  RuntimeError
103  Raised if image types do not match or amplifier has no raw amplifier info.
104  """
105  if type(destImage.Factory) != type(rawImage.Factory): # noqa: E721
106  raise RuntimeError(f"destImage type = {type(destImage.Factory).__name__} != "
107  f"{type(rawImage.Factory).__name__} = rawImage type")
108  inBBox = amplifier.getRawBBox()
109  inView = rawImage.Factory(rawImage, inBBox)
110  outBBox = amplifier.getRawBBox()
111  outBBox.shift(amplifier.getRawXYOffset())
112  outView = destImage.Factory(destImage, outBBox)
113 
114  _insertPixelChunk(outView, inView, amplifier,
115  hasattr(rawImage, "getArrays"))
116 
117 
119  """Return a Detector that has had the definitions of amplifier geometry
120  updated post assembly.
121 
122  Parameters
123  ----------
124  ccd : `lsst.afw.image.Detector`
125  The detector to copy and update.
126  """
127  builder = ccd.rebuild()
128  for amp in builder.getAmplifiers():
129  bbox = amp.getRawBBox()
130  awidth, aheight = bbox.getDimensions()
131  #
132  # Figure out how far flipping the amp LR and/or TB offsets the bboxes
133  #
134  boxMin0 = bbox.getMin() # initial position of rawBBox's LLC corner
135  if amp.getRawFlipX():
136  bbox.flipLR(awidth)
137  if amp.getRawFlipY():
138  bbox.flipTB(aheight)
139  shift = boxMin0 - bbox.getMin()
140 
141  for bboxName in ("",
142  "HorizontalOverscan",
143  "Data",
144  "VerticalOverscan",
145  "Prescan"):
146  bbox = getattr(amp, f"getRaw{bboxName}BBox")()
147  if amp.getRawFlipX():
148  bbox.flipLR(awidth)
149  if amp.getRawFlipY():
150  bbox.flipTB(aheight)
151  bbox.shift(amp.getRawXYOffset() + shift)
152 
153  getattr(amp, f"setRaw{bboxName}BBox")(bbox)
154  #
155  # All of these have now been transferred to the per-amp geometry
156  #
157  amp.setRawXYOffset(lsst.geom.ExtentI(0, 0))
158  amp.setRawFlipX(False)
159  amp.setRawFlipY(False)
160 
161  return builder.finish()
table::Key< int > type
Definition: Detector.cc:163
def assembleAmplifierRawImage(destImage, rawImage, amplifier)
def assembleAmplifierImage(destImage, rawImage, amplifier)