{ "cells": [ { "cell_type": "markdown", "id": "27977b1b", "metadata": {}, "source": [ "## Example of a Surface-based searchlight" ] }, { "cell_type": "code", "execution_count": 1, "id": "c6ea7628", "metadata": {}, "outputs": [], "source": [ "import AnatSearchlight.searchlight as sl\n", "import numpy as np\n", "import nibabel as nib" ] }, { "cell_type": "markdown", "id": "99a52172", "metadata": {}, "source": [ "To define a searchlight we need a: \n", "\n", "* Pial Surface (individual)\n", "* Gray Matter Mask (individual)\n", "* Functional mask image (mask.nii from GLM) telling us which voxels are availabe for searchlight analysis\n", "\n", "If we want to calculate the searchlight only for a part of a the surface, we can use a roi_specification (i.e. excluding the medial wall). \n", "\n", "The searchlight can be specified to have a specific radius in mm (on the surface) or a specific number of voxels. \n" ] }, { "cell_type": "code", "execution_count": 2, "id": "f042c110", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Processing center 0 of 29759\n", "Processing center 1000 of 29759\n", "Processing center 2000 of 29759\n", "Processing center 3000 of 29759\n", "Processing center 4000 of 29759\n", "Processing center 5000 of 29759\n", "Processing center 6000 of 29759\n", "Processing center 7000 of 29759\n", "Processing center 8000 of 29759\n", "Processing center 9000 of 29759\n", "Processing center 10000 of 29759\n", "Processing center 11000 of 29759\n", "Processing center 12000 of 29759\n", "Processing center 13000 of 29759\n", "Processing center 14000 of 29759\n", "Processing center 15000 of 29759\n", "Processing center 16000 of 29759\n", "Processing center 17000 of 29759\n", "Processing center 18000 of 29759\n", "Processing center 19000 of 29759\n", "Processing center 20000 of 29759\n", "Processing center 21000 of 29759\n", "Processing center 22000 of 29759\n", "Processing center 23000 of 29759\n", "Processing center 24000 of 29759\n", "Processing center 25000 of 29759\n", "Processing center 26000 of 29759\n", "Processing center 27000 of 29759\n", "Processing center 28000 of 29759\n", "Processing center 29000 of 29759\n" ] } ], "source": [ "# Give it an appropriate structure name: Used for generating cifti-files for output\n", "mySearchlight = sl.SearchlightSurface('left_cortex')\n", "# These are the inndividual surfaces\n", "surf = ['example_data/sub-02_space-32k_hemi-L_pial.surf.gii',\n", " 'example_data/sub-02_space-32k_hemi-L_white.surf.gii']\n", "# This is the mask image for the functional data space\n", "voxel_mask = 'example_data/sub-02_ses-s1_mask.nii'\n", "\n", "# Optionally, you can define a roi-mask for the searchlight region on the surface. Centers outside of the mask will be ignored.\n", "# Instead of a gifti-image you can also use a numpy array with the indices of the vertices that should be included in the searchlight.\n", "roi_mask = 'example_data/tpl-fs32k_hemi-L_mask.label.gii'\n", "\n", "# Here we defining\n", "mySearchlight.define(surf,voxel_mask,roi=roi_mask,maxradius=20,maxvoxels=np.inf)\n", "mySearchlight.save('example_data/searchlight_surf.h5')" ] }, { "cell_type": "code", "execution_count": 3, "id": "80ab5dcb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Average size of the searchlight: 20.0 mm\n", "Average number of voxels: 325.5\n" ] } ], "source": [ "# You can now use the pre-computed searchlight.\n", "\n", "mySearchlight = sl.load('example_data/searchlight_surf.h5')\n", "print(f'Average size of the searchlight: {mySearchlight.radius.mean():.1f} mm')\n", "print(f'Average number of voxels: {mySearchlight.nvoxels.mean():.1f}')" ] }, { "cell_type": "code", "execution_count": 4, "id": "fafee176", "metadata": {}, "outputs": [], "source": [ "# Define the MVPA function that will be used in the searchlight\n", "# The functions take a n_images x n_voxels array as input.\n", "# and return either a scalar or vector as output.\n", "# Here we use simple example that calculate the mean activity in the searchlight region.\n", "def mvpa_mean_function(data):\n", " # Example of MVPA function that returns a scalar as an output argument\n", " return np.mean(data)\n", "\n", "def mvpa_multi_function(data):\n", " # Example of MVPA function that returns a vector as an output argument\n", " return np.mean(data,axis=1)\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "eefc2bc5", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "## Run the searchlight with the defined scalar MVPA function\n", "datafiles = [f\"example_data/sub-02_ses-s1_run-{r:02d}_reg-{s:02d}_beta.nii\" for r in range(1,3) for s in range(2)]\n", "results = mySearchlight.run(datafiles, mvpa_mean_function,verbose=False)\n", "mySearchlight.data_to_cifti(results,outfilename='example_data/output.dscalar.nii')" ] }, { "cell_type": "code", "execution_count": 6, "id": "3ccba25c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "## Run the searchlight with the defined scalar vector function\n", "datafiles = [f\"example_data/sub-02_ses-s1_run-{r:02d}_reg-{s:02d}_beta.nii\" for r in range(1,3) for s in range(2)]\n", "results = mySearchlight.run(datafiles, mvpa_multi_function,verbose=False)\n", "mySearchlight.data_to_cifti(results,outfilename='example_data/output_vector.dscalar.nii')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.0" } }, "nbformat": 4, "nbformat_minor": 5 }