{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "0zPY_FV0glOV"
},
"source": [
"# fMRI as Graph"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lCbZROxBwXUd"
},
"source": [
"**Prerequisite**:\n",
"1. ผู้เรียนควรศึกษาเนื้อหา Introduction to fMRI Preprocessing มาแล้ว โดยเฉพาะการเข้าใจว่า\n",
" \n",
" 1.1 fMRI เป็นข้อมูลที่มีทั้ง spatial dimension และ time dimension ซึ่งการ visualize ข้อมูลก็ทำได้หลายวิธี เช่น การดูภาพสมองที่เวลาใดเวลาหนึ่ง หรือ การดูข้อมูล time series ที่ voxel ใด voxel หนึ่ง\n",
"\n",
" 1.2 การทำ registration จะช่วยให้เราสามารถแปลงข้อมูล fMRI ที่เราเก็บมา ให้มีตำแหน่งของอวัยวะต่าง ๆ ตรงกับ template บางอย่าง (เช่น MRI Atlas ซึ่งมีข้อมูลเกี่ยวกับการแบ่งส่วนต่าง ๆ ของสมอง (brain parcellation)) ซึ่งจะช่วยให้เราสามารถนำเอาข้อมูลไปใช้ทำการวิเคราะห์ต่อได้ง่ายมากยิ่งขึ้น เช่น เราสามารถดึงเอา voxel จากบริเวณสมองที่เราสนใจออกมาทำการวิเคราะห์ต่อได้\n",
"\n",
"2. ผู้เรียนควรผ่านการศึกษาเนื้อหา Brain Building Blocks โดยเฉพาะบทเรียน [Functional Area & Network](https://youtu.be/DPiVUyxK3oM?si=JJwSyYKPbadxc9hG) และเนื้อหาที่เกี่ยวข้องกับ fMRI ทั้งหมด\n",
"\n",
"3. ผู้เรียนควรศึกษาเนื้อหา Signal Processing ของ Brain Code Camp มาแล้ว\n",
"\n",
"4. ผู้เรียนควรมีความรู้ความเข้าใจทางสถิติเบื้องต้น เช่น\n",
" \n",
" 4.1 ค่าเฉลี่ย (mean)\n",
" \n",
" 4.2 standard deviation/variance\n",
" \n",
" 4.3 correlation\n",
"\n",
"
\n",
"\n",
"**Main Source**: บทเรียนนี้ได้นำเอาโค้ดจากบทเรียน [Functional connectivity with nilearn](https://main-educational.github.io/intro_nilearn/functional-connectivity-with-nilearn.html), [Default mode network extraction of ADHD dataset](https://nilearn.github.io/stable/auto_examples/04_glm_first_level/plot_adhd_dmn.html) และ [Comparing connectomes on different reference atlases](https://nilearn.github.io/stable/auto_examples/03_connectivity/plot_atlas_comparison.html#sphx-glr-auto-examples-03-connectivity-plot-atlas-comparison-py) ของ [`nilearn`](https://nilearn.github.io/) มาปรับแก้และต่อยอด เพื่อให้มีสอดคล้องกับหลักสูตรของ Brain Code Camp มากยิ่งขึ้น"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_2ulN2kKNAtU"
},
"source": [
"## Overview\n",
"\n",
"เราได้เห็นแล้วว่าการทำ preprocessing ทั้งหมดในบทเรียนก่อนหน้า ใช้เวลาค่อนข้างนาน ดังนั้นในบทเรียนนี้ เราจะ load เอาข้อมูลที่ผ่านการทำ registration แล้วมาใช้สำหรับเรียนรู้กัน\n",
"\n",
"ขั้นตอนการวิเคราะห์ในบทเรียนนี้ประกอบด้วย\n",
"1. **fMRI Data Loading and Simple Exploration** การโหลดข้อมูล fMRI ที่ผ่านการ register ไปยัง template เรียบร้อยแล้ว โดยการเรียกใช้ `nilearn.datasets.fetch_developement_fmri`\n",
"2. **fMRI as Graph** การมอง fMRI เป็นข้อมูลประเภท graph\n",
"3. **Graph Visualization**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "ETsZUDPr3TUr",
"outputId": "7d09e32b-4805-4b51-ff80-f25e4d714b06"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: nilearn in /usr/local/lib/python3.13/dist-packages (0.14.1)\n",
"Requirement already satisfied: jinja2>=3.1.6 in /usr/local/lib/python3.13/dist-packages (from nilearn) (3.1.6)\n",
"Requirement already satisfied: joblib>=1.2.0 in /usr/local/lib/python3.13/dist-packages (from nilearn) (1.5.3)\n",
"Requirement already satisfied: nibabel>=5.2.0 in /usr/local/lib/python3.13/dist-packages (from nilearn) (5.4.2)\n",
"Requirement already satisfied: numpy>=1.26.0 in /usr/local/lib/python3.13/dist-packages (from nilearn) (2.1.3)\n",
"Requirement already satisfied: packaging>=26.0.0 in /usr/local/lib/python3.13/dist-packages (from nilearn) (26.3)\n",
"Requirement already satisfied: pandas>=2.3.0 in /usr/local/lib/python3.13/dist-packages (from nilearn) (3.0.5)\n",
"Requirement already satisfied: requests>=2.33.0 in /usr/local/lib/python3.13/dist-packages (from nilearn) (2.34.2)\n",
"Requirement already satisfied: scikit-learn!=1.7.0,!=1.9.0,>=1.5.0 in /usr/local/lib/python3.13/dist-packages (from nilearn) (1.6.1)\n",
"Requirement already satisfied: scipy>=1.11.1 in /usr/local/lib/python3.13/dist-packages (from nilearn) (1.16.3)\n",
"Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.13/dist-packages (from jinja2>=3.1.6->nilearn) (3.0.3)\n",
"Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.13/dist-packages (from pandas>=2.3.0->nilearn) (2.9.0.post0)\n",
"Requirement already satisfied: charset_normalizer<4,>=2 in /usr/local/lib/python3.13/dist-packages (from requests>=2.33.0->nilearn) (3.4.9)\n",
"Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.13/dist-packages (from requests>=2.33.0->nilearn) (3.19)\n",
"Requirement already satisfied: urllib3<3,>=1.26 in /usr/local/lib/python3.13/dist-packages (from requests>=2.33.0->nilearn) (2.5.0)\n",
"Requirement already satisfied: certifi>=2023.5.7 in /usr/local/lib/python3.13/dist-packages (from requests>=2.33.0->nilearn) (2026.7.22)\n",
"Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/lib/python3.13/dist-packages (from scikit-learn!=1.7.0,!=1.9.0,>=1.5.0->nilearn) (3.6.0)\n",
"Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.13/dist-packages (from python-dateutil>=2.8.2->pandas>=2.3.0->nilearn) (1.17.0)\n"
]
}
],
"source": [
"!pip install nilearn"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "uvYGpRHqARlV"
},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"import nilearn\n",
"from nilearn import datasets, plotting, maskers\n",
"from nilearn import image as ni_image\n",
"from nilearn.connectome import ConnectivityMeasure"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ACVF7f_LNF9q"
},
"source": [
"## fMRI Data Loading and Simple Exploration"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "svjBpru7F9m9"
},
"source": [
"### Data Loading"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "z1LlaOarPfzh"
},
"source": [
"โหลดข้อมูล fMRI มาจากคน 2 คน แล้ว save ไว้ใน folder ที่ระบุไว้ใน `data_dir` ผ่านการเรียกใช้ `nilearn.datasets.fetch_adhd`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 33
},
"id": "uoifjj9EEmJS",
"outputId": "09afa902-c773-405b-e834-15c7eb3811a0"
},
"outputs": [
{
"data": {
"text/html": [
"
[fetch_adhd] Dataset directory found: nilearn_data/adhd\n", "\n" ], "text/plain": [ "\u001b[1;34m[\u001b[0m\u001b[34mfetch_adhd\u001b[0m\u001b[1;34m]\u001b[0m Dataset directory found: nilearn_data/adhd\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "data_dir = './nilearn_data'\n", "num_subjects = 2\n", "fmri_multi_subjects = datasets.fetch_adhd(n_subjects=num_subjects, data_dir=data_dir)" ] }, { "cell_type": "markdown", "metadata": { "id": "jS1eDxQfGGSW" }, "source": [ "### Simple Exploration" ] }, { "cell_type": "markdown", "metadata": { "id": "h2TUzYv7Pbox" }, "source": [ "สำรวจข้อมูลดูว่าสิ่งที่เราโหลดมา มีข้อมูลอะไรอยู่บ้าง" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "Va51-GolEmgp", "outputId": "6f72601d-ebe4-4ab9-b525-d82b25513695" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dict_keys(['func', 'confounds', 'phenotypic', 'description', 't_r'])\n" ] } ], "source": [ "print(fmri_multi_subjects.keys())" ] }, { "cell_type": "markdown", "metadata": { "id": "K46v-cnQGcu1" }, "source": [ "หากต้องการทราบว่า key ไหนเป็นข้อมูลประเภทอะไร เราสามารถเข้าไปหาข้อมูลใน documentation ของ [`nilearn.datasets.fetch_adhd`](https://nilearn.github.io/dev/modules/description/adhd.html#adhd-dataset) ซึ่งเราจะพบว่าข้อมูลชุดนี้ ถูกนำมาจาก [The ADHD-200 Sample](https://fcon_1000.projects.nitrc.org/indi/adhd200/index.html) อีกที\n", "\n", "\n", "เรามาลองเริ่มต้นด้วยการ print ตัว `func` ออกมาดู" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "pYRMjAVEF-WP", "outputId": "5f427b9d-dfa1-499a-90bb-4b5252937d5a" }, "outputs": [ { "data": { "text/plain": [ "['nilearn_data/adhd/data/0010042/0010042_rest_tshift_RPI_voreg_mni.nii.gz',\n", " 'nilearn_data/adhd/data/0010064/0010064_rest_tshift_RPI_voreg_mni.nii.gz']" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fmri_multi_subjects.func" ] }, { "cell_type": "markdown", "metadata": { "id": "7pqfbdQ-H2Gw" }, "source": [ "เราจะเห็นว่า key ที่มีชื่อว่า `func` เป็น Python list ที่มีแต่ละ element เป็น `str` ที่เก็บชื่อไฟล์ข้อมูล fMRI\n", "\n", "สิ่งที่เราสังเกตได้จากชื่อไฟล์ทั้งหมดก็คือ\n", "\n", "1. ไฟล์ทั้งหมดลงท้ายด้วย `.nii.gz` โดย `nii` คือ ไฟล์ชนิด Neuroimaging Informatics Technology Initiative (NIfTI) ซึ่งเป็น format ที่เป็นที่นิยมใช้เก็บข้อมูล MRI และ `.gz` แสดงให้เห็นว่าไฟล์นี้ได้ถูกบีบอัด (compression) เพื่อลดขนาด\n", "\n", "2. มีหลักการการตั้งชื่อที่ค่อนข้างมีระบบ เช่น\n", " \n", " 1.1 เริ่มต้นชื่อไฟล์ด้วยรหัสที่เฉพาะเจาะจงกับ fMRI ไฟล์นั้น\n", "\n", " 1.2 เราพอจะบอกข้อมูลเกี่ยวกับการทดลองจากชื่อไฟล์ได้ในระดับหนึ่ง เช่น `rest`ที่แสดงให้เห็นว่า ข้อมูลนี้เป็นข้อมูลประเภท resting-state fMRI, `rpi` ที่แสดงถึงทิศทางการเก็บข้อมูลแบบ Right-Posterior-Inferior, `voreg_mni` ที่บ่งบอกว่าข้อมูลนี้ผ่านการทำ volume registration ไปยัง MNI template แล้ว\n", "\n", "เราสามารถดูข้อมูลเพิ่มเติมได้จาก key อื่น ๆ เช่น `phenotypic`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "_acgMGStHkwH", "outputId": "13b40057-1295-40c2-f4a1-0f4ea5575fb4" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Index(['Unnamed: 0', 'Subject', 'Rest.Scan', 'MeanFD',\n", " 'NumFD_greater_than_0.20', 'rootMeanSquareFD', 'FDquartile.top1.4thFD.',\n", " 'PercentFD_greater_than_0.20', 'MeanDVARS', 'MeanFD_Jenkinson', 'site',\n", " 'sibling_id', 'data_set', 'age', 'sex', 'handedness', 'full_2_iq',\n", " 'full_4_iq', 'viq', 'piq', 'iq_measure', 'tdc', 'adhd',\n", " 'adhd_inattentive', 'adhd_combined', 'adhd_subthreshold',\n", " 'diagnosis_using_cdis', 'notes', 'sess_1_anat_2', 'oppositional',\n", " 'cog_inatt', 'hyperac', 'anxious_shy', 'perfectionism',\n", " 'social_problems', 'psychosomatic', 'conn_adhd', 'restless_impulsive',\n", " 'emot_lability', 'conn_gi_tot', 'dsm_iv_inatt', 'dsm_iv_h_i',\n", " 'dsm_iv_tot', 'study', 'sess_1_rest_1', 'sess_1_rest_1_eyes',\n", " 'sess_1_rest_2', 'sess_1_rest_2_eyes', 'sess_1_rest_3',\n", " 'sess_1_rest_3_eyes', 'sess_1_rest_4', 'sess_1_rest_4_eyes',\n", " 'sess_1_rest_5', 'sess_1_rest_5_eyes', 'sess_1_rest_6',\n", " 'sess_1_rest_6_eyes', 'sess_1_anat_1', 'sess_1_which_anat',\n", " 'sess_2_rest_1', 'sess_2_rest_1_eyes', 'sess_2_rest_2',\n", " 'sess_2_rest_2_eyes', 'sess_2_anat_1', 'defacing_ok', 'defacing_notes'],\n", " dtype='str')\n" ] } ], "source": [ "print(fmri_multi_subjects.phenotypic.columns)" ] }, { "cell_type": "markdown", "metadata": { "id": "S6qfkn10PJ1C" }, "source": [ "ถ้าเราไม่แน่ใจว่าตัวแปรต่าง ๆ มันสื่อถึงอะไร หรือ ถ้าต้องการทราบข้อมูลเชิงลึก เราควรเข้าไปศึกษาข้อมูลเพิ่มเติมจาก official documentation ด้วย เช่น เราสามารถดูว่าข้อมูลชุดนี้ผ่านการ preprocess อะไรมาแล้วบ้างได้[ที่นี่](http://preprocessed-connectomes-project.org/adhd200/)" ] }, { "cell_type": "markdown", "metadata": { "id": "wysA9z-zQ5Td" }, "source": [ "หลังจากที่เราได้เห็นภาพรวมของข้อมูลชุดนี้แล้ว เราก็จะมาลองโหลดข้อมูลจาก subject 1 คนมาดูกัน โดยใช้ `nilearn.ni_image.load_img`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "S2Dn_IJuG5qM", "outputId": "725cd5f7-6410-44a8-c690-0012ef11a298" }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Shape (x, y, z, t) = (61, 73, 61, 176)\n", "\n", "
[fetch_atlas_yeo_2011] Dataset directory found: nilearn_data/yeo_2011\n", "\n" ], "text/plain": [ "\u001b[1;34m[\u001b[0m\u001b[34mfetch_atlas_yeo_2011\u001b[0m\u001b[1;34m]\u001b[0m Dataset directory found: nilearn_data/yeo_2011\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "yeo7_atlas = datasets.fetch_atlas_yeo_2011(data_dir=data_dir, verbose=1, n_networks=7)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/", "height": 474 }, "id": "rCmxMbUTrfrq", "outputId": "0dbfc1fe-2e01-477b-dd1a-466747bcb2b3" }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/tmp/ipykernel_4780/1865255007.py:1: RuntimeWarning: \n", "The image maps contains a single image.\n", "No color map needed.\n", " plotting.plot_prob_atlas(yeo7_atlas.maps)\n" ] }, { "data": { "text/plain": [ "