Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-36797: Add RhoStatistics #47

Merged
merged 10 commits into from
Dec 22, 2022
13 changes: 13 additions & 0 deletions pipelines/coaddQualityCore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ tasks:
from lsst.analysis.tools.analysisPlots import *
from lsst.analysis.tools.analysisMetrics import *
from lsst.analysis.tools.contexts import *
analyzeObjectTableSurveyCore:
class: lsst.analysis.tools.tasks.ObjectTableSurveyAnalysisTask
config:
connections.outputName: objectTableSurvey
# If plots.X is changed, the corresponding name in RhoStatisticsPlot
# must also be changed. TODO: DM-37431.
plots.rhoStatisticsPlot: RhoStatisticsPlot
bands: ["i"]
python: |
from lsst.analysis.tools.analysisPlots import *
from lsst.analysis.tools.analysisMetrics import *
from lsst.analysis.tools.contexts import *
from lsst.analysis.tools.actions.plot import *
catalogMatchTract:
class: lsst.analysis.tools.tasks.catalogMatch.CatalogMatchTask
refCatObjectTract:
Expand Down
4 changes: 2 additions & 2 deletions python/lsst/analysis/tools/actions/plot/colorColorFitPlot.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from __future__ import annotations

from typing import Mapping, Optional, cast
from typing import Mapping, cast

import matplotlib.patheffects as pathEffects
import matplotlib.pyplot as plt
Expand Down Expand Up @@ -100,7 +100,7 @@ def _validateInput(self, data: KeyedData, **kwargs) -> None:
def makePlot(
self,
data: KeyedData,
plotInfo: Optional[Mapping[str, str]] = None,
plotInfo: Mapping[str, str],
**kwargs,
) -> Figure:
"""Make stellar locus plots using pre fitted values.
Expand Down
9 changes: 6 additions & 3 deletions python/lsst/analysis/tools/actions/plot/plotUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

__all__ = ("PanelConfig",)

from typing import List, Tuple
from typing import TYPE_CHECKING, List, Mapping, Tuple

import matplotlib
import matplotlib.pyplot as plt
Expand All @@ -34,6 +34,9 @@
from matplotlib.collections import PatchCollection
from matplotlib.patches import Rectangle

if TYPE_CHECKING:
from matplotlib.figure import Figure

null_formatter = matplotlib.ticker.NullFormatter()


Expand Down Expand Up @@ -206,7 +209,7 @@ def get_and_remove_axis_text(ax) -> Tuple[List[str], List[np.ndarray]]:
return texts, line_xys


def get_and_remove_figure_text(figure: plt.Figure):
def get_and_remove_figure_text(figure: Figure):
"""Remove text from a Figure and its Axes and return with line points.
Parameters
----------
Expand Down Expand Up @@ -234,7 +237,7 @@ def get_and_remove_figure_text(figure: plt.Figure):
return texts, lines


