Skip to content

Commit

Permalink
Deferred charge consistency/clarifications.
Browse files Browse the repository at this point in the history
  • Loading branch information
czwa committed Jul 7, 2022
1 parent 4797bf7 commit b564799
Showing 1 changed file with 26 additions and 13 deletions.
39 changes: 26 additions & 13 deletions python/lsst/cp/pipe/deferredCharge.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,26 +165,26 @@ def run(self, inputMeasurements, camera, inputDims):
RuntimeError
Raised if data from multiple detectors are passed in.
"""
detectorSet = sorted(set([d['detector'] for d in inputDims]))
detectorSet = set([d['detector'] for d in inputDims])
if len(detectorSet) != 1:
raise RuntimeError("Inputs for too many detectors passed.")
detectorId = detectorSet[0]
detectorId = detectorSet.pop()
detector = camera[detectorId]

# Initialize with detector.
calib = DeferredChargeCalib(camera=camera, detector=detector)

localCalib = self.localOffsets(inputMeasurements, calib, detector)
localCalib = self.solveLocalOffsets(inputMeasurements, calib, detector)

globalCalib = self.globalCti(inputMeasurements, localCalib, detector)
globalCalib = self.solveGlobalCti(inputMeasurements, localCalib, detector)

finalCalib = self.findTraps(inputMeasurements, globalCalib, detector)

return pipeBase.Struct(
outputCalib=finalCalib,
)

def localOffsets(self, inputMeasurements, calib, detector):
def solveLocalOffsets(self, inputMeasurements, calib, detector):
"""Solve for local (pixel-to-pixel) electronic offsets.
This method fits for \tau_L, the local electronic offset decay
Expand Down Expand Up @@ -251,11 +251,16 @@ def localOffsets(self, inputMeasurements, calib, detector):
# leaks into the overscan region.
signal = []
data = []
Nskipped = 0
for exposureEntry in inputMeasurements:
exposureDict = exposureEntry['CTI']
if exposureDict[ampName]['IMAGE_MEAN'] < self.config.maxImageMean:
signal.append(exposureDict[ampName]['IMAGE_MEAN'])
data.append(exposureDict[ampName]['OVERSCAN_VALUES'][start:stop+1])
else:
Nskipped += 1
self.log.info(f"Skipped {Nskipped} exposures brighter than {self.config.maxImageMean}.")

signal = np.array(signal)
data = np.array(data)

Expand All @@ -282,14 +287,14 @@ def localOffsets(self, inputMeasurements, calib, detector):
self.log.warning("Electronics fitting failure for amplifier %s.", ampName)

calib.globalCti[ampName] = 10**result.params['ctiexp']
calib.driftScale[ampName] = result.params['driftscale'].value if result.success else 2.4
calib.decayTime[ampName] = result.params['decaytime'].value if result.success else 0.0
calib.driftScale[ampName] = result.params['driftscale'].value if result.success else 0.0
calib.decayTime[ampName] = result.params['decaytime'].value if result.success else 2.4
self.log.info("CTI Local Fit %s: cti: %g decayTime: %g driftScale %g",
ampName, calib.globalCti[ampName], calib.decayTime[ampName],
calib.driftScale[ampName])
return calib

def globalCti(self, inputMeasurements, calib, detector):
def solveGlobalCti(self, inputMeasurements, calib, detector):
"""Solve for global CTI constant.
This method solves for the mean global CTI, b.
Expand Down Expand Up @@ -354,11 +359,16 @@ def globalCti(self, inputMeasurements, calib, detector):
# leaks into the overscan region.
signal = []
data = []
Nskipped = 0
for exposureEntry in inputMeasurements:
exposureDict = exposureEntry['CTI']
if exposureDict[ampName]['IMAGE_MEAN'] < self.config.maxSignalForCti:
signal.append(exposureDict[ampName]['IMAGE_MEAN'])
data.append(exposureDict[ampName]['OVERSCAN_VALUES'][start:stop+1])
else:
Nskipped += 1
self.log.info(f"Skipped {Nskipped} exposures brighter than {self.config.maxSignalForCti}.")

signal = np.array(signal)
data = np.array(data)

Expand Down Expand Up @@ -508,13 +518,17 @@ def findTraps(self, inputMeasurements, calib, detector):
signal = []
data = []
new_signal = []
Nskipped = 0
for exposureEntry in inputMeasurements:
exposureDict = exposureEntry['CTI']
if exposureDict[ampName]['IMAGE_MEAN'] < self.config.maxImageMean:
signal.append(exposureDict[ampName]['IMAGE_MEAN'])
data.append(exposureDict[ampName]['OVERSCAN_VALUES'][start:stop+1])
if exposureDict[ampName]['LAST_MEAN'] < self.config.maxImageMean:
new_signal.append(exposureDict[ampName]['LAST_MEAN'])
else:
Nskipped += 1
self.log.info(f"Skipped {Nskipped} exposures brighter than {self.config.maxSignalForCti}.")

signal = np.array(signal)
data = np.array(data)
new_signal = np.array(new_signal)
Expand Down Expand Up @@ -751,10 +765,7 @@ def model_results(params, signal, num_transfers, start=1, stop=10):
Model results.
"""
v = params.valuesdict()
try:
v['cti'] = 10**v['ctiexp']
except KeyError:
pass
v['cti'] = 10**v['ctiexp']

# Adjust column numbering to match DM overscan bbox.
start += 1
Expand Down Expand Up @@ -1057,6 +1068,8 @@ def update_parameters(self, scale, decay_time):
"""
if scale < 0.0:
raise ValueError("Scale must be greater than or equal to 0.")
if np.isnan(scale):
raise ValueError("Scale must be real-valued number, not NaN.")
self.scale = scale
if decay_time <= 0.0:
raise ValueError("Decay time must be greater than 0.")
Expand Down

0 comments on commit b564799

Please sign in to comment.