Source code for trspecfit.config.plot

"""
Configuration of trspecfit plotting functions
"""

import copy as cp
from dataclasses import dataclass, fields

# Plot configuration hierarchy:
#
# Project (defaults from YAML)
#    ↓
# File (can customize persistently per file)
#    ↓
# Model (inherits from File, no customization)
#    ↓
# plot call (can override temporarily for one plot)


[docs] @dataclass class PlotConfig: """ Configuration for plot appearance and behavior. This class bundles all plot-related settings that can be passed to plotting functions. It can be created standalone or from a Project instance. Attributes ---------- x_label : str X-axis label (energy for 2D, energy or time for 1D) y_label : str Y-axis label (time for 2D, intensity for 1D) z_label : str Z-axis/colorbar label (intensity for 2D plots) title : str Plot title x_dir : str X-axis direction: 'def' (default) or 'rev' (reversed) x_type : str X-axis scale: 'lin' (linear) or 'log' (logarithmic) y_dir : str Y-axis direction: 'def' (default) or 'rev' (reversed) y_type : str Y-axis scale: 'lin' (linear) or 'log' (logarithmic) x_lim : tuple[float, float] | None X-axis limits (min, max) y_lim : tuple[float, float] | None Y-axis limits (min, max) z_type : str Color scale type: 'lin' (linear) or 'log' (logarithmic) z_lim : tuple[float, float] | None Color scale limits for 2D plots (min, max) dpi_plot : int DPI for displaying plots dpi_save : int DPI for saving plots z_colormap : str Colormap name for 2D plots data_slice : list[list[int]] | None Data slicing indices for 2D plots: [[x_start, x_stop], [y_start, y_stop]] colors : list[str] | None List of colors for line plots linestyles : list[str] | None List of line styles linewidths : list[float] | None List of line widths markers : list[str] | None List of marker styles markersizes : list[float] | None List of marker sizes alphas : list[float] | None List of opacity values (0–1) for each trace legend : list[str] | None List of legend labels waterfall : float Y-offset between plots for waterfall display vlines : list[float] | None X-coordinates for vertical lines hlines : list[float] | None Y-coordinates for horizontal lines ticksize : float | None Font size for tick labels Examples -------- Create a configuration with custom settings: >>> config = PlotConfig(x_label='Energy (eV)', x_dir='rev', dpi_plot=150) >>> plot_1d(data, x, config=config) Create from Project settings: >>> project = Project(path='...', config_file='project.yaml') >>> config = PlotConfig.from_project(project) >>> plot_1d(data, x, config=config) Override Project settings: >>> config = PlotConfig.from_project(project, x_label='Binding Energy (eV)') >>> plot_2d(data, x, y, config=config) Override config for a specific plot: >>> config = PlotConfig.from_project(project) >>> plot_1d(data, x, config=config, x_dir='rev', linewidth=2) Create multiple configs from one project: >>> project = Project(path='...') >>> default_config = PlotConfig.from_project(project) >>> pub_config = PlotConfig.from_project(project, dpi_save=600) >>> talk_config = PlotConfig.from_project(project, dpi_plot=150) """ # Axis labels x_label: str = "x axis" y_label: str = "y axis" z_label: str = "z axis" title: str = "" # Axis behavior x_dir: str = "def" x_type: str = "lin" y_dir: str = "def" y_type: str = "lin" # Axis limits x_lim: tuple[float, float] | None = None y_lim: tuple[float, float] | None = None # Display settings dpi_plot: int = 100 dpi_save: int = 300 # Residual multiplier for 1D fit plots res_mult: float = 5 # 2D plot settings z_colormap: str = "viridis" z_colorbar: str = "ver" # 'ver' or 'hor' z_type: str = "lin" # 'lin' or 'log' for color scale # 2D data handling data_slice: list[list[int]] | None = None z_lim: tuple[float, float] | None = None # Line plot styles colors: list[str] | None = None linestyles: list[str] | None = None linewidths: list[float] | None = None markers: list[str] | None = None markersizes: list[float] | None = None alphas: list[float] | None = None # Plot annotations legend: list[str] | None = None waterfall: float = 0 vlines: list[float] | None = None hlines: list[float] | None = None ticksize: float | None = None # Normalization y_norm: int = 0 # 0: no normalization, 1: normalize to [0,1] y_scale: list[float] | None = None
[docs] @classmethod def from_project(cls, project, **overrides) -> "PlotConfig": """ Create PlotConfig from Project settings. Parameters ---------- project : Project Project instance with plot settings **overrides : dict Any parameters to override from project defaults Returns ------- PlotConfig Configuration object with settings from project """ project_aliases = { "x_label": "e_label", "y_label": "t_label", "dpi_plot": "dpi_plt", } limit_fields = {"x_lim", "y_lim", "z_lim"} config_dict = {} for field in fields(cls): source_attr = project_aliases.get(field.name, field.name) if not hasattr(project, source_attr): continue value = cp.deepcopy(getattr(project, source_attr)) if field.name in limit_fields and value is not None: value = tuple(value) config_dict[field.name] = value # Apply any overrides config_dict.update(overrides) return cls(**config_dict)
#
[docs] def update(self, **kwargs) -> "PlotConfig": """ Update configuration attributes. Parameters ---------- **kwargs : dict Attributes to update Returns ------- PlotConfig Self (for chaining) """ for key, value in kwargs.items(): if hasattr(self, key): setattr(self, key, value) else: raise AttributeError(f"PlotConfig has no attribute '{key}'") return self
#
[docs] def copy(self, **overrides) -> "PlotConfig": """ Create a copy of this config with optional overrides. Parameters ---------- **overrides : dict Attributes to override in the copy Returns ------- PlotConfig New configuration object """ new_config = cp.copy(self) new_config.update(**overrides) return new_config