1233 ):
1234
1235 detector = ccdExposure.getDetector()
1236
1237 overscanDetectorConfig = self.config.overscanCamera.getOverscanDetectorConfig(detector)
1238
1239 gains = ptc.gain
1240
1241 if self.config.doHeaderProvenance:
1242
1243
1244 exposureMetadata = ccdExposure.getMetadata()
1245 exposureMetadata["LSST CALIB OVERSCAN HASH"] = overscanDetectorConfig.md5
1246 exposureMetadata["LSST CALIB DATE PTC"] = self.extractCalibDate(ptc)
1247 if self.config.doDiffNonLinearCorrection:
1248 exposureMetadata["LSST CALIB DATE DNL"] = self.extractCalibDate(dnlLUT)
1249 if self.config.doBias:
1250 exposureMetadata["LSST CALIB DATE BIAS"] = self.extractCalibDate(bias)
1251 if self.config.doDeferredCharge:
1252 exposureMetadata["LSST CALIB DATE CTI"] = self.extractCalibDate(deferredChargeCalib)
1253 if self.doLinearize(detector):
1254 exposureMetadata["LSST CALIB DATE LINEARIZER"] = self.extractCalibDate(linearizer)
1255 if self.config.doCrosstalk or overscanDetectorConfig.doAnyParallelOverscanCrosstalk:
1256 exposureMetadata["LSST CALIB DATE CROSSTALK"] = self.extractCalibDate(crosstalk)
1257 if self.config.doDefect:
1258 exposureMetadata["LSST CALIB DATE DEFECTS"] = self.extractCalibDate(defects)
1259 if self.config.doBrighterFatter:
1260 exposureMetadata["LSST CALIB DATE BFK"] = self.extractCalibDate(bfKernel)
1261 if self.config.doDark:
1262 exposureMetadata["LSST CALIB DATE DARK"] = self.extractCalibDate(dark)
1263 if self.config.doFlat:
1264 exposureMetadata["LSST CALIB DATE FLAT"] = self.extractCalibDate(flat)
1265
1266
1267 badAmpDict = self.maskFullDefectAmplifiers(ccdExposure, detector, defects)
1268
1269 if self.config.doDiffNonLinearCorrection:
1270 self.diffNonLinearCorrection(ccdExposure, dnlLUT)
1271
1272 if overscanDetectorConfig.doAnySerialOverscan:
1273
1274 serialOverscans = self.overscanCorrection(
1275 "SERIAL",
1276 overscanDetectorConfig,
1277 detector,
1278 badAmpDict,
1279 ccdExposure,
1280 )
1281 else:
1282 serialOverscans = [None]*len(detector)
1283
1284 if overscanDetectorConfig.doAnyParallelOverscanCrosstalk:
1285
1286
1287
1288 self.crosstalk.run(
1289 ccdExposure,
1290 crosstalk=crosstalk,
1291 camera=camera,
1292 parallelOverscanRegion=True,
1293 detectorConfig=overscanDetectorConfig,
1294 )
1295
1296
1297
1298
1299 badAmpDict = self.maskSaturatedPixels(badAmpDict, ccdExposure, detector)
1300
1301 if overscanDetectorConfig.doAnyParallelOverscan:
1302
1303
1304 _ = self.overscanCorrection(
1305 "PARALLEL",
1306 overscanDetectorConfig,
1307 detector,
1308 badAmpDict,
1309 ccdExposure,
1310 )
1311
1312 if self.config.doAssembleCcd:
1313
1314 self.log.info("Assembling CCD from amplifiers.")
1315 ccdExposure = self.assembleCcd.assembleCcd(ccdExposure)
1316
1317 if self.config.expectWcs and not ccdExposure.getWcs():
1318 self.log.warning("No WCS found in input exposure.")
1319
1320 if self.config.doLinearize:
1321
1322 self.log.info("Applying linearizer.")
1323 linearizer = self.getLinearizer(detector=detector)
1324 linearizer.applyLinearity(image=ccdExposure.getMaskedImage().getImage(),
1325 detector=detector, log=self.log)
1326
1327 if self.config.doCrosstalk:
1328
1329 self.log.info("Applying crosstalk correction.")
1330 self.crosstalk.run(ccdExposure, crosstalk=crosstalk, isTrimmed=True)
1331
1332 if self.config.doBias:
1333
1334 self.log.info("Applying bias correction.")
1335 isrFunctions.biasCorrection(ccdExposure.getMaskedImage(), bias.getMaskedImage())
1336
1337 if self.config.doGainsCorrection:
1338
1339 self.log.info("Apply temperature dependence to the gains.")
1340 gains, readNoise = self.gainsCorrection(**kwargs)
1341
1342 if self.config.doApplyGains:
1343
1344
1345 self.log.info("Apply PTC gains (temperature corrected or not) to the image.")
1346 isrFunctions.applyGains(ccdExposure, normalizeGains=False, ptcGains=gains)
1347
1348 if self.config.doDeferredCharge:
1349
1350 self.log.info("Applying deferred charge/CTI correction.")
1351 self.deferredChargeCorrection.run(ccdExposure, deferredChargeCalib)
1352
1353 if self.config.doVariance:
1354
1355 self.variancePlane(ccdExposure, detector, ptc)
1356
1357
1358
1359 if self.config.doDefect:
1360
1361 self.log.info("Applying defects masking.")
1362 self.maskDefect(ccdExposure, defects)
1363
1364 if self.config.doNanMasking:
1365 self.log.info("Masking non-finite (NAN, inf) value pixels.")
1366 self.maskNan(ccdExposure)
1367
1368 if self.config.doWidenSaturationTrails:
1369 self.log.info("Widening saturation trails.")
1370 isrFunctions.widenSaturationTrails(ccdExposure.getMaskedImage().getMask())
1371
1372 if self.config.doDark:
1373
1374 self.log.info("Applying dark subtraction.")
1375 self.darkCorrection(ccdExposure, dark)
1376
1377 if self.config.doBrighterFatter:
1378
1379 self.log.info("Applying Bright-Fatter kernels.")
1380 bfKernelOut, bfGains = self.getBrighterFatterKernel(detector, bfKernel)
1381 ccdExposure = self.applyBrighterFatterCorrection(ccdExposure, flat, dark, bfKernelOut, bfGains)
1382
1383 if self.config.doFlat:
1384
1385 self.log.info("Applying flat correction.")
1386
1387
1388 self.flatCorrection(ccdExposure, flat)
1389
1390
1391 preInterpExp = None
1392 if self.config.doSaveInterpPixels:
1393 preInterpExp = ccdExposure.clone()
1394
1395 if self.config.doSetBadRegions:
1396 self.log.info('Counting pixels in BAD regions.')
1397 self.countBadPixels(ccdExposure)
1398
1399 if self.config.doInterpolate:
1400 self.log.info("Interpolating masked pixels.")
1401 isrFunctions.interpolateFromMask(
1402 maskedImage=ccdExposure.getMaskedImage(),
1403 fwhm=self.config.brighterFatterFwhmForInterpolation,
1404 growSaturatedFootprints=self.config.growSaturationFootprintSize,
1405 maskNameList=list(self.config.maskListToInterpolate)
1406 )
1407
1408
1409 if self.config.doStandardStatistics:
1410 metadata = ccdExposure.getMetadata()
1411 for amp in detector:
1412 ampExposure = ccdExposure.Factory(ccdExposure, amp.getBBox())
1413 ampName = amp.getName()
1414 metadata[f"LSST ISR MASK SAT {ampName}"] = isrFunctions.countMaskedPixels(
1415 ampExposure.getMaskedImage(),
1416 [self.config.saturatedMaskName]
1417 )
1418 metadata[f"LSST ISR MASK BAD {ampName}"] = isrFunctions.countMaskedPixels(
1419 ampExposure.getMaskedImage(),
1420 ["BAD"]
1421 )
1423 afwMath.MEAN | afwMath.MEDIAN | afwMath.STDEVCLIP)
1424
1425 metadata[f"LSST ISR FINAL MEAN {ampName}"] = qaStats.getValue(afwMath.MEAN)
1426 metadata[f"LSST ISR FINAL MEDIAN {ampName}"] = qaStats.getValue(afwMath.MEDIAN)
1427 metadata[f"LSST ISR FINAL STDEV {ampName}"] = qaStats.getValue(afwMath.STDEVCLIP)
1428
1429 k1 = f"LSST ISR FINAL MEDIAN {ampName}"
1430 k2 = f"LSST ISR OVERSCAN SERIAL MEDIAN {ampName}"
1431 if overscanDetectorConfig.doAnySerialOverscan and k1 in metadata and k2 in metadata:
1432 metadata[f"LSST ISR LEVEL {ampName}"] = metadata[k1] - metadata[k2]
1433 else:
1434 metadata[f"LSST ISR LEVEL {ampName}"] = numpy.nan
1435
1436
1437 outputStatistics = None
1438 if self.config.doCalculateStatistics:
1439 outputStatistics = self.isrStats.run(ccdExposure, overscanResults=serialOverscans,
1440 bias=bias, dark=dark, flat=flat, ptc=ptc,
1441 defects=defects).results
1442
1443
1444 outputBin1Exposure = None
1445 outputBin2Exposure = None
1446 if self.config.doBinnedExposures:
1447 outputBin1Exposure, outputBin2Exposure = self.makeBinnedImages(ccdExposure)
1448
1449 return pipeBase.Struct(
1450 exposure=ccdExposure,
1451
1452 outputBin1Exposure=outputBin1Exposure,
1453 outputBin2Exposure=outputBin2Exposure,
1454
1455 preInterpExposure=preInterpExp,
1456 outputExposure=ccdExposure,
1457 outputStatistics=outputStatistics,
1458 )
Statistics makeStatistics(lsst::afw::image::Image< Pixel > const &img, lsst::afw::image::Mask< image::MaskPixel > const &msk, int const flags, StatisticsControl const &sctrl=StatisticsControl())
Handle a watered-down front-end to the constructor (no variance)