1192 def run(self, ccdExposure, *, camera=None, bias=None, linearizer=None,
1193 crosstalk=None, crosstalkSources=None,
1194 dark=None, flat=None, ptc=None, bfKernel=None, bfGains=None, defects=None,
1195 fringes=pipeBase.Struct(fringes=
None), opticsTransmission=
None, filterTransmission=
None,
1196 sensorTransmission=
None, atmosphereTransmission=
None,
1197 detectorNum=
None, strayLightData=
None, illumMaskedImage=
None,
1198 deferredChargeCalib=
None,
1200 """Perform instrument signature removal on an exposure.
1202 Steps included in the ISR processing, in order performed, are:
1204 - saturation and suspect pixel masking
1205 - overscan subtraction
1206 - CCD assembly of individual amplifiers
1208 - variance image construction
1209 - linearization of non-linear response
1211 - brighter-fatter correction
1214 - stray light subtraction
1216 - masking of known defects and camera specific features
1217 - vignette calculation
1218 - appending transmission curve and distortion model
1222 ccdExposure : `lsst.afw.image.Exposure`
1223 The raw exposure that is to be run through ISR. The
1224 exposure is modified by this method.
1225 camera : `lsst.afw.cameraGeom.Camera`, optional
1226 The camera geometry for this exposure. Required if
1227 one or more of ``ccdExposure``, ``bias``, ``dark``, or
1228 ``flat`` does not have an associated detector.
1229 bias : `lsst.afw.image.Exposure`, optional
1230 Bias calibration frame.
1231 linearizer : `lsst.ip.isr.linearize.LinearizeBase`, optional
1232 Functor for linearization.
1233 crosstalk : `lsst.ip.isr.crosstalk.CrosstalkCalib`, optional
1234 Calibration for crosstalk.
1235 crosstalkSources : `list`, optional
1236 List of possible crosstalk sources.
1237 dark : `lsst.afw.image.Exposure`, optional
1238 Dark calibration frame.
1239 flat : `lsst.afw.image.Exposure`, optional
1240 Flat calibration frame.
1241 ptc : `lsst.ip.isr.PhotonTransferCurveDataset`, optional
1242 Photon transfer curve dataset, with, e.g., gains
1244 bfKernel : `numpy.ndarray`, optional
1245 Brighter-fatter kernel.
1246 bfGains : `dict` of `float`, optional
1247 Gains used to override the detector's nominal gains for the
1248 brighter-fatter correction. A dict keyed by amplifier name for
1249 the detector in question.
1250 defects : `lsst.ip.isr.Defects`, optional
1252 fringes : `lsst.pipe.base.Struct`, optional
1253 Struct containing the fringe correction data, with
1257 fringe calibration frame (`lsst.afw.image.Exposure`)
1259 random seed derived from the ``ccdExposureId`` for random
1260 number generator (`numpy.uint32`)
1261 opticsTransmission: `lsst.afw.image.TransmissionCurve`, optional
1262 A ``TransmissionCurve`` that represents the throughput of the,
1263 optics, to be evaluated in focal-plane coordinates.
1264 filterTransmission : `lsst.afw.image.TransmissionCurve`
1265 A ``TransmissionCurve`` that represents the throughput of the
1266 filter itself, to be evaluated in focal-plane coordinates.
1267 sensorTransmission : `lsst.afw.image.TransmissionCurve`
1268 A ``TransmissionCurve`` that represents the throughput of the
1269 sensor itself, to be evaluated in post-assembly trimmed detector
1271 atmosphereTransmission : `lsst.afw.image.TransmissionCurve`
1272 A ``TransmissionCurve`` that represents the throughput of the
1273 atmosphere, assumed to be spatially constant.
1274 detectorNum : `int`, optional
1275 The integer number for the detector to process.
1276 strayLightData : `object`, optional
1277 Opaque object containing calibration information for stray-light
1278 correction. If `None`, no correction will be performed.
1279 illumMaskedImage : `lsst.afw.image.MaskedImage`, optional
1280 Illumination correction image.
1284 result : `lsst.pipe.base.Struct`
1285 Result struct with component:
1288 The fully ISR corrected exposure.
1289 (`lsst.afw.image.Exposure`)
1291 An alias for ``exposure``. (`lsst.afw.image.Exposure`)
1293 Thumbnail image of the exposure after overscan subtraction.
1296 Thumbnail image of the exposure after flat-field correction.
1298 ``outputStatistics``
1299 Values of the additional statistics calculated.
1304 Raised if a configuration option is set to `True`, but the
1305 required calibration data has not been specified.
1309 The current processed exposure can be viewed by setting the
1310 appropriate `lsstDebug` entries in the ``debug.display``
1311 dictionary. The names of these entries correspond to some of
1312 the `IsrTaskConfig` Boolean options, with the value denoting the
1313 frame to use. The exposure is shown inside the matching
1314 option check and after the processing of that step has
1315 finished. The steps with debug points are:
1326 In addition, setting the ``postISRCCD`` entry displays the
1327 exposure after all ISR processing has finished.
1330 ccdExposure = self.
ensureExposure(ccdExposure, camera, detectorNum)
1335 ccd = ccdExposure.getDetector()
1336 filterLabel = ccdExposure.getFilter()
1337 physicalFilter = isrFunctions.getPhysicalFilter(filterLabel, self.log)
1340 assert not self.config.doAssembleCcd,
"You need a Detector to run assembleCcd."
1341 ccd = [
FakeAmp(ccdExposure, self.config)]
1344 if self.config.doBias
and bias
is None:
1345 raise RuntimeError(
"Must supply a bias exposure if config.doBias=True.")
1347 raise RuntimeError(
"Must supply a linearizer if config.doLinearize=True for this detector.")
1348 if self.config.doBrighterFatter
and bfKernel
is None:
1349 raise RuntimeError(
"Must supply a kernel if config.doBrighterFatter=True.")
1350 if self.config.doDark
and dark
is None:
1351 raise RuntimeError(
"Must supply a dark exposure if config.doDark=True.")
1352 if self.config.doFlat
and flat
is None:
1353 raise RuntimeError(
"Must supply a flat exposure if config.doFlat=True.")
1354 if self.config.doDefect
and defects
is None:
1355 raise RuntimeError(
"Must supply defects if config.doDefect=True.")
1356 if (self.config.doFringe
and physicalFilter
in self.fringe.config.filters
1357 and fringes.fringes
is None):
1362 raise RuntimeError(
"Must supply fringe exposure as a pipeBase.Struct.")
1363 if (self.config.doIlluminationCorrection
and physicalFilter
in self.config.illumFilters
1364 and illumMaskedImage
is None):
1365 raise RuntimeError(
"Must supply an illumcor if config.doIlluminationCorrection=True.")
1366 if (self.config.doDeferredCharge
and deferredChargeCalib
is None):
1367 raise RuntimeError(
"Must supply a deferred charge calibration if config.doDeferredCharge=True.")
1368 if (self.config.usePtcGains
and ptc
is None):
1369 raise RuntimeError(
"No ptcDataset provided to use PTC gains.")
1370 if (self.config.usePtcReadNoise
and ptc
is None):
1371 raise RuntimeError(
"No ptcDataset provided to use PTC read noise.")
1374 exposureMetadata = ccdExposure.getMetadata()
1375 doRaise = self.config.doRaiseOnCalibMismatch
1376 keywords = self.config.cameraKeywordsToCompare
1377 if self.config.doBias:
1380 if self.config.doBrighterFatter:
1382 if self.config.doCrosstalk:
1384 if self.config.doDark:
1387 if self.config.doDefect:
1389 if self.config.doDeferredCharge:
1394 deferredChargeCalib,
1398 if self.config.doFlat:
1401 if (self.config.doFringe
and physicalFilter
in self.fringe.config.filters):
1410 if (self.config.doIlluminationCorrection
and physicalFilter
in self.config.illumFilters):
1421 if self.config.usePtcGains
or self.config.usePtcReadNoise:
1423 if self.config.doStrayLight:
1436 exposureMetadata[
"LSST ISR UNITS"] =
"adu"
1437 exposureMetadata[
"LSST ISR CROSSTALK APPLIED"] =
False
1438 exposureMetadata[
"LSST ISR LINEARIZER APPLIED"] =
False
1439 exposureMetadata[
"LSST ISR CTI APPLIED"] =
False
1440 exposureMetadata[
"LSST ISR BIAS APPLIED"] =
False
1441 exposureMetadata[
"LSST ISR DARK APPLIED"] =
False
1442 exposureMetadata[
"LSST ISR BF APPLIED"] =
False
1443 exposureMetadata[
"LSST ISR FLAT APPLIED"] =
False
1444 exposureMetadata[
"LSST ISR DEFECTS APPLIED"] =
False
1447 if self.config.doConvertIntToFloat:
1448 self.log.info(
"Converting exposure to floating point values.")
1451 if self.config.doBias
and self.config.doBiasBeforeOverscan:
1452 self.log.info(
"Applying bias correction.")
1453 isrFunctions.biasCorrection(ccdExposure.getMaskedImage(), bias.getMaskedImage(),
1454 trimToFit=self.config.doTrimToMatchCalib)
1456 ccdExposure.metadata[
"LSST ISR BIAS APPLIED"] =
True
1461 if self.config.doOverscan
and self.config.overscan.doParallelOverscan:
1463 self.overscan.maskParallelOverscan(ccdExposure, ccd)
1468 if ccdExposure.getBBox().contains(amp.getBBox()):
1473 if self.config.doOverscan
and not badAmp:
1476 self.log.debug(
"Corrected overscan for amplifier %s.", amp.getName())
1477 if overscanResults
is not None and \
1478 self.config.qa
is not None and self.config.qa.saveStats
is True:
1479 if isinstance(overscanResults.overscanMean, float):
1481 mean = overscanResults.overscanMean
1482 median = overscanResults.overscanMedian
1483 sigma = overscanResults.overscanSigma
1484 residMean = overscanResults.residualMean
1485 residMedian = overscanResults.residualMedian
1486 residSigma = overscanResults.residualSigma
1490 mean = overscanResults.overscanMean[0]
1491 median = overscanResults.overscanMedian[0]
1492 sigma = overscanResults.overscanSigma[0]
1493 residMean = overscanResults.residualMean[0]
1494 residMedian = overscanResults.residualMedian[0]
1495 residSigma = overscanResults.residualSigma[0]
1497 self.metadata[f
"FIT MEDIAN {amp.getName()}"] = median
1498 self.metadata[f
"FIT MEAN {amp.getName()}"] = mean
1499 self.metadata[f
"FIT STDEV {amp.getName()}"] = sigma
1500 self.log.debug(
" Overscan stats for amplifer %s: %f +/- %f",
1501 amp.getName(), mean, sigma)
1503 self.metadata[f
"RESIDUAL MEDIAN {amp.getName()}"] = residMedian
1504 self.metadata[f
"RESIDUAL MEAN {amp.getName()}"] = residMean
1505 self.metadata[f
"RESIDUAL STDEV {amp.getName()}"] = residSigma
1506 self.log.debug(
" Overscan stats for amplifer %s after correction: %f +/- %f",
1507 amp.getName(), residMean, residSigma)
1509 ccdExposure.getMetadata().set(
'OVERSCAN',
"Overscan corrected")
1512 self.log.warning(
"Amplifier %s is bad.", amp.getName())
1513 overscanResults =
None
1515 overscans.append(overscanResults
if overscanResults
is not None else None)
1517 self.log.info(
"Skipped OSCAN for %s.", amp.getName())
1523 if self.config.doDeferredCharge:
1524 self.log.info(
"Applying deferred charge/CTI correction.")
1525 self.deferredChargeCorrection.run(
1527 deferredChargeCalib,
1530 self.
debugView(ccdExposure,
"doDeferredCharge")
1531 ccdExposure.metadata[
"LSST ISR CTI APPLIED"] =
True
1533 if self.config.doCrosstalk
and self.config.doCrosstalkBeforeAssemble:
1534 self.log.info(
"Applying crosstalk correction.")
1535 self.crosstalk.run(ccdExposure, crosstalk=crosstalk,
1536 crosstalkSources=crosstalkSources, camera=camera)
1537 self.
debugView(ccdExposure,
"doCrosstalk")
1538 ccdExposure.metadata[
"LSST ISR CROSSTALK APPLIED"] =
True
1540 if self.config.doAssembleCcd:
1541 self.log.info(
"Assembling CCD from amplifiers.")
1542 ccdExposure = self.assembleCcd.assembleCcd(ccdExposure)
1544 if self.config.expectWcs
and not ccdExposure.getWcs():
1545 self.log.warning(
"No WCS found in input exposure.")
1546 self.
debugView(ccdExposure,
"doAssembleCcd")
1549 if self.config.qa.doThumbnailOss:
1550 ossThumb = isrQa.makeThumbnail(ccdExposure, isrQaConfig=self.config.qa)
1552 if self.config.doBias
and not self.config.doBiasBeforeOverscan:
1553 self.log.info(
"Applying bias correction.")
1554 isrFunctions.biasCorrection(ccdExposure.getMaskedImage(), bias.getMaskedImage(),
1555 trimToFit=self.config.doTrimToMatchCalib)
1557 ccdExposure.metadata[
"LSST ISR BIAS APPLIED"] =
True
1559 if self.config.doVariance:
1561 if ccdExposure.getBBox().contains(amp.getBBox()):
1562 self.log.debug(
"Constructing variance map for amplifer %s.", amp.getName())
1563 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1566 if self.config.qa
is not None and self.config.qa.saveStats
is True:
1568 afwMath.MEDIAN | afwMath.STDEVCLIP)
1569 self.metadata[f
"ISR VARIANCE {amp.getName()} MEDIAN"] = \
1570 qaStats.getValue(afwMath.MEDIAN)
1571 self.metadata[f
"ISR VARIANCE {amp.getName()} STDEV"] = \
1572 qaStats.getValue(afwMath.STDEVCLIP)
1573 self.log.debug(
" Variance stats for amplifer %s: %f +/- %f.",
1574 amp.getName(), qaStats.getValue(afwMath.MEDIAN),
1575 qaStats.getValue(afwMath.STDEVCLIP))
1576 if self.config.maskNegativeVariance:
1580 self.log.info(
"Applying linearizer.")
1581 linearizer.applyLinearity(image=ccdExposure.getMaskedImage().getImage(),
1582 detector=ccd, log=self.log)
1583 ccdExposure.metadata[
"LSST ISR LINEARIZER APPLIED"] =
True
1585 if self.config.doCrosstalk
and not self.config.doCrosstalkBeforeAssemble:
1586 self.log.info(
"Applying crosstalk correction.")
1587 self.crosstalk.run(ccdExposure, crosstalk=crosstalk,
1588 crosstalkSources=crosstalkSources)
1589 self.
debugView(ccdExposure,
"doCrosstalk")
1590 ccdExposure.metadata[
"LSST ISR CROSSTALK APPLIED"] =
True
1595 if self.config.doDefect:
1596 self.log.info(
"Masking defects.")
1598 ccdExposure.metadata[
"LSST ISR DEFECTS APPLIED"] =
True
1600 if self.config.numEdgeSuspect > 0:
1601 self.log.info(
"Masking edges as SUSPECT.")
1602 self.
maskEdges(ccdExposure, numEdgePixels=self.config.numEdgeSuspect,
1603 maskPlane=
"SUSPECT", level=self.config.edgeMaskLevel)
1605 if self.config.doNanMasking:
1606 self.log.info(
"Masking non-finite (NAN, inf) value pixels.")
1609 if self.config.doWidenSaturationTrails:
1610 self.log.info(
"Widening saturation trails.")
1611 isrFunctions.widenSaturationTrails(ccdExposure.getMaskedImage().getMask())
1613 if self.config.doCameraSpecificMasking:
1614 self.log.info(
"Masking regions for camera specific reasons.")
1615 self.masking.run(ccdExposure)
1617 if self.config.doBrighterFatter:
1627 interpExp = ccdExposure.clone()
1629 isrFunctions.interpolateFromMask(
1630 maskedImage=interpExp.getMaskedImage(),
1631 fwhm=self.config.fwhm,
1632 growSaturatedFootprints=self.config.growSaturationFootprintSize,
1633 maskNameList=list(self.config.brighterFatterMaskListToInterpolate),
1634 useLegacyInterp=self.config.useLegacyInterp,
1636 bfExp = interpExp.clone()
1638 self.log.info(
"Applying brighter-fatter correction using kernel type %s / gains %s.",
1639 type(bfKernel), type(bfGains))
1640 if self.config.doFluxConservingBrighterFatterCorrection:
1644 self.config.brighterFatterMaxIter,
1645 self.config.brighterFatterThreshold,
1646 self.config.brighterFatterApplyGain,
1653 self.config.brighterFatterMaxIter,
1654 self.config.brighterFatterThreshold,
1655 self.config.brighterFatterApplyGain,
1658 bfCorrIters = bfResults[1]
1659 self.metadata[
"LSST ISR BF ITERS"] = bfCorrIters
1660 if bfCorrIters == self.config.brighterFatterMaxIter - 1:
1661 self.log.warning(
"Brighter-fatter correction did not converge, final difference %f.",
1664 self.log.info(
"Finished brighter-fatter correction in %d iterations.",
1666 image = ccdExposure.getMaskedImage().getImage()
1667 bfCorr = bfExp.getMaskedImage().getImage()
1668 bfCorr -= interpExp.getMaskedImage().getImage()
1677 self.log.info(
"Ensuring image edges are masked as EDGE to the brighter-fatter kernel size.")
1678 self.
maskEdges(ccdExposure, numEdgePixels=numpy.max(bfKernel.shape) // 2,
1681 if self.config.brighterFatterMaskGrowSize > 0:
1682 self.log.info(
"Growing masks to account for brighter-fatter kernel convolution.")
1683 for maskPlane
in self.config.brighterFatterMaskListToInterpolate:
1684 isrFunctions.growMasks(ccdExposure.getMask(),
1685 radius=self.config.brighterFatterMaskGrowSize,
1686 maskNameList=maskPlane,
1687 maskValue=maskPlane)
1689 self.
debugView(ccdExposure,
"doBrighterFatter")
1690 ccdExposure.metadata[
"LSST ISR BF APPLIED"] =
True
1692 if self.config.doDark:
1693 self.log.info(
"Applying dark correction.")
1696 ccdExposure.metadata[
"LSST ISR DARK APPLIED"] =
True
1698 if self.config.doFringe
and not self.config.fringeAfterFlat:
1699 self.log.info(
"Applying fringe correction before flat.")
1700 self.fringe.run(ccdExposure, **fringes.getDict())
1703 if self.config.doStrayLight
and self.strayLight.check(ccdExposure):
1704 self.log.info(
"Checking strayLight correction.")
1705 self.strayLight.run(ccdExposure, strayLightData)
1706 self.
debugView(ccdExposure,
"doStrayLight")
1708 if self.config.doFlat:
1709 self.log.info(
"Applying flat correction.")
1712 ccdExposure.metadata[
"LSST ISR FLAT APPLIED"] =
True
1716 if self.config.doApplyGains:
1717 self.log.info(
"Applying gain correction instead of flat.")
1718 isrFunctions.applyGains(ccdExposure, self.config.normalizeGains,
1720 exposureMetadata[
"LSST ISR UNITS"] =
"electron"
1722 if self.config.doFringe
and self.config.fringeAfterFlat:
1723 self.log.info(
"Applying fringe correction after flat.")
1724 self.fringe.run(ccdExposure, **fringes.getDict())
1726 if self.config.doVignette:
1727 if self.config.doMaskVignettePolygon:
1728 self.log.info(
"Constructing, attaching, and masking vignette polygon.")
1730 self.log.info(
"Constructing and attaching vignette polygon.")
1732 exposure=ccdExposure, doUpdateMask=self.config.doMaskVignettePolygon,
1733 vignetteValue=self.config.vignetteValue, log=self.log)
1735 if self.config.doAttachTransmissionCurve:
1736 self.log.info(
"Adding transmission curves.")
1737 isrFunctions.attachTransmissionCurve(ccdExposure, opticsTransmission=opticsTransmission,
1738 filterTransmission=filterTransmission,
1739 sensorTransmission=sensorTransmission,
1740 atmosphereTransmission=atmosphereTransmission)
1742 flattenedThumb =
None
1743 if self.config.qa.doThumbnailFlattened:
1744 flattenedThumb = isrQa.makeThumbnail(ccdExposure, isrQaConfig=self.config.qa)
1746 if self.config.doIlluminationCorrection
and physicalFilter
in self.config.illumFilters:
1747 self.log.info(
"Performing illumination correction.")
1748 isrFunctions.illuminationCorrection(ccdExposure.getMaskedImage(),
1749 illumMaskedImage, illumScale=self.config.illumScale,
1750 trimToFit=self.config.doTrimToMatchCalib)
1753 if self.config.doSaveInterpPixels:
1754 preInterpExp = ccdExposure.clone()
1769 if self.config.doSetBadRegions:
1770 badPixelCount, badPixelValue = isrFunctions.setBadRegions(ccdExposure)
1771 if badPixelCount > 0:
1772 self.log.info(
"Set %d BAD pixels to %f.", badPixelCount, badPixelValue)
1774 if self.config.doInterpolate:
1775 self.log.info(
"Interpolating masked pixels.")
1776 isrFunctions.interpolateFromMask(
1777 maskedImage=ccdExposure.getMaskedImage(),
1778 fwhm=self.config.fwhm,
1779 growSaturatedFootprints=self.config.growSaturationFootprintSize,
1780 maskNameList=list(self.config.maskListToInterpolate),
1781 useLegacyInterp=self.config.useLegacyInterp,
1787 if self.config.doAmpOffset:
1788 if self.config.ampOffset.doApplyAmpOffset:
1789 self.log.info(
"Measuring and applying amp offset corrections.")
1791 self.log.info(
"Measuring amp offset corrections only, without applying them.")
1792 self.ampOffset.run(ccdExposure)
1794 if self.config.doMeasureBackground:
1795 self.log.info(
"Measuring background level.")
1798 if self.config.qa
is not None and self.config.qa.saveStats
is True:
1800 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1802 afwMath.MEDIAN | afwMath.STDEVCLIP)
1803 self.metadata[f
"ISR BACKGROUND {amp.getName()} MEDIAN"] = qaStats.getValue(afwMath.MEDIAN)
1804 self.metadata[f
"ISR BACKGROUND {amp.getName()} STDEV"] = \
1805 qaStats.getValue(afwMath.STDEVCLIP)
1806 self.log.debug(
" Background stats for amplifer %s: %f +/- %f",
1807 amp.getName(), qaStats.getValue(afwMath.MEDIAN),
1808 qaStats.getValue(afwMath.STDEVCLIP))
1811 if self.config.doStandardStatistics:
1812 metadata = ccdExposure.getMetadata()
1814 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1815 ampName = amp.getName()
1816 metadata[f
"LSST ISR MASK SAT {ampName}"] = isrFunctions.countMaskedPixels(
1817 ampExposure.getMaskedImage(),
1818 [self.config.saturatedMaskName]
1820 metadata[f
"LSST ISR MASK BAD {ampName}"] = isrFunctions.countMaskedPixels(
1821 ampExposure.getMaskedImage(),
1825 afwMath.MEAN | afwMath.MEDIAN | afwMath.STDEVCLIP)
1827 metadata[f
"LSST ISR FINAL MEAN {ampName}"] = qaStats.getValue(afwMath.MEAN)
1828 metadata[f
"LSST ISR FINAL MEDIAN {ampName}"] = qaStats.getValue(afwMath.MEDIAN)
1829 metadata[f
"LSST ISR FINAL STDEV {ampName}"] = qaStats.getValue(afwMath.STDEVCLIP)
1831 k1 = f
"LSST ISR FINAL MEDIAN {ampName}"
1832 k2 = f
"LSST ISR OVERSCAN SERIAL MEDIAN {ampName}"
1833 if self.config.doOverscan
and k1
in metadata
and k2
in metadata:
1834 metadata[f
"LSST ISR LEVEL {ampName}"] = metadata[k1] - metadata[k2]
1836 metadata[f
"LSST ISR LEVEL {ampName}"] = numpy.nan
1839 outputStatistics =
None
1840 if self.config.doCalculateStatistics:
1841 outputStatistics = self.isrStats.run(ccdExposure, serialOverscanResults=overscans,
1842 parallelOverscanResults=[
None for _
in overscans],
1843 bias=bias, dark=dark, flat=flat, ptc=ptc,
1845 doLegacyCtiStatistics=
True).results
1848 outputBin1Exposure =
None
1849 outputBin2Exposure =
None
1850 if self.config.doBinnedExposures:
1851 self.log.info(
"Creating binned exposures.")
1852 outputBin1Exposure = self.binning.run(
1854 binFactor=self.config.binFactor1,
1856 outputBin2Exposure = self.binning.run(
1858 binFactor=self.config.binFactor2,
1861 self.
debugView(ccdExposure,
"postISRCCD")
1863 return pipeBase.Struct(
1864 exposure=ccdExposure,
1866 flattenedThumb=flattenedThumb,
1868 outputBin1Exposure=outputBin1Exposure,
1869 outputBin2Exposure=outputBin2Exposure,
1871 preInterpExposure=preInterpExp,
1872 outputExposure=ccdExposure,
1873 outputOssThumbnail=ossThumb,
1874 outputFlattenedThumbnail=flattenedThumb,
1875 outputStatistics=outputStatistics,