216 def run(self, inputExp, inputDims):
217 """Measure covariances from difference of flat pairs
221 inputExp : `dict` [`float`,
222 (`~lsst.afw.image.exposure.exposure.ExposureF`,
223 `~lsst.afw.image.exposure.exposure.ExposureF`, ...,
224 `~lsst.afw.image.exposure.exposure.ExposureF`)]
225 Dictionary that groups flat-field exposures that have the same
226 exposure time (seconds).
229 List of exposure IDs.
233 detector =
list(inputExp.values())[0][0][0].getDetector()
234 detNum = detector.getId()
235 amps = detector.getAmplifiers()
236 ampNames = [amp.getName()
for amp
in amps]
239 maxMeanSignalDict = {ampName: 1e6
for ampName
in ampNames}
240 minMeanSignalDict = {ampName: 0.0
for ampName
in ampNames}
241 for ampName
in ampNames:
242 if 'ALL_AMPS' in self.config.maxMeanSignal:
243 maxMeanSignalDict[ampName] = self.config.maxMeanSignal[
'ALL_AMPS']
244 elif ampName
in self.config.maxMeanSignal:
245 maxMeanSignalDict[ampName] = self.config.maxMeanSignal[ampName]
247 if 'ALL_AMPS' in self.config.minMeanSignal:
248 minMeanSignalDict[ampName] = self.config.minMeanSignal[
'ALL_AMPS']
249 elif ampName
in self.config.minMeanSignal:
250 minMeanSignalDict[ampName] = self.config.minMeanSignal[ampName]
252 tags = [(
'mu',
'<f8'), (
'afwVar',
'<f8'), (
'i',
'<i8'), (
'j',
'<i8'), (
'var',
'<f8'),
253 (
'cov',
'<f8'), (
'npix',
'<i8'), (
'ext',
'<i8'), (
'expTime',
'<f8'), (
'ampName',
'<U3')]
255 dummyPtcDataset = PhotonTransferCurveDataset(ampNames,
'DUMMY',
256 self.config.maximumRangeCovariancesAstier)
258 for ampName
in ampNames:
259 dummyPtcDataset.setAmpValues(ampName)
261 partialPtcDatasetList = []
264 for i
in range(len(inputDims)):
265 partialPtcDatasetList.append(dummyPtcDataset)
267 if self.config.numEdgeSuspect > 0:
269 self.log.
info(f
"Masking {self.config.numEdgeSuspect} pixels from the edges "
270 "of all exposures as SUSPECT.")
272 for expTime
in inputExp:
273 exposures = inputExp[expTime]
274 if len(exposures) == 1:
275 self.log.
warn(f
"Only one exposure found at expTime {expTime}. Dropping exposure "
276 f
"{exposures[0][1]}")
280 exp1, expId1 = exposures[0]
281 exp2, expId2 = exposures[1]
282 if len(exposures) > 2:
283 self.log.
warn(f
"Already found 2 exposures at expTime {expTime}. "
284 "Ignoring exposures: "
285 f
"{i[1] for i in exposures[2:]}")
287 if self.config.numEdgeSuspect > 0:
288 isrTask.maskEdges(exp1, numEdgePixels=self.config.numEdgeSuspect,
289 maskPlane=
"SUSPECT", level=self.config.edgeMaskLevel)
290 isrTask.maskEdges(exp2, numEdgePixels=self.config.numEdgeSuspect,
291 maskPlane=
"SUSPECT", level=self.config.edgeMaskLevel)
294 partialPtcDataset = PhotonTransferCurveDataset(ampNames,
'',
295 self.config.maximumRangeCovariancesAstier)
296 for ampNumber, amp
in enumerate(detector):
297 ampName = amp.getName()
299 doRealSpace = self.config.covAstierRealSpace
300 if self.config.detectorMeasurementRegion ==
'AMP':
301 region = amp.getBBox()
302 elif self.config.detectorMeasurementRegion ==
'FULL':
308 muDiff, varDiff, covAstier = self.measureMeanVarCov(exp1, exp2, region=region,
309 covAstierRealSpace=doRealSpace)
316 if np.isnan(muDiff)
or np.isnan(varDiff)
or (covAstier
is None):
317 msg = (f
"NaN mean or var, or None cov in amp {ampName} in exposure pair {expId1},"
318 f
" {expId2} of detector {detNum}.")
322 covArray = np.full((1, self.config.maximumRangeCovariancesAstier,
323 self.config.maximumRangeCovariancesAstier), np.nan)
324 covSqrtWeights = np.full_like(covArray, np.nan)
326 if (muDiff <= minMeanSignalDict[ampName])
or (muDiff >= maxMeanSignalDict[ampName]):
329 if covAstier
is not None:
330 tupleRows = [(muDiff, varDiff) + covRow + (ampNumber, expTime,
331 ampName)
for covRow
in covAstier]
332 tempStructArray = np.array(tupleRows, dtype=tags)
334 self.config.maximumRangeCovariancesAstier)
335 covSqrtWeights = np.nan_to_num(1./np.sqrt(vcov))
339 covArray *= varFactor**2
341 covArray[0, 0] /= varFactor
343 partialPtcDataset.setAmpValues(ampName, rawExpTime=[expTime], rawMean=[muDiff],
344 rawVar=[varDiff], inputExpIdPair=[(expId1, expId2)],
345 expIdMask=[expIdMask], covArray=covArray,
346 covSqrtWeights=covSqrtWeights)
351 datasetIndex = np.where(expId1 == np.array(inputDims))[0][0]
352 partialPtcDatasetList[datasetIndex] = partialPtcDataset
354 if nAmpsNan == len(ampNames):
355 msg = f
"NaN mean in all amps of exposure pair {expId1}, {expId2} of detector {detNum}."
357 return pipeBase.Struct(
358 outputCovariances=partialPtcDatasetList,
daf::base::PropertyList * list
def makeCovArray(inputTuple, maxRangeFromTuple=8)
def sigmaClipCorrection(nSigClip)
def run(self, skyInfo, tempExpRefList, imageScalerList, weightList, altMaskList=None, mask=None, supplementaryData=None)