Skip to content

Commit 8a32c3b

Browse files
Merge pull request #303 from lsst/tickets/DM-49497
DM-49497: Add check for valid BFK
2 parents 1b78804 + fb3776c commit 8a32c3b

File tree

1 file changed

+61
-1
lines changed

1 file changed

+61
-1
lines changed

python/lsst/cp/pipe/cpBfk.py

+61-1
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,27 @@ class BrighterFatterKernelSolveConfig(pipeBase.PipelineTaskConfig,
166166
doc="Slope of the correlation model for radii larger than correlationModelRadius",
167167
default=-1.35,
168168
)
169+
170+
nSigmaTolForValidEdge = pexConfig.Field(
171+
dtype=float,
172+
doc="A valid kernel will have all pixels in a 3px picture frame (edges) "
173+
"be within +/- nSigmaTolForValidEdge of zero.",
174+
default=5.0,
175+
)
176+
169177
useBfkPtc = pexConfig.Field(
170178
dtype=bool,
171179
doc="Use a BFK ptc in a single pipeline?",
172180
default=False,
173181
)
174182

183+
doCheckValidity = pexConfig.Field(
184+
dtype=bool,
185+
doc="Check the AMP kernels for basic validity criteria? "
186+
"Will set bfk.valid for each amp.",
187+
default=True,
188+
)
189+
175190

176191
class BrighterFatterKernelSolveTask(pipeBase.PipelineTask):
177192
"""Measure appropriate Brighter-Fatter Kernel from the PTC dataset.
@@ -415,7 +430,52 @@ def run(self, inputPtc, dummy, camera, inputDims):
415430
if self.config.level == 'DETECTOR' and ampName not in self.config.ignoreAmpsForAveraging:
416431
detectorCorrList.extend(scaledCorrList)
417432
detectorFluxes.extend(fluxes)
418-
bfk.valid[ampName] = True
433+
434+
# Check for validity
435+
if self.config.doCheckValidity:
436+
kernelSize = bfk.ampKernels[ampName].shape[0]
437+
kernelCenterValue = bfk.ampKernels[ampName][kernelSize//2, kernelSize//2]
438+
xv, yv = np.meshgrid(range(kernelSize), range(kernelSize))
439+
440+
# Get a mask for a 3px picture frame
441+
valid = True
442+
if kernelSize >= 7:
443+
edges = (xv < 3)
444+
edges += (xv > kernelSize - 3 - 1)
445+
edges += (yv < 3)
446+
edges += (yv > kernelSize - 3 - 1)
447+
448+
kernelEdges = bfk.ampKernels[ampName][edges].ravel()
449+
kernelEdgeStd = np.std(kernelEdges)
450+
451+
threshold = self.config.nSigmaTolForValidEdge*kernelEdgeStd
452+
453+
# Edges should converge to zero
454+
valid = np.all(np.isclose(
455+
kernelEdges, 0,
456+
rtol=threshold,
457+
))
458+
if not valid:
459+
self.log.warning("%s: the kernel edges did not converge to 0 within "
460+
"+/- %s sigma.", ampName, threshold)
461+
462+
# Kernel should be negative
463+
valid *= np.all(bfk.ampKernels[ampName][~edges] <= threshold)
464+
if not np.all(bfk.ampKernels[ampName][~edges] <= threshold):
465+
self.log.warning("%s: the kernel is not negative", ampName)
466+
467+
# The center should be the minimum
468+
valid *= np.all(bfk.ampKernels[ampName] >= kernelCenterValue)
469+
if not np.all(bfk.ampKernels[ampName] >= kernelCenterValue):
470+
self.log.warning("%s: the kernel center is not the absolute minimum.", ampName)
471+
else:
472+
raise RuntimeError("%s: The kernel is too small for validity check.", ampName)
473+
474+
bfk.valid[ampName] = valid
475+
else:
476+
# The kernel at this point will be valid
477+
bfk.valid[ampName] = True
478+
419479
self.log.info("Amp: %s Sum: %g Center Info Pre: %g Post: %g",
420480
ampName, finalSum, preKernel[center, center], postKernel[center, center])
421481

0 commit comments

Comments
 (0)