Coverage for python/lsst/analysis/tools/actions/plot/rhoStatisticsPlot.py: 25%
59 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-30 11:36 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-30 11:36 +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/>.
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 rhoPlots = ConfigDictField(
43 doc="A configurable dict describing the rho statistics to plot.",
44 keytype=str,
45 itemtype=XYPlot,
46 default={},
47 )
49 def setDefaults(self) -> None:
50 super().setDefaults()
51 self.rhoPlots = {rhoName: XYPlot() for rhoName in ("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")}
53 yLabels = {
54 "rho3alt": r"$\rho'_{3}(\theta) = \langle \frac{\delta T}{T}, \frac{\delta T}{T}\rangle$",
55 "rho1": r"$\rho_{1}(\theta) = \langle \delta e, \delta e \rangle$",
56 "rho2": r"$\rho_{2}(\theta) = \langle e, \delta e \rangle$",
57 "rho3": r"$\rho_{3}(\theta) = \langle e\frac{\delta T}{T} , e\frac{\delta T}{T} \rangle$",
58 "rho4": r"$\rho_{4}(\theta) = \langle \delta e, e\frac{\delta T}{T} \rangle$",
59 "rho5": r"$\rho_{5}(\theta) = \langle e, e\frac{\delta T}{T} \rangle$",
60 }
62 for rhoId, rhoPlot in self.rhoPlots.items():
63 rhoPlot.xAxisLabel = "Separation [arcmin]"
64 rhoPlot.yAxisLabel = yLabels[rhoId]
65 rhoPlot.xScale = "log"
66 rhoPlot.yScale = "symlog"
67 rhoPlot.yLinThresh = 1e-6
69 self.rhoPlots["rho3alt"].yScale = "linear" # type: ignore
71 def getInputSchema(self) -> KeyedDataSchema:
72 # Docstring inherited
73 base: list[tuple[str, type[Vector]]] = []
74 base.append(("coord_ra", Vector))
75 base.append(("coord_dec", Vector))
76 base.append(("{{band}}_ixx", Vector))
77 base.append(("{{band}}_iyy", Vector))
78 base.append(("{{band}}_ixy", Vector))
79 base.append(("{{band}}_ixxPSF", Vector))
80 base.append(("{{band}}_iyyPSF", Vector))
81 base.append(("{{band}}_ixyPSF", Vector))
82 return base
84 def getOutputNames(self) -> Iterable[str]:
85 # Docstring inherited
86 return ("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")
88 def __call__(self, data: KeyedData, **kwargs) -> Mapping[str, Figure]:
89 self._validateInput(data)
90 return self.makePlot(data, **kwargs)
92 def _validateInput(self, data: KeyedData) -> None:
93 if not set(("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")).issubset(data.keys()):
94 raise ValueError("Input data must contain rho3alt, rho1, rho2, rho3, rho4, and rho5.")
96 def makePlot(
97 self, data: KeyedData, plotInfo: Mapping[str, str] | None = None, **kwargs: Any
98 ) -> Mapping[str, Figure]:
99 """Make the plot.
101 Parameters
102 ----------
103 data : `~pandas.core.frame.DataFrame`
104 The catalog containing various rho statistics.
105 plotInfo : `dict`, optional
106 A dictionary of information about the data being plotted with keys:
107 ``"run"``
108 The output run for the plots (`str`).
109 ``"skymap"``
110 The type of skymap used for the data (`str`).
111 ``"filter"``
112 The filter used for this data (`str`).
113 ``"tract"``
114 The tract that the data comes from (`str`).
115 **kwargs
116 Additional keyword arguments to pass to the plot
117 """
118 # The prefix for the plot names must match the prefix in the pipeline.
119 # This is therefore obtained from the plotInfo dict.
120 default_prefix = "rhoStatisticsPlot"
121 prefix = plotInfo.get("plotName", default_prefix) if plotInfo else default_prefix
123 fig_dict: dict[str, Figure] = {}
124 for rho_name in ("rho1", "rho2", "rho3", "rho4", "rho5"):
125 rho: XYPlot = self.rhoPlots[rho_name]
126 rhoPlot_name = f"{prefix}_{rho_name}"
128 subdata = {
129 "x": data[rho_name].meanr, # type: ignore
130 "y": data[rho_name].xip, # type: ignore
131 "yerr": np.sqrt(data[rho_name].varxip), # type: ignore
132 "xerr": None,
133 }
134 fig = rho(subdata, **kwargs)
135 if plotInfo is not None:
136 fig_dict[rhoPlot_name] = addPlotInfo(fig, plotInfo)
138 # rho3alt is handled differently because its attributes differ.
139 subdata = {
140 "x": data["rho3alt"].meanr, # type: ignore
141 "y": data["rho3alt"].xi, # type: ignore
142 "yerr": np.sqrt(data["rho3alt"].varxi), # type: ignore
143 "xerr": None,
144 }
145 fig = self.rhoPlots["rho3alt"](subdata, **kwargs) # type: ignore[misc]
146 if plotInfo is not None:
147 fig_dict["rhoStatisticsPlot_rho3alt"] = addPlotInfo(fig, plotInfo)
149 return fig_dict