Source code for simularium_metrics_calculator.plot_info
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Optional
from .constants import PLOT_TYPE, SCATTER_PLOT_MODE
from .exceptions import IncompatibleMetricsError, InconsistentPlotTypeError
from .metric_info import MetricInfo
[docs]
class PlotInfo:
plot_type: PLOT_TYPE
metric_id_x: int
metric_id_y: int
scatter_plot_mode: SCATTER_PLOT_MODE
title: str
def __init__(
self,
plot_type: PLOT_TYPE,
metric_id_x: int,
metric_id_y: int = -1,
scatter_plot_mode: SCATTER_PLOT_MODE = SCATTER_PLOT_MODE.MARKERS,
title: str = "",
):
"""
This object takes Simularium trajectory data
and calculates metrics that can be plotted
in the Simularium Viewer.
Parameters
----------
plot_type: PLOT_TYPE
What type of plot to make.
metric_id_x : int
ID for the metric to plot on the x-axis.
metric_id_y : int (Optional)
ID for the metric to plot on the y-axis.
If not provided, the plot will be a histogram.
scatter_plot_mode : SCATTER_PLOT_MODE (Optional)
If the plot is a scatterplot, how to draw the points.
Default: SCATTER_PLOT_MODE.MARKERS (draw as dots)
title: str
Title to display above plot.
"""
self.plot_type = plot_type
self.metric_id_x = metric_id_x
self.metric_id_y = metric_id_y
self.scatter_plot_mode = scatter_plot_mode
self.title = title
self.display_title = title
[docs]
def validate_plot_configuration(
self, metric_info_x: MetricInfo, metric_info_y: Optional[MetricInfo]
) -> None:
"""
Check that the plot type and number of metrics are consistent,
and that the X and Y metrics are of the same type
if this is not a histogram.
Parameters
----------
metric_info_x: MetricInfo
Info about the metric to plot on the x-axis.
metric_info_y: MetricInfo (optional)
Info about the metric to plot on the y-axis.
Default: None (only for histograms)
"""
self._check_plot_type_is_consistent()
self._check_metrics_are_compatible(metric_info_x, metric_info_y)
def _check_plot_type_is_consistent(self) -> None:
"""
Make sure the number of metrics is consistent with the plot type,
1 metric for histogram and 2 for scatter.
"""
if not (self.metric_id_y < 0) == (self.plot_type == PLOT_TYPE.HISTOGRAM):
raise InconsistentPlotTypeError(self.plot_type)
def _check_metrics_are_compatible(
self, metric_info_x: MetricInfo, metric_info_y: Optional[MetricInfo]
) -> None:
"""
Check that the X and Y metrics are of the same type,
if this is not a histogram.
"""
if metric_info_y is None:
return
x_metric_type = metric_info_x.metric_type
y_metric_type = metric_info_y.metric_type
if x_metric_type != y_metric_type:
x_metric_name = metric_info_x.display_name
y_metric_name = metric_info_y.display_name
raise IncompatibleMetricsError(x_metric_name, y_metric_name)
[docs]
def set_display_title(
self, metric_info_x: MetricInfo, metric_info_y: Optional[MetricInfo]
) -> None:
"""
Return the title to display above the plot.
If no title is provided, default to "Y metric name vs. X metric name".
Parameters
----------
metric_info_x: MetricInfo
Info about the metric to plot on the x-axis.
metric_info_y: MetricInfo (optional)
Info about the metric to plot on the y-axis.
Default: None (only for histograms)
"""
if self.title:
# use custom title
self.display_title = self.title
return
x_metric_name = metric_info_x.display_name
if metric_info_y is None:
# histogram
self.display_title = f"{x_metric_name}"
return
# scatter plot
y_metric_name = metric_info_y.display_name
self.display_title = f"{y_metric_name} vs. {x_metric_name.lower()}"
def __str__(self) -> str:
"""
Get the title and type of this plot.
Returns
-------
str
"[title] [type of plot]"
"""
title = f"{self.display_title} " if self.display_title else ""
pt = "histogram" if self.plot_type == PLOT_TYPE.HISTOGRAM else "scatter plot"
return f"{title}{pt}"