Adding a new RailPlotter
All of the various plotting classes
are implemented as subclasses of the rail.plotting.plotter.RailPlotter class.
A RailPlotter is intended to take a particular set of inputs and configuration parameters,
run a single bit of analysis, and produce one or more plots. The inputs, outputs
and configuration parameters are all defined in particular ways to allow RailPlotter
objects to be integrated into larger data analysis pipelines.
New RailPlotter Example
The following example has all of the required pieces of a RailPlotter and almost nothing else.
class PZPlotterPointEstimateVsTrueHist2D(RailPlotter):
"""Class to make a 2D histogram of p(z) point estimates
versus true redshift
"""
config_options: dict[str, StageParameter] = RailPlotter.config_options.copy()
config_options.update(
z_min=StageParameter(float, 0.0, fmt="%0.2f", msg="Minimum Redshift"),
z_max=StageParameter(float, 3.0, fmt="%0.2f", msg="Maximum Redshift"),
n_zbins=StageParameter(int, 150, fmt="%i", msg="Number of z bins"),
)
input_type = RailPZPointEstimateDataset
def _make_2d_hist_plot(
self,
prefix: str,
truth: np.ndarray,
pointEstimate: np.ndarray,
dataset_holder: RailDatasetHolder | None = None,
) -> RailPlotHolder:
figure, axes = plt.subplots()
bin_edges = np.linspace(
self.config.z_min, self.config.z_max, self.config.n_zbins + 1
)
axes.hist2d(
truth,
pointEstimate,
bins=(bin_edges, bin_edges),
)
plt.xlabel("True Redshift")
plt.ylabel("Estimated Redshift")
plot_name = self._make_full_plot_name(prefix, "")
return RailPlotHolder(
name=plot_name, figure=figure, plotter=self, dataset_holder=dataset_holder
)
def _make_plots(self, prefix: str, **kwargs: Any) -> dict[str, RailPlotHolder]:
find_only = kwargs.get("find_only", False)
figtype = kwargs.get("figtype", "png")
dataset_holder = kwargs.get("dataset_holder")
out_dict: dict[str, RailPlotHolder] = {}
truth: np.ndarray = kwargs["truth"]
pointEstimate: np.ndarray = kwargs["pointEstimate"]
if find_only:
plot_name = self._make_full_plot_name(prefix, "")
assert dataset_holder
plot = RailPlotHolder(
name=plot_name,
path=os.path.join(dataset_holder.config.name, f"{plot_name}.{figtype}"),
plotter=self,
dataset_holder=dataset_holder,
)
else:
plot = self._make_2d_hist_plot(
prefix=prefix,
truth=truth,
pointEstimate=pointEstimate,
dataset_holder=dataset_holder,
)
out_dict[plot.name] = plot
return out_dict
The required pieces, in the order that they appear are:
The
PZPlotterPointEstimateVsTrueHist2D(RailPlotter):defines a class calledPZPlotterPointEstimateVsTrueHist2Dand specifies that it inherits fromRailPlotter.The
config_optionslines define the configuration parameters for this class, as well as their default values. Note that here we are copying the configuration parameters from theRailPlotteras well as defining some new ones.The
input_type = RailPZPointEstimateDatasetspecifies that this plotter expects arail.plotting.pz_plotters.RailPZPointEstimateDatasettype dataset, which in this case is an dict with one item (calledtruth) that is a numpy array, and a second item (calledpointEstimate) that is a also a numpy array.The
__init__method does any class-specific initialization. In this case there isn’t any and the method is superfluous.The
_make_2d_hist_plot(...)method does the actual work, note it takes some of the same arguements are define ininputsand that it usesself.configto access the configuration parameters.The
_make_plots(self, prefix: str, **kwargs: Any)method provides an interface to format the data for _make_2d_hist_plot(), the arguments to this function are specified in theRailPlotterclass