23 """Load a full reference catalog in numpy/table/dataframe format.
25 This task will load multi-band reference objects, apply a reference selector,
26 and apply color terms.
29 from astropy
import units
41 __all__ = [
'LoadReferenceCatalogConfig',
'LoadReferenceCatalogTask']
45 """Config for LoadReferenceCatalogTask"""
46 refObjLoader = pexConfig.ConfigurableField(
47 target=LoadIndexedReferenceObjectsTask,
48 doc=
"Reference object loader for photometry",
50 doApplyColorTerms = pexConfig.Field(
51 doc=(
"Apply photometric color terms to reference stars? "
52 "Requires that colorterms be set to a ColorTermLibrary"),
56 colorterms = pexConfig.ConfigField(
57 doc=
"Library of photometric reference catalog name to color term dict.",
58 dtype=ColortermLibrary,
60 referenceSelector = pexConfig.ConfigurableField(
61 target=ReferenceSourceSelectorTask,
62 doc=
"Selection of reference sources",
64 doReferenceSelection = pexConfig.Field(
65 doc=
"Run the reference selector on the reference catalog?",
73 msg =
"applyColorTerms=True requires the `colorterms` field be set to a ColortermLibrary."
74 raise pexConfig.FieldValidationError(LoadReferenceCatalogConfig.colorterms, self, msg)
78 """Load multi-band reference objects from a reference catalog.
82 dataIds : iterable of `lsst.daf.butler.dataId`, optional
83 An iterable object of dataIds which point to reference catalogs
84 in a Gen3 repository. Required for Gen3.
85 refCats : iterable of `lsst.daf.butler.DeferredDatasetHandle`, optional
86 An iterable object of dataset refs for reference catalogs in
87 a Gen3 repository. Required for Gen3.
88 butler : `lsst.daf.persistence.Butler`, optional
89 A Gen2 butler. Required for Gen2.
91 ConfigClass = LoadReferenceCatalogConfig
92 _DefaultName =
"loadReferenceCatalog"
94 def __init__(self, dataIds=None, refCats=None, butler=None, **kwargs):
95 if dataIds
is not None and refCats
is not None:
96 pipeBase.Task.__init__(self, **kwargs)
97 refConfig = self.config.refObjLoader
102 elif butler
is not None:
103 raise RuntimeError(
"LoadReferenceCatalogTask does not support Gen2 Butlers.")
105 raise RuntimeError(
"Must instantiate LoadReferenceCatalogTask with "
106 "dataIds and refCats (Gen3)")
108 if self.config.doReferenceSelection:
109 self.makeSubtask(
'referenceSelector')
115 bboxToSpherePadding=None):
116 """Get a multi-band reference catalog by specifying a bounding box and WCS.
118 The catalog will be in `numpy.ndarray`, with positions proper-motion
119 corrected to "epoch" (if specified, and if the reference catalog has
120 proper motions); sources cut on a reference selector (if
121 "config.doReferenceSelection = True"); and color-terms applied (if
122 "config.doApplyColorTerms = True").
124 The format of the reference catalog will be of the format:
126 dtype = [('ra', 'np.float64'),
127 ('dec', 'np.float64'),
128 ('refMag', 'np.float32', (len(filterList), )),
129 ('refMagErr', 'np.float32', (len(filterList), ))]
131 Reference magnitudes (AB) and errors will be 99 for non-detections
136 bbox : `lsst.geom.Box2I`
137 Box which bounds a region in pixel space.
138 wcs : `lsst.afw.geom.SkyWcs`
139 Wcs object defining the pixel to sky (and reverse) transform for
141 filterList : `List` [ `str` ]
142 List of camera physicalFilter names to retrieve magnitudes.
143 epoch : `astropy.time.Time`, optional
144 Epoch to which to correct proper motion and parallax
145 (if available), or `None` to not apply such corrections.
146 bboxToSpherePadding : `int`, optional
147 Padding to account for translating a set of corners into a
148 spherical (convex) boundary that is certain to encompass the
149 entire area covered by the bbox.
153 refCat : `numpy.ndarray`
158 center = wcs.pixelToSky(bbox.getCenter())
163 bboxToSpherePadding=bboxToSpherePadding)
165 if not skyBox.refCat.isContiguous():
166 refCat = skyBox.refCat.copy(deep=
True)
168 refCat = skyBox.refCat
173 catalogFormat='numpy'):
174 """Get a multi-band reference catalog by specifying a center and radius.
176 The catalog will be in `numpy.ndarray`, with positions proper-motion
177 corrected to "epoch" (if specified, and if the reference catalog has
178 proper motions); sources cut on a reference selector (if
179 "config.doReferenceSelection = True"); and color-terms applied (if
180 "config.doApplyColorTerms = True").
182 The format of the reference catalog will be of the format:
184 dtype = [('ra', 'np.float64'),
185 ('dec', 'np.float64'),
186 ('refMag', 'np.float32', (len(filterList), )),
187 ('refMagErr', 'np.float32', (len(filterList), ))]
189 Reference magnitudes (AB) and errors will be 99 for non-detections
194 center : `lsst.geom.SpherePoint`
195 Point defining the center of the circular region.
196 radius : `lsst.geom.Angle`
197 Defines the angular radius of the circular region.
198 filterList : `List` [ `str` ]
199 List of camera physicalFilter names to retrieve magnitudes.
200 epoch : `astropy.time.Time`, optional
201 Epoch to which to correct proper motion and parallax
202 (if available), or `None` to not apply such corrections.
206 refCat : `numpy.ndarray`
213 skyCircle = self.
refObjLoaderrefObjLoader.loadSkyCircle(center, radius,
217 if not skyCircle.refCat.isContiguous():
218 refCat = skyCircle.refCat.copy(deep=
True)
220 refCat = skyCircle.refCat
224 def _formatCatalog(self, refCat, filterList):
225 """Format a reference afw table into the final format.
227 This method applies reference selections and color terms as specified
232 refCat : `lsst.afw.table.SourceCatalog`
233 Reference catalog in afw format.
234 filterList : `list` [`str`]
235 List of camera physicalFilter names to apply color terms.
239 refCat : `numpy.ndarray`
242 if self.config.doReferenceSelection:
243 goodSources = self.referenceSelector.selectSources(refCat)
244 selected = goodSources.selected
246 selected = np.ones(len(refCat), dtype=bool)
248 npRefCat = np.zeros(np.sum(selected), dtype=[(
'ra',
'f8'),
250 (
'refMag',
'f4', (len(filterList), )),
251 (
'refMagErr',
'f4', (len(filterList), ))])
253 if npRefCat.size == 0:
260 npRefCat[
'ra'] = np.rad2deg(refCat[
'coord_ra'][selected])
261 npRefCat[
'dec'] = np.rad2deg(refCat[
'coord_dec'][selected])
264 npRefCat[
'refMag'][:, :] = 99.0
265 npRefCat[
'refMagErr'][:, :] = 99.0
267 if self.config.doApplyColorTerms:
268 if isinstance(self.
refObjLoaderrefObjLoader, ReferenceObjectLoader):
270 refCatName = self.
refObjLoaderrefObjLoader.config.value.ref_dataset_name
273 refCatName = self.
refObjLoaderrefObjLoader.ref_dataset_name
276 if fluxField
is None:
280 self.log.
debug(
"Applying color terms for filterName='%s'", filterName)
282 colorterm = self.config.colorterms.getColorterm(filterName, refCatName, doRaise=
True)
284 refMag, refMagErr = colorterm.getCorrectedMagnitudes(refCat)
290 good, = np.where((np.nan_to_num(refMag[selected], nan=99.0) < 90.0)
291 & (np.nan_to_num(refMagErr[selected], nan=99.0) < 90.0)
292 & (np.nan_to_num(refMagErr[selected]) > 0.0))
294 npRefCat[
'refMag'][good, i] = refMag[selected][good]
295 npRefCat[
'refMagErr'][good, i] = refMagErr[selected][good]
301 good, = np.where((np.nan_to_num(refCat[fluxField][selected]) > 0.0)
302 & (np.nan_to_num(refCat[fluxField+
'Err'][selected]) > 0.0))
303 refMag = (refCat[fluxField][selected][good]*units.nJy).to_value(units.ABmag)
305 refCat[fluxField][selected][good])
306 npRefCat[
'refMag'][good, i] = refMag
307 npRefCat[
'refMagErr'][good, i] = refMagErr
311 def _determineFluxFields(self, center, filterList):
312 """Determine the flux field names for a reference catalog.
314 This method sets self._fluxFields, self._referenceFilter.
318 center : `lsst.geom.SpherePoint`
319 The center around which to load test sources.
320 filterList : `list` [`str`]
321 List of camera physicalFilter names.
325 foundReferenceFilter =
False
331 configIntersection = {k: getattr(self.
refObjLoaderrefObjLoader.config, k)
333 if (k
in configTemp.keys()
and k !=
"connections")}
335 configIntersection[
'requireProperMotion'] =
False
336 configTemp.update(**configIntersection)
340 for filterName
in filterList:
341 if self.config.refObjLoader.anyFilterMapsToThis
is not None:
342 refFilterName = self.config.refObjLoader.anyFilterMapsToThis
344 refFilterName = self.config.refObjLoader.filterMap.get(filterName)
345 if refFilterName
is None:
348 results = self.
refObjLoaderrefObjLoader.loadSkyCircle(center,
349 0.05*lsst.geom.degrees,
351 foundReferenceFilter =
True
354 except RuntimeError
as err:
357 if 'not find flux' in err.args[0]:
366 if not foundReferenceFilter:
367 raise RuntimeError(
"Could not find any valid flux field(s) %s" %
368 (
", ".join(filterList)))
375 for filterName
in filterList:
378 if self.config.refObjLoader.anyFilterMapsToThis
is not None:
379 refFilterName = self.config.refObjLoader.anyFilterMapsToThis
381 refFilterName = self.config.refObjLoader.filterMap.get(filterName)
383 if refFilterName
is not None:
385 fluxField =
getRefFluxField(results.refCat.schema, filterName=refFilterName)
390 if fluxField
is None:
391 self.log.
warning(
'No reference flux field for camera filter %s', filterName)
std::vector< SchemaItem< Flag > > * items
def getPixelBoxCatalog(self, bbox, wcs, filterList, epoch=None, bboxToSpherePadding=None)
def __init__(self, dataIds=None, refCats=None, butler=None, **kwargs)
def _determineFluxFields(self, center, filterList)
def _formatCatalog(self, refCat, filterList)
def getSkyCircleCatalog(self, center, radius, filterList, epoch=None, catalogFormat='numpy')
std::shared_ptr< FrameSet > append(FrameSet const &first, FrameSet const &second)
Construct a FrameSet that performs two transformations in series.
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
double abMagErrFromFluxErr(double fluxErr, double flux)
Compute AB magnitude error from flux and flux error in Janskys.
def getRefFluxField(schema, filterName=None)
Fit spatial kernel using approximate fluxes for candidates, and solving a linear system of equations.