Coverage for python/lsst/analysis/tools/analysisPlots/analysisPlots.py: 33%
138 statements
« prev ^ index » next coverage.py v6.4.4, created at 2022-08-31 11:38 +0000
« prev ^ index » next coverage.py v6.4.4, created at 2022-08-31 11:38 +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.plotName = "wPerp_psfFlux"
176class Ap12PsfSkyPlot(AnalysisPlot):
177 def setDefaults(self):
178 super().setDefaults()
179 self.prep.selectors.flagSelector = CoaddPlotFlagSelector()
180 self.prep.selectors.flagSelector.bands = ["{band}"]
182 self.prep.selectors.snSelector = SnSelector()
183 self.prep.selectors.snSelector.fluxType = "{band}_psfFlux"
184 self.prep.selectors.snSelector.threshold = 300
186 self.prep.selectors.starSelector = StarSelector()
187 self.prep.selectors.starSelector.vectorKey = "{band}_extendedness"
189 # TODO: Can we make these defaults somewhere?
190 self.process.buildActions.xStars = LoadVector()
191 self.process.buildActions.xStars.vectorKey = "coord_ra"
192 self.process.buildActions.yStars = LoadVector()
193 self.process.buildActions.yStars.vectorKey = "coord_dec"
194 self.process.buildActions.starStatMask = SnSelector()
195 self.process.buildActions.starStatMask.fluxType = "{band}_psfFlux"
197 self.process.buildActions.zStars = ExtinctionCorrectedMagDiff()
198 self.process.buildActions.zStars.magDiff.col1 = "{band}_ap12Flux"
199 self.process.buildActions.zStars.magDiff.col2 = "{band}_psfFlux"
201 self.produce = SkyPlot()
202 self.produce.plotTypes = ["stars"]
203 self.produce.plotName = "ap12-psf_{band}"
204 self.produce.xAxisLabel = "R.A. (degrees)"
205 self.produce.yAxisLabel = "Dec. (degrees)"
206 self.produce.zAxisLabel = "Ap 12 - PSF [mag]"
207 self.produce.plotOutlines = False
210class TargetRefCatDelta(AnalysisPlot):
211 """Plot the difference in milliseconds between a target catalog and a
212 reference catalog for the coordinate set in `setDefaults`.
213 """
215 parameterizedBand = Field[bool](
216 doc="Does this AnalysisTool support band as a name parameter", default=True
217 )
219 def coaddContext(self) -> None:
220 self.prep = CoaddPrep()
221 self.process.buildActions.starSelector.vectorKey = "{band}_extendedness"
222 self.process.buildActions.mags = MagColumnNanoJansky(vectorKey="{band}_psfFlux")
223 self.process.filterActions.psfFlux = DownselectVector(
224 vectorKey="{band}_psfFlux", selector=VectorSelector(vectorKey="starSelector")
225 )
226 self.process.filterActions.psfFluxErr = DownselectVector(
227 vectorKey="{band}_psfFluxErr", selector=VectorSelector(vectorKey="starSelector")
228 )
230 def visitContext(self) -> None:
231 self.parameterizedBand = False
232 self.prep = VisitPrep()
233 self.process.buildActions.starSelector.vectorKey = "extendedness"
234 self.process.buildActions.mags = MagColumnNanoJansky(vectorKey="psfFlux")
235 self.process.filterActions.psfFlux = DownselectVector(
236 vectorKey="psfFlux", selector=VectorSelector(vectorKey="starSelector")
237 )
238 self.process.filterActions.psfFluxErr = DownselectVector(
239 vectorKey="psfFluxErr", selector=VectorSelector(vectorKey="starSelector")
240 )
242 def setDefaults(self, coordinate):
243 super().setDefaults()
245 self.process.buildActions.starSelector = StarSelector()
246 coordStr = coordinate.lower()
247 self.process.buildActions.astromDiff = AstromDiff(
248 col1=f"coord_{coordStr}_target", col2=f"coord_{coordStr}_ref"
249 )
251 self.process.filterActions.xStars = DownselectVector(
252 vectorKey="mags", selector=VectorSelector(vectorKey="starSelector")
253 )
254 self.process.filterActions.yStars = DownselectVector(
255 vectorKey="astromDiff", selector=VectorSelector(vectorKey="starSelector")
256 )
258 self.process.calculateActions.stars = ScatterPlotStatsAction(vectorKey="yStars")
259 self.process.calculateActions.stars.lowSNSelector.fluxType = "psfFlux"
260 self.process.calculateActions.stars.highSNSelector.fluxType = "psfFlux"
261 self.process.calculateActions.stars.fluxType = "psfFlux"
263 self.produce = ScatterPlotWithTwoHists()
265 self.produce.plotTypes = ["stars"]
266 self.produce.xAxisLabel = "PSF Magnitude (mag)"
267 self.produce.yAxisLabel = f"${coordinate}_{{target}} - {coordinate}_{{ref}}$ (marcsec)"
268 self.produce.magLabel = "PSF Magnitude (mag)"
271class TargetRefCatDeltaRAScatterPlot(TargetRefCatDelta):
272 """Plot the difference in milliseconds between the RA of a target catalog
273 and a reference catalog
274 """
276 def setDefaults(self):
277 super().setDefaults(coordinate="RA")
280class TargetRefCatDeltaDecScatterPlot(TargetRefCatDelta):
281 """Plot the difference in milliseconds between the Dec of a target catalog
282 and a reference catalog
283 """
285 def setDefaults(self):
286 super().setDefaults(coordinate="Dec")