def addPlotInfo(fig, plotInfo):
def addPlotInfo(fig: Figure, plotInfo: Mapping[str, str]) -> Figure:
"""Add useful information to the plot
Parameters
----------
Expand Down
145 changes: 145 additions & 0 deletions python/lsst/analysis/tools/actions/plot/rhoStatisticsPlot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# This file is part of analysis_tools.
#
# Developed for the LSST Data Management System.
# This product includes software developed by the LSST Project
# (https://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Iterable, Mapping

__all__ = ("RhoStatisticsPlotAction",)

import numpy as np
from lsst.pex.config import ConfigDictField

from ...interfaces import PlotAction, Vector
from .plotUtils import addPlotInfo
from .xyPlot import XYPlot

if TYPE_CHECKING:
from matplotlib.figure import Figure

from ...interfaces import KeyedData, KeyedDataSchema


class RhoStatisticsPlotAction(PlotAction):
rhoPlots = ConfigDictField(
doc="A configurable dict describing the rho statistics to plot.",
keytype=str,
itemtype=XYPlot,
default={},
)

def setDefaults(self) -> None:
super().setDefaults()
self.rhoPlots = {rhoName: XYPlot() for rhoName in ("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")}

yLabels = {
"rho3alt": r"$\rho'_{3}(\theta) = \langle \frac{\delta T}{T}, \frac{\delta T}{T}\rangle$",
"rho1": r"$\rho_{1}(\theta) = \langle \delta e, \delta e \rangle$",
"rho2": r"$\rho_{2}(\theta) = \langle e, \delta e \rangle$",
"rho3": r"$\rho_{3}(\theta) = \langle e\frac{\delta T}{T} , e\frac{\delta T}{T} \rangle$",
"rho4": r"$\rho_{4}(\theta) = \langle \delta e, e\frac{\delta T}{T} \rangle$",
"rho5": r"$\rho_{5}(\theta) = \langle e, e\frac{\delta T}{T} \rangle$",
}

for rhoId, rhoPlot in self.rhoPlots.items():
rhoPlot.xAxisLabel = "Separation [arcmin]"
rhoPlot.yAxisLabel = yLabels[rhoId]
rhoPlot.xScale = "log"
rhoPlot.yScale = "symlog"
rhoPlot.yLinThresh = 1e-6

self.rhoPlots["rho3alt"].yScale = "linear" # type: ignore

def getInputSchema(self) -> KeyedDataSchema:
# Docstring inherited
base: list[tuple[str, type[Vector]]] = []
base.append(("coord_ra", Vector))
base.append(("coord_dec", Vector))
base.append(("{{band}}_ixx", Vector))
base.append(("{{band}}_iyy", Vector))
base.append(("{{band}}_ixy", Vector))
base.append(("{{band}}_ixxPSF", Vector))
base.append(("{{band}}_iyyPSF", Vector))
base.append(("{{band}}_ixyPSF", Vector))
return base

def getOutputNames(self) -> Iterable[str]:
# Docstring inherited
return ("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")

def __call__(self, data: KeyedData, **kwargs) -> Mapping[str, Figure]:
self._validateInput(data)
return self.makePlot(data, **kwargs)

def _validateInput(self, data: KeyedData) -> None:
if not set(("rho3alt", "rho1", "rho2", "rho3", "rho4", "rho5")).issubset(data.keys()):
raise ValueError("Input data must contain rho3alt, rho1, rho2, rho3, rho4, and rho5.")

def makePlot(
self, data: KeyedData, plotInfo: Mapping[str, str] | None = None, **kwargs: Any
) -> Mapping[str, Figure]:
"""Make the plot.

Parameters
----------
data : `~pandas.core.frame.DataFrame`
The catalog containing various rho statistics.
plotInfo : `dict`
A dictionary of information about the data being plotted with keys:
``"run"``
The output run for the plots (`str`).
``"skymap"``
The type of skymap used for the data (`str`).
``"filter"``
The filter used for this data (`str`).
``"tract"``
The tract that the data comes from (`str`).
**kwargs
Additional keyword arguments to pass to the plot
"""
fig_dict: dict[str, Figure] = {}
for rho_name in ("rho1", "rho2", "rho3", "rho4", "rho5"):
rho: XYPlot = self.rhoPlots[rho_name]
# The prefix below must match the prefix in the pipeline yaml.
# TODO: This will be fixed in DM-37431.
rhoPlot_name = f"rhoStatisticsPlot_{rho_name}"
subdata = {
"x": data[rho_name].meanr, # type: ignore
"y": data[rho_name].xip, # type: ignore
"yerr": np.sqrt(data[rho_name].varxip), # type: ignore
"xerr": None,
}
fig = rho(subdata, **kwargs)
if plotInfo is not None:
fig_dict[rhoPlot_name] = addPlotInfo(fig, plotInfo)

# rho3alt is handled differently because its attributes differ.
subdata = {
"x": data["rho3alt"].meanr, # type: ignore
"y": data["rho3alt"].xi, # type: ignore
"yerr": np.sqrt(data["rho3alt"].varxi), # type: ignore
"xerr": None,
}
fig = self.rhoPlots["rho3alt"](subdata, **kwargs) # type: ignore[misc]
if plotInfo is not None:
fig_dict["rhoStatisticsPlot_rho3alt"] = addPlotInfo(fig, plotInfo)

return fig_dict
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ def makePlot(
self,
data: KeyedData,
skymap: BaseSkyMap,
plotInfo: Optional[Mapping[str, str]] = None,
plotInfo: Mapping[str, str],
sumStats: Optional[Mapping] = None,
**kwargs,
) -> Figure:
Expand Down