Source code for polyzymd.analyses.shared.multi_run_formatting

"""Shared formatting helpers for multi-run analysis outputs."""

from __future__ import annotations

from collections.abc import Callable

SINGLE_REPLICATE_SEM_NOTE = "SEM: n/a (single replicate; not estimable)"


[docs] def is_sem_estimable(n_replicates: int) -> bool: """Return whether SEM can be estimated from replicate-level values. Parameters ---------- n_replicates : int Number of replicate values contributing to the summary. Returns ------- bool ``True`` when at least two replicates are available. """ return n_replicates >= 2
[docs] def format_sem_value( sem: float | None, n_replicates: int, *, precision: int = 2, unit: str = "", ) -> str: """Format SEM without implying singleton uncertainty is estimable. Parameters ---------- sem : float | None SEM value to display when enough replicates are available. n_replicates : int Number of replicates contributing to the summary. precision : int, optional Decimal places for numeric SEM values, by default 2. unit : str, optional Unit suffix appended to numeric SEM values, by default ``""``. Returns ------- str ``"n/a"`` for singleton summaries, otherwise a formatted SEM value. """ if not is_sem_estimable(n_replicates) or sem is None: return "n/a" return f"{sem:.{precision}f}{unit}"
[docs] def format_sem_phrase( sem: float | None, n_replicates: int, *, precision: int = 2, unit: str = "", ) -> str: """Format a compact ``SEM: ...`` phrase for summaries. Parameters ---------- sem : float | None SEM value to display when enough replicates are available. n_replicates : int Number of replicates contributing to the summary. precision : int, optional Decimal places for numeric SEM values, by default 2. unit : str, optional Unit suffix appended to numeric SEM values, by default ``""``. Returns ------- str ``"SEM: n/a (single replicate)"`` for singleton summaries, otherwise a numeric SEM phrase. """ if not is_sem_estimable(n_replicates): return "SEM: n/a (single replicate)" return f"SEM: {format_sem_value(sem, n_replicates, precision=precision, unit=unit)}"
[docs] def make_section_title(title: str, width: int) -> list[str]: """Build a section title and separator lines.""" return ["", title, "=" * width]
[docs] def make_ranked_table_header(*, mean_label: str) -> list[str]: """Build standard ranked-table headers for text output.""" header = f"{'Condition':<18} {mean_label:<15} {'SEM':<8} {'Rank':<4}" return [header, "-" * len(header)]
[docs] def make_ranked_markdown_header(*, mean_label: str) -> list[str]: """Build standard ranked-table headers for markdown output.""" return [ f"| Condition | {mean_label} | SEM | Rank |", "|-----------|---------------|-----|------|", ]
[docs] def format_pairwise_line( *, condition_a: str, condition_b: str, direction: str, p_value: float, effect_size: float, effect_label: str, percent_change: float, significant: bool, prefix: str = "Pairwise", ) -> str: """Format one standard pairwise comparison line.""" from polyzymd.analyses.stats import format_pct sig_marker = "*" if significant else "" return ( f"{prefix}: {condition_b} vs {condition_a} — " f"Δ={format_pct(percent_change)}, p={p_value:.3f} {sig_marker}, " f"d={effect_size:.2f} ({effect_label}), {direction}" )
[docs] def format_anova_line(*, f_statistic: float, p_value: float, significant: bool) -> str: """Format one standard ANOVA line.""" sig_marker = "*" if significant else "" return f"ANOVA: F={f_statistic:.2f}, p={p_value:.3f} {sig_marker}"
[docs] def format_markdown_bullet(prefix: str, line: str) -> str: """Format a markdown bullet line with consistent prefixing.""" return f"- {prefix}: {line}"
[docs] def make_ranked_rows( ranking: list[str], get_values: Callable[[str], tuple[float, float]], ) -> list[tuple[str, float, float, int]]: """Build ranked rows as ``(label, mean, sem, rank)`` tuples.""" rows: list[tuple[str, float, float, int]] = [] for rank, condition_label in enumerate(ranking, 1): mean_value, sem_value = get_values(condition_label) rows.append((condition_label, mean_value, sem_value, rank)) return rows