146 def run(self, *, exposure, catalog):
147 """Measure the Normalized calibration flux.
148
149 Parameters
150 ----------
151 exposure : `lsst.afw.image.Exposure`
152 Exposure the normalized calibration flux is measured on.
153 catalog : `lsst.afw.table.SourceCatalog`
154 SourceCatalog containing measurements to be used to compute
155 normalized calibration fluxes. The catalog is modified in-place.
156
157 Returns
158 -------
159 Struct : `lsst.pipe.base.Struct`
160 Contains the following:
161
162 ``ap_corr_map``
163 aperture correction map (`lsst.afw.image.ApCorrMap`)
164 that contains two entries for the raw flux field:
165 - flux field (e.g. config.{raw_calibflux_name}_instFlux): 2d model
166 - flux sigma field (e.g. config.{raw_calibflux_name}_instFluxErr): 0 field
167 """
168 self.log.info("Measuring normalized calibration flux from %s", self.config.raw_calibflux_name)
169
170 raw_name = self.config.raw_calibflux_name
171 raw_flux_name = raw_name + "_instFlux"
172 raw_fluxerr_name = raw_name + "_instFluxErr"
173 norm_name = self.config.normalized_calibflux_name
174
175 if self.config.do_measure_ap_corr:
176 ap_corr_field, ap_corr_err_field = self._measure_aperture_correction(exposure, catalog)
177 else:
178 use_identity = False
179 ap_corr_map = exposure.info.getApCorrMap()
180 if ap_corr_map is None:
181 self.log.warning(
182 "Exposure does not have a valid normalization map; using identity normalization.",
183 )
184 use_identity = True
185 else:
186 ap_corr_field = ap_corr_map.get(raw_flux_name)
187 ap_corr_err_field = ap_corr_map.get(raw_fluxerr_name)
188 if not ap_corr_field or not ap_corr_err_field:
189 self.log.warning(
190 "Exposure aperture correction map is missing %s/%s for normalization; "
191 "using identity normalization.",
192 raw_flux_name,
193 raw_fluxerr_name,
194 )
195 use_identity = True
196
197 if use_identity:
198 ap_corr_field = ChebyshevBoundedField(exposure.getBBox(), np.array([[1.0]]))
199 ap_corr_err_field = ChebyshevBoundedField(exposure.getBBox(), np.array([[0.0]]))
200
201 corrections = ap_corr_field.evaluate(
202 catalog["slot_Centroid_x"],
203 catalog["slot_Centroid_y"],
204 )
205
206 input_flux_name = raw_flux_name
207 input_fluxerr_name = raw_fluxerr_name
208 input_flag_name = raw_name + "_flag"
209 output_flux_name = norm_name + "_instFlux"
210 output_fluxerr_name = norm_name + "_instFluxErr"
211 output_flag_name = norm_name + "_flag"
212
213 if catalog.isContiguous():
214 catalog[output_flux_name] = catalog[input_flux_name] * corrections
215 catalog[output_fluxerr_name] = catalog[input_fluxerr_name] * corrections
216
217 output_flag = catalog[input_flag_name].copy()
218 output_flag[corrections <= 0.0] = True
219 catalog[output_flag_name] = output_flag
220 else:
221
222 for i, row in enumerate(catalog):
223 row[output_flux_name] = row[input_flux_name] * corrections[i]
224 row[output_fluxerr_name] = row[input_fluxerr_name] * corrections[i]
225
226 if row[input_flag_name] or corrections[i] <= 0.0:
227 row[output_flag_name] = True
228
229 ap_corr_map = ApCorrMap()
230 ap_corr_map[raw_flux_name] = ap_corr_field
231 ap_corr_map[raw_fluxerr_name] = ap_corr_err_field
232
233 return lsst.pipe.base.Struct(
234 ap_corr_map=ap_corr_map,
235 )
236