27import lsst.pipe.base
as pipeBase
28from lsstDebug
import getDebugFrame
30__all__ = [
"AssembleCcdTask"]
34 doTrim = pexConfig.Field(
35 doc=
"trim out non-data regions?",
39 keysToRemove = pexConfig.ListField(
40 doc=
"FITS headers to remove (in addition to DATASEC, BIASSEC, TRIMSEC and perhaps GAIN)",
55 @anchor AssembleCcdTask_
57 @brief Assemble a set of amplifier images into a full detector size set of pixels.
59 @section ip_isr_assemble_Contents Contents
61 -
@ref ip_isr_assemble_Purpose
62 -
@ref ip_isr_assemble_Initialize
63 -
@ref ip_isr_assemble_IO
64 -
@ref ip_isr_assemble_Config
65 -
@ref ip_isr_assemble_Debug
66 -
@ref ip_isr_assemble_Example
68 @section ip_isr_assemble_Purpose Description
70 This task assembles sections of an image into a larger mosaic. The sub-sections
71 are typically amplifier sections
and are to be assembled into a detector size pixel grid.
72 The assembly
is driven by the entries
in the raw amp information. The task can be configured
73 to
return a detector image
with non-data (e.g. overscan) pixels included. The task can also
74 renormalize the pixel values to a nominal gain of 1. The task also removes exposure metadata that
75 has context
in raw amps, but
not in trimmed detectors (e.g.
'BIASSEC').
77 @section ip_isr_assemble_Initialize Task initialization
81 @section ip_isr_assemble_IO Inputs/Outputs to the assembleCcd method
85 @section ip_isr_assemble_Config Configuration parameters
87 See
@ref AssembleCcdConfig
89 @section ip_isr_assemble_Debug Debug variables
91 The
@link lsst.pipe.base.cmdLineTask.CmdLineTask command line task
@endlink interface supports a
92 flag
@c -d to
import @b debug.py
from your
@c PYTHONPATH; see <a
93 href=
"https://developer.lsst.io/stack/debug.html">Debugging Tasks
with lsstDebug</a>
for more
94 about
@b debug.py files.
96 The available variables
in AssembleCcdTask are:
99 <DD> A dictionary containing debug point names
as keys
with frame number
as value. Valid keys are:
101 <DT> assembledExposure
102 <DD> display assembled exposure
106 @section ip_isr_assemble_Example A complete example of using AssembleCcdTask
109 To investigate the
@ref ip_isr_assemble_Debug, put something like
114 if name ==
"lsst.ip.isr.assembleCcdTask":
115 di.display = {
'assembledExposure':2}
120 into your debug.py file
and run runAssembleTask.py
with the
@c --debug flag.
124 Display code should be updated once we settle on a standard way of controlling what
is displayed.
126 ConfigClass = AssembleCcdConfig
127 _DefaultName = "assembleCcd"
130 """!Initialize the AssembleCcdTask
132 The keys for removal specified
in the config are added to a default set:
133 (
'DATASEC',
'BIASSEC',
'TRIMSEC',
'GAIN')
135 pipeBase.Task.__init__(self, **kwargs)
137 self.allKeysToRemoveallKeysToRemove = ('DATASEC',
'BIASSEC',
'TRIMSEC',
'GAIN') + tuple(self.config.keysToRemove)
140 """!Assemble a set of amps into a single CCD size image
141 @param[
in] assembleInput -- Either a dictionary of amp lsst.afw.image.Exposures
or a single
143 amps. If a dictionary of amp exposures,
144 the key should be the amp name.
147 @throws TypeError
with the following string:
150 <DT> Expected either a dictionary of amp exposures
or a single raw exposure
151 <DD> The input exposures to be assembled do
not adhere to the required format.
154 @throws RuntimeError
with the following string:
157 <DT> No ccd detector found
158 <DD> The detector set on the input exposure
is not set.
162 if isinstance(assembleInput, dict):
166 ccd = next(iter(assembleInput.values())).getDetector()
168 def getNextExposure(amp):
169 return assembleInput[amp.getName()]
170 elif hasattr(assembleInput,
"getMaskedImage"):
172 ccd = assembleInput.getDetector()
174 def getNextExposure(amp):
177 raise TypeError(
"Expected either a dictionary of amp exposures or a single raw exposure")
180 raise RuntimeError(
"No ccd detector found")
182 if not self.config.doTrim:
183 outBox = cameraGeomUtils.calcRawCcdBBox(ccd)
185 outBox = ccd.getBBox()
186 outExposure = afwImage.ExposureF(outBox)
187 outMI = outExposure.getMaskedImage()
189 if self.config.doTrim:
190 assemble = cameraGeom.assembleAmplifierImage
192 assemble = cameraGeom.assembleAmplifierRawImage
195 inMI = getNextExposure(amp).getMaskedImage()
196 assemble(outMI, inMI, amp)
202 if not self.config.doTrim:
203 ccd = cameraGeom.makeUpdatedDetector(ccd)
205 outExposure.setDetector(ccd)
206 self.
postprocessExposurepostprocessExposure(outExposure=outExposure, inExposure=getNextExposure(ccd[0]))
211 """Set exposure non-image attributes, including wcs and metadata and display exposure (if requested)
213 Call after assembling the pixels
215 @param[
in,out] outExposure assembled exposure:
216 - removes unwanted keywords
217 - sets wcs, filter,
and detector
218 @param[
in] inExposure input exposure
220 if inExposure.hasWcs():
221 outExposure.setWcs(inExposure.getWcs())
223 exposureMetadata = inExposure.getMetadata()
225 if exposureMetadata.exists(key):
226 exposureMetadata.remove(key)
227 outExposure.setMetadata(exposureMetadata)
230 outExposure.setFilterLabel(inExposure.getFilterLabel())
231 outExposure.getInfo().setVisitInfo(inExposure.getInfo().getVisitInfo())
233 frame = getDebugFrame(self._display,
"assembledExposure")
235 afwDisplay.Display(frame=frame).mtv(outExposure, title=
"postprocessExposure")
def assembleCcd(self, assembleInput)
Assemble a set of amps into a single CCD size image.
def __init__(self, **kwargs)
Initialize the AssembleCcdTask.
def postprocessExposure(self, outExposure, inExposure)