mrsiprep.mrsi.filtering
Biharmonic-style MRSI spike filtering.
Ports the exact two-stage repair algorithm from mrsitoolbox's
mrsitoolbox.filters.biharmonic.BiHarmonic.proc (median-filter spike
repair, then biharmonic inpainting of missing voxels, then masked
smoothing) so mrsiprep's spike-filtered output matches the legacy
pipeline without depending on mrsitoolbox at runtime.
Functions
|
Two-stage spike repair matching |
|
Default cap on a spike cluster's voxel count before it's treated as real focal signal rather than noise, auto-scaled to the MRSI acquisition's native voxel size. |
|
|
|
Voxels exceeding |
- mrsiprep.mrsi.filtering.biharmonic_repair(data, brain, spike_mask, header, affine, fwhm_mm=None)[source]
Two-stage spike repair matching
BiHarmonic.proc.Replace spikes with a local 3x3x3 median (excluding the center voxel).
Biharmonic-inpaint voxels that are still zero inside the brain mask.
Smooth with FWHM
fwhm_mm(or, when unset, the native MRSI voxel size), splicing the smoothed values back in only at repaired locations.
- Parameters:
data (ndarray)
brain (ndarray)
spike_mask (ndarray)
affine (ndarray)
fwhm_mm (float | None)
- Return type:
tuple[ndarray, ndarray]
- mrsiprep.mrsi.filtering.default_spike_max_cluster_voxels(voxel_mm)[source]
Default cap on a spike cluster's voxel count before it's treated as real focal signal rather than noise, auto-scaled to the MRSI acquisition's native voxel size.
A connected cluster of spike-thresholded voxels that's large and spatially coherent is more likely a real, focal signal feature (e.g. an actual metabolic abnormality) than sensor/reconstruction noise, which tends to hit isolated single voxels. Filtering (median-repair + biharmonic inpaint) should only apply to the small, isolated case.
Derived empirically from connected-component cluster-size distributions of
get_spike_mask()(defaultpercentile=99) computed across real acquisitions: 1075 3T metabolite maps (BioPsych-Project + Mindfulness-Project, ~5.0mm isotropic) and 445 7T metabolite maps (22q11-Project, ~3.4mm isotropic). The chosen cutoff is each field strength's 90th-percentile cluster size (3T: 6 voxels, 7T: 9 voxels) -- conservative enough to still repair the large majority (>=90%) of real noise clusters, while protecting genuinely large focal clusters from being smoothed away. Since voxel size is what's actually available at runtime (not a field-strength tag), this maps voxel volume to the nearer of the two measured field-strength regimes by proximity to their respective native voxel volumes (3T ~5.0mm, 7T ~3.4mm isotropic), rather than hardcoding a scanner-specific lookup.- Parameters:
voxel_mm (tuple[float, float, float])
- Return type:
int
- mrsiprep.mrsi.filtering.filter_metabolite_maps(config, subject, session, metabolite_maps, brainmask)[source]
- Parameters:
subject (str)
session (str | None)
metabolite_maps (dict[str, Path])
brainmask (Path)
- Return type:
dict[str, Path]
- mrsiprep.mrsi.filtering.get_spike_mask(data, percentile=99.0, max_cluster_voxels=None)[source]
Voxels exceeding
percentileof positive signal, restricted to connected clusters no larger thanmax_cluster_voxels(26-connectivity).max_cluster_voxels=Nonedisables cluster-size filtering, matching the original flat per-voxel threshold behavior (every above-threshold voxel is treated as a spike, regardless of how large its connected cluster is).- Parameters:
data (ndarray)
percentile (float)
max_cluster_voxels (int | None)
- Return type:
ndarray