22from __future__
import annotations
25 "SingleFrameCompensatedGaussianFluxConfig",
26 "SingleFrameCompensatedGaussianFluxPlugin",
31import scipy.stats
as sps
36from ..sfm
import SingleFramePlugin, SingleFramePluginConfig
37from ..pluginRegistry
import register
39from .._measBaseLib
import _compensatedGaussianFiltInnerProduct
47 kernel_widths = ListField(
48 doc=
"The widths (in pixels) of the kernels for which to measure compensated apertures.",
55 doc=
"Scale parameter of outer Gaussian compared to inner Gaussian.",
61@register("base_CompensatedGaussianFlux")
63 ConfigClass = SingleFrameCompensatedGaussianFluxConfig
71 config: SingleFrameCompensatedGaussianFluxConfig,
78 super().
__init__(config, name, schema, metadata, logName, **kwds)
82 f
"{name}_flag", type=
"Flag", doc=
"Set to 1 for any fatal failure."
87 f
"{name}_bounds_flag",
89 doc=
"Flag set to 1 if not all filters fit within exposure.",
97 for width
in config.kernel_widths:
98 base_key = f
"{name}_{width}"
101 flux_str = f
"{base_key}_instFlux"
102 flux_key = schema.addField(
105 doc=
"Compensated Gaussian flux measurement.",
110 err_str = f
"{base_key}_instFluxErr"
111 err_key = schema.addField(
114 doc=
"Compensated Gaussian flux error.",
119 mask_str = f
"{base_key}_mask_bits"
120 mask_key = schema.addField(mask_str, type=np.int32, doc=
"Mask bits set within aperture.")
122 self.
width_keys[width] = (flux_key, err_key, mask_key)
123 self.
_rads[width] = math.ceil(sps.norm.ppf((0.995,), scale=width * config.t)[0])
127 def fail(self, measRecord, error=None):
128 if isinstance(error, OutOfBoundsError):
133 center = measRecord.getCentroid()
134 bbox = exposure.getBBox()
136 if Point2I(center)
not in exposure.getBBox().erodedBy(self.
_max_rad):
137 raise OutOfBoundsError(
"Not all the kernels for this source fit inside the exposure.")
139 y = center.getY() - bbox.beginY
140 x = center.getX() - bbox.beginX
142 y_floor = math.floor(y)
143 x_floor = math.floor(x)
145 for width, (flux_key, err_key, mask_key)
in self.
width_keys.items():
146 rad = self.
_rads[width]
147 y_slice = slice(y_floor - rad, y_floor + rad + 1, 1)
148 x_slice = slice(x_floor - rad, x_floor + rad + 1, 1)
149 y_mean = y - y_floor + rad
150 x_mean = x - x_floor + rad
152 flux, var = _compensatedGaussianFiltInnerProduct(
153 exposure.image.array[y_slice, x_slice],
154 exposure.variance.array[y_slice, x_slice],
160 measRecord.set(flux_key, flux)
161 measRecord.set(err_key, np.sqrt(var))
162 measRecord.set(mask_key, np.bitwise_or.reduce(exposure.mask.array[y_slice, x_slice], axis=
None))
measure(self, measRecord, exposure)
__init__(self, SingleFrameCompensatedGaussianFluxConfig config, str name, schema, metadata, logName=None, **kwds)
fail(self, measRecord, error=None)