nispace.helpers.null_maps_from_nimare

nispace.helpers.null_maps_from_nimare(result, parcellation, corrected_result=None, voxel_thresh=0.001, outcome_map='stat', cluster_stat='size', alpha=0.05, n_perm=1000, map_label=None, observed_map=None, validate=True, seed=None, n_proc=1, dtype=<class 'numpy.float32'>, verbose=True)[source]

Generate parcellated null maps from a fitted NiMARE MetaResult.

Re-implements NiMARE’s MonteCarlo FWE coordinate-sampling loop: for each permutation, study coordinates are drawn uniformly at random from the brain mask, a full ALE map is computed, and the result is parcellated. This produces null maps under the same generative model NiMARE uses for its own FWE correction, making them the principled null for colocalization of meta-analytic maps.

Two modes are supported:

  • Continuous (default, corrected_result=None): each null map contains parcellated ALE stat values, matching an unthresholded result.get_map("stat") as Y.

  • Binary cluster (corrected_result provided): each null ALE map is converted to z-scores via the estimator’s null distribution, thresholded at the voxel-level CDT, and parcellated to a [0, 1] cluster-coverage map. The FWE cluster extent filter is not applied to null maps — applying it would make ~95% of them empty by construction (that is what FWE alpha=0.05 means). Null maps represent CDT-thresholded random ALE; the FWE correction is already reflected in the observed Y image from get_binary_cluster_map().

Parameters:
  • result (nimare.results.MetaResult) – Fitted MetaResult (e.g. from ALE().fit(dataset)). Must embed a CBMA estimator with inputs_["coordinates"] and kernel_transformer. IBMA estimators are not supported.

  • parcellation (str or Parcellation) – Parcellation to use. Either a NiSpace parcellation name (e.g. "Schaefer200") or a Parcellation object (e.g. nsp._parc from a fitted NiSpace instance). Must have at least one volumetric/MNI space — surface-only parcellations are not supported.

  • corrected_result (nimare.results.MetaResult or None, optional) – The corrected MetaResult returned by FWECorrector.transform(result). If provided, switches to binary cluster mode: the FWE cluster extent threshold is extracted from corrected_result.estimator.null_distributions_ via nimare_fwe_thresholds() and applied to each null ALE map. Only method="montecarlo" is supported. Default: None (continuous mode).

  • voxel_thresh (float, optional) – Uncorrected voxel-level p-value for the cluster-defining threshold (CDT) used when corrected_result is provided. Must match the threshold actually applied during FWE correction. NiMARE’s default (and the default here) is 0.001 (z ≈ 3.09). NiMARE’s FWECorrector silently ignores voxel_thresh passed to its constructor, so always specify it here explicitly if you used a non-default CDT. Ignored when corrected_result is None. Default: 0.001.

  • outcome_map (str, optional) – Key in result.maps used as the default map_label and for the continuous-mode sanity check. For ALE, available keys are "stat" (ALE values), "z", and "p". The permutation loop always starts from ALE stat values (_compute_summarystat) regardless of this setting. Default: "stat".

  • cluster_stat ({"size", "mass"}, optional) –

    Cluster-level statistic used for FWE correction. Only relevant when corrected_result is provided.

    • "size" (default): cluster extent in voxels. Each null cluster is removed if its voxel count is below the FWE threshold.

    • "mass" : cluster mass (sum of z-scores within the cluster). Each null cluster is removed if its mass is below the FWE threshold.

    Must match the statistic used to produce the observed Y image (i.e. the map_key passed to get_binary_cluster_map()).

  • alpha (float, optional) – FWE significance level passed to nimare_fwe_thresholds() when corrected_result is provided, to derive the cluster extent threshold. Default: 0.05.

  • n_perm (int, optional) – Number of null permutations. Default: 1000.

  • map_label (str or None, optional) – Key in the returned dict. Defaults to outcome_map. Must match the Y-map label in your NiSpace instance so that permute(maps_nulls=...) routes to the right null distribution.

  • observed_map (NIfTI image or array-like of shape (n_parcels,), optional) – Y map for a sanity check (Pearson r against the expected observed map, warned if < 0.99). Accepts either a NIfTI image in NiMARE’s native space (parcellated internally) or a pre-parcellated array. In continuous mode: compared against the parcellated result.get_map(outcome_map). In binary cluster mode: compared against the observed ALE z-map thresholded and cluster-filtered with the same parameters — i.e. the exact procedure applied to each null map. Pass the output of get_binary_cluster_map() here (image or parcellated array).

  • validate (bool, optional) –

    If True (default), log validation metrics after the permutation loop.

    • Cluster mode: compares the (1-alpha) percentile of the max-cluster-stat null distribution collected across permutations against the threshold from corrected_result.estimator.null_distributions_ (these should agree within sampling noise). If observed_map is provided, also re-derives the cluster map using our threshold and reports Pearson r against observed_map.

    • Continuous mode: computes empirical parcel-level p-values from the null array and correlates (Spearman) against NiMARE’s parametric voxelwise p-map parcellated with the same scheme.

  • seed (int or None, optional) – Random seed for reproducibility. Default: None.

  • n_proc (int, optional) – Number of parallel processes (joblib.Parallel n_jobs). Default: 1.

  • dtype (numpy dtype, optional) – Output array dtype. Default: np.float32.

  • verbose (bool, optional) – Show progress bar and log messages. Default: True.

