Source code for prolint.plotting.base

"""Plotting base module.

This module provides the base classes and registry for ProLint plotters.
"""

from abc import ABC, abstractmethod
from typing import Dict, List, Tuple, Type
from matplotlib.figure import Figure
from matplotlib.axes import Axes

from prolint.analysis.base import AnalysisResult


[docs] class BasePlotter(ABC): """Abstract base class for all ProLint plotters. Plotters convert AnalysisResult objects into matplotlib visualizations. Subclasses must implement the ``plot()`` method. Attributes ---------- name : str Plotter name for registry lookup. required_analysis : str Name of the analysis type this plotter expects. description : str Human-readable description. See Also -------- PlottingRegistry : Registry for creating plotters by name plot : Convenience function for plotting """
[docs] name: str = "base_plotter"
[docs] required_analysis: str = ""
[docs] description: str = "Base plotter class"
@classmethod
[docs] def validate_result(cls, result: AnalysisResult) -> None: """Validate that the AnalysisResult contains required data keys. Parameters ---------- result : AnalysisResult Result to validate. Raises ------ ValueError If result is missing required keys for this plotter. """ pass
@classmethod @abstractmethod
[docs] def plot(cls, result: AnalysisResult, **kwargs) -> Tuple[Figure, Axes]: """Create the plot from an AnalysisResult. Parameters ---------- result : AnalysisResult Analysis result containing data to plot. **kwargs : dict Plotter-specific options. Returns ------- tuple of (Figure, Axes) Matplotlib figure and axes objects. """ pass
[docs] class PlottingRegistry: """Registry for plotter types. Manages registration and creation of plotter classes. All built-in plotters are registered automatically on import. Examples -------- List available plotters: >>> from prolint.plotting import PlottingRegistry >>> PlottingRegistry.available() ['heatmap', 'density_map', 'survival_curve', ...] Create a plot: >>> fig, ax = PlottingRegistry.plot("heatmap", result) """ _registry: Dict[str, Type[BasePlotter]] = {} @classmethod
[docs] def register(cls, name: str, plotter_class: Type[BasePlotter]) -> None: """Register a plotter class. Parameters ---------- name : str Name to register under. plotter_class : type Plotter class (must inherit from BasePlotter). """ if not issubclass(plotter_class, BasePlotter): raise TypeError(f"{plotter_class} must be a subclass of BasePlotter") cls._registry[name] = plotter_class
@classmethod
[docs] def plot(cls, name: str, result: AnalysisResult, **kwargs) -> Tuple[Figure, Axes]: """Create a plot using a registered plotter. Parameters ---------- name : str Plotter type name. result : AnalysisResult Analysis result to plot. **kwargs : dict Plotter-specific options. Returns ------- tuple of (Figure, Axes) Matplotlib figure and axes objects. Raises ------ ValueError If plotter name is not registered. """ if name not in cls._registry: available = ", ".join(sorted(cls._registry.keys())) raise ValueError(f"Unknown plot type: '{name}'. Available: {available}") plotter = cls._registry[name] plotter.validate_result(result) return plotter.plot(result, **kwargs)
@classmethod
[docs] def available(cls) -> List[str]: """List all available plot types. Returns ------- list of str Registered plotter names. """ return sorted(cls._registry.keys())
@classmethod
[docs] def get_class(cls, name: str) -> Type[BasePlotter]: """Get a plotter class by name. Parameters ---------- name : str Plotter name. Returns ------- type Plotter class. """ if name not in cls._registry: raise ValueError(f"Unknown plot type: {name}") return cls._registry[name]
@classmethod
[docs] def get_info(cls, name: str) -> Dict[str, str]: """Get information about a plotter. Parameters ---------- name : str Plotter name. Returns ------- dict Dict with name, required_analysis, and description keys. """ plotter = cls.get_class(name) return { "name": plotter.name, "required_analysis": plotter.required_analysis, "description": plotter.description, }
@classmethod
[docs] def list_plotters(cls) -> List[Dict[str, str]]: """List all plotters with their info. Returns ------- list of dict Info dict for each registered plotter. """ return [cls.get_info(name) for name in cls.available()]
[docs] def plot(name: str, result: AnalysisResult, **kwargs) -> Tuple[Figure, Axes]: """Create a plot from an AnalysisResult. Convenience function that delegates to PlottingRegistry.plot(). Parameters ---------- name : str Plotter type name. result : AnalysisResult Analysis result to plot. **kwargs : dict Plotter-specific options. Returns ------- tuple of (Figure, Axes) Matplotlib figure and axes objects. Examples -------- >>> from prolint.plotting import plot >>> fig, ax = plot("heatmap", timeseries_result) >>> fig, ax = plot("survival_curve", kinetics_result) """ return PlottingRegistry.plot(name, result, **kwargs)