22__all__ = [
'assembleAmplifierImage',
'assembleAmplifierRawImage',
23 'makeUpdatedDetector',
'AmplifierIsolator']
27 False: slice(
None,
None, 1),
28 True: slice(
None,
None, -1),
32def _insertPixelChunk(outView, inView, amplifier, hasArrays):
37 xSlice = _SliceDict[amplifier.getRawFlipX()]
38 ySlice = _SliceDict[amplifier.getRawFlipY()]
41 inArrList = inView.getArrays()
42 outArrList = outView.getArrays()
44 inArrList = [inView.getArray()]
45 outArrList = [outView.getArray()]
47 for inArr, outArr
in zip(inArrList, outArrList):
49 outArr[:] = inArr[ySlice, xSlice]
52def assembleAmplifierImage(destImage, rawImage, amplifier):
53 """Assemble the amplifier region of an image from a raw image.
58 Assembled image; the region amplifier.getBBox()
is overwritten
with
59 the assembled amplifier image.
61 Raw image (same type
as destImage).
63 Amplifier geometry,
with raw amplifier info.
68 Raised
if image types do
not match
or amplifier has no raw amplifier info.
70 if type(destImage.Factory) !=
type(rawImage.Factory):
71 raise RuntimeError(f
"destImage type = {type(destImage.Factory).__name__} != "
72 f
"{type(rawImage.Factory).__name__} = rawImage type")
73 inView = rawImage.Factory(rawImage, amplifier.getRawDataBBox())
74 outView = destImage.Factory(destImage, amplifier.getBBox())
76 _insertPixelChunk(outView, inView, amplifier,
77 hasattr(rawImage,
"getArrays"))
80def assembleAmplifierRawImage(destImage, rawImage, amplifier):
81 """Assemble the amplifier region of a raw CCD image.
83 For most cameras this is a no-op: the raw image already
is an assembled
85 However, it
is useful
for camera such
as LSST
for which each amplifier
86 image
is a separate image.
91 CCD Image; the region amplifier.getRawAmplifier().getBBox()
92 is overwritten
with the raw amplifier image.
94 Raw image (same type
as destImage).
96 Amplifier geometry
with raw amplifier info
101 Raised
if image types do
not match
or amplifier has no raw amplifier info.
103 if type(destImage.Factory) !=
type(rawImage.Factory):
104 raise RuntimeError(f
"destImage type = {type(destImage.Factory).__name__} != "
105 f
"{type(rawImage.Factory).__name__} = rawImage type")
106 inBBox = amplifier.getRawBBox()
107 inView = rawImage.Factory(rawImage, inBBox)
108 outBBox = amplifier.getRawBBox()
109 outBBox.shift(amplifier.getRawXYOffset())
110 outView = destImage.Factory(destImage, outBBox)
112 _insertPixelChunk(outView, inView, amplifier,
113 hasattr(rawImage,
"getArrays"))
117 """Return a Detector that has had the definitions of amplifier geometry
118 updated post assembly.
122 ccd : `lsst.afw.image.Detector`
123 The detector to copy and update.
125 builder = ccd.rebuild()
126 for amp
in builder.getAmplifiers():
128 return builder.finish()
132 """A class that can extracts single-amplifier subimages from trimmed or
133 untrimmed assembled images and transforms them to a particular orientation
137 generally just use the `apply`
class method. Other methods can be used to
138 implement subimage loads of on on-disk images (e.g. formatter classes
in
139 ``obs_base``)
or obtain subsets
from other image classes.
143 amplifier : `Amplifier`
144 Amplifier object that identifies the amplifier to load
and sets the
145 orientation
and offset of the returned subimage.
147 Bounding box of the assembled parent image. This must be equal to
148 either ``parent_detector.getBBox()``
or
149 ``parent_detector.getRawBBox()``; which one
is used to determine
150 whether the parent image (
and hence the amplifier subimages)
is
152 parent_detector : `Detector`
153 Detector object that describes the parent image.
156 def __init__(self, amplifier, parent_bbox, parent_detector):
167 f
"The given amplifier's trimmed bounding box ({self._amplifier.getBBox()}) is not the "
168 "same as the trimmed bounding box of the same amplifier in the parent image "
169 f
"({self._parent_amplifier.getBBox()})."
176 "The given amplifier's subregions are fundamentally incompatible with those of the "
177 "parent image's amplifier."
182 """The bounding box of the target amplifier in the parent image
191 """Transform an already-extracted subimage to match the orientation
192 and offset of the target amplifier.
196 subimage : image-like
203 transformed : image-like
204 Transformed image of the same type
as ``subimage``.
207 if hasattr(subimage,
"getMaskedImage"):
211 result = subimage.clone()
212 result.setMaskedImage(
214 subimage.getMaskedImage(),
226 result.setXY0(self.
_amplifier.getBBox().getMin())
232 """Create a single-amplifier detector that describes the transformed
237 detector : `Detector`
238 Detector object with a single amplifier, a trimmed bounding box
239 equal to the amplifier
's trimmed bounding box, and no crosstalk.
245 detector.unsetCrosstalk()
246 return detector.finish()
249 def apply(cls, parent_exposure, amplifier):
250 """Obtain a single-amplifier `lsst.afw.image.Exposure` subimage that
251 masquerades as full-detector image
for a single-amp detector.
256 Parent image to obtain a subset
from.
257 `~lsst.afw.image.Exposure.getDetector` must
not return `
None`.
258 amplifier : `Amplifier`
259 Target amplifier
for the subimage. May differ
from the amplifier
260 obtained by ``parent_exposure.getDetector()[amplifier.getName()]``
261 only by flips
and differences
in `~Amplifier.getRawXYOffset`.
266 Exposure subimage
for the target amplifier,
with the
267 orientation
and XY0 described by that amplifier,
and a single-amp
268 detector holding a copy of that amplifier.
272 Because we use the target amplifier
's bounding box as the bounding box
273 of the detector attached to the returned exposure, other exposure
274 components that are passed through unmodified (e.g. the WCS) should
275 still be valid for the single-amp exposure after it
is trimmed
and
276 "assembled". Unlike most trimmed+assembled images, however, it will
277 have a nonzero XY0,
and code that (incorrectly!) does
not pay attention
280 instance = cls(amplifier, parent_bbox=parent_exposure.getBBox(),
281 parent_detector=parent_exposure.getDetector())
282 result = instance.transform_subimage(parent_exposure[instance.subimage_bbox])
283 result.setDetector(instance.make_detector())
def transform_subimage(self, subimage)
def __init__(self, amplifier, parent_bbox, parent_detector)
def apply(cls, parent_exposure, amplifier)
Geometry and electronic information about raw amplifier images.
A class to contain the data, WCS, and other information needed to describe an image of the sky.
A class to represent a 2-dimensional array of pixels.
Represent a 2-dimensional array of bitmask pixels.
A class to manipulate images, masks, and variance as a single object.
An integer coordinate rectangle.
def makeUpdatedDetector(ccd)