conninfpy.pairwise_stats
Pairwise statistical testing module for network analysis.
This module provides functions for computing t-statistics and p-values
using permutation testing, with optional enhancement (TFNBS, NBS, cNBS,
NI-TFNBS, FBC-TFNBS) applied via shared apply_* wrappers from
conninfpy._enhancement.
Main Functions
compute_p_val : Compute p-values using permutation testing (with enhancement) compute_t_stat : Compute t-statistics for paired, one-sample, or two-sample tests compute_null_dist : Compute null distribution via permutation testing
- class conninfpy.pairwise_stats.TestType(value)[source]
-
Statistical test types for permutation testing.
- PAIRED = 'paired'
Paired samples t-test (within-subjects design).
- ONE_SAMPLE = 'one-sample'
One-sample t-test against zero.
- TWO_SAMPLE = 'two-sample'
Independent samples t-test (between-subjects design).
- class conninfpy.pairwise_stats.StatMethod(value)[source]
-
Statistical method for network analysis.
- TFNBS = 'tfnbs'
Threshold-Free Network-Based Statistics (TFCE-style).
- TSTAT = 'tstat'
Raw t-statistics without enhancement.
- NBS = 'nbs'
Classical Network-Based Statistics with fixed threshold.
- CNBS = 'cnbs'
Constrained NBS with predefined network partitions.
- NI_TFNBS = 'ni_tfnbs'
Network-Informed TFNBS with functional block density weighting.
- FBC_TFNBS = 'fbc_tfnbs'
Functional Block Clustering TFNBS (block-defined clustering).
- BONFERRONI = 'bonferroni'
Parametric Bonferroni correction (no permutation testing).
- BH_FDR = 'bh_fdr'
Parametric Benjamini-Hochberg FDR correction (no permutation testing).
- BH_FDR_PERM = 'bh_fdr_perm'
Permutation-based BH-FDR correction (per-edge permutation p-values).
- conninfpy.pairwise_stats.compute_p_val(group1: ndarray[tuple[Any, ...], dtype[float64]], group2: ndarray[tuple[Any, ...], dtype[float64]] | None = None, n_permutations: int = 1000, test_type: str | TestType = TestType.PAIRED, method: str | StatMethod = StatMethod.TFNBS, use_mp: bool = True, rng: None | int | Generator | RandomState = None, random_state: int | None = None, n_processes: int | None = None, acceleration: str | None = None, verbose: bool = False, net_labels: ndarray[tuple[Any, ...], dtype[int64]] | None = None, threshold: float = 2.0, nbs_stat: str = 'extent', e: float | List[float] = 0.3, h: float | List[float] = 3.0, n: int = 10, start_thres: float = 1.65, min_cluster_size: int = 3, normalization: str = 'sqrt', strata: ndarray[tuple[Any, ...], dtype[Any]] | None = None, **kwargs) InferenceResult[source]
Compute p-values using permutation testing with various network-based methods.
Warning
Welch + group-label permutation under unequal variances
The two-sample path uses Welch’s t (unequal-variance) unconditionally. Under unequal variances with unbalanced group sizes the exchangeability assumption underlying permutation breaks and Type I error inflates (Anderson & Robinson 2001; Hayes 2000). A pooled-variance option will be added in v2.2 with an explicit
var_equal=True|Falseknob; until then, treat two-sample results with caution when both group sizes and variances differ substantially.Supports multiple statistical methods: tfnbs, tstat, nbs, cnbs, ni_tfnbs, fbc_tfnbs, bonferroni, bh_fdr, bh_fdr_perm.
Note
cNBS null distribution
This implementation uses the max-statistic null distribution for cNBS, where each permutation contributes its global maximum cNBS score to the null. This is the same family-wise error rate (FWER) control strategy used by classical NBS (Zalesky et al. 2010) and TFNBS.
Noble & Scheinost (2020) originally proposed computing per-block null distributions with Bonferroni correction across blocks. The max-statistic approach used here is more conservative (controls FWER globally) but provides a consistent framework across all methods in this package.
Note
Bonferroni and BH-FDR methods
StatMethod.BONFERRONIandStatMethod.BH_FDRare parametric baselines that do not use permutation testing. They compute p-values from the t-distribution and apply multiple comparison corrections. Then_permutationsparameter is ignored for these methods. In the two-sample path, the parametric baseline uses edge-wise Welch-Satterthwaite degrees of freedom to match the Welch statistic.Note
Permutation p-values
Empirical max-statistic p-values count ties conservatively (
null >= observed) and use the Phipson-Smyth +1 correction:p = (count + 1) / (B + 1).- Parameters:
group1 (ndarray of shape (n_subjects_g1, N, N)) – Input connectivity matrices for group 1.
group2 (ndarray of shape (n_subjects_g2, N, N), optional) – Input connectivity matrices for group 2. Required for paired/two-sample tests.
n_permutations (int, default=1000) – Number of permutations for null distribution.
test_type ({'paired', 'one-sample', 'two-sample'} or TestType, default='paired') – Type of statistical test.
method ({'tfnbs', 'tstat', 'nbs', 'cnbs', 'ni_tfnbs', 'fbc_tfnbs'} or StatMethod, default='tfnbs') – Statistical method to use for scoring.
use_mp (bool, default=True) – Use multiprocessing for permutation testing. Automatically disabled when called from inside a multiprocessing worker to prevent deadlocks.
random_state (int, optional) – Random seed for reproducibility.
n_processes (int, optional) – Number of CPU cores for parallel computing.
net_labels (ndarray of shape (N,), optional) – Network labels for each node. Required for cnbs, ni_tfnbs, and fbc_tfnbs.
threshold (float, default=2.0) – T-statistic threshold for NBS (only used when method=’nbs’).
nbs_stat ({'extent', 'intensity'}, default='extent') – Cluster statistic for NBS (only used when method=’nbs’).
e (float or sequence of float, default=0.3) – Extent exponent for TFNBS-based methods. Pass an equal-length sequence with
hto evaluate a whole(E, H)grid in one permutation pass — TFNBS’s threshold integration runs once and broadcasts the per-cell exponentiation, so a K-cell grid costs ~the same wall-clock as a single cell. In grid mode the returnedInferenceResultcarries the parameter axis (result.is_grid,result.e_grid,result.h_grid); useresult.select(param_idx)or passparam_idx=tosignificant_edges/to_csvto project to a single cell.h (float or sequence of float, default=3.0) – Height exponent for TFNBS-based methods. See
efor grid mode.n (int, default=10) – Number of threshold steps for TFNBS-based methods.
start_thres (float, default=1.65) – Starting threshold for TFNBS integration.
min_cluster_size (int, default=3) – Minimum cluster size for FBC-TFNBS (only used when method=’fbc_tfnbs’).
normalization ({'sqrt', 'linear', 'none'}, default='sqrt') – Block density normalization for NI-TFNBS (only used when method=’ni_tfnbs’).
strata (array-like of shape (n,), optional) – Exchangeability-block labels per subject (e.g. site IDs after ComBat harmonization). When provided, the two-sample group-label permutation is restricted to within-stratum swaps, holding per-stratum group totals fixed. This prevents the shadow-of-H₀ leak that occurs when ComBat is fit on observed labels but downstream permutation reshuffles across sites. Paired / one-sample sign-flip paths are stratum-invariant by construction;
stratais silently accepted but has no effect there.**kwargs – Additional keyword arguments (for future extensions).
- Returns:
Dict-like result with p-value arrays:
’negative’: P-values for group 1 > group 2.
’positive’: P-values for group 2 > group 1.
- Return type:
InferenceResult
- Raises:
ValueError – If constrained methods (cnbs, ni_tfnbs, fbc_tfnbs) are used without net_labels.
Examples
>>> import numpy as np >>> np.random.seed(2) >>> group1 = np.random.rand(5, 3, 3) >>> for arr in group1: np.fill_diagonal(arr, 0) >>> group2 = np.random.rand(8, 3, 3) >>> for arr in group2: np.fill_diagonal(arr, 0) >>> # Standard t-test >>> p_vals = compute_p_val(group1, group2, n_permutations=10, ... test_type='two-sample', method='tstat', ... use_mp=False, random_state=0) >>> # TFNBS >>> p_vals = compute_p_val(group1, group2, n_permutations=10, ... test_type='two-sample', method='tfnbs', ... use_mp=False, random_state=0) >>> # cNBS with network labels >>> labels = np.array([0, 0, 1]) >>> p_vals = compute_p_val(group1, group2, n_permutations=10, ... test_type='two-sample', method='cnbs', ... net_labels=labels, use_mp=False, random_state=0)
- conninfpy.pairwise_stats.compute_t_stat(group1: ndarray[tuple[Any, ...], dtype[float64]], group2: ndarray[tuple[Any, ...], dtype[float64]] | None = None, test_type: str | TestType = TestType.PAIRED) Dict[str, ndarray[tuple[Any, ...], dtype[float64]]][source]
Compute t-statistics for paired, one-sample, or two-sample tests.
- Parameters:
group1 (ndarray of shape (n_samples_1, N, N)) – Data array for group 1.
group2 (ndarray of shape (n_samples_2, N, N), optional) – Data array for group 2. Required for paired/two-sample tests.
test_type ({'paired', 'one-sample', 'two-sample'} or TestType) – Type of statistical test.
- Returns:
Dictionary with ‘positive’ and ‘negative’ t-statistic arrays.
- Return type:
- Raises:
ValueError – If test_type is invalid or dimensions don’t match.
- conninfpy.pairwise_stats.compute_null_dist(group1: ndarray[tuple[Any, ...], dtype[float64]], group2: ndarray[tuple[Any, ...], dtype[float64]] | None = None, func: Callable[[...], Any] | None = None, n_permutations: int = 1000, test_type: str | TestType = TestType.PAIRED, random_state: int | None = None, n_processes: int | None = None, use_mp: bool = True, verbose: bool = False, strata: ndarray[tuple[Any, ...], dtype[Any]] | None = None, **func_kwargs) Dict[str, ndarray[tuple[Any, ...], dtype[float64]]][source]
Compute null distribution of maximum t-statistics via permutation testing.
Optimized implementation with:
Fixed indexing bug in sequential mode
Efficient result collection
Context-aware multiprocessing (auto-disables inside worker processes)
- Parameters:
group1 (ndarray of shape
(n_samples_1, *dims)) – Data array for group 1.group2 (ndarray of shape
(n_samples_2, *dims), optional) – Data array for group 2. Required for ‘paired’ and ‘two-sample’ tests.func (callable, optional) – Function to compute the t-statistic.
n_permutations (int, default=1000) – Number of permutations.
test_type ({'paired', 'one-sample', 'two-sample'} or TestType) – Type of statistical test.
random_state (int, optional) – Seed for reproducibility.
n_processes (int, optional) – Number of parallel processes. Defaults to CPU count.
use_mp (bool, default=True) – Whether to use multiprocessing. Automatically disabled when called from inside a multiprocessing worker to prevent nested pools.
**func_kwargs – Additional keyword arguments passed to func.
- Returns:
Dictionary with ‘negative’ and ‘positive’ arrays of shape (n_permutations,) or (n_permutations, n_params) for multi-parameter TFCE.
- Return type:
- Raises:
ValueError – If test_type is invalid or required group2 is missing.
- conninfpy.pairwise_stats.compute_t_stat_diff(diff: ndarray[tuple[Any, ...], dtype[float64]]) Dict[str, ndarray[tuple[Any, ...], dtype[float64]]][source]
Compute t-statistics for paired differences.
- Parameters:
diff (ndarray of shape
(n_samples, *dims)) – Array containing paired differences.- Returns:
Dictionary with:
’positive’: Positive t-values (where group 2 > group 1).
’negative’: Negative t-values converted to positive.
- Return type:
- Raises:
ValueError – If fewer than 2 samples are provided.