freesurfertools module
- class clabtoolkit.freesurfertools.AnnotParcellation(parc_file=None, annot_id=None, ref_surf=None, cont_tech='local', cont_image=None)[source]
Bases:
objectThis class contains methods to work with FreeSurfer annot files # Implemented methods: # - Correct the parcellation by refilling the vertices from the cortex label file that do not have a label in the annotation file # - Convert FreeSurfer annot files to gcs files # Methods to be implemented: # Grouping regions to create a coarser parcellation # Removing regions from the parcellation # Correct parcellations by removing small clusters of vertices labeled inside another region
- __init__(parc_file=None, annot_id=None, ref_surf=None, cont_tech='local', cont_image=None)[source]
Initialize the AnnotParcellation object
- Parameters:
parc_file (str or Path, optional) – Path to the parcellation file (annot, gii, or gcs format). If None, the object is initialized without loading any file.
annot_id (str, optional) – Annotation ID to use for the parcellation. If None, uses the file name without extension.
ref_surf (str or Path, optional) – Reference surface for conversion. If None, uses the default FreeSurfer white surface.
cont_tech (str, optional) – Container technology to use (e.g., ‘local’, ‘docker’). Default is ‘local’.
cont_image (str or Path, optional) – Container image to use. If None, uses the default for the specified container technology.
- load_from_file(parc_file, annot_id=None, ref_surf=None, cont_tech='local', cont_image=None)[source]
Load parcellation data from file
- Parameters:
parc_file (str or Path) – Path to the parcellation file (annot, gii, or gcs format)
annot_id (str, optional) – Annotation ID to use for the parcellation. If None, uses the file name.
ref_surf (str or Path, optional) – Reference surface for conversion. If None, uses the default FreeSurfer white surface.
cont_tech (str, optional) – Container technology to use (e.g., ‘local’, ‘docker’). Default is ‘local’.
cont_image (str or Path, optional) – Container image to use. If None, uses the default for the specified container technology.
Notes
This method checks for consistency between the region codes, color table and region names. If there are codes in the table that are not in the vertex-wise data, those entries will be removed from the table and the region names list.
- Raises:
ValueError – If the parcellation file does not exist.
Examples
>>> annot = AnnotParcellation('/opt/freesurfer/subjects/bert/label/lh.aparc.annot') >>> annot.get_info()
- get_info(verbose=True)[source]
Display and return comprehensive information about the AnnotParcellation object.
Provides a formatted overview of the parcellation including identification, vertex statistics, region table properties, and label consistency checks. Useful for quick inspection and validation of annotation data.
- The method displays:
Basic annotation identification (name, ID, hemisphere, file path)
Vertex statistics (total vertices, unique labels found)
Region table properties (number of defined regions)
Label consistency (labels present in vertices but absent from table,
and regions defined in table but absent from vertices)
- Parameters:
verbose (bool, optional) – If True, prints the information in a formatted table. If False, only returns the info dictionary without printing. Default is True.
- Returns:
info – Dictionary containing the following keys:
- ’name’str
Annotation filename or None if not loaded from file.
- ’id’str
Annotation identifier string.
- ’hemi’str or None
Hemisphere (‘lh’, ‘rh’, or None if not detected).
- ’filename’str or None
Full path to the annotation file, or None.
- ’n_vertices’int
Total number of vertices in the vertex-wise label array.
- ’n_regions_table’int
Number of regions defined in the color/region table (regtable).
- ’n_unique_labels’int
Number of distinct label values found across all vertices.
- ’labels_not_in_table’list
List of label values present in the vertex array (codes) that have no corresponding entry in the region table. Ideally empty.
- ’regions_not_in_vertices’list
List of region names whose table codes do not appear in any vertex. These are defined but unused regions.
- Return type:
Notes
Label consistency checks are only performed when parcellation data has been loaded (i.e., self.codes and self.regtable are not None).
Examples
>>> annot = AnnotParcellation('/opt/freesurfer/subjects/bert/label/lh.aparc.annot') >>> info = annot.get_info() ╔════════════════════════════════════════════════════════════════╗ ║ ANNOTATION PARCELLATION INFO ║ ╠════════════════════════════════════════════════════════════════╣ ║ Name : lh.aparc.annot ║ ║ ID : lh.aparc ║ ║ Hemi : lh ║ ║ File : /opt/freesurfer/subjects/bert/label/lh.aparc.annot ║ ╠════════════════════════════════════════════════════════════════╣ ║ VERTEX STATISTICS ║ ║ Total vertices : 163,842 ║ ║ Unique labels : 36 ║ ╠════════════════════════════════════════════════════════════════╣ ║ REGION TABLE ║ ║ Regions defined : 36 ║ ╠════════════════════════════════════════════════════════════════╣ ║ LABEL CONSISTENCY ║ ║ Labels not in table : 0 ║ ║ Regions not in vertices : 0 ║ ╚════════════════════════════════════════════════════════════════╝
- create_from_data(codes, regtable, regnames, annot_id, hemi='lh', filename=None)[source]
Create parcellation from existing data arrays. This method is useful for creating an AnnotParcellation object from data that may have been generated or modified in memory, rather than loaded from a file. It ensures that the internal state of the object is consistent and that the region codes, colors, and names are aligned with the vertex-wise data.
- Parameters:
Notes
This method checks for consistency between the region codes, color table and region names. If there are codes in the table that are not in the vertex-wise data, those entries will be removed from the table and the region names list.
- save_annotation(out_file=None, force=True)[source]
Save the annotation file. If the file already exists, it will be overwritten.
- Parameters:
Optional (force -)
Optional
- get_info_from_name(region_name)[source]
Retrieve information about a parcellation region by its name.
- Parameters:
region_name (str) – The name of the region to look up.
- Returns:
A dictionary of the form:
{region_name: {'id': int, 'color': np.ndarray, 'n_vertices': int}}
where ‘color’ is an RGB array (shape (3,)) and ‘n_vertices’ is the number of surface vertices assigned to the region. Returns None if the name is not found or the input type is invalid.
- Return type:
dict or None
- Raises:
TypeError – If region_name is not a string.
Examples
>>> annot = AnnotParcellation('/opt/freesurfer/subjects/bert/label/lh.aparc.annot') >>> info = annot.get_info_from_name('bankssts') >>> print(info) {'bankssts': {'id': 2647065, 'color': array([25, 100, 40]), 'n_vertices': 2137}}
- get_info_from_id(region_id)[source]
Retrieve information about a parcellation region by its integer ID.
- Parameters:
region_id (int) – The integer ID of the region to look up (typically stored in column 4 of the regtable).
- Returns:
A dictionary of the form:
{region_name: {'id': int, 'color': np.ndarray, 'n_vertices': int}}
where ‘color’ is an RGB array (shape (3,)) and ‘n_vertices’ is the number of surface vertices assigned to the region. Returns None if the ID is not found or the input type is invalid.
- Return type:
dict or None
- Raises:
TypeError – If region_id is not an integer (or numpy integer).
Examples
>>> annot = AnnotParcellation('/opt/freesurfer/subjects/bert/label/lh.aparc.annot') >>> info = annot.get_info_from_id(2647065) >>> print(info) {'bankssts': {'id': 2647065, 'color': array([25, 100, 40]), 'n_vertices': 2137}}
- get_regions_info(region_list=None, return_df=False)[source]
Retrieve information about multiple parcellation regions.
Accepts flexible input types for region_list and dispatches each element to get_info_from_name (for string items) or get_info_from_id (for integer items). Regions that cannot be resolved are skipped with a warning.
- Parameters:
region_list (str | int | np.integer | list[str] | list[int] | np.ndarray, optional) –
One or more region identifiers. Accepted forms:
A single region name (str).
A single region ID (int or np.integer).
A list of names (list[str]).
A list of IDs (list[int]).
A NumPy array of names (dtype str/object) or IDs (dtype int).
A mixed list of names and IDs is not supported; provide a
homogeneous collection.
If None, all regions available in the annotation are returned.
return_df (bool, optional) – If True, returns the results as a pandas DataFrame. If False (default), returns a list of dictionaries.
- Returns:
Results in the requested format, or None if no regions are available or region_list cannot be interpreted.
- Return type:
list[dict] or pandas.DataFrame or None
- Raises:
TypeError – If region_list is not one of the accepted input types.
ValueError – If out_format is not
'dict'or'dataframe'.
Examples
>>> annot = AnnotParcellation('/opt/freesurfer/subjects/bert/label/lh.aparc.annot')
Return a list of dicts (default):
>>> annot.get_regions_info(['bankssts', 'precentral'])
Return a DataFrame:
>>> annot.get_regions_info(['bankssts', 'precentral'], return_df=True) >>> annot.get_regions_info(np.array([2647065, 14423100]), return_df=True) >>> annot.get_regions_info('bankssts', return_df=True) >>> annot.get_regions_info(2647065, return_df=True)
Return all regions as a DataFrame:
>>> annot.get_regions_info(return_df=True)
- correct_vertexwise_parcellation(surf, cortex_file=None, min_cluster_size=None)[source]
Correct a vertex-wise parcellation by relabelling small disconnected clusters.
For each labelled region: - If multiple components exist, zero any non-largest component below the size threshold.
If only one component exists, zero the whole region if it’s below the size threshold.
Isolated single vertices with no neighbours in the same region are always zeroed out regardless of the threshold.
After corrections, the parcellation is filled using the cortex label to ensure all vertices are assigned to a region.
- Parameters:
annot (AnnotParcellation) – The input annotation parcellation to be corrected.
surf (Surface) – The surface object corresponding to the annotation, used to extract edges for connectivity analysis.
cortex_file (str or Path, optional) – Path to the cortex label file used to fill the parcellation after corrections. If None, filling is skipped.
min_cluster_size (int, optional) – Minimum size (in vertices) for a cluster to be retained. Clusters smaller than this will be zeroed out. If None, all non-largest components will be zeroed regardless of size of the largest component. Default is None.
- Returns:
A new AnnotParcellation object with the corrected parcellation.
- Return type:
Notes
If min_cluster_size is None, all non-largest components will be zeroed regardless of size of the largest component.
Isolated single vertices with no neighbours in the same region are always zeroed out regardless of the threshold.
Examples
>>> annot_corrected = correct_vertexwise_parcellation(annot_obj, surf_file, cortex_file=cortex_file, min_cluster_size=100)
- fill_parcellation(label_file, surf_file, corr_annot=None)[source]
Correct the parcellation by refilling vertices from the cortex label file that do not have a label in the annotation file.
This method iteratively fills unlabeled vertices (those with value -1 or 0) by assigning the most frequent label from their neighboring vertices. The algorithm focuses on boundary vertices - those at the edges of the parcellation - and continues until all vertices within the cortex have been assigned labels or no further progress can be made.
- Parameters:
label_file (str) – Path to the cortex label file containing vertex indices that define the cortical surface. This file typically has a .label extension and is used to mask vertices to only those within the cortex.
surf_file (str) – Path to the surface geometry file containing vertex coordinates and face connectivity information. This is typically a FreeSurfer surface file (e.g., lh.pial, rh.white) that defines the mesh topology.
corr_annot (str, optional) – Path where the corrected annotation file should be saved. If None, the original annotation filename will be used. The directory will be created if it doesn’t exist. Default is None.
- Returns:
corr_annot (str) – Path to the corrected annotation file that was saved.
vert_lab (numpy.ndarray) – Array of vertex labels after correction, where each element corresponds to the label assigned to that vertex index.
reg_ctable (numpy.ndarray) – Region color table containing RGB color values for each region in the parcellation.
reg_names (list) – List of region names corresponding to each label in the parcellation. May include “unknown” as the first element if unlabeled vertices were initially present.
- Raises:
ValueError – If the surface file does not exist. Both annotation and surface files are mandatory for the parcellation correction process.
ValueError – If the cortex label file does not exist. The cortex label file is required to define which vertices should be considered for labeling.
Notes
The algorithm works by:
Loading surface geometry and cortex label information
Identifying vertices with missing labels (value -1, converted to 0)
Finding boundary faces that contain both labeled and unlabeled vertices
Iteratively assigning labels to unlabeled boundary vertices based on the most frequent label among their neighbors
Repeating until no more vertices can be labeled or all vertices are filled
The method modifies the internal state of the annotation object and optionally saves the result to a file.
Examples
Basic usage with an annotation object:
>>> # Assuming 'annot' is an annotation object >>> label_file = '/path/to/lh.cortex.label' >>> surf_file = '/path/to/lh.pial' >>> output_file = '/path/to/lh.corrected.annot' >>> >>> corrected_path, labels, ctable, names = annot.fill_parcellation( ... label_file=label_file, ... surf_file=surf_file, ... corr_annot=output_file ... ) >>> >>> print(f"Corrected annotation saved to: {corrected_path}") >>> print(f"Number of regions: {len(names)}")
Usage without specifying output file (uses original filename):
>>> corrected_path, labels, ctable, names = annot.fill_parcellation( ... label_file=label_file, ... surf_file=surf_file ... )
See also
nibabel.freesurfer.read_geometryFor reading surface files
nibabel.freesurfer.read_labelFor reading label files
save_annotationFor saving annotation files
- export_to_tsv(prefix2add=None, reg_offset=1000, hemi='L', tsv_file=None, output_format=None)[source]
Export the parcellation table to a TSV file containing region information.
Creates a comprehensive table with region indices, annotation IDs, parcellation IDs, names, and hexadecimal color codes. This is useful for creating lookup tables, documentation, or interfacing with other neuroimaging tools that require parcellation metadata in tabular format.
- Parameters:
prefix2add (str, optional) – Prefix string to prepend to all region names. This is useful for distinguishing regions from different hemispheres (e.g., ‘lh_’ or ‘rh_’) or different atlases. If None, original region names are preserved. Default is None.
reg_offset (int, optional) – Integer offset to add to the parcellation IDs. This helps avoid ID conflicts when combining multiple parcellations or when specific ID ranges are required. The offset is added to sequential indices starting from 0. Default is 1000.
hemi (str, optional) – Hemisphere identifier to include in the region names (e.g., ‘L’ or ‘R’). This is purely for naming purposes and does not affect the data. Default is ‘L’.
tsv_file (str or Path, optional) – Path where the TSV file should be saved. If provided, the DataFrame will be written to this file with tab separation. The parent directory will be created if it doesn’t exist. If None, no file is saved and only the DataFrame is returned. Default is None.
output_format (str, optional) – If set to “templateflow”, the output DataFrame will follow the TemplateFlow parcellation table format, which includes only ‘index’, ‘hemi’, ‘name’, and ‘color’ columns. In this format, ‘index’ corresponds to the original annotation IDs, and ‘name’ includes the optional prefix. If None (default), the full format with ‘index’, ‘annotid’, ‘parcid’, ‘name’, and ‘color’ is used.
- Returns:
tsv_df (pandas.DataFrame) – DataFrame containing the parcellation table with the following columns:
’index’: Sequential indices starting from 0 for each region
’annotid’: Original annotation IDs from the FreeSurfer annotation file
’parcid’: Parcellation IDs (index + reg_offset)
’name’: Region names, optionally prefixed
’color’: Hexadecimal color codes (e.g., ‘#FF0000’ for red)
tsv_file (str) – Path to the saved TSV file if tsv_file parameter was provided, otherwise returns the input tsv_file parameter (which may be None).
- Raises:
PermissionError – If the specified directory for the TSV file cannot be created due to insufficient write permissions. The method will print an error message and exit the program.
Notes
The method processes the internal parcellation data as follows:
1. Converts RGB color values to hexadecimal format using the first 3 columns of the region table 2. Applies optional prefix to region names using a name correction function 3. Creates sequential indices and applies the specified offset to parcellation IDs 4. Combines all information into a structured DataFrame 5. Optionally saves to TSV format with tab separation and no row indices
The annotation IDs correspond to the original FreeSurfer annotation values, while parcellation IDs provide a more standardized numbering scheme.
Examples
Basic usage - return DataFrame only:
>>> # Assuming 'annot' is an annotation object >>> df, filename = annot.export_to_tsv() >>> print(df.head()) index annotid parcid name color 0 0 1234 1000 unknown #000000 1 1 5678 1001 precentral #FF0000 2 2 9012 1002 postcentral #00FF00
Add prefix to region names:
>>> df, filename = annot.export_to_tsv(prefix2add='lh_') >>> print(df['name'].head()) 0 lh_unknown 1 lh_precentral 2 lh_postcentral
Save to file with custom offset:
>>> output_file = '/path/to/parcellation_table.tsv' >>> df, saved_path = annot.export_to_tsv( ... prefix2add='rh_', ... reg_offset=2000, ... tsv_file=output_file ... ) >>> print(f"Table saved to: {saved_path}") >>> print(f"Parcellation IDs range: {df['parcid'].min()}-{df['parcid'].max()}")
Create hemisphere-specific tables:
>>> # Left hemisphere >>> lh_df, lh_file = lh_annot.export_to_tsv( ... prefix2add='lh_', ... reg_offset=1000, ... tsv_file='lh_parcellation.tsv' ... ) >>> >>> # Right hemisphere >>> rh_df, rh_file = rh_annot.export_to_tsv( ... prefix2add='rh_', ... reg_offset=2000, ... tsv_file='rh_parcellation.tsv' ... ) >>> >>> # Combine both hemispheres >>> combined_df = pd.concat([lh_df, rh_df], ignore_index=True)
See also
pandas.DataFrame.to_csvFor saving DataFrames in various formats
cltcol.multi_rgb2hexFor converting RGB values to hexadecimal
cltcol.correct_namesFor applying prefixes to region names
- map_values(regional_values, is_dataframe=False)[source]
Map regional values to vertex-wise values using the parcellation codes and region table.
This method transforms region-level data (e.g., statistical measures, anatomical properties, or functional metrics computed per brain region) into vertex-level data for surface visualization. Each vertex is assigned the value corresponding to its parcellation region, enabling surface-based visualization of regional data.
- Parameters:
regional_values (str or pandas.DataFrame or numpy.ndarray) –
Regional values to map to vertices. Can be provided in three formats:
str: Path to a text/CSV file containing regional values. The file
should have one row per region matching the parcellation. Single column files are read as arrays, while multi-column CSV files can optionally be read with headers when is_dataframe=True.
pandas.DataFrame: DataFrame with one row per region and columns
representing different measures. Must have numeric values and column names. The number of rows must match the number of regions in the parcellation.
numpy.ndarray: Array with shape (n_regions, n_measures) where
n_regions matches the number of regions in the parcellation. Can be 1D for single measures or 2D for multiple measures.
is_dataframe (bool, optional) – Whether to read text files as DataFrames with column headers. Only applies when regional_values is a file path (str). If True, the first row is treated as column names and preserved in the output. If False, the file is read without headers. Default is False.
- Returns:
vertex_wise_values – Vertex-wise values mapped from the regional values. The output format depends on the input:
numpy.ndarray: Returned when input is a numpy array or a file
read without headers (is_dataframe=False). Shape is (n_vertices,) for single measures or (n_vertices, n_measures) for multiple measures.
pandas.DataFrame: Returned when input is a DataFrame or a file
read with headers (is_dataframe=True). Has one row per vertex and preserves original column names.
- Return type:
- Raises:
ValueError – If the regional values file does not exist (when input is a file path).
ValueError – If the number of rows in regional_values does not match the number of regions in the parcellation. This ensures proper mapping between regions and values.
ValueError – If the DataFrame contains non-numeric values. All regional values must be numeric for proper mapping to vertices.
ValueError – If regional_values is not one of the supported types (str, DataFrame, or ndarray).
Notes
The mapping process works as follows:
1. Input validation: Checks that the input format is supported and that dimensions match the parcellation structure.
2. Format standardization: Converts all input types to numpy arrays while preserving column information when applicable.
3. Vertex assignment: Uses the internal region_to_vertexwise function to assign each vertex the value from its corresponding region based on the parcellation codes.
4. Output formatting: Returns data in the same structural format as the input (array vs DataFrame) to maintain consistency.
The parcellation codes (self.codes) define which region each vertex belongs to, and the region table (self.regtable) provides the mapping structure. Vertices with undefined regions (typically background or unknown areas) may receive special handling depending on the implementation of region_to_vertexwise.
Examples
Map single measure from numpy array:
>>> import numpy as np >>> # Regional thickness values for each region >>> thickness_values = np.array([2.5, 3.1, 2.8, 3.2, 2.9]) # 5 regions >>> vertex_values = annot.map_values(thickness_values) >>> print(f"Mapped {len(vertex_values)} vertices") >>> print(f"Value range: {vertex_values.min():.2f} - {vertex_values.max():.2f}")
Map multiple measures from DataFrame:
>>> import pandas as pd >>> # Multiple regional measures >>> regional_data = pd.DataFrame({ ... 'thickness': [2.5, 3.1, 2.8, 3.2, 2.9], ... 'volume': [1200, 1500, 1100, 1400, 1300], ... 'surface_area': [850, 920, 780, 900, 840] ... }) >>> vertex_df = annot.map_values(regional_data) >>> print(f"Output columns: {list(vertex_df.columns)}") >>> print(f"Vertex data shape: {vertex_df.shape}")
Read from CSV file without headers:
>>> # File contains single column of regional values >>> vertex_values = annot.map_values('regional_thickness.txt') >>> print(f"Mapped values type: {type(vertex_values)}")
Read from CSV file with headers:
>>> # File contains multiple columns with headers >>> vertex_df = annot.map_values( ... 'regional_measures.csv', ... is_dataframe=True ... ) >>> print(f"Preserved columns: {list(vertex_df.columns)}")
Typical neuroimaging workflow:
>>> # Load regional statistics from analysis >>> regional_stats = pd.read_csv('region_statistics.csv') >>> >>> # Map to surface for visualization >>> surface_data = annot.map_values(regional_stats) >>> >>> # Save for visualization software >>> if isinstance(surface_data, pd.DataFrame): ... surface_data.to_csv('surface_values.csv', index=False) ... else: ... np.savetxt('surface_values.txt', surface_data)
Error handling example:
>>> try: ... # This will fail if dimensions don't match ... wrong_size = np.array([1, 2, 3]) # Only 3 values for 5 regions ... vertex_values = annot.map_values(wrong_size) ... except ValueError as e: ... print(f"Dimension mismatch: {e}")
See also
region_to_vertexwiseUnderlying function that performs the mapping
pandas.read_csvFor reading CSV files with various options
numpy.loadtxtAlternative for reading simple numeric files
- static gii2annot(gii_file, annot_file=None)[source]
Convert a GIFTI label file (.label.gii) to a FreeSurfer annotation file (.annot) using nibabel, without requiring a FreeSurfer installation.
- Parameters:
gii_file (str) – Path to the input GIFTI label file. The file must contain at least one integer data array (the per-vertex label keys) and a populated
LabelTablewith RGBA colors and region names.annot_file (str, optional) – Path for the output FreeSurfer annotation file. If None, the output is placed in the same directory as the input with the
.giiextension replaced by.annot. Default is None.
- Returns:
annot_file – Absolute path to the created
.annotfile.- Return type:
- Raises:
ValueError – If
gii_filedoes not exist.ValueError – If the GIFTI file contains no data arrays.
ValueError – If the GIFTI LabelTable is empty.
Notes
- FreeSurfer annotation format
Each vertex is assigned a packed integer code computed as
R + G*256 + B*65536(alpha is ignored in the code but stored in the ctab). The ctab is an(n_regions, 5)int32 array whose columns are[R, G, B, A, code].- GIFTI colour range
nibabel exposes
GiftiLabelRGBA attributes as floats in[0, 1]. This method multiplies by 255 and rounds to obtain uint8 values.- Missing colours / names
Labels whose RGBA values are
Nonedefault to(0, 0, 0, 255). Labels whoselabelattribute isNonereceive the name"region_<key>".
Examples
>>> annot = AnnotParcellation.gii2annot( ... gii_file='lh.Schaefer2018_400Parcels.label.gii' ... ) >>> print(annot) # lh.Schaefer2018_400Parcels.label.annot
>>> annot = AnnotParcellation.gii2annot( ... gii_file='/path/to/rh.custom.label.gii', ... annot_file='/output/rh.custom.annot', ... )
See also
annot2giiReverse conversion from
.annotto GIFTI format.
- static annot2gii(annot_file, gii_file=None)[source]
Convert a FreeSurfer annotation file (.annot) to a GIFTI label file (.label.gii) using nibabel, without requiring a FreeSurfer installation.
- Parameters:
annot_file (str) – Path to the input FreeSurfer annotation file. The file must contain a valid per-vertex label array and a colour table.
gii_file (str, optional) – Path for the output GIFTI label file. If None, the output is placed in the same directory as the input with the
.annotextension replaced by.label.gii. Default is None.
- Returns:
gii_file – Absolute path to the created
.label.giifile.- Return type:
- Raises:
ValueError – If
annot_filedoes not exist.
Notes
- FreeSurfer annotation format
Each vertex stores a packed integer code
R + G*256 + B*65536. The ctab is an(n_regions, 5)int32 array with columns[R, G, B, A, code].- GIFTI colour range
GiftiLabelRGBA attributes are floats in[0, 1]. This method divides the uint8 ctab values by 255.- Region names
nibabel may return names as bytes or strings depending on the file. Both are handled and decoded to plain strings in the LabelTable.
Examples
>>> gii = AnnotParcellation.annot2gii( ... annot_file='lh.aparc.annot' ... ) >>> print(gii) # lh.aparc.label.gii
>>> gii = AnnotParcellation.annot2gii( ... annot_file='/path/to/rh.Destrieux.annot', ... gii_file='/output/rh.Destrieux.label.gii', ... )
See also
gii2annotReverse conversion from GIFTI to
.annotformat.
- static gcs2annot(gcs_file, annot_file=None, freesurfer_dir=None, ref_id='fsaverage', cont_tech='local', cont_image=None)[source]
Convert FreeSurfer GCS (Gaussian Classifier Surface) files to annotation files.
This method applies a trained GCS classifier to generate subject-specific parcellations. GCS files contain statistical models trained on manual parcellations that can be applied to new subjects to automatically generate anatomically consistent region labels.
- Parameters:
gcs_file (str or Path) – Path to the input GCS classifier file. These files contain trained Gaussian classifiers for automatic parcellation (e.g., aparc.gcs, aparc.a2009s.gcs). The hemisphere is automatically detected from the filename.
annot_file (str or Path, optional) – Path for the output annotation file. If None, the output file is created in the same directory as the GCS file with the extension changed from .gcs to .annot. Default is None.
freesurfer_dir (str or Path, optional) – Path to the FreeSurfer subjects directory containing the reference subject data. If None, uses the SUBJECTS_DIR environment variable. The directory will be created if it doesn’t exist. Default is None.
ref_id (str, optional) – Subject ID of the reference subject containing the surface files needed for classification (sphere.reg, cortex.label, aseg.mgz). Typically ‘fsaverage’ for standard space analysis. Default is ‘fsaverage’.
cont_tech (str, optional) – Container technology for running FreeSurfer commands. Options include ‘local’ (run directly), ‘singularity’, ‘docker’, or other supported containerization methods. Default is ‘local’.
cont_image (str or Path, optional) – Container image specification when using containerized execution. Required when cont_tech is not ‘local’. Should specify the FreeSurfer container image (e.g., ‘freesurfer/freesurfer:7.2.0’). Default is None.
- Returns:
annot_file – Path to the created annotation file containing the classified parcellation labels.
- Return type:
- Raises:
ValueError – If the input GCS file does not exist.
ValueError – If neither freesurfer_dir is provided nor SUBJECTS_DIR environment variable is set, and FREESURFER_HOME is also not available.
Notes
This method uses FreeSurfer’s mris_ca_label command to apply the GCS classifier. The command structure is:
mris_ca_label -l cortex.label -aseg aseg.mgz subject_id hemisphere \ sphere.reg classifier.gcs output.annot
The classification process requires several FreeSurfer files from the reference subject:
cortex.label: Defines the cortical vertices to be labeled
aseg.mgz: Volumetric segmentation for spatial context
sphere.reg: Spherical surface registration for spatial normalization
The method automatically manages the FreeSurfer environment by setting the SUBJECTS_DIR variable and ensuring the necessary directory structure exists. The hemisphere is detected from the GCS filename.
GCS-based parcellation is particularly useful for:
Applying consistent parcellation schemes across subjects
Automated processing pipelines
Reproducing published parcellation protocols
Cross-study standardization
Examples
Basic GCS application with default settings:
>>> # Apply Desikan-Killiany parcellation >>> gcs_file = '/path/to/lh.aparc.gcs' >>> annot_file = AnnotParcellation.gcs2annot(gcs_file) >>> print(f"Created parcellation: {annot_file}")
Specify custom FreeSurfer directory:
>>> # Use custom subjects directory >>> gcs_file = '/atlases/rh.aparc.a2009s.gcs' >>> fs_dir = '/data/freesurfer_subjects' >>> >>> result = AnnotParcellation.gcs2annot( ... gcs_file=gcs_file, ... freesurfer_dir=fs_dir, ... ref_id='fsaverage' ... )
Apply to individual subject space:
>>> # Use subject-specific reference >>> gcs_file = '/atlases/lh.aparc.gcs' >>> output_file = '/subjects/sub001/label/lh.aparc.annot' >>> >>> annot_file = AnnotParcellation.gcs2annot( ... gcs_file=gcs_file, ... annot_file=output_file, ... ref_id='sub001' # Use subject's own surfaces ... )
Using Docker for processing:
>>> # Run classification in container >>> result = AnnotParcellation.gcs2annot( ... gcs_file='parcellation.gcs', ... freesurfer_dir='/data/subjects', ... cont_tech='docker', ... cont_image='freesurfer/freesurfer:7.2.0' ... )
Batch processing multiple GCS files:
>>> import glob >>> gcs_files = glob.glob('/atlases/*.gcs') >>> >>> for gcs_file in gcs_files: ... output_dir = '/parcellations' ... basename = os.path.basename(gcs_file).replace('.gcs', '.annot') ... output_file = os.path.join(output_dir, basename) ... ... AnnotParcellation.gcs2annot( ... gcs_file=gcs_file, ... annot_file=output_file, ... freesurfer_dir='/data/freesurfer' ... )
- annot2gcs(gcs_file=None, freesurfer_dir=None, fssubj_id=None, hemi=None, cont_tech='local', cont_image=None)[source]
Convert FreeSurfer annotation files to GCS (Gaussian Classifier Surface) files.
This method creates a trained Gaussian classifier from an existing manual or semi-manual parcellation. The resulting GCS file can be applied to new subjects to automatically generate parcellations with the same regional definitions and boundaries as the training annotation.
- Parameters:
gcs_file (str or Path, optional) – Path for the output GCS classifier file. If None, the file is saved in the same directory as the annotation file with the extension changed from .annot to .gcs. Default is None.
freesurfer_dir (str or Path, optional) – Path to the FreeSurfer subjects directory containing the training subject data. If None, uses the SUBJECTS_DIR environment variable. The directory will be created if it doesn’t exist. Default is None.
fssubj_id (str, required) – Subject ID of the FreeSurfer subject to use for training the classifier. This subject must have the required surface files (sphere.reg) and should be the same subject from which the annotation was derived. No default value - must be provided.
hemi (str, optional) – Hemisphere specification (‘lh’ or ‘rh’). If None, the hemisphere is automatically detected from the annotation filename. Default is None.
cont_tech (str, optional) – Container technology for running FreeSurfer commands. Options include ‘local’ (run directly), ‘singularity’, ‘docker’, or other supported containerization methods. Default is ‘local’.
cont_image (str or Path, optional) – Container image specification when using containerized execution. Required when cont_tech is not ‘local’. Should specify the FreeSurfer container image (e.g., ‘freesurfer/freesurfer:7.2.0’). Default is None.
- Returns:
gcs_name – Filename (not full path) of the created GCS classifier file.
- Return type:
- Raises:
ValueError – If SUBJECTS_DIR environment variable is not set and freesurfer_dir is not provided.
ValueError – If fssubj_id is not provided (required parameter).
ValueError – If the FreeSurfer subject directory does not exist.
ValueError – If the required sphere.reg file is not found in the subject directory.
ValueError – If the hemisphere cannot be determined from the filename and is not provided as a parameter.
Notes
This method uses FreeSurfer’s mris_ca_train command to create the GCS classifier. The process involves:
1. Color table creation: Generates a temporary .ctab file with region names and RGB color values from the annotation.
2. Classifier training: Uses spherical surface registration and the annotation labels to train Gaussian classifiers for each region.
3. Model output: Creates a .gcs file containing the trained statistical models that can be applied to new subjects.
The command structure is:
mris_ca_train -n 2 -t color_table.ctab hemisphere sphere.reg \ annotation.annot subject_id output.gcs
Required FreeSurfer files for the training subject:
sphere.reg: Spherical surface registration for spatial normalization
Proper directory structure: Standard FreeSurfer subject organization
The resulting GCS file can be used with the gcs2annot method to apply the same parcellation scheme to new subjects automatically.
Examples
Basic GCS creation with required subject ID:
>>> # Train classifier from manual parcellation >>> annot = Annotation('/data/sub001/label/lh.manual.annot') >>> gcs_name = AnnotParcellation.annot2gcs(fssubj_id='sub001') >>> print(f"Created classifier: {gcs_name}")
Specify custom output location:
>>> # Save GCS file to specific location >>> output_file = '/atlases/custom_parcellation.gcs' >>> gcs_name = AnnotParcellation.annot2gcs( ... gcs_file=output_file, ... fssubj_id='fsaverage', ... freesurfer_dir='/data/freesurfer' ... )
Create classifier from template subject:
>>> # Use fsaverage as training template >>> annot = Annotation('/templates/fsaverage/label/rh.custom.annot') >>> gcs_name = AnnotParcellation.annot2gcs( ... fssubj_id='fsaverage', ... hemi='rh', ... freesurfer_dir='/usr/local/freesurfer/subjects' ... )
Using Docker for training:
>>> # Train classifier in container environment >>> gcs_name = AnnotParcellation.annot2gcs( ... fssubj_id='training_subject', ... cont_tech='docker', ... cont_image='freesurfer/freesurfer:7.2.0' ... )
Complete workflow - train and apply:
>>> # Step 1: Create GCS from manual annotation >>> manual_annot = AnnotParcellation('/manual/lh.expert_labels.annot') >>> gcs_file = '/classifiers/expert_parcellation.gcs' >>> >>> gcs_name = manual_annot.annot2gcs( ... gcs_file=gcs_file, ... fssubj_id='template_subject' ... ) >>> >>> # Step 2: Apply to new subjects >>> for subject in ['sub002', 'sub003', 'sub004']: ... output_annot = f'/results/{subject}/lh.expert_auto.annot' ... AnnotParcellation.gcs2annot( ... gcs_file=gcs_file, ... annot_file=output_annot, ... ref_id=subject ... )
Quality control after training:
>>> # Verify the trained classifier works >>> test_output = '/tmp/test_application.annot' >>> AnnotParcellation.gcs2annot( ... gcs_file='/atlases/new_classifier.gcs', ... annot_file=test_output, ... ref_id='fsaverage' ... ) >>> >>> # Compare with original >>> original = AnnotParcellation('/original/annotation.annot') >>> test_result = AnnotParcellation(test_output) >>> # Implement comparison logic...
See also
gcs2annotApply GCS classifiers to generate annotations
mris_ca_trainFreeSurfer command for training surface classifiers
export_to_tsvExport parcellation metadata for analysis
- group_into_lobes(grouping='desikan', lobes_json=None, out_annot=None, ctxprefix=None, force=False)[source]
Group parcellation regions into anatomical lobes for coarser-grained analysis.
This method combines fine-grained brain regions into larger anatomical units (lobes) based on predefined or custom grouping schemes. This is useful for reducing dimensionality in analyses, creating simplified visualizations, or studying brain function at the lobar level.
- Parameters:
grouping (str, optional) – Grouping method or scheme name to use for lobar organization. Built-in options include ‘desikan’ for Desikan-Killiany atlas grouping. Custom groupings can be specified when providing a lobes_json file. Default is ‘desikan’.
lobes_json (str or Path, optional) –
Path to a JSON file containing custom lobe definitions and region mappings. If None, uses the default grouping scheme called lobes.json. This file is located in the clabtoolkit package directory (e.g., clabtoolkit/config/lobes.json).
Default is None.
out_annot (str or Path, optional) – Path where the new lobar annotation file should be saved. If None, the parcellation is only returned as an object without saving to disk. The output directory will be created if it doesn’t exist. Default is None.
ctxprefix (str, optional) – Prefix string to prepend to the lobe names. This is useful for distinguishing between hemispheres (e.g., ‘lh_’ or ‘rh_’) or different analysis contexts. If None, no prefix is added. Default is None.
force (bool, optional) – Whether to overwrite existing output files. If False and the output file already exists, an error will be raised. If True, existing files will be overwritten without warning. Default is False.
- Returns:
lobar_parcellation – New AnnotParcellation object containing the lobar parcellation where original regions have been grouped into larger anatomical units. The object contains updated region names, codes, and color tables corresponding to the lobes.
- Return type:
- Raises:
FileExistsError – If the output annotation file already exists and force=False.
FileNotFoundError – If the specified lobes_json file does not exist.
ValueError – If the JSON file format is invalid or missing required keys.
KeyError – If regions specified in the JSON file are not found in the current parcellation.
Notes
The grouping process works as follows:
1. Region mapping: Original parcellation regions are mapped to their corresponding lobes based on the grouping scheme.
2. Label reassignment: Vertex labels are updated to reflect the new lobar assignments rather than fine-grained regional assignments.
3. Color assignment: New color table is created for the lobes, either from the JSON file specification or using default colors.
4. Metadata update: Region names and identifiers are updated to reflect the lobar structure.
The method is particularly useful for:
Simplifying complex parcellations for visualization
Reducing multiple comparisons in statistical analyses
Creating anatomically meaningful ROI groups
Cross-study comparisons at the lobar level
Educational and clinical applications
Examples
Basic lobar grouping with default scheme:
>>> # Group Desikan-Killiany regions into standard lobes >>> lobar_parc = parc.group_into_lobes(grouping='desikan') >>> print(f"Original regions: {len(parc.regnames)}") >>> print(f"Lobar regions: {len(lobar_parc.regnames)}") >>> print(f"Lobe names: {lobar_parc.regnames}")
Save lobar parcellation to file:
>>> # Create and save lobar parcellation >>> output_file = '/results/lh.desikan_lobes.annot' >>> lobar_parc = parc.group_into_lobes( ... grouping='desikan', ... out_annot=output_file ... ) >>> print(f"Lobar parcellation saved to: {output_file}")
Use custom JSON grouping file:
>>> # Create custom lobe definitions >>> custom_json = '/configs/custom_lobes.json' >>> lobar_parc = parc.group_into_lobes( ... grouping='mylobes', ... lobes_json=custom_json ... )
Force overwrite existing files:
>>> # Overwrite existing lobar parcellation >>> lobar_parc = parc.group_into_lobes( ... grouping='desikan', ... out_annot='/existing/file.annot', ... force=True ... )
See also
export_to_tsvExport parcellation tables for external analysis
map_valuesMap regional values to surface vertices
AnnotParcellationMain class for parcellation handling
- class clabtoolkit.freesurfertools.FreeSurferSubject(subj_id, subjs_dir=None)[source]
Bases:
objectA comprehensive class for managing and analyzing FreeSurfer subject data.
This class provides methods to work with FreeSurfer subjects, including initialization of file structures, processing status checking, launching FreeSurfer commands, and extracting morphometric statistics.
- __init__(subj_id, subjs_dir=None)[source]
Initialize the FreeSurferSubject object with subject ID and subjects directory.
Creates organized dictionaries containing paths to all standard FreeSurfer outputs including MRI volumes, surface files, parcellations, and statistics.
- Parameters:
subj_id (str) – FreeSurfer subject identifier matching the directory name in the FreeSurfer subjects directory.
subjs_dir (str or Path, optional) – Path to the FreeSurfer subjects directory. If None, uses the SUBJECTS_DIR environment variable. Directory will be created if it doesn’t exist. Default is None.
- fs_files
Nested dictionary containing organized paths to all FreeSurfer files organized by data type (mri, surf, stats) and hemisphere.
- Type:
Examples
>>> subject = FreeSurferSubject('sub-001') >>> print(subject.fs_files['mri']['T1']) >>> lh_thickness = subject.fs_files['surf']['lh']['map']['thickness']
- get_hemi_dicts(subj_dir, hemi)[source]
Create organized dictionaries containing hemisphere-specific FreeSurfer file paths.
Helper method that constructs structured dictionaries for surface meshes, morphometric maps, parcellations, and statistics files for a specified hemisphere.
- Parameters:
- Returns:
s_dict (dict) – Surface mesh file paths (pial, white, inflated, sphere). Empty string if not found.
m_dict (dict) – Morphometric map file paths (curv, sulc, thickness, area, volume, lgi). Empty string if not found.
p_dict (dict) – Parcellation annotation file paths (desikan, destrieux, dkt). Empty string if not found.
t_dict (dict) – Statistics file paths for each parcellation and curvature. Empty string if not found.
Examples
>>> surf, maps, parc, stats = subject.get_hemi_dicts(subj_dir, 'lh') >>> print(surf['pial'])
- get_proc_status()[source]
Check the FreeSurfer processing status for this subject.
Evaluates which FreeSurfer processing stages have been completed by checking for the existence of key output files. Handles missing pial surface files by copying from pial.T1 files when needed.
Attributes Set
- pstatusstr
Processing status: ‘unprocessed’, ‘autorecon1’, ‘autorecon2’, or ‘processed’.
Notes
‘unprocessed’: No processing done
‘autorecon1’: Basic preprocessing completed
‘autorecon2’: Surface reconstruction completed
‘processed’: Full processing including parcellation completed
Examples
>>> subject.get_proc_status() >>> print(f"Status: {subject.pstatus}") >>> if subject.pstatus == 'processed': ... print("Ready for analysis")
- get_cras()[source]
Extract the CRAS (Center of Rotation in AC-PC Space) coordinates from the Talairach transform file. Reads the Talairach transform file (talairach.lta) to extract the CRAS coordinates, which represent the center of rotation in the AC-PC aligned space. These coordinates are essential for accurate spatial normalization and alignment of brain images.
- Parameters:
None
- Returns:
cras – A tuple containing the CRAS coordinates (x, y, z) in millimeters.
- Return type:
- Raises:
ValueError – If the Talairach transform file does not exist.
Examples
>>> subject.get_cras() >>> print(f"CRAS coordinates: {subject.cras}")
- launch_freesurfer(t1w_img=None, proc_stage='all', extra_proc=None, cont_tech='local', cont_image=None, fs_license=None, force=False)[source]
Launch FreeSurfer recon-all processing with flexible options and containerization support.
Provides interface for running FreeSurfer’s recon-all pipeline with support for containerized execution, incremental processing, and additional modules.
- Parameters:
t1w_img (str or Path, optional) – Path to input T1-weighted MRI image. Required for unprocessed subjects.
proc_stage (str or list, optional) – Processing stage(s): ‘all’, ‘autorecon1’, ‘autorecon2’, ‘autorecon3’, or list of stages. Default is ‘all’.
extra_proc (str or list, optional) – Additional modules: ‘lgi’, ‘thalamus’, ‘brainstem’, ‘hippocampus’, ‘amygdala’, ‘hypothalamus’. Default is None.
cont_tech (str, optional) – Container technology: ‘local’, ‘docker’, ‘singularity’. Default is ‘local’.
cont_image (str or Path, optional) – Container image specification when using containerization.
fs_license (str or Path, optional) – Path to FreeSurfer license file for containers.
force (bool, optional) – Force reprocessing even if outputs exist. Default is False.
- Returns:
proc_status – Updated processing status after completion.
- Return type:
- Raises:
ValueError – If invalid processing stages or missing required files.
Examples
>>> # Basic processing >>> status = subject.launch_freesurfer(t1w_img='/data/T1w.nii.gz') >>> >>> # With extra modules >>> status = subject.launch_freesurfer( ... t1w_img='/data/T1w.nii.gz', ... extra_proc=['lgi', 'hippocampus'] ... ) >>> >>> # Using Docker >>> status = subject.launch_freesurfer( ... t1w_img='/data/T1w.nii.gz', ... cont_tech='docker', ... cont_image='freesurfer/freesurfer:7.2.0' ... )
- create_stats_table(lobes_grouping='desikan', add_bids_entities=False, output_file=None)[source]
Generate comprehensive FreeSurfer statistics table combining morphometric measurements.
Extracts and organizes cortical and volumetric measurements from FreeSurfer outputs into a structured DataFrame suitable for analysis.
- Parameters:
lobes_grouping (str, optional) – Parcellation grouping method for lobar regions: ‘desikan’ or ‘desikan+cingulate’. Default is ‘desikan’.
add_bids_entities (bool, optional) – Whether to extract BIDS entities from subject ID. Default is False.
output_file (str or Path, optional) – Path to save the DataFrame as CSV. If None, not saved. Default is None.
- Returns:
pd.DataFrame – Comprehensive statistics table with surface-based and volumetric measurements across multiple parcellation schemes.
Attributes Set
————–
stats_table (pd.DataFrame) – The generated statistics table stored as object attribute.
- Return type:
DataFrame
Examples
>>> # Generate basic stats table >>> stats_df = subject.create_stats_table() >>> print(f"Generated {len(stats_df)} measurements") >>> >>> # Save to file with BIDS entities >>> stats_df = subject.create_stats_table( ... add_bids_entities=True, ... output_file='/results/subject_stats.csv' ... )
- volume_morpho(parcellations=['desikan+aseg', 'destrieux+aseg', 'dkt+aseg'], lobes_grouping='desikan')[source]
Compute volume measurements from FreeSurfer volumetric parcellations.
Extracts volumetric measurements from specified FreeSurfer parcellations and returns organized DataFrame with volume values per region.
- Parameters:
parcellations (list, optional) – List of parcellation names to compute volumes from. Default includes Desikan-Killiany, Destrieux, and DKT atlases combined with subcortical segmentation.
lobes_grouping (str, optional) – Grouping method for lobar segmentation: ‘desikan’ or ‘desikan+cingulate’. Default is ‘desikan’.
- Returns:
DataFrame with volume measurements organized by parcellation atlas and brain region.
- Return type:
pd.DataFrame
Examples
>>> # Compute volumes for default parcellations >>> vol_df = subject.volume_morpho() >>> print(f"Computed volumes for {len(vol_df)} regions") >>> >>> # Custom parcellations >>> vol_df = subject.volume_morpho( ... parcellations=['desikan+aseg', 'dkt+aseg'] ... )
- surface_hemi_morpho(hemi='lh', lobes_grouping='desikan', verbose=False)[source]
Compute morphometric metrics for a hemisphere using cortical surface data.
Extracts morphometric properties like thickness, surface area, and curvature from cortical surfaces, maps, and parcellations for the specified hemisphere.
- Parameters:
- Returns:
DataFrame with morphometric measurements including thickness, area, curvature, and Euler characteristics organized by parcellation and region.
- Return type:
pd.DataFrame
Examples
>>> # Process left hemisphere >>> lh_df = subject.surface_hemi_morpho(hemi='lh') >>> print(f"Extracted {len(lh_df)} morphometric measurements") >>> >>> # Process with verbose output >>> rh_df = subject.surface_hemi_morpho( ... hemi='rh', ... verbose=True ... )
- static set_freesurfer_directory(fs_dir=None)[source]
Set up the FreeSurfer subjects directory and configure environment variables.
Creates the FreeSurfer directory if it doesn’t exist and sets the SUBJECTS_DIR environment variable. Used to ensure proper FreeSurfer environment setup.
- Parameters:
fs_dir (str or Path, optional) – Path to FreeSurfer subjects directory. If None, extracts from SUBJECTS_DIR environment variable. Directory will be created if it doesn’t exist. Default is None.
- Returns:
The directory path is set in the SUBJECTS_DIR environment variable.
- Return type:
None
- Raises:
ValueError – If fs_dir is None and SUBJECTS_DIR environment variable is not set.
Examples
>>> # Use environment variable >>> FreeSurferSubject.set_freesurfer_directory() >>> >>> # Set custom directory >>> FreeSurferSubject.set_freesurfer_directory('/data/freesurfer') >>> print(os.environ['SUBJECTS_DIR'])
- annot2ind(ref_id, hemi, fs_annot, ind_annot, cont_tech='local', cont_image=None, force=False, verbose=False)[source]
Map annotation parcellation from reference space to individual subject space.
Uses FreeSurfer’s mri_surf2surf to transfer parcellation labels from a reference subject to the individual subject’s surface, followed by gap-filling to ensure complete cortical coverage.
- Parameters:
ref_id (str) – FreeSurfer subject ID of the reference subject containing the source annotation file.
hemi (str) – Hemisphere identifier: ‘lh’ or ‘rh’.
fs_annot (str or Path) – Path to source annotation file or basename. Can be full path or just the annotation name (e.g., ‘aparc’). Also accepts GIFTI files (.gii).
ind_annot (str or Path) – Path for output annotation file in individual subject space.
cont_tech (str, optional) – Container technology: ‘local’, ‘docker’, ‘singularity’. Default is ‘local’.
cont_image (str or Path, optional) – Container image specification when using containerization. Default is None.
force (bool, optional) – Force processing even if output file exists. Default is False.
verbose (bool, optional) – Print verbose messages about processing status. Default is False.
- Returns:
ind_annot – Path to the created individual space annotation file.
- Return type:
- Raises:
FileNotFoundError – If the source annotation file cannot be found in expected locations.
Notes
The method performs the following steps: 1. Converts GIFTI to annotation format if needed 2. Uses mri_surf2surf for surface-to-surface mapping 3. Applies gap-filling to ensure complete cortical labeling 4. Handles containerized execution with proper volume mounting
Examples
>>> # Map Desikan-Killiany parcellation >>> output_file = subject.annot2ind( ... ref_id='fsaverage', ... hemi='lh', ... fs_annot='aparc', ... ind_annot='/output/lh.aparc.individual.annot' ... ) >>> >>> # Using Docker container >>> output_file = subject.annot2ind( ... ref_id='fsaverage', ... hemi='rh', ... fs_annot='/path/to/custom.annot', ... ind_annot='/output/rh.custom.individual.annot', ... cont_tech='docker', ... cont_image='freesurfer/freesurfer:7.2.0' ... )
- gcs2ind(fs_gcs, ind_annot, hemi, cont_tech='local', cont_image=None, force=False, verbose=False)[source]
Apply GCS classifier to generate individual subject parcellation.
Uses FreeSurfer’s mris_ca_label to apply a trained Gaussian Classifier Surface (GCS) file to the individual subject, creating subject-specific parcellation followed by gap-filling for complete coverage.
- Parameters:
fs_gcs (str or Path) – Path to the FreeSurfer GCS (Gaussian Classifier Surface) file containing the trained classifier model.
ind_annot (str or Path) – Path for output annotation file in individual subject space.
hemi (str) – Hemisphere identifier: ‘lh’ or ‘rh’.
cont_tech (str, optional) – Container technology: ‘local’, ‘docker’, ‘singularity’. Default is ‘local’.
cont_image (str or Path, optional) – Container image specification when using containerization. Default is None.
force (bool, optional) – Force processing even if output file exists. Default is False.
verbose (bool, optional) – Print verbose messages about processing status. Default is False.
- Returns:
ind_annot – Path to the created individual space annotation file.
- Return type:
Notes
The method performs the following steps: 1. Uses mris_ca_label with cortex label and sphere registration 2. Applies the GCS classifier to generate parcellation labels 3. Performs gap-filling to ensure complete cortical coverage 4. Handles containerized execution with proper volume mounting
Requires the following FreeSurfer files for the individual subject: - cortex.label: Defines cortical vertices - sphere.reg: Spherical surface registration - Standard FreeSurfer directory structure
Examples
>>> # Apply Desikan-Killiany GCS classifier >>> output_file = subject.gcs2ind( ... fs_gcs='/atlases/lh.aparc.gcs', ... ind_annot='/output/lh.aparc.individual.annot', ... hemi='lh' ... ) >>> >>> # Force reprocessing with custom classifier >>> output_file = subject.gcs2ind( ... fs_gcs='/custom/rh.custom_atlas.gcs', ... ind_annot='/output/rh.custom.individual.annot', ... hemi='rh', ... force=True, ... verbose=True ... )
- surf2vol(atlas, out_vol, gm_grow='0', color_table=None, bool_native=False, bool_mixwm=False, cont_tech='local', cont_image=None, force=False, verbose=False)[source]
Create volumetric parcellation from surface annotation files.
Converts surface-based parcellation annotations to volumetric format, with options for label growing, white matter mixing, and coordinate space selection.
- Parameters:
atlas (str or Path) – Atlas identifier or name for the surface parcellation to convert. Should correspond to available annotation files for both hemispheres.
out_vol (str or Path) – Path for output volumetric parcellation file.
gm_grow (int or str, optional) – Amount in millimeters to grow gray matter labels into surrounding tissue. Can help fill gaps between surface and volume. Default is “0”.
color_table (list or str, optional) – Format(s) for saving color lookup table: ‘tsv’, ‘lut’, or list of both [‘tsv’, ‘lut’]. Default is None (no color table saved).
bool_native (bool, optional) – If True, output parcellation in native subject space. If False, uses FreeSurfer’s standard space. Default is False.
bool_mixwm (bool, optional) – Mix cortical white matter growing with gray matter labels. Extends cortical labels into white matter regions. Default is False.
cont_tech (str, optional) – Container technology: ‘local’, ‘docker’, ‘singularity’. Default is ‘local’.
cont_image (str or Path, optional) – Container image specification when using containerization. Default is None.
force (bool, optional) – Force processing even if output file exists. Default is False.
verbose (bool, optional) – Print verbose messages about processing progress. Default is False.
- Returns:
out_vol – Path to the created volumetric parcellation file.
- Return type:
Notes
This method is particularly useful for: - Creating volumetric ROIs from surface parcellations - Bridging surface-based and volume-based analyses - Generating masks for volume-based connectivity analysis - Converting surface atlases to volume format for other software
The process typically involves projecting surface labels onto the volumetric space, with optional growing and white matter integration to ensure comprehensive tissue coverage.
Examples
>>> # Basic surface-to-volume conversion >>> vol_file = subject.surf2vol( ... atlas='aparc', ... out_vol='/output/aparc_volume.mgz' ... ) >>> >>> # With gray matter growing and color table >>> vol_file = subject.surf2vol( ... atlas='aparc.a2009s', ... out_vol='/output/destrieux_volume.mgz', ... gm_grow="2", ... color_table=['tsv', 'lut'], ... bool_mixwm=True ... ) >>> >>> # Native space output >>> vol_file = subject.surf2vol( ... atlas='custom_atlas', ... out_vol='/output/custom_native.nii.gz', ... bool_native=True, ... force=True ... )
- conform2native(mgz_conform, nii_native, interp_method='nearest', cont_tech='local', cont_image=None, force=False)[source]
Transform image from FreeSurfer conform space to native acquisition space.
Uses FreeSurfer’s mri_vol2vol to transform images from the standardized conform space (256³ isotropic) back to the original native acquisition space and dimensions.
- Parameters:
mgz_conform (str or Path) – Path to input image in FreeSurfer conform space (typically .mgz format).
nii_native (str or Path) – Path for output image in native acquisition space.
interp_method (str, optional) – Interpolation method for resampling: ‘nearest’, ‘trilinear’, or ‘cubic’. Use ‘nearest’ for label/segmentation images. Default is ‘nearest’.
cont_tech (str, optional) – Container technology: ‘local’, ‘docker’, ‘singularity’. Default is ‘local’.
cont_image (str or Path, optional) – Container image specification when using containerization. Default is None.
force (bool, optional) – Force processing even if output exists. If False, checks dimensions before deciding whether to reprocess. Default is False.
- Returns:
Output file is created at the specified nii_native path.
- Return type:
None
- Raises:
FileNotFoundError – If the required rawavg.mgz file (native space reference) doesn’t exist.
Notes
This method is essential for bringing FreeSurfer processing results back to native space for integration with other analyses or visualization in original acquisition coordinates. The transformation uses the header information from rawavg.mgz as the target native space reference.
Examples
>>> # Convert parcellation to native space >>> subject.conform2native( ... mgz_conform='/fs/mri/aparc+aseg.mgz', ... nii_native='/output/aparc_native.nii.gz' ... ) >>> >>> # Convert with trilinear interpolation >>> subject.conform2native( ... mgz_conform='/fs/mri/T1.mgz', ... nii_native='/output/T1_native.nii.gz', ... interp_method='trilinear' ... )
- get_surface(hemi, surf_type)[source]
Get the file path for a specific surface mesh.
Returns the path to surface files organized in the fs_files structure based on hemisphere and surface type specifications.
- Parameters:
- Returns:
surf_file – Full path to the requested surface file.
- Return type:
- Raises:
ValueError – If hemisphere is not ‘lh’ or ‘rh’.
ValueError – If surf_type is not one of the valid surface types.
Examples
>>> # Get left hemisphere pial surface >>> pial_surf = subject.get_surface('lh', 'pial') >>> print(pial_surf) >>> >>> # Get right hemisphere white matter surface >>> white_surf = subject.get_surface('rh', 'white')
- get_vertexwise_map(hemi, map_type)[source]
Get the file path for a specific vertex-wise morphometric map.
Returns the path to morphometric map files organized in the fs_files structure based on hemisphere and map type specifications.
- Parameters:
- Returns:
map_file – Full path to the requested morphometric map file.
- Return type:
- Raises:
ValueError – If hemisphere is not ‘lh’ or ‘rh’.
ValueError – If map_type is not one of the valid morphometric map types.
Examples
>>> # Get left hemisphere cortical thickness >>> thickness_map = subject.get_vertexwise_map('lh', 'thickness') >>> print(thickness_map) >>> >>> # Get right hemisphere curvature >>> curv_map = subject.get_vertexwise_map('rh', 'curv')
- get_annotation(hemi, annot_type)[source]
Get the file path for a specific parcellation annotation.
Returns the path to annotation files organized in the fs_files structure based on hemisphere and annotation type specifications.
- Parameters:
- Returns:
annot_file – Full path to the requested annotation file.
- Return type:
- Raises:
ValueError – If hemisphere is not ‘lh’ or ‘rh’.
ValueError – If annot_type is not one of the valid annotation types.
Examples
>>> # Get left hemisphere Desikan-Killiany parcellation >>> aparc_file = subject.get_annotation('lh', 'desikan') >>> print(aparc_file) >>> >>> # Get right hemisphere Destrieux parcellation >>> destrieux_file = subject.get_annotation('rh', 'destrieux')
- clabtoolkit.freesurfertools.create_individual_freesurfer_table(subj_id, subjs_dir=None, out_tab_file=None, add_bids_entities=False)[source]
Create a dataset table from the subjects in the given directory. :param subj_id: The subject ID for which to create the dataset table. :type subj_id: str :param subjs_dir: The directory containing the FreeSurfer subjects. If None, uses the
FREESURFER_HOME environment variable to locate the subjects directory.
- Parameters:
- Returns:
A DataFrame containing the morphometry table for the subject.
- Return type:
pd.DataFrame
- Raises:
ValueError – If the provided subjs_dir is not a valid directory.
- clabtoolkit.freesurfertools.process_subject(fs_fullid, fs_subject_dir, out_folder)[source]
Process a single subject and return the result.
- clabtoolkit.freesurfertools.create_freesurfer_table(out_folder, ids_file=None, fs_subject_dir=None, max_workers=1)[source]
Create FreeSurfer stats tables for multiple subjects in parallel.
- Parameters:
out_folder (str or Path) – The output folder for stats tables.
ids_file (str or List[str], optional) – A text file containing subject IDs (one per line) or a list of subject IDs. If None, an error is raised.
fs_subject_dir (str or Path, optional) – The FreeSurfer subjects directory. If None, uses the SUBJECTS_DIR environment variable.
max_workers (int, optional) – The maximum number of worker threads to use for parallel processing. Default is 1 (non-parallel).
- Return type:
None
Notes
This function processes each subject in parallel using ThreadPoolExecutor and displays a progress bar. It handles errors gracefully and provides a summary of completed and failed subjects.
Example
>>> create_freesurfer_table("/path/to/output", "/path/to/ids.txt", "/path/to/freesurfer/subjects", max_workers=4)
- clabtoolkit.freesurfertools.create_fsaverage_links(fssubj_dir, fsavg_dir=None, refsubj_name=None)[source]
Create symbolic links to the fsaverage reference subject folder.
Creates symbolic links from a custom FreeSurfer subjects directory to the standard fsaverage template, enabling FreeSurfer tools to locate reference data.
- Parameters:
fssubj_dir (str or Path) – Target FreeSurfer subjects directory where the link will be created.
fsavg_dir (str or Path, optional) – Source fsaverage directory path. If None, uses FREESURFER_HOME/subjects/fsaverage. Default is None.
refsubj_name (str, optional) – Reference subject name. If None, uses ‘fsaverage’. Default is None.
- Returns:
link_folder – Path to the created symbolic link.
- Return type:
- Raises:
ValueError – If the FreeSurfer subjects directory or fsaverage directory doesn’t exist.
Examples
>>> # Create standard fsaverage link >>> link_path = create_fsaverage_links('/data/freesurfer_subjects') >>> >>> # Create link with custom reference >>> link_path = create_fsaverage_links( ... '/data/freesurfer_subjects', ... refsubj_name='fsaverage6' ... )
- clabtoolkit.freesurfertools.remove_fsaverage_links(linkavg_folder)[source]
Remove symbolic links to the fsaverage folder.
Safely removes symbolic links to fsaverage directories that don’t point to the original FreeSurfer installation location.
- Parameters:
linkavg_folder (str or Path) – Path to the fsaverage link folder to potentially remove.
Notes
Only removes links that don’t point to the original FREESURFER_HOME location to prevent accidental deletion of the actual fsaverage data.
Examples
>>> # Remove custom fsaverage link >>> remove_fsaverage_links('/data/freesurfer_subjects/fsaverage')
- clabtoolkit.freesurfertools.region_to_vertexwise(reg_values, labels, reg_ctable)[source]
Map regional values to vertex-wise values using parcellation labels.
Assigns regional measurements to individual vertices based on their parcellation labels, creating vertex-wise data from region-wise data.
- Parameters:
reg_values (np.ndarray) – Array of values for each region. Can be 1D or 2D array.
labels (np.ndarray) – Array of parcellation labels for each vertex.
reg_ctable (np.ndarray) – Color table with shape (N, 5) where column 4 contains region labels.
- Returns:
vertex_values – Array with values mapped to each vertex. Shape: (num_vertices, num_measures).
- Return type:
np.ndarray
- Raises:
ValueError – If number of regions in reg_values doesn’t match reg_ctable dimensions or if reg_values has more than 2 dimensions.
Examples
>>> # Map thickness values to vertices >>> regional_thickness = np.array([2.5, 3.1, 2.8]) >>> vertex_thickness = region_to_vertexwise( ... regional_thickness, vertex_labels, color_table ... )
- clabtoolkit.freesurfertools.create_vertex_colors(labels, reg_ctable)[source]
Create per-vertex RGBA colors based on parcellation labels.
Assigns colors to vertices based on their parcellation region using the color table information.
- Parameters:
labels (np.ndarray) – Array of parcellation labels for each vertex.
reg_ctable (np.ndarray) – Color table with shape (N, 5) where first 3 columns are RGB values and column 4 contains region labels.
- Returns:
vertex_colors – Array of RGB colors for each vertex with shape (num_vertices, 3). Default color is gray (240, 240, 240) for unlabeled vertices.
- Return type:
np.ndarray
Examples
>>> # Create vertex colors for visualization >>> colors = create_vertex_colors(vertex_labels, color_table) >>> print(f"Colors shape: {colors.shape}") # (num_vertices, 3)
- clabtoolkit.freesurfertools.colors2colortable(colors)[source]
Convert color list to FreeSurfer color table format.
Transforms hexadecimal colors or RGB arrays into FreeSurfer’s standard color table format with packed RGB values.
- Parameters:
colors (list or np.ndarray) – List of hexadecimal color strings (e.g., [‘#FF0000’, ‘#00FF00’]) or numpy array of RGB values.
- Returns:
colortable – FreeSurfer color table with shape (N, 5) containing RGB values, alpha channel, and packed RGB values.
- Return type:
np.ndarray
- Raises:
ValueError – If colors is not a list or numpy array.
Examples
>>> # Convert hex colors to color table >>> hex_colors = ["#FF0000", "#00FF00", "#0000FF"] >>> ctab = colors2colortable(hex_colors) >>> print(f"Color table shape: {ctab.shape}")
- clabtoolkit.freesurfertools.resolve_colortable_duplicates(color_table)[source]
Make all RGB colors in FreeSurfer color table unique.
Identifies duplicate RGB colors and modifies them by incrementing color channels until uniqueness is achieved. Updates packed RGB values accordingly.
- Parameters:
color_table (np.ndarray) – FreeSurfer color table with shape (n, 5) where columns 0-2 are RGB, column 3 is alpha, and column 4 is packed RGB value.
- Returns:
modified_table (np.ndarray) – Updated color table with unique colors.
modification_log (dict) – Dictionary containing details of changes made including original duplicates count and list of modifications.
packed_values_mapping (dict) – Dictionary with ‘old_values’ and ‘new_values’ arrays for updating label maps accordingly.
Examples
>>> # Resolve duplicate colors >>> unique_table, log, mapping = resolve_colortable_duplicates(color_table) >>> print(f"Modified {len(log['modifications_made'])} colors")
- clabtoolkit.freesurfertools.find_unique_color(rgb, rgb_to_indices)[source]
Find unique RGB color by systematically modifying channels.
Helper function that searches for an unused RGB color by incrementing or decrementing color channels in order: Blue, Green, Red.
- Parameters:
rgb (np.ndarray) – Original RGB values [R, G, B].
rgb_to_indices (dict) – Dictionary mapping RGB tuples to indices for collision detection.
- Returns:
New unique RGB values.
- Return type:
np.ndarray
- Raises:
RuntimeError – If no unique color can be found (extremely rare).
- clabtoolkit.freesurfertools.verify_packed_rgb_values(color_table)[source]
Verify that packed RGB values are correctly calculated.
Checks if the packed RGB values (column 4) match the calculated values from RGB channels using the formula: R + (G << 8) + (B << 16).
- Parameters:
color_table (np.ndarray) – FreeSurfer color table to verify.
- Returns:
all_correct (bool) – True if all packed values are correct.
incorrect_indices (list) – List of dictionaries with details of incorrect entries.
Examples
>>> # Verify color table integrity >>> is_correct, errors = verify_packed_rgb_values(color_table) >>> if not is_correct: ... print(f"Found {len(errors)} incorrect packed values")
- clabtoolkit.freesurfertools.detect_hemi(file_name)[source]
Detect hemisphere from filename using common naming conventions.
Identifies left (‘lh’) or right (‘rh’) hemisphere from FreeSurfer and BIDS-style filenames using various naming patterns.
- Parameters:
file_name (str or Path) – Filename to analyze for hemisphere information.
- Returns:
hemi – Hemisphere identifier (‘lh’ or ‘rh’) or None if not detected.
- Return type:
str or None
Notes
Recognizes patterns like ‘lh.’, ‘rh.’, ‘hemi-L’, ‘hemi-left’, etc. Issues warning if hemisphere cannot be determined.
Examples
>>> # Detect from FreeSurfer filename >>> hemi = detect_hemi('lh.aparc.annot') >>> print(hemi) # 'lh' >>> >>> # Detect from BIDS filename >>> hemi = detect_hemi('sub-01_hemi-L_pial.surf.gii') >>> print(hemi) # 'lh'
- clabtoolkit.freesurfertools.parse_freesurfer_lta(filepath)[source]
Parse a FreeSurfer .lta (Linear Transform Array) file.
Parameters:
- filepathstr or Path
Path to the .lta file
Returns:
- dict
Dictionary containing parsed information including cras coordinates
- clabtoolkit.freesurfertools.get_cras_coordinates(filepath, source=True)[source]
Simple function to extract just the cras coordinates.
Parameters:
- filepathstr or Path
Path to the .lta file
- sourcebool
If True, return source cras; if False, return destination cras
Returns:
- tuple
(x, y, z) coordinates
- clabtoolkit.freesurfertools.load_lobes_json(lobes_json=None)[source]
Load JSON file containing anatomical lobe definitions.
Loads configuration file that defines how brain regions are grouped into anatomical lobes for coarser-grained analyses.
- Parameters:
lobes_json (str, Path, optional) – Path to custom JSON file. If None, uses default configuration file included with the package. Default is None.
- Returns:
pipe_dict – Dictionary containing lobe definitions and grouping schemes.
- Return type:
- Raises:
ValueError – If the specified JSON file doesn’t exist.
Examples
>>> # Load default lobe definitions >>> lobes_config = load_lobes_json() >>> print(lobes_config.keys()) >>> >>> # Load custom definitions >>> custom_config = load_lobes_json('/path/to/custom_lobes.json')
- clabtoolkit.freesurfertools.get_version(cont_tech='local', cont_image=None)[source]
Get FreeSurfer version number from installation or container.
Queries FreeSurfer installation to determine version number, supporting both local installations and containerized environments.
- Parameters:
- Returns:
vers_cad – FreeSurfer version number (e.g., ‘7.2.0’).
- Return type:
Examples
>>> # Get local FreeSurfer version >>> version = get_version() >>> print(f"FreeSurfer version: {version}") >>> >>> # Get version from Docker container >>> version = get_version( ... cont_tech='docker', ... cont_image='freesurfer/freesurfer:7.2.0' ... )
The freesurfertools module provides comprehensive integration with the FreeSurfer neuroimaging suite, enabling processing of cortical surfaces, annotation files, and morphometric data.
Key Features
Process FreeSurfer annotation files (.annot, .gcs formats)
Correct and validate parcellations
Parse FreeSurfer statistics files
Surface-based morphometry computation
Container technology integration
Multi-format conversion capabilities
Extract CRAS coordinates from transform files
Parse FreeSurfer LTA transform files
Main Classes
AnnotParcellation
The primary class for working with FreeSurfer annotation files.
Key Methods:
- load_from_file(): Load annotation files with optional reference surfaces
- correct_parcellation(): Fix unlabeled vertices in parcellations
- save_as_gcs(): Convert annotation to GCS format
- get_region_info(): Extract parcellation region information
- get_cras(): Extract CRAS coordinates from Talairach transform file
Common Usage Examples
Working with annotation files:
from clabtoolkit.freesurfertools import AnnotParcellation
# Load annotation file
annot = AnnotParcellation("lh.aparc.a2009s.annot")
# Correct parcellation by filling unlabeled vertices
annot.correct_parcellation()
# Convert to GCS format
annot.save_as_gcs("lh.aparc.a2009s.gcs")
# Get region information
region_info = annot.get_region_info()
Surface morphometry processing:
# Compute morphometry table for FreeSurfer subjects directory
from clabtoolkit import freesurfertools as fs
# Process all subjects in FreeSurfer subjects directory
morphometry_table = fs.compute_morphometry_table(
subjects_dir="/path/to/freesurfer/subjects",
parcellation="aparc.a2009s"
)
Transform and coordinate processing:
from clabtoolkit.freesurfertools import AnnotParcellation, parse_freesurfer_lta, get_cras_coordinates
# Extract CRAS coordinates from an annotation object
annot = AnnotParcellation("lh.aparc.a2009s.annot")
cras_coords = annot.get_cras()
print(f"CRAS coordinates: {cras_coords}")
# Parse LTA transform file
lta_data = parse_freesurfer_lta("/path/to/transforms/talairach.lta")
transform_matrix = lta_data['transform_matrix']
source_cras = lta_data['source_cras']
dest_cras = lta_data['dest_cras']
# Extract CRAS coordinates directly from LTA file
cras_coordinates = get_cras_coordinates(
"/path/to/transforms/talairach.lta",
source=True
)