Coverage for python/lsst/analysis/tools/analysisPlots/analysisPlots.py: 27%
168 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-30 03:20 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-30 03:20 -0800
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 "Ap12PsfSkyPlot",
28 "WPerpPSFPlot",
29 "WPerpCModelPlot",
30 "XPerpPSFPlot",
31 "XPerpCModelPlot",
32 "YPerpPSFPlot",
33 "YPerpCModelPlot",
34 "TargetRefCatDeltaRAScatterPlot",
35 "TargetRefCatDeltaRAScatterPlot",
36)
38from lsst.pex.config import Field
40from ..actions.plot.colorColorFitPlot import ColorColorFitPlot
41from ..actions.plot.histPlot import HistPanel, HistPlot
42from ..actions.plot.scatterplotWithTwoHists import ScatterPlotStatsAction, ScatterPlotWithTwoHists
43from ..actions.plot.skyPlot import SkyPlot
44from ..actions.vector import (
45 AstromDiff,
46 CoaddPlotFlagSelector,
47 DownselectVector,
48 ExtinctionCorrectedMagDiff,
49 LoadVector,
50 MagColumnNanoJansky,
51 SnSelector,
52 StarSelector,
53 VectorSelector,
54)
55from ..analysisParts.baseFluxRatio import BasePsfApRatio
56from ..analysisParts.genericPrep import CoaddPrep, VisitPrep
57from ..analysisParts.shapeSizeFractional import BasePsfResidualMixin
58from ..analysisParts.stellarLocus import WPerpCModel, WPerpPSF, XPerpCModel, XPerpPSF, YPerpCModel, YPerpPSF
59from ..interfaces import AnalysisPlot
62class BasePsfResidualScatterPlot(AnalysisPlot, BasePsfResidualMixin):
63 """Base class for scatter plots of PSF residuals.
65 This is shared by size and ellipticity plots.
66 """
68 def setDefaults(self):
69 super().setDefaults()
70 self.prep.selectors.flagSelector = CoaddPlotFlagSelector()
71 self.prep.selectors.snSelector = SnSelector(fluxType="{band}_psfFlux", threshold=100)
73 self.process.buildActions.patchWhole = LoadVector()
74 self.process.buildActions.patchWhole.vectorKey = "patch"
76 self.process.buildActions.mags = MagColumnNanoJansky(vectorKey="{band}_psfFlux")
77 # pre-compute a stellar selector mask so it can be used in the filter
78 # actions while only being computed once, alternatively the stellar
79 # selector could be calculated and applied twice in the filter stage
80 self.process.buildActions.starSelector = StarSelector()
82 self.process.filterActions.xStars = DownselectVector(
83 vectorKey="mags", selector=VectorSelector(vectorKey="starSelector")
84 )
85 # downselect the psfFlux as well
86 self.process.filterActions.psfFlux = DownselectVector(
87 vectorKey="{band}_psfFlux", selector=VectorSelector(vectorKey="starSelector")
88 )
89 self.process.filterActions.psfFluxErr = DownselectVector(
90 vectorKey="{band}_psfFluxErr", selector=VectorSelector(vectorKey="starSelector")
91 )
93 self.process.filterActions.patch = DownselectVector(
94 vectorKey="patchWhole", selector=VectorSelector(vectorKey="starSelector")
95 )
97 self.process.calculateActions.stars = ScatterPlotStatsAction(
98 vectorKey="yStars",
99 )
100 # use the downselected psfFlux
101 self.process.calculateActions.stars.highSNSelector.fluxType = "psfFlux"
102 self.process.calculateActions.stars.lowSNSelector.fluxType = "psfFlux"
103 self.process.calculateActions.stars.fluxType = "psfFlux"
105 self.produce = ScatterPlotWithTwoHists()
107 self.produce.plotTypes = ["stars"]
108 self.produce.xAxisLabel = "PSF Magnitude (mag)"
109 self.produce.magLabel = "PSF Magnitude (mag)"
110 self.produce.addSummaryPlot = True
113class ShapeSizeFractionalDiffScatterPlot(BasePsfResidualScatterPlot):
114 def setDefaults(self):
115 super().setDefaults()
116 self.process.filterActions.yStars = DownselectVector(
117 vectorKey="fracDiff", selector=VectorSelector(vectorKey="starSelector")
118 )
119 self.produce.yAxisLabel = "Fractional size residuals (S/S_PSF - 1)"
122class E1DiffScatterPlot(BasePsfResidualScatterPlot):
123 def setDefaults(self):
124 super().setDefaults()
125 self.process.filterActions.yStars = DownselectVector(
126 vectorKey="e1Diff", selector=VectorSelector(vectorKey="starSelector")
127 )
128 self.produce.yAxisLabel = "Ellipticty residuals (e1 - e1_PSF)"
131class E2DiffScatterPlot(BasePsfResidualScatterPlot):
132 def setDefaults(self):
133 super().setDefaults()
134 self.process.filterActions.yStars = DownselectVector(
135 vectorKey="e2Diff", selector=VectorSelector(vectorKey="starSelector")
136 )
137 self.produce.yAxisLabel = "Ellipticty residuals (e2 - e2_PSF)"
140class WPerpPSFPlot(WPerpPSF, AnalysisPlot):
141 def setDefaults(self):
142 super().setDefaults()
144 self.produce = ColorColorFitPlot()
145 self.produce.xAxisLabel = "g - r (PSF) [mags]"
146 self.produce.yAxisLabel = "r - i (PSF) [mags]"
147 self.produce.magLabel = "PSF Mag"
148 self.produce.plotName = "wPerp_psfFlux"
151class WPerpCModelPlot(WPerpCModel, AnalysisPlot):
152 def setDefaults(self):
153 super().setDefaults()
155 self.produce = ColorColorFitPlot()
156 self.produce.xAxisLabel = "g - r (CModel) [mags]"
157 self.produce.yAxisLabel = "r - i (CModel) [mags]"
158 self.produce.magLabel = "CModel Mag"
159 self.produce.plotName = "wPerp_cmodelFlux"
162class XPerpPSFPlot(XPerpPSF, AnalysisPlot):
163 def setDefaults(self):
164 super().setDefaults()
166 self.produce = ColorColorFitPlot()
167 self.produce.xAxisLabel = "g - r (PSF) [mags]"
168 self.produce.yAxisLabel = "r - i (PSF) [mags]"
169 self.produce.magLabel = "PSF Mag"
170 self.produce.plotName = "xPerp_psfFlux"
173class XPerpCModelPlot(XPerpCModel, AnalysisPlot):
174 def setDefaults(self):
175 super().setDefaults()
177 self.produce = ColorColorFitPlot()
178 self.produce.xAxisLabel = "g - r (CModel) [mags]"
179 self.produce.yAxisLabel = "r - i (CModel) [mags]"
180 self.produce.magLabel = "CModel Mag"
181 self.produce.plotName = "xPerp_cmodelFlux"
184class YPerpPSFPlot(YPerpPSF, AnalysisPlot):
185 def setDefaults(self):
186 super().setDefaults()
188 self.produce = ColorColorFitPlot()
189 self.produce.xAxisLabel = "r - i (PSF) [mags]"
190 self.produce.yAxisLabel = "i - z (PSF) [mags]"
191 self.produce.magLabel = "PSF Mag"
192 self.produce.plotName = "yPerp_psfFlux"
195class YPerpCModelPlot(YPerpCModel, AnalysisPlot):
196 def setDefaults(self):
197 super().setDefaults()
199 self.produce = ColorColorFitPlot()
200 self.produce.xAxisLabel = "r - i (CModel) [mags]"
201 self.produce.yAxisLabel = "i - z (CModel) [mags]"
202 self.produce.magLabel = "CModel Mag"
203 self.produce.plotName = "yPerp_cmodelFlux"
206class Ap12PsfSkyPlot(AnalysisPlot):
207 def setDefaults(self):
208 super().setDefaults()
209 self.prep.selectors.flagSelector = CoaddPlotFlagSelector()
210 # Set this to an empty list to look at the band
211 # the plot is being made in.
212 self.prep.selectors.flagSelector.bands = []
214 self.prep.selectors.snSelector = SnSelector()
215 self.prep.selectors.snSelector.fluxType = "{band}_psfFlux"
216 self.prep.selectors.snSelector.threshold = 300
218 self.prep.selectors.starSelector = StarSelector()
219 self.prep.selectors.starSelector.vectorKey = "{band}_extendedness"
221 # TODO: Can we make these defaults somewhere?
222 self.process.buildActions.xStars = LoadVector()
223 self.process.buildActions.xStars.vectorKey = "coord_ra"
224 self.process.buildActions.yStars = LoadVector()
225 self.process.buildActions.yStars.vectorKey = "coord_dec"
226 self.process.buildActions.starStatMask = SnSelector()
227 self.process.buildActions.starStatMask.fluxType = "{band}_psfFlux"
229 self.process.buildActions.zStars = ExtinctionCorrectedMagDiff()
230 self.process.buildActions.zStars.magDiff.col1 = "{band}_ap12Flux"
231 self.process.buildActions.zStars.magDiff.col2 = "{band}_psfFlux"
233 self.produce = SkyPlot()
234 self.produce.plotTypes = ["stars"]
235 self.produce.plotName = "ap12-psf_{band}"
236 self.produce.xAxisLabel = "R.A. (degrees)"
237 self.produce.yAxisLabel = "Dec. (degrees)"
238 self.produce.zAxisLabel = "Ap 12 - PSF [mag]"
239 self.produce.plotOutlines = False
242class TargetRefCatDelta(AnalysisPlot):
243 """Plot the difference in milliseconds between a target catalog and a
244 reference catalog for the coordinate set in `setDefaults`.
245 """
247 parameterizedBand = Field[bool](
248 doc="Does this AnalysisTool support band as a name parameter", default=True
249 )
251 def coaddContext(self) -> None:
252 self.prep = CoaddPrep()
253 self.process.buildActions.starSelector.vectorKey = "{band}_extendedness"
254 self.process.buildActions.mags = MagColumnNanoJansky(vectorKey="{band}_psfFlux")
255 self.process.filterActions.psfFlux = DownselectVector(
256 vectorKey="{band}_psfFlux", selector=VectorSelector(vectorKey="starSelector")
257 )
258 self.process.filterActions.psfFluxErr = DownselectVector(
259 vectorKey="{band}_psfFluxErr", selector=VectorSelector(vectorKey="starSelector")
260 )
262 def visitContext(self) -> None:
263 self.parameterizedBand = False
264 self.prep = VisitPrep()
265 self.process.buildActions.starSelector.vectorKey = "extendedness"
266 self.process.buildActions.mags = MagColumnNanoJansky(vectorKey="psfFlux")
267 self.process.filterActions.psfFlux = DownselectVector(
268 vectorKey="psfFlux", selector=VectorSelector(vectorKey="starSelector")
269 )
270 self.process.filterActions.psfFluxErr = DownselectVector(
271 vectorKey="psfFluxErr", selector=VectorSelector(vectorKey="starSelector")
272 )
274 def setDefaults(self, coordinate):
275 super().setDefaults()
277 self.process.buildActions.starSelector = StarSelector()
278 coordStr = coordinate.lower()
279 self.process.buildActions.astromDiff = AstromDiff(
280 col1=f"coord_{coordStr}_target", col2=f"coord_{coordStr}_ref"
281 )
283 self.process.filterActions.xStars = DownselectVector(
284 vectorKey="mags", selector=VectorSelector(vectorKey="starSelector")
285 )
286 self.process.filterActions.yStars = DownselectVector(
287 vectorKey="astromDiff", selector=VectorSelector(vectorKey="starSelector")
288 )
290 self.process.calculateActions.stars = ScatterPlotStatsAction(vectorKey="yStars")
291 self.process.calculateActions.stars.lowSNSelector.fluxType = "psfFlux"
292 self.process.calculateActions.stars.highSNSelector.fluxType = "psfFlux"
293 self.process.calculateActions.stars.fluxType = "psfFlux"
295 self.produce = ScatterPlotWithTwoHists()
297 self.produce.plotTypes = ["stars"]
298 self.produce.xAxisLabel = "PSF Magnitude (mag)"
299 self.produce.yAxisLabel = f"${coordinate}_{{target}} - {coordinate}_{{ref}}$ (marcsec)"
300 self.produce.magLabel = "PSF Magnitude (mag)"
303class TargetRefCatDeltaRAScatterPlot(TargetRefCatDelta):
304 """Plot the difference in milliseconds between the RA of a target catalog
305 and a reference catalog
306 """
308 def setDefaults(self):
309 super().setDefaults(coordinate="RA")
312class TargetRefCatDeltaDecScatterPlot(TargetRefCatDelta):
313 """Plot the difference in milliseconds between the Dec of a target catalog
314 and a reference catalog
315 """
317 def setDefaults(self):
318 super().setDefaults(coordinate="Dec")
321class FluxRatioPlot(AnalysisPlot, BasePsfApRatio):
322 """Plot a histogram of the PSF and AP flux ratios of sources."""
324 def setDefaults(self):
325 super().setDefaults()
327 self.produce = HistPlot()
329 self.produce.panels["panel_flux"] = HistPanel()
330 self.produce.panels["panel_flux"].label = "Psf/Ap Ratio"
331 self.produce.panels["panel_flux"].hists = dict(fluxRatioMetric="Ratio")