{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# How to transform between various macaque MRI templates" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Authors:** Nikoloz Sirmpilatze (NSirmpilatze@dpz.eu) & Chris Klink (c.klink@nin.knaw.nl)\n", "\n", "**Last updated:** 16 Feb 2020\n", "\n", "**Requirements:**\n", "1. Using the command line\n", " * _ANTs_ >= 2.1.0\n", " * _antsApplyTransforms_ needs to be in your path as executable\n", "2. Using the nipype interface\n", " * _ANTs_ >= 2.1.0\n", " * _antsApplyTransforms_ needs to be in your path as executable\n", " * _python_ >= 3.7\n", " * _nipype_ >= 1.2.0\n", " \n", "PS: if you have older versions of ANTs or python on your system, make sure to still give it a try. There is a high chance that it will work. It's just not tested." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Warps are provided for transformations between the following templates\n", "1. [NMT v1.2](https://github.com/jms290/NMT)\n", "2. [NMT v1.3](https://github.com/jms290/NMT)\n", "3. [D99](https://afni.nimh.nih.gov/Macaque)\n", "4. [INIA19](https://www.nitrc.org/projects/inia19/https://www.nitrc.org/projects/inia19/)\n", "5. [MNI macaque](http://www.bic.mni.mcgill.ca/ServicesAtlases/Macaque)\n", "6. [Yerkes19](https://github.com/Washington-University/NHPPipelines)\n", "\n", "Within this notebook, they are abbreviated as *NMTv12*, *NMTv13*, *D99*, *INIA*, *MNI*, and *YRK* \n", "\n", "There are 30 warps in total (15 unique template pairs, with 2 directions per pair). The naming of the warps follows the scheme: \n", "* InputAbbrev_to_OutputAbbrev_CompositeWarp.nii.gz\n", "For example:\n", "* NMTv12_to_D99_CompositeWarp.nii.gz\n", "\n", "The 'Composite' refers to the fact that this warp combines information from a linear *affine* transform and a non-linear *SyN* transform.\n", "\n", "The code in this notebook also requires the template brain files. We do not provide copies of these templates (licenses often forbids redistribution), but you follow the links above and download them at the source. We do offer the warp files that will be produced by this workflow. They can be downloaded from [Zenodo](https://doi.org/10.5281/zenodo.3786357). " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you want to emulate this code, we suggest you use the following directory structure: \n", "\n", "|--- RheMAP \n", "  |--- notebooks \n", "  |--- templates \n", "  |--- warps \n", "    |--- final \n", "      |--- D99_to_INIA_CompositeWarp.nii.gz \n", "      |--- D99_to_MNI_CompositeWarp.nii.gz \n", "      |--- etc \n", "    |--- linear \n", "      |--- D99_to_INIA_affine_0GenericAffine.mat \n", "      |--- D99_to_MNI_affine_0GenericAffine.mat \n", "      |--- etc \n", "    |--- nonlinear \n", "      |--- D99_to_INIA_1InverseWarp.nii.gz \n", "      |--- D99_to_INIA_1Warp.nii.gz \n", "      |--- D99_to_MNI_1InverseWarp.nii.gz \n", "      |--- D99_to_MNI_1Warp.nii.gz \n", "      |--- etc \n", "  |--- warped_templates \n", "    |--- final \n", "      |--- D99_in_INIA_composite.nii.gz \n", "      |--- D99_in_MNI_composite.nii.gz \n", "      |--- etc \n", "    |--- linear \n", "      |--- D99_in_INIA_linear.nii.gz \n", "      |--- D99_in_MNI_linear.nii.gz \n", "      |--- etc \n", "    |--- nonlinear \n", "      |--- D99_in_INIA_linear+SyN.nii.gz \n", "      |--- D99_in_MNI_linear+SyN.nii.gz \n", "      |--- etc " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Based on the warp files and warped templates you could of course reconstruct the original templates with something like the following. \n", "\n", "Command line: \n", "```bash\n", "antsApplyTransforms -i \\\n", " -r \\ \n", " -o \\\n", " -t [,1] \\\n", " -n Linear \\\n", " -d 3\n", "``` \n", "\n", "NiPype: \n", "```python\n", "import nipype.interfaces.ants as ants \n", "ants.ApplyTransforms(\n", " input_image=,\n", " reference_image=, \n", " output_image=,\n", " transforms=,\n", " invert_transform_flags=True,\n", " interpolation='Linear',\n", " dimension=3)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Import libraries" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import time\n", "import os\n", "import nipype.interfaces.ants as ants # nipype interface for ANTs\n", "from nilearn.plotting import plot_roi, plot_stat_map #for visualization only" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Example 1: Transforming an atlas (parcellation) \n", "Let's take the D99 atlas and transform it from [D99](https://afni.nimh.nih.gov/Macaque) space to [MNI macaque](http://www.bic.mni.mcgill.ca/ServicesAtlases/Macaque) space" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First let's define relative paths to the necessary files.\n", "\n", "**You need to change these depending on where they are stored on your system.**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# ================================================================\n", "# NB! Specific for each individiual system \n", "# ================================================================\n", "base_path = os.path.dirname(os.getcwd()) + '/' # repo base folder\n", "templates_path = base_path + 'templates/'\n", "warps_path = base_path + 'warps/final/' # check with the existing warps\n", "data_path = base_path + 'example_data/'\n", "output_path = base_path + 'output/'\n", "\n", "D99_path = templates_path + 'D99/'\n", "MNI_path = templates_path + 'MNI/'\n", "NMTv12_path = templates_path + 'NMT/NMT_v1.2/'\n", "\n", "D99_brain = D99_path + 'D99_template.nii.gz'\n", "MNI_brain = MNI_path + 'macaque_25_model-MNI_brain.nii.gz'\n", "NMTv12_brain = NMTv12_path + 'NMT_SS.nii.gz'\n", "\n", "D99_atlas = D99_path + 'D99_atlas_1.2a.nii.gz'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# The name of the output file\n", "D99_atlas_in_MNI = output_path + 'D99_atlas_1.2a_in_MNI.nii.gz'\n", "\n", "# Full (affine + SyN) composite warp \n", "warp_D99_to_MNI = warps_path + 'D99_to_MNI_CompositeWarp.nii.gz'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot_roi(D99_atlas, bg_img=D99_brain, annotate=False,\n", " title='D99 atlas on D99 template');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Option a: using antsApplyTransforms through the command line" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Command:\n", "```bash\n", "antsApplyTransforms -i $D99_atlas -r $MNI_brain -o $D99_atlas_in_MNI \n", "-t $warp -n NearestNeighbor\n", "```\n", "Let's explain the arguments, which are passed through flags:\n", "* -i: input image\n", "* -r: reference image (target space)\n", "* -o: output image\n", "* -t: transform \n", "* -n: interpolation\n", " * The default is _Linear_, but here we set it to _NearestNeighbor_. Since the parcellation is defined with discrete numerical values, this ensures that we won't end up with any intermediate numbers in the output image" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's give this a try" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!antsApplyTransforms -i $D99_atlas -r $MNI_brain -o $D99_atlas_in_MNI -t $warp_D99_to_MNI -n NearestNeighbor" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot_roi(D99_atlas_in_MNI, bg_img=MNI_brain, annotate=False, dim=-0.5,\n", " title='D99 atlas on MNI template');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Option b: using the nipype interface for antsApplyTransforms\n", "[Read the nipype documentation here](https://nipype.readthedocs.io/en/latest/interfaces/generated/interfaces.ants/resampling.html#applytransforms)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "apply_warp = ants.ApplyTransforms(\n", " input_image=D99_atlas,\n", " reference_image=MNI_brain,\n", " output_image=D99_atlas_in_MNI,\n", " transforms=warp_D99_to_MNI,\n", " interpolation='NearestNeighbor')\n", "apply_warp.run();" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot_roi(D99_atlas_in_MNI, bg_img=MNI_brain, annotate=False, dim=-0.5,\n", " title='D99 atlas on MNI template');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The results with both options should be identical" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Example 2: Transforming a statistical map" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's transform an example statistical map from from [NMT](https://github.com/jms290/NMT) space to [D99](https://afni.nimh.nih.gov/Macaque) space" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stat_map_in_NMTv12 = data_path + 'example_stat_map_in_NMTv1.2.nii.gz'\n", "# The name of the output file\n", "stat_map_in_D99 = output_path + 'example_stat_map_in_D99.nii.gz'\n", "# Full (affine + SyN) composite warp \n", "warp_NMTv12_to_D99 = warps_path + 'NMTv1.2_to_D99_CompositeWarp.nii.gz'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot_stat_map(stat_map_in_NMTv12, bg_img=NMTv12_brain, annotate=False,\n", " threshold= 0.2, vmax=0.8, dim=-1,\n", " title='Statistical map on NMT template');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Option a: using antsApplyTransforms through the command line" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that this time we use _Linear_ interpolation. More advanced interpolation options are also available (e.g. 'BSpline'). " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!antsApplyTransforms -i $stat_map_in_NMTv12 -r $D99_brain -o $stat_map_in_D99 -t $warp_NMTv12_to_D99 -n Linear" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot_stat_map(stat_map_in_D99, bg_img=D99_brain, annotate=False,\n", " threshold= 0.2, vmax=0.8,\n", " title='Statistical map on D99 template');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Option b: using the nipype interface for antsApplyTransforms\n", "[Read the documentation here](https://nipype.readthedocs.io/en/latest/interfaces/generated/interfaces.ants/resampling.html#applytransforms)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "apply_warp = ants.ApplyTransforms(\n", " input_image=stat_map_in_NMTv12,\n", " reference_image=D99_brain,\n", " output_image=stat_map_in_D99,\n", " transforms=warp_NMTv12_to_D99,\n", " interpolation='Linear')\n", "apply_warp.run();" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plot_stat_map(stat_map_in_D99, bg_img=D99_brain, annotate=False,\n", " threshold= 0.2, vmax=0.8,\n", " title='Statistical map on D99 template');" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "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.7.6" } }, "nbformat": 4, "nbformat_minor": 4 }