Returns:

{map_label: ndarray(n_perm, n_parcels)}, directly passable as maps_nulls= to permute().

Return type:

dict

Notes

Binary cluster mode — value distributions and correlation method. After parcellation, each parcel in the binary cluster map receives the fraction of its voxels that fall inside the significant cluster (values in [0, 1], typically 0–0.4 for the observed map). Use method="pearson" in colocalize() — Pearson on a fractional cluster-coverage map is equivalent to point-biserial correlation and is more appropriate than Spearman, which degrades due to heavy ties at zero.

Binary null maps are thresholded at the voxel-level CDT only; the FWE cluster extent filter is not applied to null maps (applying it would make ~95% of them empty by construction — that is what FWE alpha=0.05 means). Null maps therefore have a lower value range (typically 0–0.05–0.1) than the observed map: random coordinates produce many small scattered clusters while real coordinates converge into one focused cluster. This contrast is the signal the permutation test exploits.

Relies on the private NiMARE methods _compute_summarystat and _summarystat_to_p (or _ale_to_p for older versions). Requires NiMARE >= 0.2.0; informative errors are raised for missing attributes.

NiMARE’s default brain mask is MNI152NLin6Asym at 2 mm. The MNI152NLin6Asym image for the parcellation is preferred to minimise resampling error. The parcellation is resampled to ALE space once before the permutation loop; each null map is parcellated with a direct array operation rather than a per-iteration neuromaps call.

Continuous workflow (unthresholded ALE stat map as Y):

import nimare
from nimare.meta.cbma import ALE
from nimare.tests.utils import get_test_data_path
from nispace import NiSpace, null_maps_from_nimare
from nispace.datasets import fetch_reference

dset = nimare.dataset.Dataset(get_test_data_path() + "/test_pain_dataset.json")
result = ALE().fit(dset)
ale_img = result.get_map("stat")

ref = fetch_reference("pet", maps="VAChT", parcellation="Schaefer200")
nsp = NiSpace(x=ref, y=ale_img, y_labels=["pain_ale"],
              parcellation="Schaefer200")
nsp.fit()
nsp.colocalize()

null_maps = null_maps_from_nimare(
    result, nsp._parc,
    map_label="pain_ale",
    observed_map=ale_img,
    n_perm=1000,
)
nsp.permute("maps", maps_which="Y", maps_nulls=null_maps, n_perm=1000)
p = nsp.get_p_values()

Binary cluster workflow (FWE cluster map binarized as Y):

from nimare.correct import FWECorrector
from nispace import get_binary_cluster_map

fwe = FWECorrector(method="montecarlo", n_iters=1000)
corrected = fwe.transform(result)    # null_distributions_ live here
binary_img = get_binary_cluster_map(corrected)

nsp = NiSpace(x=ref, y=binary_img, y_labels=["pain_cluster"],
              parcellation="Schaefer200")
nsp.fit()
nsp.colocalize()

null_maps = null_maps_from_nimare(
    result, nsp._parc,
    corrected_result=corrected,      # pass the corrected MetaResult
    voxel_thresh=0.001,
    map_label="pain_cluster",
    observed_map=binary_img,
    n_perm=1000,
)
nsp.permute("maps", maps_which="Y", maps_nulls=null_maps, n_perm=1000)
p = nsp.get_p_values()