1193 def run(self, ccdExposure, *, camera=None, bias=None, linearizer=None,
1194 crosstalk=None, crosstalkSources=None,
1195 dark=None, flat=None, ptc=None, bfKernel=None, bfGains=None, defects=None,
1196 fringes=pipeBase.Struct(fringes=
None), opticsTransmission=
None, filterTransmission=
None,
1197 sensorTransmission=
None, atmosphereTransmission=
None,
1198 detectorNum=
None, strayLightData=
None, illumMaskedImage=
None,
1199 deferredChargeCalib=
None,
1201 """Perform instrument signature removal on an exposure.
1203 Steps included in the ISR processing, in order performed, are:
1205 - saturation and suspect pixel masking
1206 - overscan subtraction
1207 - CCD assembly of individual amplifiers
1209 - variance image construction
1210 - linearization of non-linear response
1212 - brighter-fatter correction
1215 - stray light subtraction
1217 - masking of known defects and camera specific features
1218 - vignette calculation
1219 - appending transmission curve and distortion model
1223 ccdExposure : `lsst.afw.image.Exposure`
1224 The raw exposure that is to be run through ISR. The
1225 exposure is modified by this method.
1226 camera : `lsst.afw.cameraGeom.Camera`, optional
1227 The camera geometry for this exposure. Required if
1228 one or more of ``ccdExposure``, ``bias``, ``dark``, or
1229 ``flat`` does not have an associated detector.
1230 bias : `lsst.afw.image.Exposure`, optional
1231 Bias calibration frame.
1232 linearizer : `lsst.ip.isr.linearize.LinearizeBase`, optional
1233 Functor for linearization.
1234 crosstalk : `lsst.ip.isr.crosstalk.CrosstalkCalib`, optional
1235 Calibration for crosstalk.
1236 crosstalkSources : `list`, optional
1237 List of possible crosstalk sources.
1238 dark : `lsst.afw.image.Exposure`, optional
1239 Dark calibration frame.
1240 flat : `lsst.afw.image.Exposure`, optional
1241 Flat calibration frame.
1242 ptc : `lsst.ip.isr.PhotonTransferCurveDataset`, optional
1243 Photon transfer curve dataset, with, e.g., gains
1245 bfKernel : `numpy.ndarray`, optional
1246 Brighter-fatter kernel.
1247 bfGains : `dict` of `float`, optional
1248 Gains used to override the detector's nominal gains for the
1249 brighter-fatter correction. A dict keyed by amplifier name for
1250 the detector in question.
1251 defects : `lsst.ip.isr.Defects`, optional
1253 fringes : `lsst.pipe.base.Struct`, optional
1254 Struct containing the fringe correction data, with
1258 fringe calibration frame (`lsst.afw.image.Exposure`)
1260 random seed derived from the ``ccdExposureId`` for random
1261 number generator (`numpy.uint32`)
1262 opticsTransmission: `lsst.afw.image.TransmissionCurve`, optional
1263 A ``TransmissionCurve`` that represents the throughput of the,
1264 optics, to be evaluated in focal-plane coordinates.
1265 filterTransmission : `lsst.afw.image.TransmissionCurve`
1266 A ``TransmissionCurve`` that represents the throughput of the
1267 filter itself, to be evaluated in focal-plane coordinates.
1268 sensorTransmission : `lsst.afw.image.TransmissionCurve`
1269 A ``TransmissionCurve`` that represents the throughput of the
1270 sensor itself, to be evaluated in post-assembly trimmed detector
1272 atmosphereTransmission : `lsst.afw.image.TransmissionCurve`
1273 A ``TransmissionCurve`` that represents the throughput of the
1274 atmosphere, assumed to be spatially constant.
1275 detectorNum : `int`, optional
1276 The integer number for the detector to process.
1277 strayLightData : `object`, optional
1278 Opaque object containing calibration information for stray-light
1279 correction. If `None`, no correction will be performed.
1280 illumMaskedImage : `lsst.afw.image.MaskedImage`, optional
1281 Illumination correction image.
1285 result : `lsst.pipe.base.Struct`
1286 Result struct with component:
1289 The fully ISR corrected exposure.
1290 (`lsst.afw.image.Exposure`)
1292 An alias for ``exposure``. (`lsst.afw.image.Exposure`)
1294 Thumbnail image of the exposure after overscan subtraction.
1297 Thumbnail image of the exposure after flat-field correction.
1299 ``outputStatistics``
1300 Values of the additional statistics calculated.
1305 Raised if a configuration option is set to `True`, but the
1306 required calibration data has not been specified.
1310 The current processed exposure can be viewed by setting the
1311 appropriate `lsstDebug` entries in the ``debug.display``
1312 dictionary. The names of these entries correspond to some of
1313 the `IsrTaskConfig` Boolean options, with the value denoting the
1314 frame to use. The exposure is shown inside the matching
1315 option check and after the processing of that step has
1316 finished. The steps with debug points are:
1327 In addition, setting the ``postISRCCD`` entry displays the
1328 exposure after all ISR processing has finished.
1331 ccdExposure = self.
ensureExposure(ccdExposure, camera, detectorNum)
1336 ccd = ccdExposure.getDetector()
1337 filterLabel = ccdExposure.getFilter()
1338 physicalFilter = isrFunctions.getPhysicalFilter(filterLabel, self.log)
1341 assert not self.config.doAssembleCcd,
"You need a Detector to run assembleCcd."
1342 ccd = [
FakeAmp(ccdExposure, self.config)]
1345 if self.config.doBias
and bias
is None:
1346 raise RuntimeError(
"Must supply a bias exposure if config.doBias=True.")
1348 raise RuntimeError(
"Must supply a linearizer if config.doLinearize=True for this detector.")
1349 if self.config.doBrighterFatter
and bfKernel
is None:
1350 raise RuntimeError(
"Must supply a kernel if config.doBrighterFatter=True.")
1351 if self.config.doDark
and dark
is None:
1352 raise RuntimeError(
"Must supply a dark exposure if config.doDark=True.")
1353 if self.config.doFlat
and flat
is None:
1354 raise RuntimeError(
"Must supply a flat exposure if config.doFlat=True.")
1355 if self.config.doDefect
and defects
is None:
1356 raise RuntimeError(
"Must supply defects if config.doDefect=True.")
1357 if (self.config.doFringe
and physicalFilter
in self.fringe.config.filters
1358 and fringes.fringes
is None):
1363 raise RuntimeError(
"Must supply fringe exposure as a pipeBase.Struct.")
1364 if (self.config.doIlluminationCorrection
and physicalFilter
in self.config.illumFilters
1365 and illumMaskedImage
is None):
1366 raise RuntimeError(
"Must supply an illumcor if config.doIlluminationCorrection=True.")
1367 if (self.config.doDeferredCharge
and deferredChargeCalib
is None):
1368 raise RuntimeError(
"Must supply a deferred charge calibration if config.doDeferredCharge=True.")
1369 if (self.config.usePtcGains
and ptc
is None):
1370 raise RuntimeError(
"No ptcDataset provided to use PTC gains.")
1371 if (self.config.usePtcReadNoise
and ptc
is None):
1372 raise RuntimeError(
"No ptcDataset provided to use PTC read noise.")
1375 exposureMetadata = ccdExposure.getMetadata()
1376 doRaise = self.config.doRaiseOnCalibMismatch
1377 keywords = self.config.cameraKeywordsToCompare
1378 if self.config.doBias:
1381 if self.config.doBrighterFatter:
1383 if self.config.doCrosstalk:
1385 if self.config.doDark:
1388 if self.config.doDefect:
1390 if self.config.doDeferredCharge:
1395 deferredChargeCalib,
1399 if self.config.doFlat:
1402 if (self.config.doFringe
and physicalFilter
in self.fringe.config.filters):
1411 if (self.config.doIlluminationCorrection
and physicalFilter
in self.config.illumFilters):
1422 if self.config.usePtcGains
or self.config.usePtcReadNoise:
1424 if self.config.doStrayLight:
1437 exposureMetadata[
"LSST ISR UNITS"] =
"adu"
1438 exposureMetadata[
"LSST ISR CROSSTALK APPLIED"] =
False
1439 exposureMetadata[
"LSST ISR LINEARIZER APPLIED"] =
False
1440 exposureMetadata[
"LSST ISR CTI APPLIED"] =
False
1441 exposureMetadata[
"LSST ISR BIAS APPLIED"] =
False
1442 exposureMetadata[
"LSST ISR DARK APPLIED"] =
False
1443 exposureMetadata[
"LSST ISR BF APPLIED"] =
False
1444 exposureMetadata[
"LSST ISR FLAT APPLIED"] =
False
1445 exposureMetadata[
"LSST ISR DEFECTS APPLIED"] =
False
1448 if self.config.doConvertIntToFloat:
1449 self.log.info(
"Converting exposure to floating point values.")
1452 if self.config.doBias
and self.config.doBiasBeforeOverscan:
1453 self.log.info(
"Applying bias correction.")
1454 isrFunctions.biasCorrection(ccdExposure.getMaskedImage(), bias.getMaskedImage(),
1455 trimToFit=self.config.doTrimToMatchCalib)
1457 ccdExposure.metadata[
"LSST ISR BIAS APPLIED"] =
True
1462 if self.config.doOverscan
and self.config.overscan.doParallelOverscan:
1464 self.overscan.maskParallelOverscan(ccdExposure, ccd)
1469 if ccdExposure.getBBox().contains(amp.getBBox()):
1474 if self.config.doOverscan
and not badAmp:
1477 self.log.debug(
"Corrected overscan for amplifier %s.", amp.getName())
1478 if overscanResults
is not None and \
1479 self.config.qa
is not None and self.config.qa.saveStats
is True:
1480 if isinstance(overscanResults.overscanMean, float):
1482 mean = overscanResults.overscanMean
1483 median = overscanResults.overscanMedian
1484 sigma = overscanResults.overscanSigma
1485 residMean = overscanResults.residualMean
1486 residMedian = overscanResults.residualMedian
1487 residSigma = overscanResults.residualSigma
1491 mean = overscanResults.overscanMean[0]
1492 median = overscanResults.overscanMedian[0]
1493 sigma = overscanResults.overscanSigma[0]
1494 residMean = overscanResults.residualMean[0]
1495 residMedian = overscanResults.residualMedian[0]
1496 residSigma = overscanResults.residualSigma[0]
1498 self.metadata[f
"FIT MEDIAN {amp.getName()}"] = median
1499 self.metadata[f
"FIT MEAN {amp.getName()}"] = mean
1500 self.metadata[f
"FIT STDEV {amp.getName()}"] = sigma
1501 self.log.debug(
" Overscan stats for amplifer %s: %f +/- %f",
1502 amp.getName(), mean, sigma)
1504 self.metadata[f
"RESIDUAL MEDIAN {amp.getName()}"] = residMedian
1505 self.metadata[f
"RESIDUAL MEAN {amp.getName()}"] = residMean
1506 self.metadata[f
"RESIDUAL STDEV {amp.getName()}"] = residSigma
1507 self.log.debug(
" Overscan stats for amplifer %s after correction: %f +/- %f",
1508 amp.getName(), residMean, residSigma)
1510 ccdExposure.getMetadata().set(
'OVERSCAN',
"Overscan corrected")
1513 self.log.warning(
"Amplifier %s is bad.", amp.getName())
1514 overscanResults =
None
1516 overscans.append(overscanResults
if overscanResults
is not None else None)
1518 self.log.info(
"Skipped OSCAN for %s.", amp.getName())
1524 if self.config.doDeferredCharge:
1525 self.log.info(
"Applying deferred charge/CTI correction.")
1526 self.deferredChargeCorrection.
run(
1528 deferredChargeCalib,
1531 self.
debugView(ccdExposure,
"doDeferredCharge")
1532 ccdExposure.metadata[
"LSST ISR CTI APPLIED"] =
True
1534 if self.config.doCrosstalk
and self.config.doCrosstalkBeforeAssemble:
1535 self.log.info(
"Applying crosstalk correction.")
1536 self.crosstalk.
run(ccdExposure, crosstalk=crosstalk,
1537 crosstalkSources=crosstalkSources, camera=camera)
1538 self.
debugView(ccdExposure,
"doCrosstalk")
1539 ccdExposure.metadata[
"LSST ISR CROSSTALK APPLIED"] =
True
1541 if self.config.doAssembleCcd:
1542 self.log.info(
"Assembling CCD from amplifiers.")
1543 ccdExposure = self.assembleCcd.assembleCcd(ccdExposure)
1545 if self.config.expectWcs
and not ccdExposure.getWcs():
1546 self.log.warning(
"No WCS found in input exposure.")
1547 self.
debugView(ccdExposure,
"doAssembleCcd")
1550 if self.config.qa.doThumbnailOss:
1551 ossThumb = isrQa.makeThumbnail(ccdExposure, isrQaConfig=self.config.qa)
1553 if self.config.doBias
and not self.config.doBiasBeforeOverscan:
1554 self.log.info(
"Applying bias correction.")
1555 isrFunctions.biasCorrection(ccdExposure.getMaskedImage(), bias.getMaskedImage(),
1556 trimToFit=self.config.doTrimToMatchCalib)
1558 ccdExposure.metadata[
"LSST ISR BIAS APPLIED"] =
True
1560 if self.config.doVariance:
1562 if ccdExposure.getBBox().contains(amp.getBBox()):
1563 self.log.debug(
"Constructing variance map for amplifer %s.", amp.getName())
1564 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1567 if self.config.qa
is not None and self.config.qa.saveStats
is True:
1568 qaStats = afwMath.makeStatistics(ampExposure.getVariance(),
1569 afwMath.MEDIAN | afwMath.STDEVCLIP)
1570 self.metadata[f
"ISR VARIANCE {amp.getName()} MEDIAN"] = \
1571 qaStats.getValue(afwMath.MEDIAN)
1572 self.metadata[f
"ISR VARIANCE {amp.getName()} STDEV"] = \
1573 qaStats.getValue(afwMath.STDEVCLIP)
1574 self.log.debug(
" Variance stats for amplifer %s: %f +/- %f.",
1575 amp.getName(), qaStats.getValue(afwMath.MEDIAN),
1576 qaStats.getValue(afwMath.STDEVCLIP))
1577 if self.config.maskNegativeVariance:
1581 self.log.info(
"Applying linearizer.")
1582 linearizer.applyLinearity(image=ccdExposure.getMaskedImage().getImage(),
1583 detector=ccd, log=self.log)
1584 ccdExposure.metadata[
"LSST ISR LINEARIZER APPLIED"] =
True
1586 if self.config.doCrosstalk
and not self.config.doCrosstalkBeforeAssemble:
1587 self.log.info(
"Applying crosstalk correction.")
1588 self.crosstalk.
run(ccdExposure, crosstalk=crosstalk,
1589 crosstalkSources=crosstalkSources)
1590 self.
debugView(ccdExposure,
"doCrosstalk")
1591 ccdExposure.metadata[
"LSST ISR CROSSTALK APPLIED"] =
True
1596 if self.config.doDefect:
1597 self.log.info(
"Masking defects.")
1599 ccdExposure.metadata[
"LSST ISR DEFECTS APPLIED"] =
True
1601 if self.config.numEdgeSuspect > 0:
1602 self.log.info(
"Masking edges as SUSPECT.")
1603 self.
maskEdges(ccdExposure, numEdgePixels=self.config.numEdgeSuspect,
1604 maskPlane=
"SUSPECT", level=self.config.edgeMaskLevel)
1606 if self.config.doNanMasking:
1607 self.log.info(
"Masking non-finite (NAN, inf) value pixels.")
1610 if self.config.doWidenSaturationTrails:
1611 self.log.info(
"Widening saturation trails.")
1612 isrFunctions.widenSaturationTrails(ccdExposure.getMaskedImage().getMask())
1614 if self.config.doCameraSpecificMasking:
1615 self.log.info(
"Masking regions for camera specific reasons.")
1616 self.masking.
run(ccdExposure)
1618 if self.config.doBrighterFatter:
1628 interpExp = ccdExposure.clone()
1630 isrFunctions.interpolateFromMask(
1631 maskedImage=interpExp.getMaskedImage(),
1632 fwhm=self.config.fwhm,
1633 growSaturatedFootprints=self.config.growSaturationFootprintSize,
1634 maskNameList=list(self.config.brighterFatterMaskListToInterpolate),
1635 useLegacyInterp=self.config.useLegacyInterp,
1637 bfExp = interpExp.clone()
1639 self.log.info(
"Applying brighter-fatter correction using kernel type %s / gains %s.",
1640 type(bfKernel), type(bfGains))
1641 if self.config.doFluxConservingBrighterFatterCorrection:
1645 self.config.brighterFatterMaxIter,
1646 self.config.brighterFatterThreshold,
1647 self.config.brighterFatterApplyGain,
1654 self.config.brighterFatterMaxIter,
1655 self.config.brighterFatterThreshold,
1656 self.config.brighterFatterApplyGain,
1659 bfCorrIters = bfResults[1]
1660 self.metadata[
"LSST ISR BF ITERS"] = bfCorrIters
1661 if bfCorrIters == self.config.brighterFatterMaxIter - 1:
1662 self.log.warning(
"Brighter-fatter correction did not converge, final difference %f.",
1665 self.log.info(
"Finished brighter-fatter correction in %d iterations.",
1667 image = ccdExposure.getMaskedImage().getImage()
1668 bfCorr = bfExp.getMaskedImage().getImage()
1669 bfCorr -= interpExp.getMaskedImage().getImage()
1678 self.log.info(
"Ensuring image edges are masked as EDGE to the brighter-fatter kernel size.")
1679 self.
maskEdges(ccdExposure, numEdgePixels=numpy.max(bfKernel.shape) // 2,
1682 if self.config.brighterFatterMaskGrowSize > 0:
1683 self.log.info(
"Growing masks to account for brighter-fatter kernel convolution.")
1684 for maskPlane
in self.config.brighterFatterMaskListToInterpolate:
1685 isrFunctions.growMasks(ccdExposure.getMask(),
1686 radius=self.config.brighterFatterMaskGrowSize,
1687 maskNameList=maskPlane,
1688 maskValue=maskPlane)
1690 self.
debugView(ccdExposure,
"doBrighterFatter")
1691 ccdExposure.metadata[
"LSST ISR BF APPLIED"] =
True
1693 if self.config.doDark:
1694 self.log.info(
"Applying dark correction.")
1697 ccdExposure.metadata[
"LSST ISR DARK APPLIED"] =
True
1699 if self.config.doFringe
and not self.config.fringeAfterFlat:
1700 self.log.info(
"Applying fringe correction before flat.")
1701 self.fringe.
run(ccdExposure, **fringes.getDict())
1704 if self.config.doStrayLight
and self.strayLight.check(ccdExposure):
1705 self.log.info(
"Checking strayLight correction.")
1706 self.strayLight.
run(ccdExposure, strayLightData)
1707 self.
debugView(ccdExposure,
"doStrayLight")
1709 if self.config.doFlat:
1710 self.log.info(
"Applying flat correction.")
1713 ccdExposure.metadata[
"LSST ISR FLAT APPLIED"] =
True
1717 if self.config.doApplyGains:
1718 self.log.info(
"Applying gain correction instead of flat.")
1719 isrFunctions.applyGains(ccdExposure, self.config.normalizeGains,
1721 exposureMetadata[
"LSST ISR UNITS"] =
"electron"
1723 if self.config.doFringe
and self.config.fringeAfterFlat:
1724 self.log.info(
"Applying fringe correction after flat.")
1725 self.fringe.
run(ccdExposure, **fringes.getDict())
1727 if self.config.doVignette:
1728 if self.config.doMaskVignettePolygon:
1729 self.log.info(
"Constructing, attaching, and masking vignette polygon.")
1731 self.log.info(
"Constructing and attaching vignette polygon.")
1733 exposure=ccdExposure, doUpdateMask=self.config.doMaskVignettePolygon,
1734 vignetteValue=self.config.vignetteValue, log=self.log)
1736 if self.config.doAttachTransmissionCurve:
1737 self.log.info(
"Adding transmission curves.")
1738 isrFunctions.attachTransmissionCurve(ccdExposure, opticsTransmission=opticsTransmission,
1739 filterTransmission=filterTransmission,
1740 sensorTransmission=sensorTransmission,
1741 atmosphereTransmission=atmosphereTransmission)
1743 flattenedThumb =
None
1744 if self.config.qa.doThumbnailFlattened:
1745 flattenedThumb = isrQa.makeThumbnail(ccdExposure, isrQaConfig=self.config.qa)
1747 if self.config.doIlluminationCorrection
and physicalFilter
in self.config.illumFilters:
1748 self.log.info(
"Performing illumination correction.")
1749 isrFunctions.illuminationCorrection(ccdExposure.getMaskedImage(),
1750 illumMaskedImage, illumScale=self.config.illumScale,
1751 trimToFit=self.config.doTrimToMatchCalib)
1754 if self.config.doSaveInterpPixels:
1755 preInterpExp = ccdExposure.clone()
1770 if self.config.doSetBadRegions:
1771 badPixelCount, badPixelValue = isrFunctions.setBadRegions(ccdExposure)
1772 if badPixelCount > 0:
1773 self.log.info(
"Set %d BAD pixels to %f.", badPixelCount, badPixelValue)
1775 if self.config.doInterpolate:
1776 self.log.info(
"Interpolating masked pixels.")
1777 isrFunctions.interpolateFromMask(
1778 maskedImage=ccdExposure.getMaskedImage(),
1779 fwhm=self.config.fwhm,
1780 growSaturatedFootprints=self.config.growSaturationFootprintSize,
1781 maskNameList=list(self.config.maskListToInterpolate),
1782 useLegacyInterp=self.config.useLegacyInterp,
1788 if self.config.doAmpOffset:
1789 if self.config.ampOffset.doApplyAmpOffset:
1790 self.log.info(
"Measuring and applying amp offset corrections.")
1792 self.log.info(
"Measuring amp offset corrections only, without applying them.")
1793 self.ampOffset.
run(ccdExposure)
1795 if self.config.doMeasureBackground:
1796 self.log.info(
"Measuring background level.")
1799 if self.config.qa
is not None and self.config.qa.saveStats
is True:
1801 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1802 qaStats = afwMath.makeStatistics(ampExposure.getImage(),
1803 afwMath.MEDIAN | afwMath.STDEVCLIP)
1804 self.metadata[f
"ISR BACKGROUND {amp.getName()} MEDIAN"] = qaStats.getValue(afwMath.MEDIAN)
1805 self.metadata[f
"ISR BACKGROUND {amp.getName()} STDEV"] = \
1806 qaStats.getValue(afwMath.STDEVCLIP)
1807 self.log.debug(
" Background stats for amplifer %s: %f +/- %f",
1808 amp.getName(), qaStats.getValue(afwMath.MEDIAN),
1809 qaStats.getValue(afwMath.STDEVCLIP))
1812 if self.config.doStandardStatistics:
1813 metadata = ccdExposure.getMetadata()
1815 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1816 ampName = amp.getName()
1817 metadata[f
"LSST ISR MASK SAT {ampName}"] = isrFunctions.countMaskedPixels(
1818 ampExposure.getMaskedImage(),
1819 [self.config.saturatedMaskName]
1821 metadata[f
"LSST ISR MASK BAD {ampName}"] = isrFunctions.countMaskedPixels(
1822 ampExposure.getMaskedImage(),
1825 qaStats = afwMath.makeStatistics(ampExposure.getImage(),
1826 afwMath.MEAN | afwMath.MEDIAN | afwMath.STDEVCLIP)
1828 metadata[f
"LSST ISR FINAL MEAN {ampName}"] = qaStats.getValue(afwMath.MEAN)
1829 metadata[f
"LSST ISR FINAL MEDIAN {ampName}"] = qaStats.getValue(afwMath.MEDIAN)
1830 metadata[f
"LSST ISR FINAL STDEV {ampName}"] = qaStats.getValue(afwMath.STDEVCLIP)
1832 k1 = f
"LSST ISR FINAL MEDIAN {ampName}"
1833 k2 = f
"LSST ISR OVERSCAN SERIAL MEDIAN {ampName}"
1834 if self.config.doOverscan
and k1
in metadata
and k2
in metadata:
1835 metadata[f
"LSST ISR LEVEL {ampName}"] = metadata[k1] - metadata[k2]
1837 metadata[f
"LSST ISR LEVEL {ampName}"] = numpy.nan
1840 outputStatistics =
None
1841 if self.config.doCalculateStatistics:
1842 outputStatistics = self.isrStats.
run(ccdExposure, serialOverscanResults=overscans,
1843 parallelOverscanResults=[
None for _
in overscans],
1844 bias=bias, dark=dark, flat=flat, ptc=ptc,
1846 doLegacyCtiStatistics=
True).results
1849 outputBin1Exposure =
None
1850 outputBin2Exposure =
None
1851 if self.config.doBinnedExposures:
1852 self.log.info(
"Creating binned exposures.")
1853 outputBin1Exposure = self.binning.
run(
1855 binFactor=self.config.binFactor1,
1857 outputBin2Exposure = self.binning.
run(
1859 binFactor=self.config.binFactor2,
1862 self.
debugView(ccdExposure,
"postISRCCD")
1864 return pipeBase.Struct(
1865 exposure=ccdExposure,
1867 flattenedThumb=flattenedThumb,
1869 outputBin1Exposure=outputBin1Exposure,
1870 outputBin2Exposure=outputBin2Exposure,
1872 preInterpExposure=preInterpExp,
1873 outputExposure=ccdExposure,
1874 outputOssThumbnail=ossThumb,
1875 outputFlattenedThumbnail=flattenedThumb,
1876 outputStatistics=outputStatistics,