Skip to content

Commit ae3ce06

Browse files
committed
DOC: Document the PET notebook
Document the PET notebook: add markdown cells explaining the steps.
1 parent c7afb8f commit ae3ce06

File tree

1 file changed

+88
-11
lines changed

1 file changed

+88
-11
lines changed

docs/notebooks/pet_motion_estimation.ipynb

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,38 @@
11
{
22
"cells": [
33
{
4-
"cell_type": "code",
5-
"execution_count": 1,
6-
"id": "4111cc1b-5123-407a-8ec6-56d65bc94bc4",
74
"metadata": {},
5+
"cell_type": "markdown",
6+
"source": [
7+
"# Positron emission tomography (PET) data realignment example\n",
8+
"\n",
9+
"This example shows how to estimate the head motion of a PET dataset using\n",
10+
"`NiFreeze`.\n",
11+
"\n",
12+
"The notebook uses the `sub-02` dataset that was generated synthetically from\n",
13+
"a real PET dataset by adding random motion. The dataset\n",
14+
"can be installed from [GIN G-node](https://gin.g-node.org/nipreps-data/tests-nifreeze):\n",
15+
"\n",
16+
"```\n",
17+
"$ datalad install -g https://gin.g-node.org/nipreps-data/tests-nifreeze.git\n",
18+
"```\n",
19+
"\n",
20+
"after which the environment variable `TEST_DATA_HOME` will need to be set to\n",
21+
"point to the corresponding folder."
22+
],
23+
"id": "e8a4c20508512623"
24+
},
25+
{
26+
"metadata": {},
27+
"cell_type": "code",
828
"outputs": [],
29+
"execution_count": 1,
930
"source": [
1031
"from os import getenv\n",
1132
"from pathlib import Path\n",
1233
"\n",
1334
"from nifreeze.data.pet import PET\n",
1435
"\n",
15-
"# Install test data from gin.g-node.org:\n",
16-
"# $ datalad install -g https://gin.g-node.org/nipreps-data/tests-nifreeze.git\n",
17-
"# and point the environment variable TEST_DATA_HOME to the corresponding folder\n",
1836
"DATA_PATH = Path(getenv(\"TEST_DATA_HOME\", str(Path.home() / \"nifreeze-tests\")))\n",
1937
"WORKDIR = Path.home() / \"tmp\" / \"nifreezedev\" / \"pet_data\"\n",
2038
"WORKDIR.mkdir(parents=True, exist_ok=True)\n",
@@ -30,7 +48,8 @@
3048
")\n",
3149
"\n",
3250
"pet_dataset = PET.load(pet_file, json_file)"
33-
]
51+
],
52+
"id": "a258948070bbc0c"
3453
},
3554
{
3655
"cell_type": "code",
@@ -53,6 +72,17 @@
5372
"pet_dataset"
5473
]
5574
},
75+
{
76+
"metadata": {},
77+
"cell_type": "markdown",
78+
"source": [
79+
"## Model fitting and motion correction\n",
80+
"\n",
81+
"The relevant structure to model PET data is `nifreeze.model.PETModel`. We\n",
82+
"instantiate it by providing it with the loaded PET dataset."
83+
],
84+
"id": "22dd60dcdd65f09d"
85+
},
5686
{
5787
"cell_type": "code",
5888
"execution_count": 4,
@@ -417,19 +447,35 @@
417447
"id": "d541ae17-8bf8-457a-8aeb-986a4324434a",
418448
"metadata": {},
419449
"outputs": [],
450+
"source": "model.fit_predict(None)"
451+
},
452+
{
453+
"metadata": {},
454+
"cell_type": "markdown",
420455
"source": [
421-
"model.fit_predict(None)"
422-
]
456+
"Let's now ask the model for a prediction on the `midframe[2]` time point. By\n",
457+
"calling `model.fit_predict` the model is fitted using all the available data,\n",
458+
"and a prediction is requested on the time provided as the argument. By\n",
459+
"default, the PET model employs a B-Spline based method for motion correction."
460+
],
461+
"id": "fa33b648ed70d336"
423462
},
424463
{
425464
"cell_type": "code",
426465
"execution_count": 7,
427466
"id": "dee05183-57b5-46ed-811a-c0b26a53a386",
428467
"metadata": {},
429468
"outputs": [],
469+
"source": "predicted = model.fit_predict(pet_dataset.midframe[2])"
470+
},
471+
{
472+
"metadata": {},
473+
"cell_type": "markdown",
430474
"source": [
431-
"predicted = model.fit_predict(pet_dataset.midframe[2])"
432-
]
475+
"We now save the uncorrected and corrected data so that we can visualize\n",
476+
"the difference."
477+
],
478+
"id": "c4985826e2d8bc54"
433479
},
434480
{
435481
"cell_type": "code",
@@ -451,6 +497,15 @@
451497
"nifti_img_after.to_filename(output_path_after)"
452498
]
453499
},
500+
{
501+
"metadata": {},
502+
"cell_type": "markdown",
503+
"source": [
504+
"Let's now visualize a number of axial, sagittal and coronal slices of the\n",
505+
"uncorrected and corrected data."
506+
],
507+
"id": "7dfb887dcc76aa65"
508+
},
454509
{
455510
"cell_type": "code",
456511
"execution_count": 10,
@@ -2240,6 +2295,19 @@
22402295
")"
22412296
]
22422297
},
2298+
{
2299+
"metadata": {},
2300+
"cell_type": "markdown",
2301+
"source": [
2302+
"## Motion estimation\n",
2303+
"\n",
2304+
"We now want to have an estimate of the motion that the model corrects. We will\n",
2305+
"need to instantiate the `nifreeze.estimator.PETMotionEstimator`, which will\n",
2306+
"take an instance of the model. We will call `run` to get the parameters of the\n",
2307+
"affine transform estimation."
2308+
],
2309+
"id": "95b6939bea2d1394"
2310+
},
22432311
{
22442312
"cell_type": "code",
22452313
"execution_count": 13,
@@ -2431,6 +2499,15 @@
24312499
"affines"
24322500
]
24332501
},
2502+
{
2503+
"metadata": {},
2504+
"cell_type": "markdown",
2505+
"source": [
2506+
"Let's now visualize the estimated motion: we will plot the translation and\n",
2507+
"rotation components in the affine transform for each axis."
2508+
],
2509+
"id": "991990094e4a07f3"
2510+
},
24342511
{
24352512
"cell_type": "code",
24362513
"execution_count": 16,

0 commit comments

Comments
 (0)