Coverage for python/lsst/faro/measurement/TractMeasurementTasks.py : 44%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of faro.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22import astropy.units as u
23import numpy as np
25from lsst.pipe.base import Struct, Task
26from lsst.verify import Measurement, Datum
27from lsst.pex.config import Config, Field
28from lsst.faro.utils.stellar_locus import stellarLocusResid, calcQuartileClippedStats
29from lsst.faro.utils.matcher import makeMatchedPhotom
30from lsst.faro.utils.extinction_corr import extinction_corr
31from lsst.faro.utils.tex import calculateTEx
33__all__ = ("WPerpConfig", "WPerpTask", "TExConfig", "TExTask")
36class WPerpConfig(Config):
37 # These are cuts to apply to the r-band only:
38 bright_rmag_cut = Field(
39 doc="Bright limit of catalog entries to include", dtype=float, default=17.0
40 )
41 faint_rmag_cut = Field(
42 doc="Faint limit of catalog entries to include", dtype=float, default=23.0
43 )
46class WPerpTask(Task):
47 ConfigClass = WPerpConfig
48 _DefaultName = "WPerpTask"
50 def run(
51 self, metricName, catalogs, photoCalibs=None, astromCalibs=None, dataIds=None
52 ):
53 self.log.info("Measuring %s", metricName)
54 bands = set([f["band"] for f in dataIds])
56 if ("g" in bands) & ("r" in bands) & ("i" in bands):
57 rgicatAll = makeMatchedPhotom(dataIds, catalogs, photoCalibs)
58 magcut = (rgicatAll["base_PsfFlux_mag_r"] < self.config.faint_rmag_cut) & (
59 rgicatAll["base_PsfFlux_mag_r"] > self.config.bright_rmag_cut
60 )
61 rgicat = rgicatAll[magcut]
62 extVals = extinction_corr(rgicat, bands)
64 wPerp = self.calcWPerp(rgicat, extVals, metricName)
65 return wPerp
66 else:
67 return Struct(measurement=Measurement(metricName, np.nan * u.mmag))
69 def calcWPerp(self, phot, extinctionVals, metricName):
70 p1, p2, p1coeffs, p2coeffs = stellarLocusResid(
71 phot["base_PsfFlux_mag_g"] - extinctionVals["A_g"],
72 phot["base_PsfFlux_mag_r"] - extinctionVals["A_r"],
73 phot["base_PsfFlux_mag_i"] - extinctionVals["A_i"],
74 )
76 if np.size(p2) > 2:
77 p2_rms = calcQuartileClippedStats(p2).rms * u.mag
78 extras = {
79 "p1_coeffs": Datum(
80 p1coeffs * u.Unit(""),
81 label="p1_coefficients",
82 description="p1 coeffs from wPerp fit",
83 ),
84 "p2_coeffs": Datum(
85 p2coeffs * u.Unit(""),
86 label="p2_coefficients",
87 description="p2_coeffs from wPerp fit",
88 ),
89 }
91 return Struct(
92 measurement=Measurement(metricName, p2_rms.to(u.mmag), extras=extras)
93 )
94 else:
95 return Struct(measurement=Measurement(metricName, np.nan * u.mmag))
98class TExConfig(Config):
99 minSep = Field(
100 doc="Inner radius of the annulus in arcmin", dtype=float, default=0.25
101 )
102 maxSep = Field(
103 doc="Outer radius of the annulus in arcmin", dtype=float, default=1.0
104 )
105 nbins = Field(doc="Number of log-spaced angular bins", dtype=int, default=10)
106 rhoStat = Field(doc="Rho statistic to be computed", dtype=int, default=1)
107 shearConvention = Field(
108 doc="Use shear ellipticity convention rather than distortion",
109 dtype=bool,
110 default=False,
111 )
112 columnPsf = Field(
113 doc="Column to use for PSF model shape moments",
114 dtype=str,
115 default="base_SdssShape_psf",
116 )
117 column = Field(
118 doc="Column to use for shape moments", dtype=str, default="base_SdssShape"
119 )
120 # Eventually want to add option to use only PSF reserve stars
123class TExTask(Task):
124 ConfigClass = TExConfig
125 _DefaultName = "TExTask"
127 def run(
128 self, metricName, catalogs, photoCalibs=None, astromCalibs=None, dataIds=None
129 ):
130 self.log.info("Measuring %s", metricName)
132 result = calculateTEx(catalogs, photoCalibs, astromCalibs, self.config)
133 if "corr" not in result.keys():
134 return Struct(measurement=Measurement(metricName, np.nan * u.Unit("")))
136 writeExtras = True
137 if writeExtras:
138 extras = {}
139 extras["radius"] = Datum(
140 result["radius"], label="radius", description="Separation (arcmin)."
141 )
142 extras["corr"] = Datum(
143 result["corr"], label="Correlation", description="Correlation."
144 )
145 extras["corrErr"] = Datum(
146 result["corrErr"],
147 label="Correlation Uncertianty",
148 description="Correlation Uncertainty.",
149 )
150 else:
151 extras = None
152 return Struct(
153 measurement=Measurement(
154 metricName, np.mean(np.abs(result["corr"])), extras=extras
155 )
156 )