33 Removes the Poisson contribution from actual sources in the variance plane
36 If neither gain nor gains are provided, the function estimates the gain(s).
37 If ``average_across_amps`` is True, a single gain value for the entire
38 image is estimated. If False, individual gain values for each amplifier are
39 estimated. The estimation involves a linear fit of variance versus image
44 exposure : `~lsst.afw.image.Exposure`
45 The background-subtracted exposure containing a variance plane to be
46 corrected for source contributions.
47 gain : `float`, optional
48 The gain value for the entire image. This parameter is used if
49 ``gains`` is not provided. If both ``gain`` and ``gains`` are None, and
50 ``average_across_amps`` is True, ``gain`` is estimated from the image
52 gains : dict[`str`, `float`], optional
53 A dictionary mapping amplifier ID (as a string) to gain value. This
54 parameter is used if ``gain`` is not provided. If both ``gain`` and
55 ``gains`` are None, and ``average_across_amps`` is False, ``gains`` are
56 estimated from the image and variance planes.
57 average_across_amps : `bool`, optional
58 Determines the gain estimation strategy. If True, the gain for the
59 entire image is estimated at once. If False, individual gains for each
60 amplifier are estimated. This parameter is ignored if either ``gain``
61 or ``gains`` is specified.
62 in_place : `bool`, optional
63 If True, the variance plane of the input Exposure is modified in place.
64 A modified copy of the variance plane is always returned irrespective
69 variance_plane : `~lsst.afw.image.Image`
70 The corrected variance plane, with the signal contribution removed.
75 If amplifiers cannot be retrieved from the exposure.
77 If both ``gain`` and ``gains`` are provided, or if the number of
78 provided ``gains`` does not match the number of amplifiers.
80 variance_plane = exposure.variance
if in_place
else exposure.variance.clone()
81 if gain
is None and gains
is None:
82 if average_across_amps:
83 amp_bboxes = [exposure.getBBox()]
86 amps = exposure.getDetector().getAmplifiers()
87 amp_bboxes = [amp.getBBox()
for amp
in amps]
88 except AttributeError:
90 "Could not retrieve amplifiers from exposure. To compute a simple gain value across the "
91 "entire image, use average_across_amps=True."
96 for amp_bbox
in amp_bboxes:
97 amp_im_arr = exposure[amp_bbox].image.array
98 amp_var_arr = variance_plane[amp_bbox].array
99 good = (amp_var_arr != 0) & np.isfinite(amp_var_arr) & np.isfinite(amp_im_arr)
100 fit = np.polyfit(amp_im_arr[good], amp_var_arr[good], deg=1)
102 amp_gain = 1.0 / fit[0]
103 variance_plane[amp_bbox].array[good] -= amp_im_arr[good] / amp_gain
104 elif gain
is None and gains
is not None:
105 amps = exposure.getDetector().getAmplifiers()
107 if len(gains) != namps:
109 f
"Incorrect number of gains provided: {len(gains)} values for {namps} amplifiers."
112 amp_bbox = amp.getBBox()
113 amp_gain = gains[amp.getName()]
114 im_arr = exposure[amp_bbox].image.array
115 variance_plane[amp_bbox].array -= im_arr / amp_gain
116 elif gain
is not None and gains
is None:
117 im_arr = exposure.image.array
118 variance_plane.array -= im_arr / gain
119 elif gain
is not None and gains
is not None:
121 "Both 'gain' and 'gains' are provided. Please provide only one of them or none at "
122 "all in case of automatic gain estimation from the image and variance planes."
125 if np.any(variance_plane.array < 0):
126 raise ValueError(
"Corrected variance plane has negative values.")
127 return variance_plane