21__all__ = [
"PropagateSourceFlagsConfig",
"PropagateSourceFlagsTask"]
25from smatch.matcher
import Matcher
32 """Configuration for propagating source flags to coadd objects."""
33 source_flags = pexConfig.DictField(
39 "calib_psf_candidate": 0.2,
40 "calib_psf_used": 0.2,
41 "calib_psf_reserved": 0.2,
42 "calib_astrometry_used": 0.2,
43 "calib_photometry_used": 0.2,
44 "calib_photometry_reserved": 0.2
46 doc=(
"Source flags to propagate, with the threshold of relative occurrence "
47 "(valid range: [0-1]). Coadd object will have flag set if fraction "
48 "of input visits in which it is flagged is greater than the threshold."),
50 finalized_source_flags = pexConfig.DictField(
60 doc=(
"Finalized source flags to propagate, with the threshold of relative "
61 "occurrence (valid range: [0-1]). Coadd object will have flag set if "
62 "fraction of input visits in which it is flagged is greater than the "
65 x_column = pexConfig.Field(
66 doc=
"Name of column with source x position (sourceTable_visit).",
70 y_column = pexConfig.Field(
71 doc=
"Name of column with source y position (sourceTable_visit).",
75 finalized_x_column = pexConfig.Field(
76 doc=
"Name of column with source x position (finalized_src_table).",
78 default=
"slot_Centroid_x",
80 finalized_y_column = pexConfig.Field(
81 doc=
"Name of column with source y position (finalized_src_table).",
83 default=
"slot_Centroid_y",
85 match_radius = pexConfig.Field(
88 doc=
"Source matching radius (arcsec)"
97 raise ValueError(f
"The set of source_flags {source_flags} must not overlap "
98 f
"with the finalized_source_flags {finalized_source_flags}")
102 """Task to propagate source flags to coadd objects.
104 Flagged sources may come from a mix of two different types of source catalogs.
105 The source_table catalogs
from ``CalibrateTask`` contain flags
for the first
106 round of astromety/photometry/psf fits.
107 The finalized_source_table catalogs
from ``FinalizeCalibrationTask`` contain
108 flags
from the second round of psf fitting.
110 ConfigClass = PropagateSourceFlagsConfig
113 pipeBase.Task.__init__(self, **kwargs)
116 for f
in self.config.source_flags:
117 self.
schemaschema.addField(f, type=
"Flag", doc=
"Propagated from sources")
118 for f
in self.config.finalized_source_flags:
119 self.
schemaschema.addField(f, type=
"Flag", doc=
"Propagated from finalized sources")
121 def run(self, coadd_object_cat, ccd_inputs,
122 source_table_handle_dict=None, finalized_source_table_handle_dict=None):
123 """Propagate flags from single-frame sources to coadd objects.
125 Flags are only propagated if a configurable percentage of the sources
126 are matched to the coadd objects. This task will match both
"plain"
127 source flags
and "finalized" source flags.
132 Table of coadd objects.
134 Table of single-frame inputs to coadd.
135 source_table_handle_dict : `dict` [`int`: `lsst.daf.butler.DeferredDatasetHandle`]
136 Dict
for sourceTable_visit handles (key
is visit). May be
None if
137 ``config.source_flags`` has no entries.
138 finalized_source_table_handle_dict : `dict` [`int`:
139 `lsst.daf.butler.DeferredDatasetHandle`]
140 Dict
for finalized_src_table handles (key
is visit). May be
None if
141 ``config.finalized_source_flags`` has no entries.
143 if len(self.config.source_flags) == 0
and len(self.config.finalized_source_flags) == 0:
147 self.config.x_column,
148 self.config.y_column,
149 self.config.source_flags.keys()
152 self.config.finalized_x_column,
153 self.config.finalized_y_column,
154 self.config.finalized_source_flags.keys(),
160 num_overlaps = np.zeros(len(coadd_object_cat), dtype=np.int32)
161 for i, obj
in enumerate(coadd_object_cat):
162 num_overlaps[i] = len(ccd_inputs.subsetContaining(obj.getCoord(),
True))
164 visits = np.unique(ccd_inputs[
"visit"])
166 matcher = Matcher(np.rad2deg(coadd_object_cat[
"coord_ra"]),
167 np.rad2deg(coadd_object_cat[
"coord_dec"]))
169 source_flag_counts = {f: np.zeros(len(coadd_object_cat), dtype=np.int32)
170 for f
in self.config.source_flags}
171 finalized_source_flag_counts = {f: np.zeros(len(coadd_object_cat), dtype=np.int32)
172 for f
in self.config.finalized_source_flags}
174 handles_list = [source_table_handle_dict, finalized_source_table_handle_dict]
175 columns_list = [source_columns, finalized_columns]
176 counts_list = [source_flag_counts, finalized_source_flag_counts]
177 x_column_list = [self.config.x_column, self.config.finalized_x_column]
178 y_column_list = [self.config.y_column, self.config.finalized_y_column]
180 for handle_dict, columns, flag_counts, x_col, y_col
in zip(handles_list,
185 if handle_dict
is not None and len(columns) > 0:
187 handle = handle_dict[visit]
188 df = handle.get(parameters={
"columns": columns})
191 for row
in ccd_inputs[ccd_inputs[
"visit"] == visit]:
192 detector = row[
"ccd"]
195 df_det = df[df[
"detector"] == detector]
200 ra, dec = wcs.pixelToSkyArray(df_det[x_col].values,
201 df_det[y_col].values,
208 idx, i1, i2, d = matcher.query_radius(
211 self.config.match_radius/3600.,
218 for flag
in flag_counts:
219 flag_values = df_det[flag].values
220 flag_counts[flag][i1] += flag_values[i2].astype(np.int32)
222 for flag
in source_flag_counts:
223 thresh = num_overlaps*self.config.source_flags[flag]
224 object_flag = (source_flag_counts[flag] > thresh)
225 coadd_object_cat[flag] = object_flag
226 self.log.info(
"Propagated %d sources with flag %s", object_flag.sum(), flag)
228 for flag
in finalized_source_flag_counts:
229 thresh = num_overlaps*self.config.finalized_source_flags[flag]
230 object_flag = (finalized_source_flag_counts[flag] > thresh)
231 coadd_object_cat[flag] = object_flag
232 self.log.info(
"Propagated %d finalized sources with flag %s", object_flag.sum(), flag)
234 def _get_source_table_column_names(self, x_column, y_column, flags):
235 """Get the list of source table columns from the config.
240 Name of column with x centroid.
242 Name of column
with y centroid.
243 flags : `list` [`str`]
244 List of flags to retrieve.
248 columns : [`list`] [`str`]
251 columns = ["visit",
"detector",
253 columns.extend(flags)
def __init__(self, schema, **kwargs)
def _get_source_table_column_names(self, x_column, y_column, flags)
def run(self, coadd_object_cat, ccd_inputs, source_table_handle_dict=None, finalized_source_table_handle_dict=None)