Rhaister / tests /test_evaluate.py
Shreshth Gandhi
Import Rhaister main branch from GitHub source
5a72781
Raw
History Blame Contribute Delete
4.3 kB
"""Tests for evaluation orchestration in prepare_combined.py."""
import numpy as np
import pytest
from rhaister.prepare_combined import evaluate, make_evaluator
# ---------------------------------------------------------------------------
# evaluate()
# ---------------------------------------------------------------------------
class TestEvaluate:
def test_all_metric_keys_present(self):
"""evaluate() with all inputs should return all expected metric keys."""
rng = np.random.default_rng(42)
n, g = 20, 50
Y = rng.normal(size=(n, g))
P = rng.uniform(0, 1, size=(n, g))
D = rng.normal(size=(n, g))
F = rng.uniform(0, 1, size=(n, g))
cells = np.array([f"C{i}" for i in range(n)])
treats = np.array([f"T{i}" for i in range(n)])
genes = [f"gene_{j}" for j in range(g)]
result = evaluate(
Y_true=Y,
Y_pred=Y,
P_true=P,
P_pred=P,
D_true=D,
D_pred=D,
F_true=F,
F_pred=F,
test_cells=cells,
test_treatments=treats,
gene_cols=genes,
)
assert "pdex_static/pearson_delta_mean" in result
assert "n_samples" in result
assert result["n_samples"] == n
assert "state/pearson_delta_mean" in result
assert "state/pr_auc_mean" in result
assert "state/de_overlap_mean" in result
assert "state/de_spearman_sig" in result
assert "state/spearman_lfc_sig_mean" in result
def test_perfect_fc_pearson(self):
"""When Y_pred == Y_true, legacy FC pearson should be ~1.0."""
rng = np.random.default_rng(42)
n, g = 15, 40
Y = rng.normal(size=(n, g))
result = evaluate(Y_true=Y, Y_pred=Y)
assert result["pdex_static/pearson_delta_mean"] > 0.999
def test_fc_only(self):
"""evaluate() with only FC arrays (no p-values, no deltas) should still work."""
rng = np.random.default_rng(42)
Y = rng.normal(size=(10, 30))
result = evaluate(Y_true=Y, Y_pred=Y)
assert "pdex_static/pearson_delta_mean" in result
assert "state/pr_auc_mean" not in result # no p-values provided
def test_pvalue_auprc(self):
"""When P_pred == P_true, AUPRC should be high."""
rng = np.random.default_rng(42)
n, g = 20, 100
Y = rng.normal(size=(n, g))
P = rng.uniform(0, 1, size=(n, g))
result = evaluate(Y_true=Y, Y_pred=Y, P_true=P, P_pred=P)
assert "pdex_static/auprc_p05" in result
assert result["pdex_static/auprc_p05"] > 0.9
# ---------------------------------------------------------------------------
# make_evaluator() — one-shot semantics
# ---------------------------------------------------------------------------
class TestMakeEvaluator:
def test_first_call_succeeds(self):
rng = np.random.default_rng(42)
n, g = 10, 20
Y_test = rng.normal(size=(n, g))
P_test = rng.uniform(0, 1, size=(n, g))
D_test = rng.normal(size=(n, g))
F_test = rng.uniform(0, 1, size=(n, g))
cells = np.array([f"C{i}" for i in range(n)])
treats = np.array([f"T{i}" for i in range(n)])
genes = [f"gene_{j}" for j in range(g)]
eval_fn = make_evaluator(Y_test, P_test, D_test, F_test, cells, treats, genes)
Y_pred = rng.normal(size=(n, g))
result = eval_fn(Y_pred)
assert isinstance(result, dict)
assert "pdex_static/pearson_delta_mean" in result
def test_second_call_raises(self):
rng = np.random.default_rng(42)
n, g = 10, 20
Y_test = rng.normal(size=(n, g))
P_test = rng.uniform(0, 1, size=(n, g))
D_test = rng.normal(size=(n, g))
F_test = rng.uniform(0, 1, size=(n, g))
cells = np.array([f"C{i}" for i in range(n)])
treats = np.array([f"T{i}" for i in range(n)])
genes = [f"gene_{j}" for j in range(g)]
eval_fn = make_evaluator(Y_test, P_test, D_test, F_test, cells, treats, genes)
Y_pred = rng.normal(size=(n, g))
eval_fn(Y_pred) # first call
with pytest.raises(RuntimeError, match="already called"):
eval_fn(Y_pred) # second call should fail