Coverage for python/lsst/analysis/tools/actions/plot/rhoStatisticsPlot.py: 25%
59 statements
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-09 03:19 -0700
« prev ^ index » next coverage.py v7.2.5, created at 2023-05-09 03:19 -0700
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/>.
22from __future__ import annotations
24from typing import TYPE_CHECKING, Any, Iterable, Mapping
26__all__ = ("RhoStatisticsPlotAction",)
28import numpy as np
29from lsst.pex.config import ConfigDictField
31from ...interfaces import PlotAction, Vector
32from .plotUtils import addPlotInfo
33from .xyPlot import XYPlot
35if TYPE_CHECKING: 35 ↛ 36line 35 didn't jump to line 36, because the condition on line 35 was never true
36 from matplotlib.figure import Figure
38 from ...interfaces import KeyedData, KeyedDataSchema
41class RhoStatisticsPlotAction(PlotAction):
42 """Make multiple plots of rho statistics.
44 Rho statistics capture the spatial correlation amongst various PSF size and
45 shape residual quantities. For exact definitions, see
46 :ref:`here <rho_definitions>`.
47 """
49 rhoPlots = ConfigDictField(
50 doc="A configurable dict describing the rho statistics to plot.",
51 keytype=str,
52 itemtype=XYPlot,
53 default={},
54 )
56 def setDefaults(self) -> None:
57 super().setDefaults()
58 self.rhoPlots = {rhoName: XYPlot() for rhoName in ("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")}
60 yLabels = {
61 "rho3alt": r"$\rho'_{3}(\theta) = \langle \frac{\delta T}{T}, \frac{\delta T}{T}\rangle$",
62 "rho1": r"$\rho_{1}(\theta) = \langle \delta e, \delta e \rangle$",
63 "rho2": r"$\rho_{2}(\theta) = \langle e, \delta e \rangle$",
64 "rho3": r"$\rho_{3}(\theta) = \langle e\frac{\delta T}{T} , e\frac{\delta T}{T} \rangle$",
65 "rho4": r"$\rho_{4}(\theta) = \langle \delta e, e\frac{\delta T}{T} \rangle$",
66 "rho5": r"$\rho_{5}(\theta) = \langle e, e\frac{\delta T}{T} \rangle$",
67 }
69 for rhoId, rhoPlot in self.rhoPlots.items():
70 rhoPlot.xAxisLabel = "Separation [arcmin]"
71 rhoPlot.yAxisLabel = yLabels[rhoId]
72 rhoPlot.xScale = "log"
73 rhoPlot.yScale = "symlog"
74 rhoPlot.yLinThresh = 1e-6
76 self.rhoPlots["rho3alt"].yScale = "linear" # type: ignore
78 def getInputSchema(self) -> KeyedDataSchema:
79 # Docstring inherited
80 base: list[tuple[str, type[Vector]]] = []
81 base.append(("coord_ra", Vector))
82 base.append(("coord_dec", Vector))
83 base.append(("{{band}}_ixx", Vector))
84 base.append(("{{band}}_iyy", Vector))
85 base.append(("{{band}}_ixy", Vector))
86 base.append(("{{band}}_ixxPSF", Vector))
87 base.append(("{{band}}_iyyPSF", Vector))
88 base.append(("{{band}}_ixyPSF", Vector))
89 return base
91 def getOutputNames(self) -> Iterable[str]:
92 # Docstring inherited
93 return ("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")
95 def __call__(self, data: KeyedData, **kwargs) -> Mapping[str, Figure]:
96 self._validateInput(data)
97 return self.makePlot(data, **kwargs)
99 def _validateInput(self, data: KeyedData) -> None:
100 if not set(("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")).issubset(data.keys()):
101 raise ValueError("Input data must contain rho3alt, rho1, rho2, rho3, rho4, and rho5.")
103 def makePlot(
104 self, data: KeyedData, plotInfo: Mapping[str, str] | None = None, **kwargs: Any
105 ) -> Mapping[str, Figure]:
106 r"""Make the plot(s).
108 Parameters
109 ----------
110 data : `~pandas.core.frame.DataFrame`
111 The catalog containing various rho statistics.
112 plotInfo : `dict`, optional
113 A dictionary of information about the data being plotted with keys:
114 ``"run"``
115 The output run for the plots (`str`).
116 ``"skymap"``
117 The type of skymap used for the data (`str`).
118 ``"filter"``
119 The filter used for this data (`str`).
120 ``"tract"``
121 The tract that the data comes from (`str`).
122 **kwargs
123 Additional keyword arguments to pass to the plot
125 Returns
126 -------
127 fig_dict : `dict` [`~matplotlib.figure.Figure`]
128 The resulting figures.
129 The figure corresponding :math:`\rho_1(\theta)` can be accessed
130 with the key `rho1` and similarly for the other rho statistics.
131 :math:`\rho_3'` is accessed with the key `rho3alt`.
133 Examples
134 --------
135 An example rho statistics plot may be seen below:
137 .. image:: /_static/analysis_tools/rhoPlotExample.png
139 For further details on how to generate a plot, please refer to the
140 :ref:`getting started guide<analysis-tools-getting-started>`.
141 """
142 # The prefix for the plot names must match the prefix in the pipeline.
143 # This is therefore obtained from the plotInfo dict.
144 default_prefix = "rhoStatisticsPlot"
145 prefix = plotInfo.get("plotName", default_prefix) if plotInfo else default_prefix
147 fig_dict: dict[str, Figure] = {}
148 for rho_name in ("rho1", "rho2", "rho3", "rho4", "rho5"):
149 rho: XYPlot = self.rhoPlots[rho_name]
150 rhoPlot_name = f"{prefix}_{rho_name}"
152 subdata = {
153 "x": data[rho_name].meanr, # type: ignore
154 "y": data[rho_name].xip, # type: ignore
155 "yerr": np.sqrt(data[rho_name].varxip), # type: ignore
156 "xerr": None,
157 }
158 fig = rho(subdata, **kwargs)
159 if plotInfo is not None:
160 fig_dict[rhoPlot_name] = addPlotInfo(fig, plotInfo)
162 # rho3alt is handled differently because its attributes differ.
163 subdata = {
164 "x": data["rho3alt"].meanr, # type: ignore
165 "y": data["rho3alt"].xi, # type: ignore
166 "yerr": np.sqrt(data["rho3alt"].varxi), # type: ignore
167 "xerr": None,
168 }
169 fig = self.rhoPlots["rho3alt"](subdata, **kwargs) # type: ignore[misc]
170 if plotInfo is not None:
171 fig_dict["rhoStatisticsPlot_rho3alt"] = addPlotInfo(fig, plotInfo)
173 return fig_dict