Skip to content

permutation

tit.stats.permutation

Cluster-based permutation testing for TI-Toolbox.

Entry points

run_group_comparison(config) -- GroupComparisonResult run_correlation(config) -- CorrelationResult

Both accept an optional callback_handler (logging.Handler) for GUI console integration and a stop_callback callable for user-initiated cancellation.

run_group_comparison

run_group_comparison(config: GroupComparisonConfig, callback_handler: Handler | None = None, stop_callback: Callable[[], bool] | None = None) -> GroupComparisonResult

Run cluster-based permutation testing for a two-group comparison.

Loads responder and non-responder field maps, performs voxelwise (or, for config.space == "fsaverage", vertexwise) t-tests, applies cluster-based permutation correction, generates diagnostic plots, and saves all outputs under <project>/derivatives/ti-toolbox/stats/group_comparison/<analysis_name>/.

Parameters

config : GroupComparisonConfig Fully specified group comparison configuration. callback_handler : logging.Handler or None, optional Extra handler attached to the run-scoped logger (used by the app to stream log lines). stop_callback : callable or None, optional Zero-argument callable returning True to request early termination. Checked between pipeline stages.

Returns

GroupComparisonResult Summary of the outcome: output directory, subject counts, significant voxel/cluster counts, the permutation-derived cluster threshold and the per-cluster details.

Raises

KeyboardInterrupt If stop_callback returns True during execution. ValueError If the subjects' NIfTIs do not share one grid (the message names the offending subject). FileNotFoundError If a subject's MNI-space NIfTI (per config.nifti_file_pattern) or fsaverage projection is missing.

Notes

Permutation p-values are (b + 1) / (m + 1), so with 1000 permutations the floor is 1/1001; a result is never exactly 0.

Examples

from tit.stats import GroupComparisonConfig, run_group_comparison subjects = GroupComparisonConfig.load_subjects("subjects.csv") # doctest: +SKIP cfg = GroupComparisonConfig( ... analysis_name="active_vs_sham", subjects=subjects, ... test_type="unpaired", n_permutations=1000, tissue_type="grey", ... ) # doctest: +SKIP res = run_group_comparison(cfg) # doctest: +SKIP res.success, res.n_significant_clusters, res.output_dir # doctest: +SKIP (True, 2, '.../derivatives/ti-toolbox/stats/group_comparison/active_vs_sham')

See Also

GroupComparisonConfig : The configuration consumed here. GroupComparisonResult : The returned container. run_correlation : Brain-behaviour correlation with the same correction.

Source code in tit/stats/permutation.py
def run_group_comparison(
    config: GroupComparisonConfig,
    callback_handler: logging.Handler | None = None,
    stop_callback: Callable[[], bool] | None = None,
) -> GroupComparisonResult:
    """Run cluster-based permutation testing for a two-group comparison.

    Loads responder and non-responder field maps, performs voxelwise (or,
    for ``config.space == "fsaverage"``, vertexwise) t-tests, applies
    cluster-based permutation correction, generates diagnostic plots, and
    saves all outputs under
    ``<project>/derivatives/ti-toolbox/stats/group_comparison/<analysis_name>/``.

    Parameters
    ----------
    config : GroupComparisonConfig
        Fully specified group comparison configuration.
    callback_handler : logging.Handler or None, optional
        Extra handler attached to the run-scoped logger (used by the app
        to stream log lines).
    stop_callback : callable or None, optional
        Zero-argument callable returning ``True`` to request early
        termination.  Checked between pipeline stages.

    Returns
    -------
    GroupComparisonResult
        Summary of the outcome: output directory, subject counts,
        significant voxel/cluster counts, the permutation-derived cluster
        threshold and the per-cluster details.

    Raises
    ------
    KeyboardInterrupt
        If *stop_callback* returns ``True`` during execution.
    ValueError
        If the subjects' NIfTIs do not share one grid (the message names
        the offending subject).
    FileNotFoundError
        If a subject's MNI-space NIfTI (per ``config.nifti_file_pattern``)
        or fsaverage projection is missing.

    Notes
    -----
    Permutation p-values are ``(b + 1) / (m + 1)``, so with 1000
    permutations the floor is ``1/1001``; a result is never exactly 0.

    Examples
    --------
    >>> from tit.stats import GroupComparisonConfig, run_group_comparison
    >>> subjects = GroupComparisonConfig.load_subjects("subjects.csv")  # doctest: +SKIP
    >>> cfg = GroupComparisonConfig(
    ...     analysis_name="active_vs_sham", subjects=subjects,
    ...     test_type="unpaired", n_permutations=1000, tissue_type="grey",
    ... )  # doctest: +SKIP
    >>> res = run_group_comparison(cfg)  # doctest: +SKIP
    >>> res.success, res.n_significant_clusters, res.output_dir  # doctest: +SKIP
    (True, 2, '.../derivatives/ti-toolbox/stats/group_comparison/active_vs_sham')

    See Also
    --------
    GroupComparisonConfig : The configuration consumed here.
    GroupComparisonResult : The returned container.
    run_correlation : Brain-behaviour correlation with the same correction.
    """
    from tit.telemetry import track_operation
    from tit import constants as _const

    with track_operation(_const.TELEMETRY_OP_STATS):
        try:
            if config.space == GroupComparisonConfig.AnalysisSpace.FSAVERAGE:
                from tit.stats.surface import run_surface_group_comparison

                return run_surface_group_comparison(
                    config, callback_handler, stop_callback
                )
            return _run_group_comparison_inner(config, callback_handler, stop_callback)
        except KeyboardInterrupt:
            raise
        except Exception as exc:
            _log_failure("group_comparison", exc)
            raise

