Skip to content

Instantly share code, notes, and snippets.

@benkay86
Created March 14, 2024 02:31
Show Gist options
  • Save benkay86/98adad49994445611531acad619b9889 to your computer and use it in GitHub Desktop.
Save benkay86/98adad49994445611531acad619b9889 to your computer and use it in GitHub Desktop.
convert a cifti dense label (dlabel) file to a different volume space

Volume Space Conversion

The Problem

A collaborator shares some fMRI data with you in a file called other.dtseries.nii. You try to parcellate the data and get this error:

wb_command -cifti-parcellate \
  other.dtseries.nii \
  parcellation.dlabel.nii \
  COLUMN \
  output.ptseries.nii
ERROR: input cifti files must have the same volume space

A closer look at the input files reveals the problem.

wb_command -file-information other.dtseries.nii
...
Type:                           CIFTI - Dense Data Series
Maps to Surface:                true
Maps to Volume:                 true
Number of Rows:                 91206
CIFTI Dim[1]:                   91206
...

The input dense timeseries contains volume data with 91206 elements.

wb_command -file-information parcellation.dlabel.nii
...
Type:                           CIFTI - Dense Label
Maps to Surface:                true
Maps to Volume:                 true
Maps with LabelTable:           true
Number of Rows:                 91282
CIFTI Dim[1]:                   91282
...

The label file contains a volume map with 91282 elements. The number of volume (subcortical) elements is not equal. To apply your parcellation to data in the other volume space, you must resample your dense label file.

Note: Sometimes you may get this error even if the number of volume elements is the same. If so, the qform and sform of the volume data may not match. This procedure will fix qform and sform mismatches too.

Resampling the Easy Way

Note: This procedure assumes both volume spaces are in the same stereotactic space (e.g. MNI space) and differ only in the number of volume elements.

Connectome Workbench has a built-in command for resampling a cifti file from one volume space to another, -cifti-resample. The following resamples your parcellation to the other space using other.dtseries.nii as a template.

wb_command -cifti-resample \
  parcellation.dlabel.nii COLUMN \
  other.dtseries.nii COLUMN \
  BARYCENTRIC ENCLOSING_VOXEL \
  parcellation_other.dlabel.nii

You can then apply the new parcellation with:

wb_command -cifti-parcellate \
  other.dtseries.nii \
  parcellation_other.dlabel.nii \
  COLUMN \
  other.ptseries.nii

Hint: If you don't have a label file then you can generate one using a dense timeseries and a parcellated timeseries in your volume space as templates.

wb_command -cifti-parcel-mapping-to-label \
 template.ptseries.nii COLUMN \
 template.dtseries.nii \
 parcellation.dlabel.nii

Resampling the Hard Way

There is no particular reason not to use -cifti-resample, but if you need more fine-tuned control over the process, or you are curious about how Connectome Workbench works, read on.

Step 1: Separate Your Label File

We begin by assuming you have a label file parcellation.dlabel.nii containing a combined cortical (surface) and subcortical parcellation in your volume space. We need to separate this into different files for the cortical (surface) and subcortical (volume) parcellations so that we can resample the volume data.

First, extract the volume (subcortical) parcellation. The file volume_labels.nii will contain the structure labels (e.g. THALAMUS_LEFT, etc) whereas the file volume_parcels.nii will contain the parcellation. If you open up volume_parcels.nii in a nifti image viewer you will see all the voxels with value 1 correspond to the first parcel, all the voxels with value 2 correspond to the second parcel, etc. The cifti header of volume_parcels.nii contains a mapping from parcel number to parcel name.

wb_command -cifti-separate \
  parcellation.dlabel.nii COLUMN \
  -volume-all volume_parcels.nii \
  -label volume_labels.nii

Then extract the cortical surfaces. Typically you will just have CORTEX_LEFT and CORTEX_RIGHT to extract. You can use wb_command -file-information to check if your label file contains other surfaces.

wb_command -cifti-separate \
  parcellation.dlabel.nii COLUMN \
  -label CORTEX_LEFT cortex_left.label.gii
wb_command -cifti-separate \
  parcellation.dlabel.nii COLUMN \
  -label CORTEX_RIGHT cortex_right.label.gii

Finally, we are going to need the label table. This contains the mappings from parcel number to parcel name.

wb_command -cifti-label-export-table parcellation.dlabel.nii 1 parcel_labels.txt

Step 2: Resample the Volume Data

Separate out just the volume data (no need for the cortical data) from the other space. We don't necessarily need a dense label file from the other space to do this. We can extract the volume structure labels from any dense timeseries file.

wb_command -cifti-separate \
  other.dtseries.nii COLUMN \
  -volume-all other_volume_parcels.nii \
  -label other_volume_labels.nii

Resample your volume parcellation into the space of the other volume structure labels. Here we use FSL's flirt to do the resampling. We assume both nifti volumes are in the same MNI space, therefore we can resample using an identity matrix to map from your space to the other space. This will overwrite other_volume_parcels.nii with your parcellation.

FSLOUTPUTTYPE=NIFTI flirt \
  -init ${FSLDIR}/etc/flirtsch/ident.mat \
  -applyxfm -ref other_volume_labels.nii \
  -in volume_parcels.nii \
  -out other_volume_parcels.nii \
  -nosearch -interp nearestneighbour

Now the file other_volume_parcels.nii contains your parcels in the other space. Success! But there is a small problem. FSL's flirt does not understand cifti headers. The file other_volume_parcels.nii is just a plain old nifti file without any parcel labels in its non-existent cifti header. We can fix this by importing the parcel labels that we exported to a table in the prior section. The option -drop-unused-labels omits the superfluous cortical parcel labels. This will (again) overwire other_volume_parcels.nii.

wb_command -volume-label-import \
  other_volume_parcels.nii \
  parcel_labels.txt \
  other_volume_parcels.nii \
  -drop-unused-labels

Step 3: Assembling a New Label File

Now that we have your volume (subcortical) parcels in the other volume space, it's time to reassemble everything back into a single dense label file.

wb_command -cifti-create-label \
  parcellation_other.dlabel.nii \
  -volume other_volume_parcels.nii other_volume_labels.nii \
  -left-label cortex_left.label.gii \
  -right-label cortex_right.label.gii

Finally, you can apply your new label file to the dense timeseries data in the other volume space.

wb_command -cifti-parcellate \
  other.dtseries.nii \
  parcellation_other.dlabel.nii \
  COLUMN \
  other.ptseries.nii

Open other.ptseries.nii in Workbench Viewer and make sure the parcels look like they are in the right place.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment