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]

Bases: str, Enum

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]

Bases: str, Enum

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|False knob; 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.BONFERRONI and StatMethod.BH_FDR are parametric baselines that do not use permutation testing. They compute p-values from the t-distribution and apply multiple comparison corrections. The n_permutations parameter 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 h to 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 returned InferenceResult carries the parameter axis (result.is_grid, result.e_grid, result.h_grid); use result.select(param_idx) or pass param_idx= to significant_edges / to_csv to project to a single cell.

  • h (float or sequence of float, default=3.0) – Height exponent for TFNBS-based methods. See e for 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; strata is 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:

dict

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:

dict

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:

dict

Raises:

ValueError – If fewer than 2 samples are provided.

conninfpy.pairwise_stats.get_available_cores()[source]