physiotrace 0.1.0a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,67 @@
1
+ """PhysioTRACE: behavioral audit of provenance reliance in frozen-encoder task heads.
2
+
3
+ Recover how decodable provenance is, Stress fixed heads by reversing only the
4
+ provenance--target association, Intervene by removing a train-localized
5
+ provenance component, and Verify the remedy against matched random controls
6
+ within a declared utility margin.
7
+ """
8
+
9
+ from . import bootstrap, intervene, metrics, recover, stress, synthetic, weights
10
+ from .audit import PairedSplit, Split, audit_observational, audit_observational_crossfit, audit_paired
11
+ from .diagnostics import Finding, Gates, PhysioTraceWarning
12
+ from .intervene import Subspace, Whitening, conditional_direction, paired_subspace, random_subspaces
13
+ from .metrics import weighted_auroc
14
+ from .recover import LPIResult, fit_calibrated_probe, lpi
15
+ from .report import AuditReport
16
+ from .stress import excess_vulnerability, regime_aurocs
17
+ from .verify import Verdict
18
+ from .weights import (
19
+ cell_weights,
20
+ designed_coupling_table,
21
+ fixed_marginal_table,
22
+ independence_weights,
23
+ observational_regimes,
24
+ )
25
+
26
+ try:
27
+ from importlib.metadata import PackageNotFoundError, version as _version
28
+
29
+ __version__ = _version("physiotrace")
30
+ except PackageNotFoundError: # running from a source tree without installation
31
+ __version__ = "0+unknown"
32
+
33
+ __all__ = [
34
+ "AuditReport",
35
+ "Finding",
36
+ "Gates",
37
+ "PhysioTraceWarning",
38
+ "Split",
39
+ "audit_observational_crossfit",
40
+ "LPIResult",
41
+ "PairedSplit",
42
+ "Subspace",
43
+ "Verdict",
44
+ "Whitening",
45
+ "audit_observational",
46
+ "audit_paired",
47
+ "bootstrap",
48
+ "cell_weights",
49
+ "conditional_direction",
50
+ "designed_coupling_table",
51
+ "excess_vulnerability",
52
+ "fit_calibrated_probe",
53
+ "fixed_marginal_table",
54
+ "independence_weights",
55
+ "intervene",
56
+ "lpi",
57
+ "metrics",
58
+ "observational_regimes",
59
+ "paired_subspace",
60
+ "random_subspaces",
61
+ "recover",
62
+ "regime_aurocs",
63
+ "stress",
64
+ "synthetic",
65
+ "weighted_auroc",
66
+ "weights",
67
+ ]
@@ -0,0 +1,54 @@
1
+ """Small input checks shared across modules."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy as np
6
+
7
+
8
+ def as_matrix(values, *, name: str) -> np.ndarray:
9
+ array = np.asarray(values, dtype=np.float64)
10
+ if array.ndim != 2:
11
+ raise ValueError(f"{name} must be a two-dimensional array, got shape {array.shape}.")
12
+ if not np.isfinite(array).all():
13
+ raise ValueError(f"{name} contains non-finite values.")
14
+ return array
15
+
16
+
17
+ def as_codes(values, *, name: str, n_levels: int | None = None) -> np.ndarray:
18
+ """Return non-negative integer codes; values must already be encoded."""
19
+
20
+ array = np.asarray(values)
21
+ if array.ndim != 1:
22
+ raise ValueError(f"{name} must be one-dimensional.")
23
+ if not np.issubdtype(array.dtype, np.integer):
24
+ if not np.issubdtype(array.dtype, np.number) or not np.all(np.equal(array, np.floor(array))):
25
+ raise ValueError(f"{name} must contain integer codes.")
26
+ codes = array.astype(np.int64)
27
+ if np.any(codes < 0):
28
+ raise ValueError(f"{name} must contain non-negative codes.")
29
+ if n_levels is not None and np.any(codes >= n_levels):
30
+ raise ValueError(f"{name} contains a code outside [0, {n_levels}).")
31
+ return codes
32
+
33
+
34
+ def encode(values, levels=None) -> tuple[np.ndarray, tuple]:
35
+ """Encode arbitrary labels as integer codes in the order of ``levels``."""
36
+
37
+ array = np.asarray(values)
38
+ if levels is None:
39
+ levels = tuple(np.unique(array).tolist())
40
+ else:
41
+ levels = tuple(levels)
42
+ lookup = {level: code for code, level in enumerate(levels)}
43
+ try:
44
+ codes = np.fromiter((lookup[value] for value in array.tolist()), dtype=np.int64, count=len(array))
45
+ except KeyError as error:
46
+ raise ValueError(f"Value {error.args[0]!r} is not among the declared levels {levels}.") from None
47
+ return codes, levels
48
+
49
+
50
+ def same_length(**arrays) -> int:
51
+ lengths = {name: len(value) for name, value in arrays.items()}
52
+ if len(set(lengths.values())) != 1:
53
+ raise ValueError(f"Inputs must have the same length, got {lengths}.")
54
+ return next(iter(lengths.values()))