Coverage for python/lsst/analysis/tools/analysisPlots/analysisPlots.py: 24%
141 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-04 10:48 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-10-04 10:48 +0000
1# This file is part of analysis_tools.
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/>.
21from __future__ import annotations
23__all__ = (
24 "E1DiffScatterPlot",
25 "E2DiffScatterPlot",
26 "ShapeSizeFractionalDiffScatterPlot",
27 "WPerpPSFPlot",
28 "Ap12PsfSkyPlot",
29 "TargetRefCatDeltaRAScatterPlot",
30 "TargetRefCatDeltaRAScatterPlot",
31)
33from lsst.pex.config import Field
35from ..actions.keyedData.stellarLocusFit import StellarLocusFitAction
36from ..actions.plot.colorColorFitPlot import ColorColorFitPlot
37from ..actions.plot.scatterplotWithTwoHists import ScatterPlotStatsAction, ScatterPlotWithTwoHists
38from ..actions.plot.skyPlot import SkyPlot
39from ..actions.scalar import ApproxFloor
40from ..actions.vector import (
41 AstromDiff,
42 CoaddPlotFlagSelector,
43 DownselectVector,
44 ExtinctionCorrectedMagDiff,
45 LoadVector,
46 MagColumnNanoJansky,
47 SnSelector,
48 StarSelector,
49 VectorSelector,
50)
51from ..analysisParts.genericPrep import CoaddPrep, VisitPrep
52from ..analysisParts.shapeSizeFractional import BasePsfResidualMixin
53from ..interfaces import AnalysisPlot
56class BasePsfResidualScatterPlot(AnalysisPlot, BasePsfResidualMixin):
57 """Base class for scatter plots of PSF residuals.
59 This is shared by size and ellipticity plots.
60 """
62 def setDefaults(self):
63 super().setDefaults()
64 self.prep.selectors.flagSelector = CoaddPlotFlagSelector()
65 self.prep.selectors.snSelector = SnSelector(fluxType="{band}_psfFlux", threshold=100)
67 self.process.buildActions.patchWhole = LoadVector()
68 self.process.buildActions.patchWhole.vectorKey = "patch"
70 self.process.buildActions.mags = MagColumnNanoJansky(vectorKey="{band}_psfFlux")
71 # pre-compute a stellar selector mask so it can be used in the filter
72 # actions while only being computed once, alternatively the stellar
73 # selector could be calculated and applied twice in the filter stage
74 self.process.buildActions.starSelector = StarSelector()
76 self.process.filterActions.xStars = DownselectVector(
77 vectorKey="mags", selector=VectorSelector(vectorKey="starSelector")
78 )
79 # downselect the psfFlux as well
80 self.process.filterActions.psfFlux = DownselectVector(
81 vectorKey="{band}_psfFlux", selector=VectorSelector(vectorKey="starSelector")
82 )
83 self.process.filterActions.psfFluxErr = DownselectVector(
84 vectorKey="{band}_psfFluxErr", selector=VectorSelector(vectorKey="starSelector")
85 )
87 self.process.filterActions.patch = DownselectVector(
88 vectorKey="patchWhole", selector=VectorSelector(vectorKey="starSelector")
89 )
91 self.process.calculateActions.stars = ScatterPlotStatsAction(
92 vectorKey="yStars",
93 )
94 # use the downselected psfFlux
95 self.process.calculateActions.stars.highSNSelector.fluxType = "psfFlux"
96 self.process.calculateActions.stars.lowSNSelector.fluxType = "psfFlux"
97 self.process.calculateActions.stars.fluxType = "psfFlux"
99 self.produce = ScatterPlotWithTwoHists()
101 self.produce.plotTypes = ["stars"]
102 self.produce.xAxisLabel = "PSF Magnitude (mag)"
103 self.produce.magLabel = "PSF Magnitude (mag)"
104 self.produce.addSummaryPlot = True
107class ShapeSizeFractionalDiffScatterPlot(BasePsfResidualScatterPlot):
108 def setDefaults(self):
109 super().setDefaults()
110 self.process.filterActions.yStars = DownselectVector(
111 vectorKey="fracDiff", selector=VectorSelector(vectorKey="starSelector")
112 )
113 self.produce.yAxisLabel = "Fractional size residuals (S/S_PSF - 1)"
116class E1DiffScatterPlot(BasePsfResidualScatterPlot):
117 def setDefaults(self):
118 super().setDefaults()
119 self.process.filterActions.yStars = DownselectVector(
120 vectorKey="e1Diff", selector=VectorSelector(vectorKey="starSelector")
121 )
122 self.produce.yAxisLabel = "Ellipticty residuals (e1 - e1_PSF)"
125class E2DiffScatterPlot(BasePsfResidualScatterPlot):
126 def setDefaults(self):
127 super().setDefaults()
128 self.process.filterActions.yStars = DownselectVector(
129 vectorKey="e2Diff", selector=VectorSelector(vectorKey="starSelector")
130 )
131 self.produce.yAxisLabel = "Ellipticty residuals (e2 - e2_PSF)"
134class WPerpPSFPlot(AnalysisPlot):
135 # WPerp does not support running in multiband mode
136 multiband: bool = False
138 def setDefaults(self):
139 super().setDefaults()
140 self.prep.selectors.flagSelector = CoaddPlotFlagSelector()
141 self.prep.selectors.flagSelector.bands = ["g", "r", "i"]
143 self.prep.selectors.snSelector = SnSelector()
144 self.prep.selectors.snSelector.bands = ["r"]
145 self.prep.selectors.snSelector.fluxType = "{band}_psfFlux"
146 self.prep.selectors.snSelector.threshold = 300
148 self.prep.selectors.starSelector = StarSelector()
149 self.prep.selectors.starSelector.vectorKey = "r_extendedness"
151 self.process.buildActions.x = ExtinctionCorrectedMagDiff()
152 self.process.buildActions.x.magDiff.col1 = "g_psfFlux"
153 self.process.buildActions.x.magDiff.col2 = "r_psfFlux"
154 self.process.buildActions.x.magDiff.returnMillimags = False
155 self.process.buildActions.y = ExtinctionCorrectedMagDiff()
156 self.process.buildActions.y.magDiff.col1 = "r_psfFlux"
157 self.process.buildActions.y.magDiff.col2 = "i_psfFlux"
158 self.process.buildActions.y.magDiff.returnMillimags = False
159 self.process.buildActions.mag = MagColumnNanoJansky(vectorKey="r_psfFlux")
161 self.process.calculateActions.approxMagDepth = ApproxFloor(vectorKey="mag")
162 self.process.calculateActions.wPerp_psfFlux = StellarLocusFitAction()
163 self.process.calculateActions.wPerp_psfFlux.stellarLocusFitDict = {
164 "xMin": 0.28,
165 "xMax": 1.0,
166 "yMin": 0.02,
167 "yMax": 0.48,
168 "mHW": 0.52,
169 "bHW": -0.08,
170 }
172 self.produce = ColorColorFitPlot()
173 self.produce.xAxisLabel = "g - r (PSF) [mags]"
174 self.produce.yAxisLabel = "r - i (PSF) [mags]"
175 self.produce.magLabel = "PSF Mag"
176 self.produce.plotName = "wPerp_psfFlux"
179class Ap12PsfSkyPlot(AnalysisPlot):
180 def setDefaults(self):
181 super().setDefaults()
182 self.prep.selectors.flagSelector = CoaddPlotFlagSelector()
183 self.prep.selectors.flagSelector.bands = ["{band}"]
185 self.prep.selectors.snSelector = SnSelector()
186 self.prep.selectors.snSelector.fluxType = "{band}_psfFlux"
187 self.prep.selectors.snSelector.threshold = 300
189 self.prep.selectors.starSelector = StarSelector()
190 self.prep.selectors.starSelector.vectorKey = "{band}_extendedness"
192 # TODO: Can we make these defaults somewhere?
193 self.process.buildActions.xStars = LoadVector()
194 self.process.buildActions.xStars.vectorKey = "coord_ra"
195 self.process.buildActions.yStars = LoadVector()
196 self.process.buildActions.yStars.vectorKey = "coord_dec"
197 self.process.buildActions.starStatMask = SnSelector()
198 self.process.buildActions.starStatMask.fluxType = "{band}_psfFlux"
200 self.process.buildActions.zStars = ExtinctionCorrectedMagDiff()
201 self.process.buildActions.zStars.magDiff.col1 = "{band}_ap12Flux"
202 self.process.buildActions.zStars.magDiff.col2 = "{band}_psfFlux"
204 self.produce = SkyPlot()
205 self.produce.plotTypes = ["stars"]
206 self.produce.plotName = "ap12-psf_{band}"
207 self.produce.xAxisLabel = "R.A. (degrees)"
208 self.produce.yAxisLabel = "Dec. (degrees)"
209 self.produce.zAxisLabel = "Ap 12 - PSF [mag]"
210 self.produce.plotOutlines = False
213class TargetRefCatDelta(AnalysisPlot):
214 """Plot the difference in milliseconds between a target catalog and a
215 reference catalog for the coordinate set in `setDefaults`.
216 """
218 parameterizedBand = Field[bool](
219 doc="Does this AnalysisTool support band as a name parameter", default=True
220 )
222 def coaddContext(self) -> None:
223 self.prep = CoaddPrep()
224 self.process.buildActions.starSelector.vectorKey = "{band}_extendedness"
225 self.process.buildActions.mags = MagColumnNanoJansky(vectorKey="{band}_psfFlux")
226 self.process.filterActions.psfFlux = DownselectVector(
227 vectorKey="{band}_psfFlux", selector=VectorSelector(vectorKey="starSelector")
228 )
229 self.process.filterActions.psfFluxErr = DownselectVector(
230 vectorKey="{band}_psfFluxErr", selector=VectorSelector(vectorKey="starSelector")
231 )
233 def visitContext(self) -> None:
234 self.parameterizedBand = False
235 self.prep = VisitPrep()
236 self.process.buildActions.starSelector.vectorKey = "extendedness"
237 self.process.buildActions.mags = MagColumnNanoJansky(vectorKey="psfFlux")
238 self.process.filterActions.psfFlux = DownselectVector(
239 vectorKey="psfFlux", selector=VectorSelector(vectorKey="starSelector")
240 )
241 self.process.filterActions.psfFluxErr = DownselectVector(
242 vectorKey="psfFluxErr", selector=VectorSelector(vectorKey="starSelector")
243 )
245 def setDefaults(self, coordinate):
246 super().setDefaults()
248 self.process.buildActions.starSelector = StarSelector()
249 coordStr = coordinate.lower()
250 self.process.buildActions.astromDiff = AstromDiff(
251 col1=f"coord_{coordStr}_target", col2=f"coord_{coordStr}_ref"
252 )
254 self.process.filterActions.xStars = DownselectVector(
255 vectorKey="mags", selector=VectorSelector(vectorKey="starSelector")
256 )
257 self.process.filterActions.yStars = DownselectVector(
258 vectorKey="astromDiff", selector=VectorSelector(vectorKey="starSelector")
259 )
261 self.process.calculateActions.stars = ScatterPlotStatsAction(vectorKey="yStars")
262 self.process.calculateActions.stars.lowSNSelector.fluxType = "psfFlux"
263 self.process.calculateActions.stars.highSNSelector.fluxType = "psfFlux"
264 self.process.calculateActions.stars.fluxType = "psfFlux"
266 self.produce = ScatterPlotWithTwoHists()
268 self.produce.plotTypes = ["stars"]
269 self.produce.xAxisLabel = "PSF Magnitude (mag)"
270 self.produce.yAxisLabel = f"${coordinate}_{{target}} - {coordinate}_{{ref}}$ (marcsec)"
271 self.produce.magLabel = "PSF Magnitude (mag)"
274class TargetRefCatDeltaRAScatterPlot(TargetRefCatDelta):
275 """Plot the difference in milliseconds between the RA of a target catalog
276 and a reference catalog
277 """
279 def setDefaults(self):
280 super().setDefaults(coordinate="RA")
283class TargetRefCatDeltaDecScatterPlot(TargetRefCatDelta):
284 """Plot the difference in milliseconds between the Dec of a target catalog
285 and a reference catalog
286 """
288 def setDefaults(self):
289 super().setDefaults(coordinate="Dec")