1020 Mask SATURATED and SUSPECT pixels and check if any amplifiers
1025 badAmpDict : `str` [`bool`]
1026 Dictionary of amplifiers, keyed by name, value is True if
1027 amplifier is fully masked.
1028 ccdExposure : `lsst.afw.image.Exposure`
1029 Input exposure to be masked.
1030 detector : `lsst.afw.cameraGeom.Detector`
1032 defects : `lsst.ip.isr.Defects`
1033 List of defects. Used to determine if an entire
1035 detectorConfig : `lsst.ip.isr.OverscanDetectorConfig`
1036 Per-amplifier configurations.
1037 ptc : `lsst.ip.isr.PhotonTransferCurveDataset`, optional
1038 PTC dataset (used if configured to use PTCTURNOFF).
1042 badAmpDict : `str`[`bool`]
1043 Dictionary of amplifiers, keyed by name.
1045 maskedImage = ccdExposure.getMaskedImage()
1047 metadata = ccdExposure.metadata
1049 if self.config.doSaturation
and self.config.defaultSaturationSource ==
"PTCTURNOFF" and ptc
is None:
1050 raise RuntimeError(
"Must provide ptc if using PTCTURNOFF as saturation source.")
1051 if self.config.doSuspect
and self.config.defaultSuspectSource ==
"PTCTURNOFF" and ptc
is None:
1052 raise RuntimeError(
"Must provide ptc if using PTCTURNOFF as suspect source.")
1054 for amp
in detector:
1055 ampName = amp.getName()
1057 ampConfig = detectorConfig.getOverscanAmpConfig(amp)
1059 if badAmpDict[ampName]:
1065 if self.config.doSaturation:
1066 if self.config.defaultSaturationSource ==
"PTCTURNOFF":
1067 limits.update({self.config.saturatedMaskName: ptc.ptcTurnoff[amp.getName()]})
1068 elif self.config.defaultSaturationSource ==
"CAMERAMODEL":
1070 limits.update({self.config.saturatedMaskName: amp.getSaturation()})
1071 elif self.config.defaultSaturationSource ==
"NONE":
1072 limits.update({self.config.saturatedMaskName: numpy.inf})
1075 if math.isfinite(ampConfig.saturation):
1076 limits.update({self.config.saturatedMaskName: ampConfig.saturation})
1077 metadata[f
"LSST ISR SATURATION LEVEL {ampName}"] = limits[self.config.saturatedMaskName]
1079 if self.config.doSuspect:
1080 if self.config.defaultSuspectSource ==
"PTCTURNOFF":
1081 limits.update({self.config.suspectMaskName: ptc.ptcTurnoff[amp.getName()]})
1082 elif self.config.defaultSuspectSource ==
"CAMERAMODEL":
1084 limits.update({self.config.suspectMaskName: amp.getSuspectLevel()})
1085 elif self.config.defaultSuspectSource ==
"NONE":
1086 limits.update({self.config.suspectMaskName: numpy.inf})
1089 if math.isfinite(ampConfig.suspectLevel):
1090 limits.update({self.config.suspectMaskName: ampConfig.suspectLevel})
1091 metadata[f
"LSST ISR SUSPECT LEVEL {ampName}"] = limits[self.config.suspectMaskName]
1093 for maskName, maskThreshold
in limits.items():
1094 if not math.isnan(maskThreshold):
1095 dataView = maskedImage.Factory(maskedImage, amp.getRawBBox())
1096 toMask = (dataView.image.array >= maskThreshold)
1097 dataView.mask.array[toMask] |= dataView.mask.getPlaneBitMask(maskName)
1101 maskView = afwImage.Mask(maskedImage.getMask(), amp.getRawDataBBox(),
1103 maskVal = maskView.getPlaneBitMask([self.config.saturatedMaskName,
1104 self.config.suspectMaskName])
1105 if numpy.all(maskView.getArray() & maskVal > 0):
1106 self.log.warning(
"Amplifier %s is bad (completely SATURATED or SUSPECT)", ampName)
1107 badAmpDict[ampName] =
True
1108 maskView |= maskView.getPlaneBitMask(
"BAD")
2034 deferredChargeCalib=None,
2037 gainCorrection=None,
2041 electroBfDistortionMatrix=None,
2046 """Run the IsrTaskLSST task.
2050 ccdExposure : `lsst.afw.image.Exposure`
2051 Exposure to run ISR.
2052 dnlLUT : `None`, optional
2053 DNL lookup table; placeholder, unused.
2054 bias : `lsst.afw.image.Exposure`, optional
2056 deferredChargeCalib : `lsst.ip.isr.DeferredChargeCalib`, optional
2057 Deferred charge calibration.
2058 linearizer : `lsst.ip.isr.Linearizer`, optional
2059 Linearizer calibration.
2060 ptc : `lsst.ip.isr.PhotonTransferCurveDataset`, optional
2062 gainCorrection : `lsst.ip.isr.GainCorrection`, optional
2063 Gain correction dataset.
2064 crosstalk : `lsst.ip.isr.CrosstalkCalib`, optional
2065 Crosstalk calibration dataset.
2066 defects : `lsst.ip.isr.Defects`, optional
2068 bfKernel : `lsst.ip.isr.BrighterFatterKernel`, optional
2069 Brighter-fatter kernel dataset.
2070 dark : `lsst.afw.image.Exposure`, optional
2072 flat : `lsst.afw.image.Exposure`, optional
2074 camera : `lsst.afw.cameraGeom.Camera`, optional
2079 result : `lsst.pipe.base.Struct`
2081 ``exposure``: `lsst.afw.image.Exposure`
2082 Calibrated exposure.
2083 ``outputBin1Exposure``: `lsst.afw.image.Exposure`
2084 Binned exposure (bin1 config).
2085 ``outputBin2Exposure``: `lsst.afw.image.Exposure`
2086 Binned exposure (bin2 config).
2087 ``outputExposure``: `lsst.afw.image.Exposure`
2088 Calibrated exposure (same as ``exposure``).
2089 ``outputStatistics``: `lsst.ip.isr.isrStatistics`
2090 Calibrated exposure statistics.
2092 detector = ccdExposure.getDetector()
2094 overscanDetectorConfig = self.config.overscanCamera.getOverscanDetectorConfig(detector)
2096 if self.config.doBootstrap:
2098 self.log.warning(
"Task configured with doBootstrap=True. Ignoring provided PTC.")
2101 if self.config.useGainsFrom ==
"LINEARIZER":
2102 if linearizer
is None:
2103 raise RuntimeError(
"doBootstrap==False and useGainsFrom == 'LINEARIZER' but "
2104 "no linearizer provided.")
2105 elif self.config.useGainsFrom ==
"PTC":
2107 raise RuntimeError(
"doBootstrap==False and useGainsFrom == 'PTC' but no PTC provided.")
2110 exposureMetadata = ccdExposure.metadata
2111 doRaise = self.config.doRaiseOnCalibMismatch
2112 keywords = self.config.cameraKeywordsToCompare
2113 if not self.config.doBootstrap:
2114 if self.config.useGainsFrom ==
"LINEARIZER":
2116 "LINEARIZER", log=self.log)
2117 elif self.config.useGainsFrom ==
"PTC":
2121 if self.config.doCorrectGains
and gainCorrection
is not None:
2131 if self.config.doCorrectGains:
2132 raise RuntimeError(
"doCorrectGains is True but no ptc provided.")
2133 if self.config.doDiffNonLinearCorrection:
2135 raise RuntimeError(
"doDiffNonLinearCorrection is True but no dnlLUT provided.")
2137 if self.config.doLinearize:
2138 if linearizer
is None:
2139 raise RuntimeError(
"doLinearize is True but no linearizer provided.")
2141 if self.config.doBias:
2143 raise RuntimeError(
"doBias is True but no bias provided.")
2146 if self.config.doCrosstalk:
2147 if crosstalk
is None:
2148 raise RuntimeError(
"doCrosstalk is True but no crosstalk provided.")
2150 if self.config.doDeferredCharge:
2151 if deferredChargeCalib
is None:
2152 raise RuntimeError(
"doDeferredCharge is True but no deferredChargeCalib provided.")
2157 deferredChargeCalib,
2161 if self.config.doDefect:
2163 raise RuntimeError(
"doDefect is True but no defects provided.")
2165 if self.config.doDark:
2167 raise RuntimeError(
"doDark is True but no dark frame provided.")
2170 if self.config.doBrighterFatter:
2171 if self.config.brighterFatterCorrectionMethod
in [
"ASTIER23",
"ASTIER23+FILTERCORRECTION"]:
2172 if electroBfDistortionMatrix
is None:
2173 raise RuntimeError(
"Must supply an electroBfDistortionMatrix if BF "
2174 "correction method is ASTIER23*.")
2176 electroBfDistortionMatrix,
"bf", log=self.log)
2177 elif self.config.brighterFatterCorrectionMethod
in [
"COULTON18",
"COULTON18_FLUX_CONSERVING"]:
2178 if bfKernel
is None:
2179 raise RuntimeError(
"Must supply an kernel if BF correction method is COULTON*.")
2182 raise ValueError(
"%s is not a known brighter-fatter correction "
2183 "method." % self.config.brighterFatterCorrectionMethod)
2184 if self.config.doFlat:
2186 raise RuntimeError(
"doFlat is True but no flat provided.")
2189 if self.config.doSaturation:
2190 if self.config.defaultSaturationSource
in [
"PTCTURNOFF",]:
2193 "doSaturation is True and defaultSaturationSource is "
2194 f
"{self.config.defaultSaturationSource}, but no ptc provided."
2196 if self.config.doSuspect:
2197 if self.config.defaultSuspectSource
in [
"PTCTURNOFF",]:
2200 "doSuspect is True and defaultSuspectSource is "
2201 f
"{self.config.defaultSuspectSource}, but no ptc provided."
2204 if self.config.doCheckUnprocessableData
and self.config.bssVoltageMinimum > 0.0:
2211 exposureMetadata[
"LSST ISR UNITS"] =
"adu"
2212 exposureMetadata[
"LSST ISR GAINCORRECTION APPLIED"] =
False
2213 exposureMetadata[
"LSST ISR CROSSTALK APPLIED"] =
False
2214 exposureMetadata[
"LSST ISR OVERSCANLEVEL CHECKED"] =
False
2215 exposureMetadata[
"LSST ISR NOISE CHECKED"] =
False
2216 exposureMetadata[
"LSST ISR LINEARIZER APPLIED"] =
False
2217 exposureMetadata[
"LSST ISR CTI APPLIED"] =
False
2218 exposureMetadata[
"LSST ISR BIAS APPLIED"] =
False
2219 exposureMetadata[
"LSST ISR DARK APPLIED"] =
False
2220 exposureMetadata[
"LSST ISR BF APPLIED"] =
False
2221 exposureMetadata[
"LSST ISR FLAT APPLIED"] =
False
2222 exposureMetadata[
"LSST ISR DEFECTS APPLIED"] =
False
2224 if self.config.doBootstrap:
2225 self.log.info(
"Configured using doBootstrap=True; using gain of 1.0 (adu units)")
2227 for amp
in detector:
2228 ptc.gain[amp.getName()] = 1.0
2229 ptc.noise[amp.getName()] = 0.0
2230 ptc.ptcTurnoff[amp.getName()] = numpy.inf
2231 elif self.config.useGainsFrom ==
"LINEARIZER":
2232 self.log.info(
"Using gains from linearizer.")
2235 for amp
in detector:
2236 ptc.gain[amp.getName()] = linearizer.inputGain[amp.getName()]
2237 ptc.noise[amp.getName()] = 0.0
2238 ptc.ptcTurnoff[amp.getName()] = linearizer.inputTurnoff[amp.getName()]
2240 exposureMetadata[
"LSST ISR BOOTSTRAP"] = self.config.doBootstrap
2247 for amp
in detector:
2248 if not math.isnan(gain := overscanDetectorConfig.getOverscanAmpConfig(amp).gain):
2249 gains[amp.getName()] = gain
2251 "Overriding gain for amp %s with configured value of %.3f.",
2258 self.log.debug(
"Converting exposure to floating point values.")
2270 if self.config.doDiffNonLinearCorrection:
2281 if overscanDetectorConfig.doAnySerialOverscan:
2284 overscanDetectorConfig,
2290 if self.config.doBootstrap
or self.config.useGainsFrom ==
"LINEARIZER":
2292 for amp, serialOverscan
in zip(detector, serialOverscans):
2293 if serialOverscan
is None:
2294 ptc.noise[amp.getName()] = 0.0
2302 ptc.noise[amp.getName()] = serialOverscan.residualSigma * gains[amp.getName()]
2304 serialOverscans = [
None]*len(detector)
2316 overscanDetectorConfig,
2322 if self.config.doCorrectGains
and gainCorrection
is not None:
2323 self.log.info(
"Correcting gains based on input GainCorrection.")
2324 gainCorrection.correctGains(gains, exposure=ccdExposure)
2325 exposureMetadata[
"LSST ISR GAINCORRECTION APPLIED"] =
True
2326 elif self.config.doCorrectGains:
2327 self.log.info(
"Skipping gain correction because no GainCorrection available.")
2332 if self.config.doApplyGains:
2333 self.log.info(
"Using gain values to convert from adu to electron units.")
2334 isrFunctions.applyGains(ccdExposure, normalizeGains=
False, ptcGains=gains, isTrimmed=
False)
2336 exposureMetadata[
"LSST ISR UNITS"] =
"electron"
2340 for amp
in detector:
2341 ampName = amp.getName()
2342 if (key := f
"LSST ISR SATURATION LEVEL {ampName}")
in exposureMetadata:
2343 exposureMetadata[key] *= gains[ampName]
2344 if (key := f
"LSST ISR SUSPECT LEVEL {ampName}")
in exposureMetadata:
2345 exposureMetadata[key] *= gains[ampName]
2348 metadata = ccdExposure.metadata
2349 metadata[
"LSST ISR READNOISE UNITS"] =
"electron"
2350 metadata[
"LSST ISR PTCTURNOFF UNITS"] =
"electron"
2351 metadata[
"LSST ISR GAIN SOURCE"] = self.config.useGainsFrom
2352 for amp
in detector:
2354 metadata[f
"LSST ISR GAIN {amp.getName()}"] = gains[amp.getName()]
2357 metadata[f
"LSST ISR READNOISE {amp.getName()}"] = ptc.noise[amp.getName()]
2360 turnoff = ptc.ptcTurnoff[amp.getName()] * gains[amp.getName()]
2361 metadata[f
"LSST ISR PTCTURNOFF {amp.getName()}"] = turnoff
2365 if self.config.doCrosstalk:
2366 self.log.info(
"Applying crosstalk corrections to full amplifier region.")
2367 if self.config.doBootstrap
and numpy.any(crosstalk.fitGains != 0):
2368 crosstalkGains =
None
2370 crosstalkGains = gains
2373 crosstalk=crosstalk,
2374 gains=crosstalkGains,
2376 badAmpDict=badAmpDict,
2377 ignoreVariance=
True,
2379 ccdExposure.metadata[
"LSST ISR CROSSTALK APPLIED"] =
True
2382 if numpy.isfinite(self.config.serialOverscanMedianShiftSigmaThreshold):
2384 ccdExposure.metadata[
"LSST ISR OVERSCANLEVEL CHECKED"] =
True
2386 if numpy.isfinite(self.config.ampNoiseThreshold):
2387 badAmpDict = self.
checkAmpNoise(badAmpDict, ccdExposure, ptc)
2388 ccdExposure.metadata[
"LSST ISR NOISE CHECKED"] =
True
2390 if numpy.isfinite(self.config.serialOverscanMedianShiftSigmaThreshold)
or \
2391 numpy.isfinite(self.config.ampNoiseThreshold):
2396 parallelOverscans =
None
2397 if overscanDetectorConfig.doAnyParallelOverscan:
2401 overscanDetectorConfig,
2409 if self.config.doLinearize:
2410 self.log.info(
"Applying linearizer.")
2414 if exposureMetadata[
"LSST ISR UNITS"] ==
"electron":
2415 linearityGains = gains
2417 linearityGains =
None
2418 linearizer.applyLinearity(
2419 image=ccdExposure.image,
2422 gains=linearityGains,
2424 ccdExposure.metadata[
"LSST ISR LINEARIZER APPLIED"] =
True
2429 if self.config.doDeferredCharge:
2430 if self.config.doBootstrap:
2431 self.log.info(
"Applying deferred charge correction with doBootstrap=True: "
2432 "will need to use deferredChargeCalib.inputGain to apply "
2433 "CTI correction in electron units.")
2434 deferredChargeGains = deferredChargeCalib.inputGain
2435 if numpy.all(numpy.isnan(list(deferredChargeGains.values()))):
2436 self.log.warning(
"All gains contained in the deferredChargeCalib are "
2437 "NaN, approximating with gain of 1.0.")
2438 deferredChargeGains = gains
2440 deferredChargeGains = gains
2441 self.deferredChargeCorrection.
run(
2443 deferredChargeCalib,
2444 gains=deferredChargeGains,
2446 ccdExposure.metadata[
"LSST ISR CTI APPLIED"] =
True
2450 untrimmedCcdExposure =
None
2451 if self.config.isrStats.doCtiStatistics:
2452 untrimmedCcdExposure = ccdExposure.clone()
2456 if self.config.doAssembleCcd:
2457 self.log.info(
"Assembling CCD from amplifiers.")
2458 ccdExposure = self.assembleCcd.assembleCcd(ccdExposure)
2460 if self.config.expectWcs
and not ccdExposure.getWcs():
2461 self.log.warning(
"No WCS found in input exposure.")
2464 if self.config.doE2VEdgeBleedMask
and detector.getPhysicalType() ==
"E2V":
2465 isrFunctions.maskE2VEdgeBleed(
2466 exposure=ccdExposure,
2467 e2vEdgeBleedSatMinArea=self.config.e2vEdgeBleedSatMinArea,
2468 e2vEdgeBleedSatMaxArea=self.config.e2vEdgeBleedSatMaxArea,
2469 e2vEdgeBleedYMax=self.config.e2vEdgeBleedYMax,
2470 saturatedMaskName=self.config.saturatedMaskName,
2475 for maskPlane
in self.config.itlDipMaskPlanes:
2476 if maskPlane
not in ccdExposure.mask.getMaskPlaneDict():
2477 self.log.info(
"Adding %s mask plane to image.", maskPlane)
2478 ccdExposure.mask.addMaskPlane(maskPlane)
2480 if self.config.doITLDipMask:
2481 isrFunctions.maskITLDip(
2482 exposure=ccdExposure,
2483 detectorConfig=overscanDetectorConfig,
2485 maskPlaneNames=self.config.itlDipMaskPlanes,
2488 if (self.config.doITLSatSagMask
or self.config.doITLEdgeBleedMask) \
2489 and detector.getPhysicalType() ==
'ITL':
2491 badAmpDict=badAmpDict)
2495 if self.config.doBias:
2496 self.log.info(
"Applying bias correction.")
2499 isrFunctions.biasCorrection(ccdExposure.maskedImage, bias.maskedImage)
2500 ccdExposure.metadata[
"LSST ISR BIAS APPLIED"] =
True
2504 if self.config.doDark:
2505 self.log.info(
"Applying dark subtraction.")
2509 ccdExposure.metadata[
"LSST ISR DARK APPLIED"] =
True
2515 if self.config.doDefect:
2516 self.log.info(
"Applying defect masking.")
2518 ccdExposure.metadata[
"LSST ISR DEFECTS APPLIED"] =
True
2520 self.log.info(
"Adding UNMASKEDNAN mask plane to image.")
2521 ccdExposure.mask.addMaskPlane(
"UNMASKEDNAN")
2522 if self.config.doNanMasking:
2523 self.log.info(
"Masking non-finite (NAN, inf) value pixels.")
2526 if self.config.doWidenSaturationTrails:
2527 self.log.info(
"Widening saturation trails.")
2528 isrFunctions.widenSaturationTrails(ccdExposure.getMaskedImage().getMask())
2532 if self.config.doBrighterFatter:
2533 if "ASTIER23" in self.config.brighterFatterCorrectionMethod:
2535 self.log.info(
"Applying electrostatic brighter-fatter "
2537 bfCalib = electroBfDistortionMatrix
2538 bfGains = electroBfDistortionMatrix.gain
2540 elif self.config.brighterFatterCorrectionMethod ==
"COULTON18":
2542 self.log.info(
"Applying brighter-fatter correction.")
2547 elif self.config.brighterFatterCorrectionMethod ==
"COULTON18_FLUX_CONSERVING":
2554 raise RuntimeError(
"Cannot perform brighter-fatter correction with unknown"
2559 if exposureMetadata[
"LSST ISR UNITS"] ==
"electron":
2560 brighterFatterApplyGain =
False
2562 brighterFatterApplyGain =
True
2564 if brighterFatterApplyGain
and (ptc
is not None)
and (bfGains != gains):
2571 self.log.warning(
"Need to apply gain for brighter-fatter, but the stored"
2572 "gains in the kernel are not the same as the gains used"
2573 f
"by {self.config.useGainsFrom}. Using the gains stored"
2577 ccdExposure = bfCorrFunction(
2582 brighterFatterApplyGain,
2586 ccdExposure.metadata[
"LSST ISR BF APPLIED"] =
True
2587 ccdExposure.metadata[
"LSST ISR BF CORR METHOD"] = self.config.brighterFatterCorrectionMethod
2591 if self.config.doVariance:
2598 if self.config.doFlat:
2599 self.log.info(
"Applying flat correction.")
2600 isrFunctions.flatCorrection(
2601 maskedImage=ccdExposure.maskedImage,
2602 flatMaskedImage=flat.maskedImage,
2603 scalingType=self.config.flatScalingType,
2604 userScale=self.config.flatUserScale,
2611 if (validPolygon := flat.info.getValidPolygon())
is not None:
2612 ccdExposure.info.setValidPolygon(validPolygon)
2614 noData = (ccdExposure.mask.array & ccdExposure.mask.getPlaneBitMask(
"NO_DATA")) > 0
2615 ccdExposure.image.array[noData] = 0.0
2616 ccdExposure.variance.array[noData] = 0.0
2618 ccdExposure.metadata[
"LSST ISR FLAT APPLIED"] =
True
2619 ccdExposure.metadata[
"LSST ISR FLAT SOURCE"] = flat.metadata.get(
"FLATSRC",
"UNKNOWN")
2623 if self.config.doSaveInterpPixels:
2624 preInterpExp = ccdExposure.clone()
2626 if self.config.doSetBadRegions:
2627 self.log.info(
'Setting values in large contiguous bad regions.')
2630 if self.config.doInterpolate:
2631 self.log.info(
"Interpolating masked pixels.")
2632 isrFunctions.interpolateFromMask(
2633 maskedImage=ccdExposure.getMaskedImage(),
2634 fwhm=self.config.brighterFatterFwhmForInterpolation,
2635 growSaturatedFootprints=self.config.growSaturationFootprintSize,
2636 maskNameList=list(self.config.maskListToInterpolate),
2637 useLegacyInterp=self.config.useLegacyInterp,
2641 if self.config.doAmpOffset:
2642 if self.config.ampOffset.doApplyAmpOffset:
2643 self.log.info(
"Measuring and applying amp offset corrections.")
2645 self.log.info(
"Measuring amp offset corrections only, without applying them.")
2646 self.ampOffset.
run(ccdExposure)
2649 if self.config.doStandardStatistics:
2650 metadata = ccdExposure.metadata
2651 for amp
in detector:
2652 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
2653 ampName = amp.getName()
2654 metadata[f
"LSST ISR MASK SAT {ampName}"] = isrFunctions.countMaskedPixels(
2655 ampExposure.getMaskedImage(),
2656 [self.config.saturatedMaskName]
2658 metadata[f
"LSST ISR MASK BAD {ampName}"] = isrFunctions.countMaskedPixels(
2659 ampExposure.getMaskedImage(),
2662 metadata[f
"LSST ISR MASK SUSPECT {ampName}"] = isrFunctions.countMaskedPixels(
2663 ampExposure.getMaskedImage(),
2666 qaStats = afwMath.makeStatistics(ampExposure.getImage(),
2667 afwMath.MEAN | afwMath.MEDIAN | afwMath.STDEVCLIP)
2669 metadata[f
"LSST ISR FINAL MEAN {ampName}"] = qaStats.getValue(afwMath.MEAN)
2670 metadata[f
"LSST ISR FINAL MEDIAN {ampName}"] = qaStats.getValue(afwMath.MEDIAN)
2671 metadata[f
"LSST ISR FINAL STDEV {ampName}"] = qaStats.getValue(afwMath.STDEVCLIP)
2673 k1 = f
"LSST ISR FINAL MEDIAN {ampName}"
2674 k2 = f
"LSST ISR OVERSCAN SERIAL MEDIAN {ampName}"
2675 if overscanDetectorConfig.doAnySerialOverscan
and k1
in metadata
and k2
in metadata:
2676 metadata[f
"LSST ISR LEVEL {ampName}"] = metadata[k1] - metadata[k2]
2678 metadata[f
"LSST ISR LEVEL {ampName}"] = numpy.nan
2681 outputStatistics =
None
2682 if self.config.doCalculateStatistics:
2683 outputStatistics = self.isrStats.
run(ccdExposure,
2684 untrimmedInputExposure=untrimmedCcdExposure,
2685 serialOverscanResults=serialOverscans,
2686 parallelOverscanResults=parallelOverscans,
2687 bias=bias, dark=dark, flat=flat,
2688 ptc=ptc, defects=defects).results
2691 outputBin1Exposure =
None
2692 outputBin2Exposure =
None
2693 if self.config.doBinnedExposures:
2694 self.log.info(
"Creating binned exposures.")
2695 outputBin1Exposure = self.binning.
run(
2697 binFactor=self.config.binFactor1,
2699 outputBin2Exposure = self.binning.
run(
2701 binFactor=self.config.binFactor2,
2704 return pipeBase.Struct(
2705 exposure=ccdExposure,
2707 outputBin1Exposure=outputBin1Exposure,
2708 outputBin2Exposure=outputBin2Exposure,
2710 preInterpExposure=preInterpExp,
2711 outputExposure=ccdExposure,
2712 outputStatistics=outputStatistics,