| name | neuroimaging |
| description | Medical neuroimaging patterns for NIfTI, DICOM, SimpleITK, and nibabel. Use when working with brain imaging data, registration, coordinate transforms, or volume I/O. |
| user-invocable | false |
Neuroimaging Development Patterns
Use this skill for medical and neuroscience image processing tasks involving volumes, registration, affines, orientation, resampling, or multimodal anatomical pipelines.
Priority Libraries and Specs
nibabel for NIfTI I/O, affines, and orientation.
SimpleITK for registration, transforms, resampling, and DICOM series.
- BIDS / BIDS-iEEG for dataset naming and metadata conventions.
numpy, scipy.ndimage, and matplotlib for numerical operations and QC figures.
NIfTI I/O with nibabel
Loading
import nibabel as nib
import numpy as np
img = nib.load(path)
data = img.get_fdata()
data = img.get_fdata(dtype=np.float32)
affine = img.affine
voxel_sizes = img.header.get_zooms()
Saving
new_img = nib.Nifti1Image(data_array, affine)
nib.save(new_img, output_path)
new_img = nib.Nifti1Image(data_array, affine, header=img.header)
Coordinate Transforms
from nibabel.affines import apply_affine
world = apply_affine(affine, voxel_coords)
voxel = apply_affine(np.linalg.inv(affine), world_coords)
world_batch = apply_affine(affine, voxel_batch)
Orientation
axcodes = nib.aff2axcodes(affine)
canonical = nib.as_closest_canonical(img)
ornt = nib.io_orientation(affine)
SimpleITK Registration
Image I/O
import SimpleITK as sitk
image = sitk.ReadImage(str(path))
sitk.WriteImage(image, str(output_path))
reader = sitk.ImageSeriesReader()
files = reader.GetGDCMSeriesFileNames(str(dicom_dir))
reader.SetFileNames(files)
image = reader.Execute()
array = sitk.GetArrayFromImage(image)
image = sitk.GetImageFromArray(array)
image.CopyInformation(reference)
Rigid Registration (CT→MRI)
initial = sitk.CenteredTransformInitializer(
fixed, moving, sitk.Euler3DTransform(),
sitk.CenteredTransformInitializerFilter.GEOMETRY,
)
reg = sitk.ImageRegistrationMethod()
reg.SetMetricAsMattesMutualInformation(numberOfHistogramBins=50)
reg.SetMetricSamplingStrategy(reg.RANDOM)
reg.SetMetricSamplingPercentage(0.25)
reg.SetInterpolator(sitk.sitkLinear)
reg.SetOptimizerAsGradientDescentLineSearch(
learningRate=1.0, numberOfIterations=200,
convergenceMinimumValue=1e-6, convergenceWindowSize=10,
)
reg.SetShrinkFactorsPerLevel([4, 2, 1])
reg.SetSmoothingSigmasPerLevel([2.0, 1.0, 0.0])
reg.SmoothingSigmasAreSpecifiedInPhysicalUnitsOn()
reg.SetInitialTransform(initial, inPlace=False)
transform = reg.Execute(fixed, moving)
Resampling
resampled = sitk.Resample(
moving, fixed, transform,
sitk.sitkLinear, 0.0, moving.GetPixelID(),
)
Transform I/O and Composition
sitk.WriteTransform(transform, str(path))
transform = sitk.ReadTransform(str(path))
composite = sitk.CompositeTransform(3)
composite.AddTransform(ct_to_t1w)
composite.AddTransform(t1w_to_mni)
composite.FlattenTransform()
Critical Conventions
Axis Order — THE #1 BUG SOURCE
| Library | Array Axes | World Convention |
|---|
| nibabel | (i, j, k) per NIfTI header | RAS+ |
| SimpleITK | (z, y, x) — REVERSED | LPS+ |
When crossing libraries: transpose arrays AND negate X,Y coordinates.
Converting SimpleITK → nibabel affine
direction = np.array(image.GetDirection()).reshape(3, 3)
spacing = np.diag(image.GetSpacing())
origin = np.array(image.GetOrigin())
affine = np.eye(4)
affine[:3, :3] = direction @ spacing
affine[:3, 3] = origin
Memory Management
- NIfTI volumes: 256^3 float64 = ~134MB — use float32 when possible
- nibabel loads lazily —
.get_fdata() materializes
- SimpleITK also lazy —
.Execute() triggers computation
- Always close matplotlib figures:
plt.close(fig)
DICOM Series Selection
series_ids = sitk.ImageSeriesReader.GetGDCMSeriesIDs(str(dicom_dir))
for sid in series_ids:
files = sitk.ImageSeriesReader.GetGDCMSeriesFileNames(str(dicom_dir), sid)
reader = sitk.ImageFileReader()
reader.SetFileName(files[0])
reader.ReadImageInformation()
modality = reader.GetMetaData("0008|0060")
desc = reader.GetMetaData("0008|103e")
For post-implant CT: prefer thin-slice (<=1mm) axial, avoid scout/localizer (few slices).
BIDS-iEEG Electrode Format
name x y z size type
LA1 -35.2 -12.1 8.4 1.5 SEEG
Tab-separated. Coordinates in T1w or MNI space (specified in sidecar JSON). Size = contact diameter mm.
When Reporting or Editing
Always state image space or orientation, voxel size or spacing, transform direction, interpolation type, and whether coordinates are voxel, scanner, subject, T1w, or MNI.
For web lookups, prefer official docs first: SimpleITK, nibabel, BIDS spec, NeuroStars, then broader web search.