Open vborghe opened 2 years ago
@pinheirochagas do you think what @complexbrains did here https://github.com/neurocausal/neurocausal_data/pull/5 actually belongs to meta rather than data? regardless of where it ends, clearly helpful for this too, no?
Next step: adapting the neuroquery code to atlas (rather than coordinates), choose atlas, convert all coordinates (and other atlases) to that one
@complexbrains's branch now has the MNI coordinates extraction code
templateflow might help with the mapping/conversions, but currently does not cover all the parcellations/atlases we had in mind (mostly MNI-ish spaces)
@complexbrains @pinheirochagas Following Jerome's suggestion, we might want to stick with MNI coordinates (i.e., convert everything to MNI coordinates) simply putting uniform values to all voxels that fall within a given atlas region
Here are a set of functions to convert atlas-specific region coordinates to MNI space and plot the regions on a standard MNI brain using nilearn. Some atlases will be fetched directly from nilearn, while others might require manual downloading of the .nii files. @complexbrai @vborghe @margokersey.
Implementation: 1. Fetching the Atlas: We've defined a function fetch_atlas(atlas_name) that fetches the atlas based on its name. Some atlases, like mars_atlas, desikan_killiany, talariach_ba, and talariach_gyrus, aal are placeholders for now and will need the paths to their respective volumetric atlas files (the function already accepts a path to the nii file: e.g.: https://www.oxcns.org/aal3.html). Atlases such as juelich, harvard_oxford and destrieux, can be fetched using nilearn's built-in datasets module.
2. Conversion to MNI Space:
For the current implementation, regions need to be entered as numerical values. In the future, we should create a dictionary that maps paper_region_name to atlas_label in order to retrieve the atlas_region_value and perform the conversion.
3. Plotting: Once the conversion is done, we have a function plot_anatomical_overlay(binary_mask_img) that plots the MNI coordinates of the region on a standard MNI brain for inspection. It looks great to me!
#%%
import numpy as np
import nibabel as nib
from nilearn import plotting, image
import nilearn
import nilearn.datasets
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
# https://github.com/neurocausal/neurocausal_meta/blob/main/atlas_labels_annotation.csv
#%%
def fetch_atlas(atlas_name):
if atlas_name == 'mars_atlas':
return None # find the volumetric atlas probably from file
elif atlas_name == 'desikan_killiany':
return None # find the volumetric atlas probably from file
if atlas_name == 'talariach_ba':
return None # find the volumetric atlas probably from file
if atlas_name == 'talariach_gyrus':
return None # find the volumetric atlas probably from file
if atlas_name == 'juelich':
return nilearn.datasets.fetch_atlas_juelich('maxprob-thr25-1mm').maps
elif atlas_name == 'harvard_oxford':
return nilearn.datasets.fetch_atlas_harvard_oxford('cort-maxprob-thr25-2mm').maps
elif atlas_name == 'destrieux':
return nilearn.datasets.fetch_atlas_destrieux_2009().maps
elif atlas_name == 'aal':
atlas_name = '/Users/pinheirochagas/Downloads/AAL3/AAL3v1.nii'
return atlas_name
else:
raise ValueError(f"Atlas {atlas_name} is not recognized or not supported in this function.")
#%%
def convert_to_mni(atlas_name, region_value):
# Fetch the atlas
atlas_obj = fetch_atlas(atlas_name)
# Load the atlas if it's a file path, otherwise proceed with the Nifti image
if isinstance(atlas_obj, str):
atlas_img = nib.load(atlas_obj)
else:
atlas_img = atlas_obj
atlas_data = atlas_img.get_fdata()
# Identify the region
region_voxels = np.argwhere(atlas_data == region_value)
# Convert the voxels to MNI space
mni_coordinates = [nib.affines.apply_affine(atlas_img.affine, voxel) for voxel in region_voxels]
return mni_coordinates
# %%
def create_mni_mask(mni_coordinates, template_shape, affine):
"""Create a binary mask in MNI space from the given coordinates."""
mask = np.zeros(template_shape)
for coord in mni_coordinates:
voxel = nib.affines.apply_affine(np.linalg.inv(affine), coord).astype(int)
mask[tuple(voxel)] = 1
mask_img = nib.Nifti1Image(mask, affine=affine)
return mask_img
def plot_anatomical_overlay(binary_mask_img):
"""Plot the binary mask on top of a standard MNI brain."""
# Create a custom colormap that only contains the color red
cmap = ListedColormap(['#000000', '#FF0000'])
# Create a matplotlib figure with a specified size
fig = plt.figure(figsize=(10, 8))
# Plot
plotting.plot_stat_map(binary_mask_img, display_mode='ortho', colorbar=False,
threshold=0.5, cmap=cmap, figure=fig)
plotting.show()
#%%
# Example usage:
region_value = 1 # replace with the value for your region of interest
mni_coords = convert_to_mni('aal', region_value)
template = nilearn.datasets.load_mni152_template()
binary_mask_img = create_mni_mask(mni_coords, template.shape, template.affine)
plot_anatomical_overlay(binary_mask_img)
# %%
atlas_list = ['juelich', 'harvard_oxford', 'destrieux', 'aal']
region_value = 1 # replace with the value for your region of interest
[plot_anatomical_overlay(create_mni_mask(convert_to_mni(atlas, region_value), template.shape, template.affine)) for atlas in atlas_list]
Example: Frontal_Inf_Oper_L from AAL into MNI
This looks great!! Thanks a lot, Pedro!
Once the papers have been filtered (#11) - key part of the preprocessing will be
Whatever the paper is using,