27 from .isr
import calcEffectiveGain
29 __all__ = [
"AssembleCcdTask"]
32 setGain = pexConfig.Field(
37 doRenorm = pexConfig.Field(
38 doc =
"renormalize to a gain of 1? (ignored if setGain false)",
42 doTrim = pexConfig.Field(
43 doc =
"trim out non-data regions?",
47 keysToRemove = pexConfig.ListField(
48 doc =
"FITS headers to remove (in addition to DATASEC, BIASSEC, TRIMSEC and perhaps GAIN)",
62 \anchor AssembleCcdTask_
64 \brief Assemble a set of amplifier images into a full detector size set of pixels.
66 \section ip_isr_assemble_Contents Contents
68 - \ref ip_isr_assemble_Purpose
69 - \ref ip_isr_assemble_Initialize
70 - \ref ip_isr_assemble_IO
71 - \ref ip_isr_assemble_Config
72 - \ref ip_isr_assemble_Debug
73 - \ref ip_isr_assemble_Example
75 \section ip_isr_assemble_Purpose Description
77 This task assembles sections of an image into a larger mosaic. The sub-sections
78 are typically amplifier sections and are to be assembled into a detector size pixel grid.
79 The assembly is driven by the entries in the raw amp information. The task can be configured
80 to return a detector image with non-data (e.g. overscan) pixels included. The task can also
81 renormalize the pixel values to a nominal gain of 1. The task also removes exposure metadata that
82 has context in raw amps, but not in trimmed detectors (e.g. 'BIASSEC').
84 \section ip_isr_assemble_Initialize Task initialization
88 \section ip_isr_assemble_IO Inputs/Outputs to the assembleCcd method
92 \section ip_isr_assemble_Config Configuration parameters
94 See \ref AssembleCcdConfig
96 \section ip_isr_assemble_Debug Debug variables
98 The \link lsst.pipe.base.cmdLineTask.CmdLineTask command line task\endlink interface supports a
99 flag \c -d to import \b debug.py from your \c PYTHONPATH; see <a
100 href="http://lsst-web.ncsa.illinois.edu/~buildbot/doxygen/x_masterDoxyDoc/base_debug.html">
101 Using lsstDebug to control debugging output</a> for more about \b debug.py files.
103 The available variables in AssembleCcdTask are:
106 <DD> A dictionary containing debug point names as keys with frame number as value. Valid keys are:
108 <DT> assembledExposure
109 <DD> display assembled exposure
113 \section ip_isr_assemble_Example A complete example of using AssembleCcdTask
115 This code is in runAssembleTask.py in the examples directory, and can be run as \em e.g.
117 python examples/runAssembleTask.py
120 \dontinclude runAssembleTask.py
121 Import the task. There are other imports. Read the source file for more info.
122 \skipline AssembleCcdTask
124 \dontinclude exampleUtils.py
125 Create some input images with the help of some utilities in examples/exampleUtils.py
126 \skip makeAssemblyInput
128 The above numbers can be changed. The assumption that the readout corner is flipped on every other amp is
129 hardcoded in createDetector.
131 \dontinclude runAssembleTask.py
132 Run the assembler task
137 To investigate the \ref ip_isr_assemble_Debug, put something like
141 di = lsstDebug.getInfo(name) # N.b. lsstDebug.Info(name) would call us recursively
142 if name == "lsst.ip.isr.assembleCcdTask":
143 di.display = {'assembledExposure':2}
146 lsstDebug.Info = DebugInfo
148 into your debug.py file and run runAssembleTask.py with the \c --debug flag.
152 Display code should be updated once we settle on a standard way of controlling what is displayed.
154 ConfigClass = AssembleCcdConfig
155 _DefaultName =
"assembleCcd"
158 """!Initialize the AssembleCcdTask
160 The keys for removal specified in the config are added to a default set:
161 ('DATASEC', 'BIASSEC', 'TRIMSEC', 'GAIN')
163 pipeBase.Task.__init__(self, **kwargs)
165 self.
allKeysToRemove = (
'DATASEC',
'BIASSEC',
'TRIMSEC',
'GAIN') + tuple(self.config.keysToRemove)
168 """!Assemble a set of amps into a single CCD size image
169 \param[in] assembleInput -- Either a dictionary of amp lsst.afw.image.Exposures or a single
170 lsst.afw.image.Exposure containing all raw
171 amps. If a dictionary of amp exposures,
172 the key should be the amp name.
173 \return assembledCcd -- An lsst.afw.image.Exposure of the assembled amp sections.
175 \throws TypeError with the following string:
178 <DT> Expected either a dictionary of amp exposures or a single raw exposure
179 <DD> The input exposures to be assembled do not adhere to the required format.
182 \throws RuntimeError with the following string:
185 <DT> No ccd detector found
186 <DD> The detector set on the input exposure is not set.
190 if hasattr(assembleInput,
"has_key"):
192 ccd = assembleInput.itervalues().next().getDetector()
194 def getNextExposure(amp):
195 return assembleInput[amp.getName()]
196 elif hasattr(assembleInput,
"getMaskedImage"):
197 ccd = assembleInput.getDetector()
199 def getNextExposure(amp):
202 raise TypeError(
"Expected either a dictionary of amp exposures or a single raw exposure")
205 raise RuntimeError(
"No ccd detector found")
207 if not self.config.doTrim:
208 outBox = cameraGeomUtils.calcRawCcdBBox(ccd)
210 outBox = ccd.getBBox()
211 outExposure = afwImage.ExposureF(outBox)
212 outMI = outExposure.getMaskedImage()
214 if self.config.doTrim:
215 assemble = cameraGeom.assembleAmplifierImage
217 assemble = cameraGeom.assembleAmplifierRawImage
220 inMI = getNextExposure(amp).getMaskedImage()
221 assemble(outMI, inMI, amp)
222 outExposure.setDetector(ccd)
228 """Set exposure non-image attributes, including wcs and metadata and display exposure (if requested)
230 Call after assembling the pixels
232 @param[in,out] outExposure assembled exposure:
233 - removes unwanted keywords
234 - sets calib, filter, and detector
235 @param[in] inExposure input exposure
237 self.
setWcs(outExposure = outExposure, inExposure = inExposure)
239 exposureMetadata = inExposure.getMetadata()
241 if exposureMetadata.exists(key):
242 exposureMetadata.remove(key)
243 outExposure.setMetadata(exposureMetadata)
245 if self.config.setGain:
246 self.
setGain(outExposure = outExposure)
248 inCalib = inExposure.getCalib()
249 outCalib = outExposure.getCalib()
250 outCalib.setExptime(inCalib.getExptime())
251 outCalib.setMidTime(inCalib.getMidTime())
253 outExposure.setFilter(inExposure.getFilter())
255 self.display(
"assembledExposure", exposure=outExposure)
257 def setWcs(self, outExposure, inExposure):
258 """Set output WCS = input WCS, adjusted as required for datasecs not starting at lower left corner
260 @param[in,out] outExposure assembled exposure; wcs is set
261 @param[in] inExposure input exposure
263 if inExposure.hasWcs():
264 wcs = inExposure.getWcs()
265 ccd = outExposure.getDetector()
268 raise RuntimeError(
"No amplifier detector information found")
269 cameraGeomUtils.prepareWcsData(wcs, amp0)
270 outExposure.setWcs(wcs)
272 self.log.log(self.log.WARN,
"No WCS found in input exposure")
275 """Renormalize, if requested, and set gain metadata
277 @param[in,out] outExposure assembled exposure:
278 - scales the pixels if config.doRenorm is true
279 - adds some gain keywords to the metadata
281 if outExposure.getMaskedImage().getVariance().getArray().max() == 0:
282 raise RuntimeError(
"Can't calculate the effective gain since the variance plane is set to zero")
283 ccd = outExposure.getDetector()
284 exposureMetadata = outExposure.getMetadata()
288 gain += amp.getGain()
291 if self.config.doRenorm:
292 mi = outExposure.getMaskedImage()
294 exposureMetadata.set(
"GAIN", 1.0)
296 exposureMetadata.add(
"MEDGAIN", medgain)
297 exposureMetadata.add(
"MEANGAIN", meangain)
298 exposureMetadata.add(
"GAINEFF", medgain)
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.