"""Plotting helpers for CAMP metrics."""
from __future__ import annotations
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib.figure import Figure
from campmc.pl._helpers import _finalize_figure
[docs]
def metric_ecdf(
values: np.ndarray,
out_png: str | Path | None = None,
*,
title: str = "Metric ECDF",
show: bool = False,
) -> Figure | None:
"""Save or display an empirical CDF plot for a 1-D metric array.
Parameters
----------
values
Metric values; non-finite entries are dropped.
out_png
If set, write the figure to this path (PNG).
title
Plot title.
show
If ``True``, display via ``plt.show()`` and return ``None``.
Returns
-------
The figure when ``show`` is false and ``out_png`` is not set; otherwise ``None``
after saving or displaying.
Examples
--------
.. exec-jupyter::
import campmc as cp
import scanpy as sc
adata = sc.datasets.pbmc68k_reduced()
cp.partition(adata, method="camp3", gamma=50, random_state=0)
qc = cp.mt.quality(adata, partition_key="camp")
cp.pl.metric_ecdf(qc["sc_ratio"].to_numpy(), title="sc_ratio ECDF", show=True)
"""
vals = np.asarray(values, dtype=float)
vals = vals[np.isfinite(vals)]
if vals.size == 0:
raise ValueError("No finite values to plot.")
x = np.sort(vals)
y = np.arange(1, x.size + 1) / x.size
fig, ax = plt.subplots(figsize=(5, 4))
ax.plot(x, y, linewidth=2)
ax.set_xlabel("value")
ax.set_ylabel("ECDF")
ax.set_title(title)
fig.tight_layout()
if out_png is not None:
fig.savefig(out_png, dpi=150)
plt.close(fig)
return None
return _finalize_figure(fig, show=show)
[docs]
def metric_lines(
df: pd.DataFrame,
out_png: str | Path | None = None,
*,
x_col: str,
y_col: str,
hue_col: str | None = None,
title: str = "Metric",
show: bool = False,
) -> Figure | None:
"""Save or display a line plot of a metric from a tidy DataFrame.
Parameters
----------
df
Tidy table of metric values.
out_png
If set, write the figure to this path (PNG).
x_col
Column for the x-axis.
y_col
Column for the y-axis.
hue_col
Optional grouping column (separate lines).
title
Plot title.
show
If ``True``, display via ``plt.show()`` and return ``None``.
Returns
-------
The figure when ``show`` is false and ``out_png`` is not set; otherwise ``None``
after saving or displaying.
Examples
--------
.. exec-jupyter::
import pandas as pd
import campmc as cp
df = pd.DataFrame(
{"gamma": [25, 50, 25, 50], "method": ["camp2", "camp2", "camp3", "camp3"], "purity": [0.9, 0.85, 0.92, 0.88]}
)
cp.pl.metric_lines(
df,
x_col="gamma",
y_col="purity",
hue_col="method",
title="Purity vs gamma",
show=True,
)
"""
fig, ax = plt.subplots(figsize=(6, 4))
if hue_col:
sns.lineplot(data=df, x=x_col, y=y_col, hue=hue_col, ax=ax)
else:
sns.lineplot(data=df, x=x_col, y=y_col, ax=ax)
ax.set_title(title)
fig.tight_layout()
if out_png is not None:
fig.savefig(out_png, dpi=150)
plt.close(fig)
return None
return _finalize_figure(fig, show=show)