1026 Mask SATURATED and SUSPECT pixels and check if any amplifiers
1031 badAmpDict : `str` [`bool`]
1032 Dictionary of amplifiers, keyed by name, value is True if
1033 amplifier is fully masked.
1034 ccdExposure : `lsst.afw.image.Exposure`
1035 Input exposure to be masked.
1036 detector : `lsst.afw.cameraGeom.Detector`
1038 defects : `lsst.ip.isr.Defects`
1039 List of defects. Used to determine if an entire
1041 detectorConfig : `lsst.ip.isr.OverscanDetectorConfig`
1042 Per-amplifier configurations.
1043 ptc : `lsst.ip.isr.PhotonTransferCurveDataset`, optional
1044 PTC dataset (used if configured to use PTCTURNOFF).
1048 badAmpDict : `str`[`bool`]
1049 Dictionary of amplifiers, keyed by name.
1051 maskedImage = ccdExposure.getMaskedImage()
1053 metadata = ccdExposure.metadata
1055 if self.config.doSaturation
and self.config.defaultSaturationSource ==
"PTCTURNOFF" and ptc
is None:
1056 raise RuntimeError(
"Must provide ptc if using PTCTURNOFF as saturation source.")
1057 if self.config.doSuspect
and self.config.defaultSuspectSource ==
"PTCTURNOFF" and ptc
is None:
1058 raise RuntimeError(
"Must provide ptc if using PTCTURNOFF as suspect source.")
1060 for amp
in detector:
1061 ampName = amp.getName()
1063 ampConfig = detectorConfig.getOverscanAmpConfig(amp)
1065 if badAmpDict[ampName]:
1071 if self.config.doSaturation:
1072 if self.config.defaultSaturationSource ==
"PTCTURNOFF":
1073 limits.update({self.config.saturatedMaskName: ptc.ptcTurnoff[amp.getName()]})
1074 elif self.config.defaultSaturationSource ==
"CAMERAMODEL":
1076 limits.update({self.config.saturatedMaskName: amp.getSaturation()})
1077 elif self.config.defaultSaturationSource ==
"NONE":
1078 limits.update({self.config.saturatedMaskName: numpy.inf})
1081 if math.isfinite(ampConfig.saturation):
1082 limits.update({self.config.saturatedMaskName: ampConfig.saturation})
1083 metadata[f
"LSST ISR SATURATION LEVEL {ampName}"] = limits[self.config.saturatedMaskName]
1085 if self.config.doSuspect:
1086 if self.config.defaultSuspectSource ==
"PTCTURNOFF":
1087 limits.update({self.config.suspectMaskName: ptc.ptcTurnoff[amp.getName()]})
1088 elif self.config.defaultSuspectSource ==
"CAMERAMODEL":
1090 limits.update({self.config.suspectMaskName: amp.getSuspectLevel()})
1091 elif self.config.defaultSuspectSource ==
"NONE":
1092 limits.update({self.config.suspectMaskName: numpy.inf})
1095 if math.isfinite(ampConfig.suspectLevel):
1096 limits.update({self.config.suspectMaskName: ampConfig.suspectLevel})
1097 metadata[f
"LSST ISR SUSPECT LEVEL {ampName}"] = limits[self.config.suspectMaskName]
1099 for maskName, maskThreshold
in limits.items():
1100 if not math.isnan(maskThreshold):
1101 dataView = maskedImage.Factory(maskedImage, amp.getRawBBox())
1102 toMask = (dataView.image.array >= maskThreshold)
1103 dataView.mask.array[toMask] |= dataView.mask.getPlaneBitMask(maskName)
1107 maskView = afwImage.Mask(maskedImage.getMask(), amp.getRawDataBBox(),
1109 maskVal = maskView.getPlaneBitMask([self.config.saturatedMaskName,
1110 self.config.suspectMaskName])
1111 if numpy.all(maskView.getArray() & maskVal > 0):
1112 self.log.warning(
"Amplifier %s is bad (completely SATURATED or SUSPECT)", ampName)
1113 badAmpDict[ampName] =
True
1114 maskView |= maskView.getPlaneBitMask(
"BAD")
2040 deferredChargeCalib=None,
2043 gainCorrection=None,
2047 electroBfDistortionMatrix=None,
2052 """Run the IsrTaskLSST task.
2056 ccdExposure : `lsst.afw.image.Exposure`
2057 Exposure to run ISR.
2058 dnlLUT : `None`, optional
2059 DNL lookup table; placeholder, unused.
2060 bias : `lsst.afw.image.Exposure`, optional
2062 deferredChargeCalib : `lsst.ip.isr.DeferredChargeCalib`, optional
2063 Deferred charge calibration.
2064 linearizer : `lsst.ip.isr.Linearizer`, optional
2065 Linearizer calibration.
2066 ptc : `lsst.ip.isr.PhotonTransferCurveDataset`, optional
2068 gainCorrection : `lsst.ip.isr.GainCorrection`, optional
2069 Gain correction dataset.
2070 crosstalk : `lsst.ip.isr.CrosstalkCalib`, optional
2071 Crosstalk calibration dataset.
2072 defects : `lsst.ip.isr.Defects`, optional
2074 bfKernel : `lsst.ip.isr.BrighterFatterKernel`, optional
2075 Brighter-fatter kernel dataset.
2076 dark : `lsst.afw.image.Exposure`, optional
2078 flat : `lsst.afw.image.Exposure`, optional
2080 camera : `lsst.afw.cameraGeom.Camera`, optional
2085 result : `lsst.pipe.base.Struct`
2087 ``exposure``: `lsst.afw.image.Exposure`
2088 Calibrated exposure.
2089 ``outputBin1Exposure``: `lsst.afw.image.Exposure`
2090 Binned exposure (bin1 config).
2091 ``outputBin2Exposure``: `lsst.afw.image.Exposure`
2092 Binned exposure (bin2 config).
2093 ``outputExposure``: `lsst.afw.image.Exposure`
2094 Calibrated exposure (same as ``exposure``).
2095 ``outputStatistics``: `lsst.ip.isr.isrStatistics`
2096 Calibrated exposure statistics.
2098 detector = ccdExposure.getDetector()
2100 overscanDetectorConfig = self.config.overscanCamera.getOverscanDetectorConfig(detector)
2102 if self.config.doBootstrap:
2104 self.log.warning(
"Task configured with doBootstrap=True. Ignoring provided PTC.")
2107 if self.config.useGainsFrom ==
"LINEARIZER":
2108 if linearizer
is None:
2109 raise RuntimeError(
"doBootstrap==False and useGainsFrom == 'LINEARIZER' but "
2110 "no linearizer provided.")
2111 elif self.config.useGainsFrom ==
"PTC":
2113 raise RuntimeError(
"doBootstrap==False and useGainsFrom == 'PTC' but no PTC provided.")
2116 exposureMetadata = ccdExposure.metadata
2117 doRaise = self.config.doRaiseOnCalibMismatch
2118 keywords = self.config.cameraKeywordsToCompare
2119 if not self.config.doBootstrap:
2120 if self.config.useGainsFrom ==
"LINEARIZER":
2122 "LINEARIZER", log=self.log)
2123 elif self.config.useGainsFrom ==
"PTC":
2127 if self.config.doCorrectGains
and gainCorrection
is not None:
2137 if self.config.doCorrectGains:
2138 raise RuntimeError(
"doCorrectGains is True but no ptc provided.")
2139 if self.config.doDiffNonLinearCorrection:
2141 raise RuntimeError(
"doDiffNonLinearCorrection is True but no dnlLUT provided.")
2143 if self.config.doLinearize:
2144 if linearizer
is None:
2145 raise RuntimeError(
"doLinearize is True but no linearizer provided.")
2147 if self.config.doBias:
2149 raise RuntimeError(
"doBias is True but no bias provided.")
2152 if self.config.doCrosstalk:
2153 if crosstalk
is None:
2154 raise RuntimeError(
"doCrosstalk is True but no crosstalk provided.")
2156 if self.config.doDeferredCharge:
2157 if deferredChargeCalib
is None:
2158 raise RuntimeError(
"doDeferredCharge is True but no deferredChargeCalib provided.")
2163 deferredChargeCalib,
2167 if self.config.doDefect:
2169 raise RuntimeError(
"doDefect is True but no defects provided.")
2171 if self.config.doDark:
2173 raise RuntimeError(
"doDark is True but no dark frame provided.")
2176 if self.config.doBrighterFatter:
2177 if self.config.brighterFatterCorrectionMethod
in [
"ASTIER23",
"ASTIER23+FILTERCORRECTION"]:
2178 if electroBfDistortionMatrix
is None:
2179 raise RuntimeError(
"Must supply an electroBfDistortionMatrix if BF "
2180 "correction method is ASTIER23*.")
2182 electroBfDistortionMatrix,
"bf", log=self.log)
2183 elif self.config.brighterFatterCorrectionMethod
in [
"COULTON18",
"COULTON18_FLUX_CONSERVING"]:
2184 if bfKernel
is None:
2185 raise RuntimeError(
"Must supply an kernel if BF correction method is COULTON*.")
2188 raise ValueError(
"%s is not a known brighter-fatter correction "
2189 "method." % self.config.brighterFatterCorrectionMethod)
2190 if self.config.doFlat:
2192 raise RuntimeError(
"doFlat is True but no flat provided.")
2195 if self.config.doSaturation:
2196 if self.config.defaultSaturationSource
in [
"PTCTURNOFF",]:
2199 "doSaturation is True and defaultSaturationSource is "
2200 f
"{self.config.defaultSaturationSource}, but no ptc provided."
2202 if self.config.doSuspect:
2203 if self.config.defaultSuspectSource
in [
"PTCTURNOFF",]:
2206 "doSuspect is True and defaultSuspectSource is "
2207 f
"{self.config.defaultSuspectSource}, but no ptc provided."
2210 if self.config.doCheckUnprocessableData
and self.config.bssVoltageMinimum > 0.0:
2217 exposureMetadata[
"LSST ISR UNITS"] =
"adu"
2218 exposureMetadata[
"LSST ISR GAINCORRECTION APPLIED"] =
False
2219 exposureMetadata[
"LSST ISR CROSSTALK APPLIED"] =
False
2220 exposureMetadata[
"LSST ISR OVERSCANLEVEL CHECKED"] =
False
2221 exposureMetadata[
"LSST ISR NOISE CHECKED"] =
False
2222 exposureMetadata[
"LSST ISR LINEARIZER APPLIED"] =
False
2223 exposureMetadata[
"LSST ISR CTI APPLIED"] =
False
2224 exposureMetadata[
"LSST ISR BIAS APPLIED"] =
False
2225 exposureMetadata[
"LSST ISR DARK APPLIED"] =
False
2226 exposureMetadata[
"LSST ISR BF APPLIED"] =
False
2227 exposureMetadata[
"LSST ISR FLAT APPLIED"] =
False
2228 exposureMetadata[
"LSST ISR DEFECTS APPLIED"] =
False
2230 if self.config.doBootstrap:
2231 self.log.info(
"Configured using doBootstrap=True; using gain of 1.0 (adu units)")
2233 for amp
in detector:
2234 ptc.gain[amp.getName()] = 1.0
2235 ptc.noise[amp.getName()] = 0.0
2236 ptc.ptcTurnoff[amp.getName()] = numpy.inf
2237 elif self.config.useGainsFrom ==
"LINEARIZER":
2238 self.log.info(
"Using gains from linearizer.")
2241 for amp
in detector:
2242 ptc.gain[amp.getName()] = linearizer.inputGain[amp.getName()]
2243 ptc.noise[amp.getName()] = 0.0
2244 ptc.ptcTurnoff[amp.getName()] = linearizer.inputTurnoff[amp.getName()]
2246 exposureMetadata[
"LSST ISR BOOTSTRAP"] = self.config.doBootstrap
2253 for amp
in detector:
2254 if not math.isnan(gain := overscanDetectorConfig.getOverscanAmpConfig(amp).gain):
2255 gains[amp.getName()] = gain
2257 "Overriding gain for amp %s with configured value of %.3f.",
2264 self.log.debug(
"Converting exposure to floating point values.")
2276 if self.config.doDiffNonLinearCorrection:
2287 if overscanDetectorConfig.doAnySerialOverscan:
2290 overscanDetectorConfig,
2296 if self.config.doBootstrap
or self.config.useGainsFrom ==
"LINEARIZER":
2298 for amp, serialOverscan
in zip(detector, serialOverscans):
2299 if serialOverscan
is None:
2300 ptc.noise[amp.getName()] = 0.0
2308 ptc.noise[amp.getName()] = serialOverscan.residualSigma * gains[amp.getName()]
2310 serialOverscans = [
None]*len(detector)
2322 overscanDetectorConfig,
2328 if self.config.doCorrectGains
and gainCorrection
is not None:
2329 self.log.info(
"Correcting gains based on input GainCorrection.")
2330 gainCorrection.correctGains(gains, exposure=ccdExposure)
2331 exposureMetadata[
"LSST ISR GAINCORRECTION APPLIED"] =
True
2332 elif self.config.doCorrectGains:
2333 self.log.info(
"Skipping gain correction because no GainCorrection available.")
2338 if self.config.doApplyGains:
2339 self.log.info(
"Using gain values to convert from adu to electron units.")
2340 isrFunctions.applyGains(ccdExposure, normalizeGains=
False, ptcGains=gains, isTrimmed=
False)
2342 exposureMetadata[
"LSST ISR UNITS"] =
"electron"
2346 for amp
in detector:
2347 ampName = amp.getName()
2348 if (key := f
"LSST ISR SATURATION LEVEL {ampName}")
in exposureMetadata:
2349 exposureMetadata[key] *= gains[ampName]
2350 if (key := f
"LSST ISR SUSPECT LEVEL {ampName}")
in exposureMetadata:
2351 exposureMetadata[key] *= gains[ampName]
2354 metadata = ccdExposure.metadata
2355 metadata[
"LSST ISR READNOISE UNITS"] =
"electron"
2356 metadata[
"LSST ISR PTCTURNOFF UNITS"] =
"electron"
2357 metadata[
"LSST ISR GAIN SOURCE"] = self.config.useGainsFrom
2358 for amp
in detector:
2360 metadata[f
"LSST ISR GAIN {amp.getName()}"] = gains[amp.getName()]
2363 metadata[f
"LSST ISR READNOISE {amp.getName()}"] = ptc.noise[amp.getName()]
2366 turnoff = ptc.ptcTurnoff[amp.getName()] * gains[amp.getName()]
2367 metadata[f
"LSST ISR PTCTURNOFF {amp.getName()}"] = turnoff
2371 if self.config.doCrosstalk:
2372 self.log.info(
"Applying crosstalk corrections to full amplifier region.")
2373 if self.config.doBootstrap
and numpy.any(crosstalk.fitGains != 0):
2374 crosstalkGains =
None
2376 crosstalkGains = gains
2379 crosstalk=crosstalk,
2380 gains=crosstalkGains,
2382 badAmpDict=badAmpDict,
2383 ignoreVariance=
True,
2385 ccdExposure.metadata[
"LSST ISR CROSSTALK APPLIED"] =
True
2388 if numpy.isfinite(self.config.serialOverscanMedianShiftSigmaThreshold):
2390 ccdExposure.metadata[
"LSST ISR OVERSCANLEVEL CHECKED"] =
True
2392 if numpy.isfinite(self.config.ampNoiseThreshold):
2393 badAmpDict = self.
checkAmpNoise(badAmpDict, ccdExposure, ptc)
2394 ccdExposure.metadata[
"LSST ISR NOISE CHECKED"] =
True
2396 if numpy.isfinite(self.config.serialOverscanMedianShiftSigmaThreshold)
or \
2397 numpy.isfinite(self.config.ampNoiseThreshold):
2402 parallelOverscans =
None
2403 if overscanDetectorConfig.doAnyParallelOverscan:
2407 overscanDetectorConfig,
2415 if self.config.doLinearize:
2416 self.log.info(
"Applying linearizer.")
2420 if exposureMetadata[
"LSST ISR UNITS"] ==
"electron":
2421 linearityGains = gains
2423 linearityGains =
None
2424 linearizer.applyLinearity(
2425 image=ccdExposure.image,
2428 gains=linearityGains,
2430 ccdExposure.metadata[
"LSST ISR LINEARIZER APPLIED"] =
True
2435 if self.config.doDeferredCharge:
2436 if self.config.doBootstrap:
2437 self.log.info(
"Applying deferred charge correction with doBootstrap=True: "
2438 "will need to use deferredChargeCalib.inputGain to apply "
2439 "CTI correction in electron units.")
2440 deferredChargeGains = deferredChargeCalib.inputGain
2441 if numpy.all(numpy.isnan(list(deferredChargeGains.values()))):
2442 self.log.warning(
"All gains contained in the deferredChargeCalib are "
2443 "NaN, approximating with gain of 1.0.")
2444 deferredChargeGains = gains
2446 deferredChargeGains = gains
2447 self.deferredChargeCorrection.
run(
2449 deferredChargeCalib,
2450 gains=deferredChargeGains,
2452 ccdExposure.metadata[
"LSST ISR CTI APPLIED"] =
True
2456 untrimmedCcdExposure =
None
2457 if self.config.isrStats.doCtiStatistics:
2458 untrimmedCcdExposure = ccdExposure.clone()
2462 if self.config.doAssembleCcd:
2463 self.log.info(
"Assembling CCD from amplifiers.")
2464 ccdExposure = self.assembleCcd.assembleCcd(ccdExposure)
2466 if self.config.expectWcs
and not ccdExposure.getWcs():
2467 self.log.warning(
"No WCS found in input exposure.")
2470 if self.config.doE2VEdgeBleedMask
and detector.getPhysicalType() ==
"E2V":
2471 isrFunctions.maskE2VEdgeBleed(
2472 exposure=ccdExposure,
2473 e2vEdgeBleedSatMinArea=self.config.e2vEdgeBleedSatMinArea,
2474 e2vEdgeBleedSatMaxArea=self.config.e2vEdgeBleedSatMaxArea,
2475 e2vEdgeBleedYMax=self.config.e2vEdgeBleedYMax,
2476 saturatedMaskName=self.config.saturatedMaskName,
2481 for maskPlane
in self.config.itlDipMaskPlanes:
2482 if maskPlane
not in ccdExposure.mask.getMaskPlaneDict():
2483 self.log.info(
"Adding %s mask plane to image.", maskPlane)
2484 ccdExposure.mask.addMaskPlane(maskPlane)
2486 if self.config.doITLDipMask:
2487 isrFunctions.maskITLDip(
2488 exposure=ccdExposure,
2489 detectorConfig=overscanDetectorConfig,
2491 maskPlaneNames=self.config.itlDipMaskPlanes,
2494 if (self.config.doITLSatSagMask
or self.config.doITLEdgeBleedMask) \
2495 and detector.getPhysicalType() ==
'ITL':
2497 badAmpDict=badAmpDict)
2501 if self.config.doBias:
2502 self.log.info(
"Applying bias correction.")
2505 isrFunctions.biasCorrection(ccdExposure.maskedImage, bias.maskedImage)
2506 ccdExposure.metadata[
"LSST ISR BIAS APPLIED"] =
True
2510 if self.config.doDark:
2511 self.log.info(
"Applying dark subtraction.")
2515 ccdExposure.metadata[
"LSST ISR DARK APPLIED"] =
True
2521 if self.config.doDefect:
2522 self.log.info(
"Applying defect masking.")
2524 ccdExposure.metadata[
"LSST ISR DEFECTS APPLIED"] =
True
2526 self.log.info(
"Adding UNMASKEDNAN mask plane to image.")
2527 ccdExposure.mask.addMaskPlane(
"UNMASKEDNAN")
2528 if self.config.doNanMasking:
2529 self.log.info(
"Masking non-finite (NAN, inf) value pixels.")
2532 if self.config.doWidenSaturationTrails:
2533 self.log.info(
"Widening saturation trails.")
2534 isrFunctions.widenSaturationTrails(ccdExposure.getMaskedImage().getMask())
2538 if self.config.doBrighterFatter:
2539 if "ASTIER23" in self.config.brighterFatterCorrectionMethod:
2541 self.log.info(
"Applying electrostatic brighter-fatter "
2543 bfCalib = electroBfDistortionMatrix
2544 bfGains = electroBfDistortionMatrix.gain
2546 elif self.config.brighterFatterCorrectionMethod ==
"COULTON18":
2548 self.log.info(
"Applying brighter-fatter correction.")
2553 elif self.config.brighterFatterCorrectionMethod ==
"COULTON18_FLUX_CONSERVING":
2560 raise RuntimeError(
"Cannot perform brighter-fatter correction with unknown"
2565 if exposureMetadata[
"LSST ISR UNITS"] ==
"electron":
2566 brighterFatterApplyGain =
False
2568 brighterFatterApplyGain =
True
2570 if brighterFatterApplyGain
and (ptc
is not None)
and (bfGains != gains):
2577 self.log.warning(
"Need to apply gain for brighter-fatter, but the stored"
2578 "gains in the kernel are not the same as the gains used"
2579 f
"by {self.config.useGainsFrom}. Using the gains stored"
2583 ccdExposure = bfCorrFunction(
2588 brighterFatterApplyGain,
2592 ccdExposure.metadata[
"LSST ISR BF APPLIED"] =
True
2593 ccdExposure.metadata[
"LSST ISR BF CORR METHOD"] = self.config.brighterFatterCorrectionMethod
2597 if self.config.doVariance:
2604 if self.config.doFlat:
2605 self.log.info(
"Applying flat correction.")
2606 isrFunctions.flatCorrection(
2607 maskedImage=ccdExposure.maskedImage,
2608 flatMaskedImage=flat.maskedImage,
2609 scalingType=self.config.flatScalingType,
2610 userScale=self.config.flatUserScale,
2617 if (validPolygon := flat.info.getValidPolygon())
is not None:
2618 ccdExposure.info.setValidPolygon(validPolygon)
2620 noData = (ccdExposure.mask.array & ccdExposure.mask.getPlaneBitMask(
"NO_DATA")) > 0
2621 ccdExposure.image.array[noData] = 0.0
2622 ccdExposure.variance.array[noData] = self.config.noDataVariance
2624 ccdExposure.metadata[
"LSST ISR FLAT APPLIED"] =
True
2625 ccdExposure.metadata[
"LSST ISR FLAT SOURCE"] = flat.metadata.get(
"FLATSRC",
"UNKNOWN")
2629 if self.config.doSaveInterpPixels:
2630 preInterpExp = ccdExposure.clone()
2632 if self.config.doSetBadRegions:
2633 self.log.info(
'Setting values in large contiguous bad regions.')
2636 if self.config.doInterpolate:
2637 self.log.info(
"Interpolating masked pixels.")
2638 isrFunctions.interpolateFromMask(
2639 maskedImage=ccdExposure.getMaskedImage(),
2640 fwhm=self.config.brighterFatterFwhmForInterpolation,
2641 growSaturatedFootprints=self.config.growSaturationFootprintSize,
2642 maskNameList=list(self.config.maskListToInterpolate),
2643 useLegacyInterp=self.config.useLegacyInterp,
2647 if self.config.doAmpOffset:
2648 if self.config.ampOffset.doApplyAmpOffset:
2649 self.log.info(
"Measuring and applying amp offset corrections.")
2651 self.log.info(
"Measuring amp offset corrections only, without applying them.")
2652 self.ampOffset.
run(ccdExposure)
2655 if self.config.doStandardStatistics:
2656 metadata = ccdExposure.metadata
2657 for amp
in detector:
2658 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
2659 ampName = amp.getName()
2660 metadata[f
"LSST ISR MASK SAT {ampName}"] = isrFunctions.countMaskedPixels(
2661 ampExposure.getMaskedImage(),
2662 [self.config.saturatedMaskName]
2664 metadata[f
"LSST ISR MASK BAD {ampName}"] = isrFunctions.countMaskedPixels(
2665 ampExposure.getMaskedImage(),
2668 metadata[f
"LSST ISR MASK SUSPECT {ampName}"] = isrFunctions.countMaskedPixels(
2669 ampExposure.getMaskedImage(),
2672 qaStats = afwMath.makeStatistics(ampExposure.getImage(),
2673 afwMath.MEAN | afwMath.MEDIAN | afwMath.STDEVCLIP)
2675 metadata[f
"LSST ISR FINAL MEAN {ampName}"] = qaStats.getValue(afwMath.MEAN)
2676 metadata[f
"LSST ISR FINAL MEDIAN {ampName}"] = qaStats.getValue(afwMath.MEDIAN)
2677 metadata[f
"LSST ISR FINAL STDEV {ampName}"] = qaStats.getValue(afwMath.STDEVCLIP)
2679 k1 = f
"LSST ISR FINAL MEDIAN {ampName}"
2680 k2 = f
"LSST ISR OVERSCAN SERIAL MEDIAN {ampName}"
2681 if overscanDetectorConfig.doAnySerialOverscan
and k1
in metadata
and k2
in metadata:
2682 metadata[f
"LSST ISR LEVEL {ampName}"] = metadata[k1] - metadata[k2]
2684 metadata[f
"LSST ISR LEVEL {ampName}"] = numpy.nan
2687 outputStatistics =
None
2688 if self.config.doCalculateStatistics:
2689 outputStatistics = self.isrStats.
run(ccdExposure,
2690 untrimmedInputExposure=untrimmedCcdExposure,
2691 serialOverscanResults=serialOverscans,
2692 parallelOverscanResults=parallelOverscans,
2693 bias=bias, dark=dark, flat=flat,
2694 ptc=ptc, defects=defects).results
2697 outputBin1Exposure =
None
2698 outputBin2Exposure =
None
2699 if self.config.doBinnedExposures:
2700 self.log.info(
"Creating binned exposures.")
2701 outputBin1Exposure = self.binning.
run(
2703 binFactor=self.config.binFactor1,
2705 outputBin2Exposure = self.binning.
run(
2707 binFactor=self.config.binFactor2,
2710 return pipeBase.Struct(
2711 exposure=ccdExposure,
2713 outputBin1Exposure=outputBin1Exposure,
2714 outputBin2Exposure=outputBin2Exposure,
2716 preInterpExposure=preInterpExp,
2717 outputExposure=ccdExposure,
2718 outputStatistics=outputStatistics,