run_correlation

run_correlation(config: CorrelationConfig, callback_handler: Handler | None = None, stop_callback: Callable[[], bool] | None = None) -> CorrelationResult

Run cluster-based permutation testing for a brain-behaviour correlation.

Correlates each voxel's field value with a continuous per-subject measure (Subject.effect_size), Pearson or Spearman, with cluster-based permutation correction (ACES-style). Outputs go under <project>/derivatives/ti-toolbox/stats/correlation/<analysis_name>/.

Parameters

config : CorrelationConfig Fully specified correlation configuration. callback_handler : logging.Handler or None, optional Extra handler attached to the run-scoped logger. stop_callback : callable or None, optional Zero-argument callable returning True to request early termination.

Returns

CorrelationResult Output directory, subject count, significant voxel/cluster counts, cluster threshold and per-cluster details.

Raises

KeyboardInterrupt If stop_callback returns True during execution. FileNotFoundError If a subject's NIfTI is missing.

Examples

from tit.stats import CorrelationConfig, run_correlation subjects = CorrelationConfig.load_subjects("subjects_continuous.csv") # doctest: +SKIP cfg = CorrelationConfig(analysis_name="dose_response", subjects=subjects, ... correlation_type="spearman") # doctest: +SKIP run_correlation(cfg).n_significant_clusters # doctest: +SKIP 1

See Also

CorrelationConfig : The configuration consumed here. run_group_comparison : Two-group comparison with the same correction.

Source code in tit/stats/permutation.py
def run_correlation(
    config: CorrelationConfig,
    callback_handler: logging.Handler | None = None,
    stop_callback: Callable[[], bool] | None = None,
) -> CorrelationResult:
    """Run cluster-based permutation testing for a brain-behaviour correlation.

    Correlates each voxel's field value with a continuous per-subject
    measure (``Subject.effect_size``), Pearson or Spearman, with
    cluster-based permutation correction (ACES-style).  Outputs go under
    ``<project>/derivatives/ti-toolbox/stats/correlation/<analysis_name>/``.

    Parameters
    ----------
    config : CorrelationConfig
        Fully specified correlation configuration.
    callback_handler : logging.Handler or None, optional
        Extra handler attached to the run-scoped logger.
    stop_callback : callable or None, optional
        Zero-argument callable returning ``True`` to request early
        termination.

    Returns
    -------
    CorrelationResult
        Output directory, subject count, significant voxel/cluster counts,
        cluster threshold and per-cluster details.

    Raises
    ------
    KeyboardInterrupt
        If *stop_callback* returns ``True`` during execution.
    FileNotFoundError
        If a subject's NIfTI is missing.

    Examples
    --------
    >>> from tit.stats import CorrelationConfig, run_correlation
    >>> subjects = CorrelationConfig.load_subjects("subjects_continuous.csv")  # doctest: +SKIP
    >>> cfg = CorrelationConfig(analysis_name="dose_response", subjects=subjects,
    ...                         correlation_type="spearman")  # doctest: +SKIP
    >>> run_correlation(cfg).n_significant_clusters  # doctest: +SKIP
    1

    See Also
    --------
    CorrelationConfig : The configuration consumed here.
    run_group_comparison : Two-group comparison with the same correction.
    """
    try:
        return _run_correlation_inner(config, callback_handler, stop_callback)
    except KeyboardInterrupt:
        raise
    except Exception as exc:
        _log_failure("correlation", exc)
        raise