Source code for petres.viewers.viewer2d.matplotlib.theme
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
[docs]
@dataclass(frozen=True)
class Matplotlib2DViewerTheme:
"""Store visual configuration for 2D Matplotlib viewers.
This dataclass centralizes figure, axes, grid, and typography defaults used
by the 2D viewer layer. Values are intentionally conservative so they work
well for both regular grids and irregular polygonal geometry.
Parameters
----------
figure_size : tuple[float, float], default=(9.0, 7.0)
Figure size in inches as ``(width, height)``.
dpi : int, default=120
Figure resolution in dots per inch.
constrained_layout : bool, default=True
Whether Matplotlib constrained layout is enabled.
background : str | tuple[float, float, float] | tuple[float, float, float, float], default="white"
Axes background color accepted by Matplotlib.
aspect : {"auto", "equal"}, default="equal"
Aspect ratio mode passed to Matplotlib axes.
margins : float, default=0.03
Relative axes margins. Must be non-negative.
grid : bool, default=True
Whether to show major grid lines.
grid_alpha : float, default=0.18
Grid line alpha in the inclusive range ``[0.0, 1.0]``.
grid_linestyle : str, default="--"
Matplotlib line style string for grid lines.
grid_linewidth : float, default=0.6
Grid line width in points. Must be non-negative.
xlabel : str, default="X Axis"
X-axis label text.
ylabel : str, default="Y Axis"
Y-axis label text.
show_labels : bool, default=True
Whether axis labels are rendered.
title_fontsize : float, default=13.0
Font size used for plot titles. Must be positive.
hide_top_right_spines : bool, default=True
Whether top and right spines are hidden.
tick_labelsize : float, default=10.0
Font size used for tick labels. Must be positive.
Raises
------
ValueError
If one or more numeric configuration fields are outside their valid
ranges.
Examples
--------
>>> theme = Matplotlib2DViewerTheme(background="whitesmoke", aspect="auto")
>>> theme.dpi
120
Notes
-----
``__init__`` is generated by ``dataclasses`` based on the declared fields.
Runtime validation is performed in ``__post_init__``.
"""
# Figure
figure_size: tuple[float, float] = (9.0, 7.0)
dpi: int = 120
constrained_layout: bool = True
# Axes
background: str | tuple[float, float, float] | tuple[float, float, float, float] = "white"
aspect: Literal["auto", "equal"] = "equal"
margins: float = 0.03
# Grid
grid: bool = False
grid_alpha: float = 0.18
grid_linestyle: str = "--"
grid_linewidth: float = 0.6
# Labels
xlabel: str = "X Axis"
ylabel: str = "Y Axis"
show_labels: bool = True
# Title
title_fontsize: float = 13.0
# Spines / ticks
hide_top_right_spines: bool = True
tick_labelsize: float = 10.0
[docs]
def __post_init__(self) -> None:
"""Validate numeric theme values after dataclass initialization.
Raises
------
ValueError
If ``margins`` or ``grid_linewidth`` is negative, if
``grid_alpha`` is outside ``[0.0, 1.0]``, if ``dpi`` is not
strictly positive, or if ``title_fontsize`` / ``tick_labelsize``
is not strictly positive.
"""
if self.margins < 0.0:
raise ValueError("margins must be >= 0.0")
if not 0.0 <= self.grid_alpha <= 1.0:
raise ValueError("grid_alpha must be within [0.0, 1.0]")
if self.grid_linewidth < 0.0:
raise ValueError("grid_linewidth must be >= 0.0")
if self.dpi <= 0:
raise ValueError("dpi must be > 0")
if self.title_fontsize <= 0.0:
raise ValueError("title_fontsize must be > 0.0")
if self.tick_labelsize <= 0.0:
raise ValueError("tick_labelsize must be > 0.0")