23"""Load reference catalog objects for input to FGCM.
25This task will load multi-band reference objects and apply color terms (if
26configured). This wrapper around LoadReferenceObjects task also allows loading
27by healpix pixel (the native pixelization of fgcm), and is self-contained so
28the task can be called by third-party code.
33from astropy
import units
35import lsst.pex.config
as pexConfig
36import lsst.pipe.base
as pipeBase
37from lsst.meas.algorithms
import LoadIndexedReferenceObjectsTask, ReferenceSourceSelectorTask
38from lsst.meas.algorithms
import getRefFluxField
39from lsst.pipe.tasks.colorterms
import ColortermLibrary
40from lsst.afw.image
import abMagErrFromFluxErr
44__all__ = [
'FgcmLoadReferenceCatalogConfig',
'FgcmLoadReferenceCatalogTask']
48 """Config for FgcmLoadReferenceCatalogTask"""
50 refObjLoader = pexConfig.ConfigurableField(
51 target=LoadIndexedReferenceObjectsTask,
52 doc=
"Reference object loader for photometry",
53 deprecated=
"refObjLoader is deprecated, and will be removed after v24.",
55 filterMap = pexConfig.DictField(
56 doc=
"Mapping from physicalFilter label to reference filter name.",
61 applyColorTerms = pexConfig.Field(
62 doc=(
"Apply photometric color terms to reference stars?"
63 "Requires that colorterms be set to a ColorTermLibrary"),
67 colorterms = pexConfig.ConfigField(
68 doc=
"Library of photometric reference catalog name to color term dict.",
69 dtype=ColortermLibrary,
71 referenceSelector = pexConfig.ConfigurableField(
72 target=ReferenceSourceSelectorTask,
73 doc=
"Selection of reference sources",
79 msg =
'Must set filterMap'
80 raise pexConfig.FieldValidationError(FgcmLoadReferenceCatalogConfig.filterMap, self, msg)
82 msg =
"applyColorTerms=True requires the `colorterms` field be set to a ColortermLibrary."
83 raise pexConfig.FieldValidationError(FgcmLoadReferenceCatalogConfig.colorterms, self, msg)
88 Load multi-band reference objects from a reference catalog.
92 refObjLoader : `lsst.meas.algorithms.ReferenceObjectLoader`
93 Reference object loader.
95 Name of reference catalog (
for color term lookups).
97 ConfigClass = FgcmLoadReferenceCatalogConfig
98 _DefaultName = 'fgcmLoadReferenceCatalog'
100 def __init__(self, refObjLoader=None, refCatName=None, **kwargs):
101 """Construct an FgcmLoadReferenceCatalogTask
103 pipeBase.Task.__init__(self, **kwargs)
107 if refObjLoader
is None or refCatName
is None:
108 raise RuntimeError(
"FgcmLoadReferenceCatalogTask requires a refObjLoader and refCatName.")
110 self.makeSubtask(
'referenceSelector')
117 Get a reference catalog that overlaps a healpix pixel, using multiple
118 filters. In addition, apply colorterms if available.
120 Return format
is a numpy recarray
for use
with fgcm,
with the format:
122 dtype = ([(
'ra', `np.float64`),
123 (
'dec', `np.float64`),
124 (
'refMag', `np.float32`, len(filterList)),
125 (
'refMagErr', `np.float32`, len(filterList)])
127 Reference magnitudes (AB) will be 99
for non-detections.
132 Healpix nside of pixel to load
134 Healpix pixel of pixel to load
136 list of `str` of camera filter names.
137 nest: `bool`, optional
138 Is the pixel
in nest format? Default
is False.
142 fgcmRefCat: `np.recarray`
146 lon, lat = hpg.pixel_to_angle(nside, pixel, nest=nest, degrees=
False)
147 center = lsst.geom.SpherePoint(lon * lsst.geom.degrees, lat * lsst.geom.radians)
149 theta_phi = hpg.boundaries(nside, pixel, step=1, nest=nest, lonlat=
False)
151 radius = 0.0 * lsst.geom.radians
152 for ctheta, cphi
in zip(*theta_phi):
153 rad = center.separation(lsst.geom.SpherePoint(cphi * lsst.geom.radians,
154 (np.pi/2. - ctheta) * lsst.geom.radians))
160 center.getDec().asDegrees(),
163 catPix = hpg.angle_to_pixel(nside, fgcmRefCat[
'ra'], fgcmRefCat[
'dec'], nest=nest)
165 inPix, = np.where(catPix == pixel)
167 return fgcmRefCat[inPix]
171 Get a reference catalog that overlaps a circular sky region, using
172 multiple filters. In addition, apply colorterms if available.
174 Return format
is a numpy recarray
for use
with fgcm.
176 dtype = ([(
'ra', `np.float64`),
177 (
'dec', `np.float64`),
178 (
'refMag', `np.float32`, len(filterList)),
179 (
'refMagErr', `np.float32`, len(filterList)])
181 Reference magnitudes (AB) will be 99
for non-detections.
186 ICRS right ascension, degrees.
188 ICRS declination, degrees.
190 Radius to search, degrees.
192 list of `str` of camera filter names.
196 fgcmRefCat: `np.recarray`
199 center = lsst.geom.SpherePoint(ra * lsst.geom.degrees, dec * lsst.geom.degrees)
206 radius * lsst.geom.degrees,
209 if not skyCircle.refCat.isContiguous():
210 refCat = skyCircle.refCat.copy(deep=
True)
212 refCat = skyCircle.refCat
215 goodSources = self.referenceSelector.selectSources(refCat)
216 selected = goodSources.selected
218 fgcmRefCat = np.zeros(np.sum(selected), dtype=[(
'ra',
'f8'),
220 (
'refMag',
'f4', len(filterList)),
221 (
'refMagErr',
'f4', len(filterList))])
222 if fgcmRefCat.size == 0:
232 conv = refCat[0][
'coord_ra'].asDegrees() / float(refCat[0][
'coord_ra'])
233 fgcmRefCat[
'ra'] = refCat[
'coord_ra'][selected] * conv
234 fgcmRefCat[
'dec'] = refCat[
'coord_dec'][selected] * conv
237 fgcmRefCat[
'refMag'][:, :] = 99.0
238 fgcmRefCat[
'refMagErr'][:, :] = 99.0
240 if self.config.applyColorTerms:
242 if fluxField
is None:
245 self.log.debug(
"Applying color terms for filtername=%r" % (filterName))
247 colorterm = self.config.colorterms.getColorterm(filterName, self.
refCatName, doRaise=
True)
249 refMag, refMagErr = colorterm.getCorrectedMagnitudes(refCat)
255 good, = np.where((np.nan_to_num(refMag[selected]) < 90.0)
256 & (np.nan_to_num(refMagErr[selected]) < 90.0)
257 & (np.nan_to_num(refMagErr[selected]) > 0.0))
259 fgcmRefCat[
'refMag'][good, i] = refMag[selected][good]
260 fgcmRefCat[
'refMagErr'][good, i] = refMagErr[selected][good]
268 good, = np.where((np.nan_to_num(refCat[fluxField][selected]) > 0.0)
269 & (np.nan_to_num(refCat[fluxField+
'Err'][selected]) > 0.0))
270 refMag = (refCat[fluxField][selected][good] * units.nJy).to_value(units.ABmag)
271 refMagErr = abMagErrFromFluxErr(refCat[fluxField+
'Err'][selected][good],
272 refCat[fluxField][selected][good])
273 fgcmRefCat[
'refMag'][good, i] = refMag
274 fgcmRefCat[
'refMagErr'][good, i] = refMagErr
278 def _determine_flux_fields(self, center, filterList):
280 Determine the flux field names for a reference catalog.
286 center: `lsst.geom.SpherePoint`
287 The center around which to load test sources.
289 list of `str` of camera filter names.
297 foundReferenceFilter =
False
298 for filterName
in filterList:
299 refFilterName = self.config.filterMap.get(filterName)
300 if refFilterName
is None:
305 0.05 * lsst.geom.degrees,
307 foundReferenceFilter =
True
315 if not foundReferenceFilter:
316 raise RuntimeError(
"Could not find any valid flux field(s) %s" %
317 (
", ".join(filterList)))
321 for filterName
in filterList:
324 refFilterName = self.config.filterMap.get(filterName)
326 if refFilterName
is not None:
328 fluxField = getRefFluxField(results.refCat.schema, filterName=refFilterName)
333 if fluxField
is None:
334 self.log.warning(f
'No reference flux field for camera filter {filterName}')
def __init__(self, refObjLoader=None, refCatName=None, **kwargs)
def getFgcmReferenceStarsSkyCircle(self, ra, dec, radius, filterList)
def _determine_flux_fields(self, center, filterList)
def getFgcmReferenceStarsHealpix(self, nside, pixel, filterList, nest=False)