"""Module containing a-matrix render functionality."""
from __future__ import annotations
from typing import TYPE_CHECKING
import numpy as np
from glotaran.utils.ipython import MarkdownStr
from tabulate import tabulate
from pyglotaran_extras.inspect.utils import pretty_format_numerical
from pyglotaran_extras.inspect.utils import pretty_format_numerical_iterable
from pyglotaran_extras.inspect.utils import wrap_in_details_tag
from pyglotaran_extras.io.utils import result_dataset_mapping
if TYPE_CHECKING:
import xarray as xr
from pyglotaran_extras.types import ResultLike
[docs]
def a_matrix_to_html_table(
a_matrix: xr.DataArray,
megacomplex_suffix: str,
*,
normalize_initial_concentration: bool = False,
decimal_places: int = 3,
) -> str:
"""Create HTML multi header table from a-matrix.
Parameters
----------
a_matrix : xr.DataArray
DataArray containing the a-matrix values and coordinates.
megacomplex_suffix : str
Megacomplex suffix used for the a-matrix data variable and coordinate names.
normalize_initial_concentration : bool
Whether or not to normalize the initial concentration. Defaults to False.
decimal_places : int
Decimal places to display. Defaults to 3.
Returns
-------
str
Multi header HTML table representing the a-matrix.
"""
species = a_matrix.coords[f"species_{megacomplex_suffix}"].to_numpy()
# Crete a copy so normalization does not mutate the original values
initial_concentration = np.array(
a_matrix.coords[f"initial_concentration_{megacomplex_suffix}"].to_numpy()
)
lifetime = a_matrix.coords[f"lifetime_{megacomplex_suffix}"].to_numpy()
if normalize_initial_concentration is True:
initial_concentration /= initial_concentration.sum()
header = (
["species<br>initial concentration<br>lifetime↓"]
+ [
f"{sp}<br>{pretty_format_numerical(ic,decimal_places)}<br> "
for sp, ic in zip(species, initial_concentration, strict=True)
]
+ ["Sum"]
)
data = [
pretty_format_numerical_iterable(
(lifetime, *amps, amps.sum()), decimal_places=decimal_places
)
for lifetime, amps in zip(lifetime, a_matrix.values, strict=True)
]
data.append(
pretty_format_numerical_iterable(
("Sum", *a_matrix.to_numpy().sum(axis=0), a_matrix.to_numpy().sum()),
decimal_places=decimal_places,
)
)
return (
tabulate(
data, headers=header, showindex=False, tablefmt="unsafehtml", disable_numparse=True
)
.replace(" 0 ", " ")
.replace(" 0<", " <")
.replace(">0 ", "> ")
)
[docs]
def show_a_matrixes(
result: ResultLike,
*,
normalize_initial_concentration: bool = False,
decimal_places: int = 3,
a_matrix_min_size: int | None = None,
expanded_datasets: tuple[str, ...] = (),
heading_offset: int = 2,
) -> MarkdownStr:
"""Show all a-matrixes of a result grouped by dataset and megacomplex name.
Each dataset is wrapped in a HTML details tag which is by default collapsed.
Parameters
----------
result : ResultLike
Result or result dataset.
normalize_initial_concentration : bool
Whether or not to normalize the initial concentration. Defaults to False.
decimal_places : int
Decimal places to display. Defaults to 3.
a_matrix_min_size : int | None
Defaults to None.
expanded_datasets : tuple[str, ...]
Names of dataset to expand the details view for. Defaults to empty tuple () which means no
dataset is expanded.
heading_offset : int
Number of heading level to offset the headings. Defaults to 2 which means that the
first/top most heading is h3.
Returns
-------
MarkdownStr
Markdown representation of the a-matrixes used in the optimization.
"""
heading_prefix = heading_offset * "#"
output_str = f"#{heading_prefix} A-Matrixes\n"
result_map = result_dataset_mapping(result)
for dataset_name in result_map:
a_matrix_names = list(
filter(
lambda var_name: var_name.startswith("a_matrix_"),
result_map[dataset_name].data_vars,
)
)
if not a_matrix_names:
continue
details_content = ""
header_newline_prefix = ""
for a_matrix_name in a_matrix_names:
mc_suffix = a_matrix_name.replace("a_matrix_", "")
a_matrix = result_map[dataset_name][a_matrix_name]
if a_matrix_min_size is not None and max(a_matrix.shape) < a_matrix_min_size:
continue
details_content += f"{header_newline_prefix}###{heading_prefix} {mc_suffix}:\n\n"
details_content += a_matrix_to_html_table(
a_matrix,
mc_suffix,
normalize_initial_concentration=normalize_initial_concentration,
decimal_places=decimal_places,
)
header_newline_prefix = "\n\n"
if details_content != "":
output_str += wrap_in_details_tag(
details_content,
summary_content=dataset_name,
summary_heading_level=2 + heading_offset,
is_open=dataset_name in expanded_datasets,
)
return MarkdownStr(output_str)