22 from __future__
import absolute_import, division, print_function
23 import lsst.afw.cameraGeom
as cameraGeom
24 import lsst.afw.cameraGeom.utils
as cameraGeomUtils
25 import lsst.afw.image
as afwImage
26 import lsst.pex.config
as pexConfig
27 import lsst.pipe.base
as pipeBase
28 from lsstDebug
import getDebugFrame
29 from lsst.afw.display
import getDisplay
31 __all__ = [
"AssembleCcdTask"]
35 doTrim = pexConfig.Field(
36 doc=
"trim out non-data regions?",
40 keysToRemove = pexConfig.ListField(
41 doc=
"FITS headers to remove (in addition to DATASEC, BIASSEC, TRIMSEC and perhaps GAIN)",
56 \anchor AssembleCcdTask_
58 \brief Assemble a set of amplifier images into a full detector size set of pixels.
60 \section ip_isr_assemble_Contents Contents
62 - \ref ip_isr_assemble_Purpose
63 - \ref ip_isr_assemble_Initialize
64 - \ref ip_isr_assemble_IO
65 - \ref ip_isr_assemble_Config
66 - \ref ip_isr_assemble_Debug
67 - \ref ip_isr_assemble_Example
69 \section ip_isr_assemble_Purpose Description
71 This task assembles sections of an image into a larger mosaic. The sub-sections
72 are typically amplifier sections and are to be assembled into a detector size pixel grid.
73 The assembly is driven by the entries in the raw amp information. The task can be configured
74 to return a detector image with non-data (e.g. overscan) pixels included. The task can also
75 renormalize the pixel values to a nominal gain of 1. The task also removes exposure metadata that
76 has context in raw amps, but not in trimmed detectors (e.g. 'BIASSEC').
78 \section ip_isr_assemble_Initialize Task initialization
82 \section ip_isr_assemble_IO Inputs/Outputs to the assembleCcd method
86 \section ip_isr_assemble_Config Configuration parameters
88 See \ref AssembleCcdConfig
90 \section ip_isr_assemble_Debug Debug variables
92 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
93 flag \c -d to import \b debug.py from your \c PYTHONPATH; see <a
94 href="http://lsst-web.ncsa.illinois.edu/~buildbot/doxygen/x_masterDoxyDoc/base_debug.html">
95 Using lsstDebug to control debugging output</a> for more about \b debug.py files.
97 The available variables in AssembleCcdTask are:
100 <DD> A dictionary containing debug point names as keys with frame number as value. Valid keys are:
102 <DT> assembledExposure
103 <DD> display assembled exposure
107 \section ip_isr_assemble_Example A complete example of using AssembleCcdTask
109 This code is in runAssembleTask.py in the examples directory, and can be run as \em e.g.
111 python examples/runAssembleTask.py
114 \dontinclude runAssembleTask.py
115 Import the task. There are other imports. Read the source file for more info.
116 \skipline AssembleCcdTask
118 \dontinclude exampleUtils.py
119 Create some input images with the help of some utilities in examples/exampleUtils.py
120 \skip makeAssemblyInput
122 The above numbers can be changed. The assumption that the readout corner is flipped on every other amp is
123 hardcoded in createDetector.
125 \dontinclude runAssembleTask.py
126 Run the assembler task
131 To investigate the \ref ip_isr_assemble_Debug, put something like
135 di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
136 if name == "lsst.ip.isr.assembleCcdTask":
137 di.display = {'assembledExposure':2}
140 lsstDebug.Info = DebugInfo
142 into your debug.py file and run runAssembleTask.py with the \c --debug flag.
146 Display code should be updated once we settle on a standard way of controlling what is displayed.
148 ConfigClass = AssembleCcdConfig
149 _DefaultName =
"assembleCcd"
152 """!Initialize the AssembleCcdTask
154 The keys for removal specified in the config are added to a default set:
155 ('DATASEC', 'BIASSEC', 'TRIMSEC', 'GAIN')
157 pipeBase.Task.__init__(self, **kwargs)
159 self.
allKeysToRemove = (
'DATASEC',
'BIASSEC',
'TRIMSEC',
'GAIN') + tuple(self.config.keysToRemove)
162 """!Assemble a set of amps into a single CCD size image
163 \param[in] assembleInput -- Either a dictionary of amp lsst.afw.image.Exposures or a single
164 lsst.afw.image.Exposure containing all raw
165 amps. If a dictionary of amp exposures,
166 the key should be the amp name.
167 \return assembledCcd -- An lsst.afw.image.Exposure of the assembled amp sections.
169 \throws TypeError with the following string:
172 <DT> Expected either a dictionary of amp exposures or a single raw exposure
173 <DD> The input exposures to be assembled do not adhere to the required format.
176 \throws RuntimeError with the following string:
179 <DT> No ccd detector found
180 <DD> The detector set on the input exposure is not set.
184 if isinstance(assembleInput, dict):
188 ccd = next(iter(assembleInput.values())).getDetector()
190 def getNextExposure(amp):
191 return assembleInput[amp.getName()]
192 elif hasattr(assembleInput,
"getMaskedImage"):
194 ccd = assembleInput.getDetector()
196 def getNextExposure(amp):
199 raise TypeError(
"Expected either a dictionary of amp exposures or a single raw exposure")
202 raise RuntimeError(
"No ccd detector found")
204 if not self.config.doTrim:
205 outBox = cameraGeomUtils.calcRawCcdBBox(ccd)
207 outBox = ccd.getBBox()
208 outExposure = afwImage.ExposureF(outBox)
209 outMI = outExposure.getMaskedImage()
211 if self.config.doTrim:
212 assemble = cameraGeom.assembleAmplifierImage
214 assemble = cameraGeom.assembleAmplifierRawImage
217 inMI = getNextExposure(amp).getMaskedImage()
218 assemble(outMI, inMI, amp)
224 if not self.config.doTrim:
225 ccd = cameraGeom.makeUpdatedDetector(ccd)
227 outExposure.setDetector(ccd)
233 """Set exposure non-image attributes, including wcs and metadata and display exposure (if requested)
235 Call after assembling the pixels
237 @param[in,out] outExposure assembled exposure:
238 - removes unwanted keywords
239 - sets calib, filter, and detector
240 @param[in] inExposure input exposure
242 self.
setWcs(outExposure=outExposure, inExposure=inExposure)
244 exposureMetadata = inExposure.getMetadata()
246 if exposureMetadata.exists(key):
247 exposureMetadata.remove(key)
248 outExposure.setMetadata(exposureMetadata)
251 outExposure.setFilter(inExposure.getFilter())
252 outExposure.getInfo().setVisitInfo(inExposure.getInfo().getVisitInfo())
254 frame = getDebugFrame(self._display,
"assembledExposure")
256 getDisplay(frame).mtv(outExposure)
258 def setWcs(self, outExposure, inExposure):
259 """Set output WCS = input WCS, adjusted as required for datasecs not starting at lower left corner
261 @param[in,out] outExposure assembled exposure; wcs is set
262 @param[in] inExposure input exposure
264 if inExposure.hasWcs():
265 wcs = inExposure.getWcs()
266 ccd = outExposure.getDetector()
269 raise RuntimeError(
"No amplifier detector information found")
270 cameraGeomUtils.prepareWcsData(wcs, amp0, isTrimmed=self.config.doTrim)
271 outExposure.setWcs(wcs)
273 self.log.warn(
"No WCS found in input exposure")
Assemble a set of amplifier images into a full detector size set of pixels.
def assembleCcd
Assemble a set of amps into a single CCD size image.
def __init__
Initialize the AssembleCcdTask.