"""Module containing overview plotting functionality."""
from __future__ import annotations
from pathlib import Path
from typing import TYPE_CHECKING
from warnings import warn
import matplotlib.pyplot as plt
from pyglotaran_extras.deprecation.deprecation_utils import FIG_ONLY_WARNING
from pyglotaran_extras.deprecation.deprecation_utils import PyglotaranExtrasApiDeprecationWarning
from pyglotaran_extras.io.load_data import load_data
from pyglotaran_extras.plotting.plot_concentrations import plot_concentrations
from pyglotaran_extras.plotting.plot_guidance import plot_guidance
from pyglotaran_extras.plotting.plot_residual import plot_residual
from pyglotaran_extras.plotting.plot_spectra import plot_sas
from pyglotaran_extras.plotting.plot_spectra import plot_spectra
from pyglotaran_extras.plotting.plot_svd import plot_lsv_residual
from pyglotaran_extras.plotting.plot_svd import plot_rsv_residual
from pyglotaran_extras.plotting.plot_svd import plot_svd
from pyglotaran_extras.plotting.style import PlotStyle
from pyglotaran_extras.plotting.utils import add_cycler_if_not_none
from pyglotaran_extras.plotting.utils import extract_irf_location
from pyglotaran_extras.types import Unset
if TYPE_CHECKING:
from cycler import Cycler
from glotaran.project.result import Result
from matplotlib.figure import Figure
from matplotlib.pyplot import Axes
from pyglotaran_extras.types import DatasetConvertible
from pyglotaran_extras.types import UnsetType
[docs]
def plot_overview(
result: DatasetConvertible | Result,
center_λ: float | None = None,
linlog: bool = True,
linthresh: float = 1,
linscale: float = 1,
show_data: bool | None = False,
main_irf_nr: int = 0,
figsize: tuple[float, float] = (18, 16),
cycler: Cycler | None = PlotStyle().cycler,
figure_only: bool | None = None,
nr_of_data_svd_vectors: int = 4,
nr_of_residual_svd_vectors: int = 2,
show_data_svd_legend: bool = True,
show_residual_svd_legend: bool = True,
show_irf_dispersion_center: bool = True,
show_zero_line: bool = True,
das_cycler: Cycler | None | UnsetType = Unset,
svd_cycler: Cycler | None | UnsetType = Unset,
use_svd_number: bool = False,
) -> tuple[Figure, Axes]:
"""Plot overview of the optimization result.
Parameters
----------
result : DatasetConvertible | Result
Result from a pyglotaran optimization as dataset, Path or Result object.
center_λ : float | None
Center wavelength (λ in nm)
linlog : bool
Whether to use 'symlog' scale or not. Defaults to False.
linthresh : float
A single float which defines the range (-x, x), within which the plot is linear.
This avoids having the plot go to infinity around zero. Defaults to 1.
linscale : float
This allows the linear range (-linthresh to linthresh) to be stretched
relative to the logarithmic range.
Its value is the number of decades to use for each half of the linear range.
For example, when linscale == 1.0 (the default), the space used for the
positive and negative halves of the linear range will be equal to one
decade in the logarithmic range. Defaults to 1.
show_data : bool | None
Whether to show the input data or residual. If set to ``None`` the plot is skipped
which improves plotting performance for big datasets. Defaults to False.
main_irf_nr : int
Index of the main ``irf`` component when using an ``irf``
parametrized with multiple peaks. Defaults to 0.
figsize : tuple[float, float]
Size of the figure (N, M) in inches. Defaults to (18, 16).
cycler : Cycler | None
Plot style cycler to use. Defaults to PlotStyle().cycler.
figure_only : bool | None
Deprecated please remove this argument for you function calls. Defaults to None.
nr_of_data_svd_vectors : int
Number of data SVD vector to plot. Defaults to 4.
nr_of_residual_svd_vectors : int
Number of residual SVD vector to plot. Defaults to 2.
show_data_svd_legend : bool
Whether or not to show the data SVD legend. Defaults to True.
show_residual_svd_legend : bool
Whether or not to show the residual SVD legend. Defaults to True.
show_irf_dispersion_center : bool
Whether to show the the IRF dispersion center as overlay on the residual/data plot.
Defaults to True.
show_zero_line : bool
Whether or not to add a horizontal line at zero to the plots of the spectra.
Defaults to True.
das_cycler : Cycler | None | UnsetType
Plot style cycler to use for DAS plots. Defaults to ``Unset`` which means that the value
of ``cycler`` is used.
svd_cycler : Cycler | None | UnsetType
Plot style cycler to use for SVD plots. Defaults to ``Unset`` which means that the value
of ``cycler`` is used.
use_svd_number : bool
Whether to use singular value number (starts at 1) instead of singular value index
(starts at 0) for labeling in plot. Defaults to False.
Returns
-------
tuple[Figure, Axes]
"""
res = load_data(result, _stacklevel=3)
if das_cycler is Unset:
das_cycler = cycler
if svd_cycler is Unset:
svd_cycler = cycler
if res.coords["time"].to_numpy().size == 1:
fig, axes = plot_guidance(res)
if figure_only is not None:
warn(PyglotaranExtrasApiDeprecationWarning(FIG_ONLY_WARNING), stacklevel=2)
return fig, axes
fig, axes = plt.subplots(4, 3, figsize=figsize, constrained_layout=True)
irf_location = extract_irf_location(res, center_λ, main_irf_nr)
if center_λ is None: # center wavelength (λ in nm)
center_λ = min(res.dims["spectral"], round(res.dims["spectral"] / 2))
# First and second row: concentrations - SAS/EAS - DAS
plot_concentrations(
res,
axes[0, 0],
center_λ,
linlog=linlog,
linthresh=linthresh,
linscale=linscale,
main_irf_nr=main_irf_nr,
cycler=cycler,
)
plot_spectra(
res, axes[0:2, 1:3], cycler=cycler, show_zero_line=show_zero_line, das_cycler=das_cycler
)
plot_svd(
res,
axes[2:4, 0:3],
linlog=linlog,
linthresh=linthresh,
cycler=svd_cycler,
nr_of_data_svd_vectors=nr_of_data_svd_vectors,
nr_of_residual_svd_vectors=nr_of_residual_svd_vectors,
show_data_svd_legend=show_data_svd_legend,
show_residual_svd_legend=show_residual_svd_legend,
irf_location=irf_location,
use_svd_number=use_svd_number,
)
plot_residual(
res,
axes[1, 0],
linlog=linlog,
linthresh=linthresh,
show_data=show_data,
cycler=cycler,
show_irf_dispersion_center=show_irf_dispersion_center,
irf_location=irf_location,
)
if figure_only is not None:
warn(PyglotaranExtrasApiDeprecationWarning(FIG_ONLY_WARNING), stacklevel=2)
return fig, axes
def plot_simple_overview(
result: DatasetConvertible | Result,
title: str | None = None,
figsize: tuple[float, float] = (12, 6),
cycler: Cycler | None = PlotStyle().cycler,
figure_only: bool | None = None,
show_irf_dispersion_center: bool = True,
show_data: bool | None = False,
svd_cycler: Cycler | None | UnsetType = Unset,
use_svd_number: bool = False,
) -> tuple[Figure, Axes]:
"""Plot simple overview.
Parameters
----------
result : DatasetConvertible | Result
Result from a pyglotaran optimization as dataset, Path or Result object.
title : str | None
Title of the figure. Defaults to None.
figsize : tuple[float, float]
Size of the figure (N, M) in inches. Defaults to (18, 16).
cycler : Cycler | None
Plot style cycler to use. Defaults to PlotStyle().cycler.
figure_only : bool | None
Deprecated please remove this argument for you function calls. Defaults to None.
show_irf_dispersion_center : bool
Whether to show the the IRF dispersion center as overlay on the residual/data plot.
Defaults to True.
show_data : bool | None
Whether to show the input data or residual. If set to ``None`` the plot is skipped
which improves plotting performance for big datasets. Defaults to False.
svd_cycler : Cycler | None | UnsetType
Plot style cycler to use for SVD plots. Defaults to ``Unset`` which means that the value
of ``cycler`` is used.
use_svd_number : bool
Whether to use singular value number (starts at 1) instead of singular value index
(starts at 0) for labeling in plot. Defaults to False.
Returns
-------
tuple[Figure, Axes]
"""
res = load_data(result, _stacklevel=3)
if svd_cycler is Unset:
svd_cycler = cycler
fig, axes = plt.subplots(2, 3, figsize=figsize, constrained_layout=True)
for ax in axes.flatten():
add_cycler_if_not_none(ax, cycler)
if title:
fig.suptitle(title, fontsize=16)
plot_concentrations(res, ax=axes[0, 0], center_λ=res.coords["spectral"].to_numpy()[0])
plot_sas(res, ax=axes[0, 1])
irf_location = extract_irf_location(res, center_λ=res.coords["spectral"].to_numpy()[0])
plot_lsv_residual(
res,
ax=axes[1, 0],
irf_location=irf_location,
cycler=svd_cycler,
use_svd_number=use_svd_number,
)
plot_rsv_residual(res, ax=axes[1, 1], cycler=svd_cycler, use_svd_number=use_svd_number)
plot_residual(
res,
axes[0, 2],
show_data=show_data,
show_irf_dispersion_center=show_irf_dispersion_center,
irf_location=irf_location,
)
plot_residual(
res,
axes[1, 2],
show_data=False,
show_irf_dispersion_center=show_irf_dispersion_center,
irf_location=irf_location,
)
if figure_only is not None:
warn(PyglotaranExtrasApiDeprecationWarning(FIG_ONLY_WARNING), stacklevel=2)
return fig, axes
if __name__ == "__main__":
import sys
result_path = Path(sys.argv[1])
res = load_data(result_path)
print(res) # noqa: T201
fig, axes = plot_overview(res)
if len(sys.argv) > 2:
fig.savefig(sys.argv[2], bbox_inches="tight")
print(f"Saved figure to: {sys.argv[2]}") # noqa: T201
else:
plt.show(block=False)
input("press <ENTER> to continue")