|
1 | 1 | {
|
2 | 2 | "cells": [
|
3 | 3 | {
|
4 |
| - "cell_type": "code", |
5 |
| - "execution_count": 1, |
6 |
| - "id": "4111cc1b-5123-407a-8ec6-56d65bc94bc4", |
7 | 4 | "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", |
8 | 28 | "outputs": [],
|
| 29 | + "execution_count": 1, |
9 | 30 | "source": [
|
10 | 31 | "from os import getenv\n",
|
11 | 32 | "from pathlib import Path\n",
|
12 | 33 | "\n",
|
13 | 34 | "from nifreeze.data.pet import PET\n",
|
14 | 35 | "\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", |
18 | 36 | "DATA_PATH = Path(getenv(\"TEST_DATA_HOME\", str(Path.home() / \"nifreeze-tests\")))\n",
|
19 | 37 | "WORKDIR = Path.home() / \"tmp\" / \"nifreezedev\" / \"pet_data\"\n",
|
20 | 38 | "WORKDIR.mkdir(parents=True, exist_ok=True)\n",
|
|
30 | 48 | ")\n",
|
31 | 49 | "\n",
|
32 | 50 | "pet_dataset = PET.load(pet_file, json_file)"
|
33 |
| - ] |
| 51 | + ], |
| 52 | + "id": "a258948070bbc0c" |
34 | 53 | },
|
35 | 54 | {
|
36 | 55 | "cell_type": "code",
|
|
53 | 72 | "pet_dataset"
|
54 | 73 | ]
|
55 | 74 | },
|
| 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 | + }, |
56 | 86 | {
|
57 | 87 | "cell_type": "code",
|
58 | 88 | "execution_count": 4,
|
|
417 | 447 | "id": "d541ae17-8bf8-457a-8aeb-986a4324434a",
|
418 | 448 | "metadata": {},
|
419 | 449 | "outputs": [],
|
420 |
| - "source": [ |
421 |
| - "model.fit_predict(None)" |
422 |
| - ] |
| 450 | + "source": "model.fit_predict(None)" |
| 451 | + }, |
| 452 | + { |
| 453 | + "metadata": {}, |
| 454 | + "cell_type": "markdown", |
| 455 | + "source": "Let's now ask the model for a prediction at the `midframe[2]` time point. By calling `model.fit_predict` the model is fitted using all the available data, and a prediction is requested on the time provided as the argument. The B-Spline PET model employs uses a B-Spline-based interpolation method to estimate the data for the requested frame.", |
| 456 | + "id": "fa33b648ed70d336" |
423 | 457 | },
|
424 | 458 | {
|
425 | 459 | "cell_type": "code",
|
|
432 | 466 | "predicted = model.fit_predict(pet_dataset.midframe[index])"
|
433 | 467 | ]
|
434 | 468 | },
|
| 469 | + { |
| 470 | + "metadata": {}, |
| 471 | + "cell_type": "markdown", |
| 472 | + "source": [ |
| 473 | + "We now save the uncorrected and corrected data so that we can visualize\n", |
| 474 | + "the difference." |
| 475 | + ], |
| 476 | + "id": "c4985826e2d8bc54" |
| 477 | + }, |
435 | 478 | {
|
436 | 479 | "cell_type": "code",
|
437 | 480 | "execution_count": 8,
|
|
452 | 495 | "nifti_img_after.to_filename(output_path_after)"
|
453 | 496 | ]
|
454 | 497 | },
|
| 498 | + { |
| 499 | + "metadata": {}, |
| 500 | + "cell_type": "markdown", |
| 501 | + "source": [ |
| 502 | + "Let's now visualize a number of axial, sagittal and coronal slices of the\n", |
| 503 | + "uncorrected and corrected data." |
| 504 | + ], |
| 505 | + "id": "7dfb887dcc76aa65" |
| 506 | + }, |
455 | 507 | {
|
456 | 508 | "cell_type": "code",
|
457 | 509 | "execution_count": 10,
|
|
2241 | 2293 | ")"
|
2242 | 2294 | ]
|
2243 | 2295 | },
|
| 2296 | + { |
| 2297 | + "metadata": {}, |
| 2298 | + "cell_type": "markdown", |
| 2299 | + "source": [ |
| 2300 | + "## Motion estimation\n", |
| 2301 | + "\n", |
| 2302 | + "We now want to have an estimate of the motion that the model corrects. We will\n", |
| 2303 | + "need to instantiate the `nifreeze.estimator.PETMotionEstimator`, which will\n", |
| 2304 | + "take an instance of the model. We will call `run` to get the parameters of the\n", |
| 2305 | + "affine transform estimation." |
| 2306 | + ], |
| 2307 | + "id": "95b6939bea2d1394" |
| 2308 | + }, |
2244 | 2309 | {
|
2245 | 2310 | "cell_type": "code",
|
2246 | 2311 | "execution_count": 13,
|
|
2427 | 2492 | "affines"
|
2428 | 2493 | ]
|
2429 | 2494 | },
|
| 2495 | + { |
| 2496 | + "metadata": {}, |
| 2497 | + "cell_type": "markdown", |
| 2498 | + "source": [ |
| 2499 | + "Let's now visualize the estimated motion: we will plot the translation and\n", |
| 2500 | + "rotation components in the affine transform for each axis." |
| 2501 | + ], |
| 2502 | + "id": "991990094e4a07f3" |
| 2503 | + }, |
2430 | 2504 | {
|
2431 | 2505 | "cell_type": "code",
|
2432 | 2506 | "execution_count": 16,
|
|
0 commit comments