diff --git a/README.md b/README.md
index 31055aa..3d28430 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,14 @@ This course is specifically aimed at MSc and PhD students with basic knowledge o
* Before seminar you are to install Docker https://www.docker.com/
* SEMINAR 1 (04.09) EEG analysis, Machine Learning in EEG
* SEMINAR 2 (04.09) MRI data analysis, sources, databases, tools
+ * Before seminar, please, do the following:
+ 1) Download data from link https://drive.google.com/drive/folders/1P0ZhS1EoDY6fncnJb7foNFPjY5uoN6r0?usp=sharing
+ 2) Clone repository to your local machine
+ 3) Run docker locally and ensure it working with command `docker run hello-world`
+ 4) In terminal: `cd to NEUROML/seminar2`
+ 5) Type command `docker build -t neuroml/seminar2:0.0.1` and wait for successfull build
+ 6) Run `docker run --rm -it -v /directory/to/downloaded/data:/workspace/data -p 8080:8080 neuroml/seminar2:0.0.1
+ 7) Open browser (preferebly Chrome) -> localhost:8080
* Before the seminar you are to install FreeSurfer https://surfer.nmr.mgh.harvard.edu/
* SEMINAR 3 (04.09) Machine Learning for structural MRI data analysis
* Before the seminar you are to get an account and granted access here https://db.humanconnectome.org/data/projects/HCP_1200
diff --git a/seminar2/Dockerfile b/seminar2/Dockerfile
index 9bcea2f..e563cbb 100644
--- a/seminar2/Dockerfile
+++ b/seminar2/Dockerfile
@@ -38,11 +38,30 @@ RUN apt-get update -qq \
grep \
less \
wget \
- bzip2 \
make \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
+ENV PATH="/opt/dcm2niix-latest/bin:$PATH"
+RUN apt-get update -qq \
+ && apt-get install -y -q --no-install-recommends \
+ cmake \
+ g++ \
+ gcc \
+ git \
+ make \
+ pigz \
+ zlib1g-dev \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* \
+ && git clone https://github.com/rordenlab/dcm2niix /tmp/dcm2niix \
+ && mkdir /tmp/dcm2niix/build \
+ && cd /tmp/dcm2niix/build \
+ && cmake -DCMAKE_INSTALL_PREFIX:PATH=/opt/dcm2niix-latest .. \
+ && make \
+ && make install \
+ && rm -rf /tmp/dcm2niix
+
ENV ANTSPATH="/opt/ants-2.2.0" \
PATH="/opt/ants-2.2.0:$PATH"
RUN echo "Downloading ANTs ..." \
@@ -102,6 +121,7 @@ RUN export PATH="/opt/miniconda-latest/bin:$PATH" \
'nilearn' \
'traits' \
'nipype' \
+ 'seaborn' \
&& sync && conda clean --all && sync
RUN wget https://ftpmirror.gnu.org/parallel/parallel-20190222.tar.bz2 \
@@ -120,8 +140,6 @@ COPY ./entrypoint.sh /entrypoint.sh
RUN chmod +x /workspace/multiproc.sh \
/entrypoint.sh
-
-
RUN "/neurodocker/startup.sh"
#RUN "./${FREESURFER_HOME}/SetUpFreeSurfer.sh"
@@ -142,6 +160,13 @@ RUN echo '{ \
\n ] \
\n ], \
\n [ \
+ \n "dcm2niix", \
+ \n { \
+ \n "version": "latest", \
+ \n "method": "source" \
+ \n } \
+ \n ], \
+ \n [ \
\n "ants", \
\n { \
\n "version": "2.2.0" \
diff --git a/seminar2/entrypoint.sh b/seminar2/entrypoint.sh
index f06ba16..4ba0ef1 100644
--- a/seminar2/entrypoint.sh
+++ b/seminar2/entrypoint.sh
@@ -1,9 +1,9 @@
#! /bin/bash
-printf 'Neurodocker startup - success'
+printf 'Neurodocker startup - success\n'
source $FREESURFER_HOME/SetUpFreeSurfer.sh
-printf 'FREESURFER - check'
+printf 'FREESURFER - check\n'
./opt/miniconda-latest/envs/neuro/bin/jupyter-lab --ip=0.0.0.0 --port=8080 --no-browser --allow-root --notebook-dir='/workspace' --NotebookApp.token=''
\ No newline at end of file
diff --git a/seminar2/seminar2_1_mri.ipynb b/seminar2/seminar2_1_mri.ipynb
index 79be393..fb95e28 100644
--- a/seminar2/seminar2_1_mri.ipynb
+++ b/seminar2/seminar2_1_mri.ipynb
@@ -1,5 +1,20 @@
{
"cells": [
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "PLAN:\n",
+ "\n",
+ "1) MRI data formats\n",
+ "2) accessing data voxel and meta data\n",
+ "3) transformations\n",
+ "4) preprocessing\n",
+ "5) visualization\n"
+ ]
+ },
{
"cell_type": "code",
"execution_count": 1,
@@ -428,7 +443,45 @@
"execution_count": null,
"metadata": {},
"outputs": [],
- "source": []
+ "source": [
+ "*Voxel size* and *Pixel spacing* are important as we for preprocessing we can use only isomorphic voxel"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Assume that you recieved new dicom from hospital and you need to convert to convinient NIFTI, let's review the tool distinctive from simple on above:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "!dcm2niix -o /workspace -f %i_%n_%p -z y /workspace/data/DICOM"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from nilearn.input_data import NiftiMasker\n",
+ "from nilearn import plotting\n",
+ "dcm_to_nii_convert = './1010_BRAIN_MR_T1_AX.nii.gz'\n",
+ "plot_convert = plotting.view_img(dcm_to_nii_convert,\n",
+ " bg_img=False,\n",
+ " cmap='gray',\n",
+ " symmetric_cmap=False,\n",
+ " threshold=0,\n",
+ " title='Drag mouse to go through slices')\n",
+ "plot_convert"
+ ]
}
],
"metadata": {
@@ -452,4 +505,4 @@
},
"nbformat": 4,
"nbformat_minor": 4
-}
+}
\ No newline at end of file
diff --git a/seminar2/seminar2_2_transform.ipynb b/seminar2/seminar2_2_transform.ipynb
index cb0bf3d..bb35f20 100644
--- a/seminar2/seminar2_2_transform.ipynb
+++ b/seminar2/seminar2_2_transform.ipynb
@@ -10,6 +10,13 @@
"warnings.filterwarnings('ignore')\n"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ ""
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
@@ -88,7 +95,7 @@
"mni_space_template = nib.load('/workspace/data/mni_icbm152_t1_tal_nlin_sym_09a.nii') # Full template\n",
"\n",
"nilearn.plotting.plot_anat(nii_file,\n",
- " title='Nifti T1 Native Space')\n",
+ " title='Nifti T1 Native Space', annotate=True)\n",
"\n",
"nilearn.plotting.plot_anat(mni_space_template,\n",
" title='Nifti MNI152 Space')\n",
@@ -154,6 +161,103 @@
"\"\"\".format(nii_file.shape, mni_space_template.shape))\n"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "You can think of the image affine as a combination of a series of transformations to go from voxel coordinates to mm coordinates in terms of the magnet isocenter. Here is the EPI affine broken down into a series of transformations, with the results shown on the localizer image:"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ ""
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from nibabel.affines import from_matvec, to_matvec, apply_affine\n",
+ "import numpy as np\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "reflect = np.array([[1, 0, 0],\n",
+ " [0, 1, 0],\n",
+ " [0, 0, 1]])\n",
+ "\n",
+ "translate_affine = from_matvec(reflect, [0, 0, 0]) # reflect + shift 10 x direction\n",
+ "translate_affine"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "transformed = np.dot(nii_file.get_qform(), translate_affine)\n",
+ "#nii_file.affine = transformed\n",
+ "print(transformed)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "header_info = nii_file.header\n",
+ "vox_data = np.array(nii_file.get_fdata())\n",
+ "transformed_nii = nib.Nifti1Image(vox_data, transformed, header_info)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "tranfsorm_image = nilearn.plotting.plot_anat(transformed_nii,\n",
+ " title='Space displacement', annotate=True)\n",
+ "tranfsorm_image.add_overlay(nii_file, threshold=0.1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "transform_image = nilearn.plotting.plot_anat(transformed_nii,\n",
+ " title='Space displacement', annotate=True)\n",
+ "transform_image.add_overlay(nii_file,threshold=0.8e3, colorbar=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "How about rotation?"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cos_gamma = np.cos(0.3)\n",
+ "sin_gamma = np.sin(0.3)\n",
+ "rotation_affine = np.array([[1, 0, 0, 0],\n",
+ " [0, cos_gamma, -sin_gamma, 0],\n",
+ " [0, sin_gamma, cos_gamma, 0],\n",
+ " [0, 0, 0, 1]])"
+ ]
+ },
{
"cell_type": "markdown",
"metadata": {},
diff --git a/seminar2/seminar2_3_freesurfer.ipynb b/seminar2/seminar2_3_freesurfer.ipynb
index 538f06d..495941f 100644
--- a/seminar2/seminar2_3_freesurfer.ipynb
+++ b/seminar2/seminar2_3_freesurfer.ipynb
@@ -1298,6 +1298,59 @@
"my_cmap = matplotlib.colors.LinearSegmentedColormap('my_colormap',cdict,64,1.9)"
]
},
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Let's look at morphological data of freesurfer, particularly thickness data defference between expert options and default options"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import seaborn as sns\n",
+ "import nibabel\n",
+ "\n",
+ "thickness_data = '/workspace/data/fs_preproc/100206/surf/lh.thickness'\n",
+ "thickness_expert = nibabel.freesurfer.io.read_morph_data(thickness_data)\n",
+ "\n",
+ "sns.distplot(thickness_expert, kde_kws={\"color\":\"b\", \"lw\": 2, \"label\":\"thickness_data_expert\"}, hist_kws={\"color\": \"b\"})\n",
+ "#sns.distplot(thickness_default, kde_kws={\"color\":\"b\", \"lw\": 2, \"label\":\"thickness_data_expert\"}, hist_kws={\"color\": \"b\"})"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plot_pial_lh = plotting.view_surf(inflated_path, thickness_data, threshold=0, cmap=my_cmap, black_bg=True)\n",
+ "plot_pial_lh"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "Plot segmentation maps"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plotting.view_img('/workspace/data/fs_preproc/100206/mri/wm.mgz', bg_img='/workspace/data/fs_preproc/100206/mri/brain.mgz',cmap='gray', opacity=0.7)"
+ ]
+ },
{
"cell_type": "code",
"execution_count": null,
@@ -1312,9 +1365,10 @@
"\n",
"hemi='lh'\n",
"subject_id='100206'\n",
- "subject_path = '/workspace/'\n",
- "inflated_path = os.path.join(subject_path, subject_id, 'surf', hemi + '.pial')\n",
- "thickness_data = nibabel.freesurfer.io.read_morph_data(os.path.join(subject_path, patient, 'surf', hemi + '.thickness'))\n",
+ "subject_path = '/workspace/data/fs_preproc'\n",
+ "pial_path = os.path.join(subject_path, subject_id, 'surf', hemi + '.pial')\n",
+ "thickness_data = nibabel.freesurfer.io.read_morph_data(os.path.join(subject_path, subject_id,\n",
+ " 'surf', hemi + '.thickness'))\n",
"inflated_path_1 = os.path.join(subject_path, subject_id, 'surf', 'rh' + '.inflated')"
]
},
@@ -1324,9 +1378,63 @@
"metadata": {},
"outputs": [],
"source": [
- "plot_pial_lh = plotting.view_surf(inflated_path, thickness_data, threshold=0, cmap=my_cmap, black_bg=True)\n",
+ "plot_pial_lh = plotting.view_surf(pial_path,\n",
+ " thickness_data,\n",
+ " threshold=0,\n",
+ " cmap=my_cmap)\n",
"plot_pial_lh"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import numpy as np\n",
+ "\n",
+ "labels, ctab, shape = nibabel.freesurfer.io.read_annot('/workspace/data/fs_preproc/100206/label/lh.aparc.annot')\n",
+ "plotting.plot_surf_roi(pial_path, roi_map=labels,\n",
+ " hemi='left', view='lateral',\n",
+ " bg_on_data=True,\n",
+ " darkness=.5)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inflated = '/workspace/data/fs_preproc/100206/surf/'\n",
+ "plot_pial_parc_lh = plotting.view_surf(pial_path,\n",
+ " labels, cmap='gist_ncar',\n",
+ " symmetric_cmap=False)\n",
+ "plot_pial_parc_lh"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "#### Extract features from stats data:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = pd.DataFrame()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
}
],
"metadata": {