|
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 can be installed\n", |
| 14 | + "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 point to the corresponding folder.\n" |
| 21 | + ], |
| 22 | + "id": "e0f292c6b783bafa" |
| 23 | + }, |
| 24 | + { |
| 25 | + "metadata": {}, |
| 26 | + "cell_type": "code", |
8 | 27 | "outputs": [], |
| 28 | + "execution_count": 1, |
9 | 29 | "source": [ |
10 | 30 | "from os import getenv\n", |
11 | 31 | "from pathlib import Path\n", |
|
30 | 50 | ")\n", |
31 | 51 | "\n", |
32 | 52 | "pet_dataset = PET.load(pet_file, json_file)" |
33 | | - ] |
| 53 | + ], |
| 54 | + "id": "6d67b411d3c9330d" |
34 | 55 | }, |
35 | 56 | { |
36 | 57 | "cell_type": "code", |
|
53 | 74 | "pet_dataset" |
54 | 75 | ] |
55 | 76 | }, |
| 77 | + { |
| 78 | + "metadata": {}, |
| 79 | + "cell_type": "markdown", |
| 80 | + "source": [ |
| 81 | + "## Model fitting and motion correction\n", |
| 82 | + "\n", |
| 83 | + "The relevant structure to model PET data is `nifreeze.model.PETModel`. We\n", |
| 84 | + "instantiate it by providing it with the loaded PET dataset." |
| 85 | + ], |
| 86 | + "id": "886c5ca9bd9eb3e4" |
| 87 | + }, |
56 | 88 | { |
57 | 89 | "cell_type": "code", |
58 | 90 | "execution_count": 4, |
|
421 | 453 | "model.fit_predict(None)" |
422 | 454 | ] |
423 | 455 | }, |
| 456 | + { |
| 457 | + "metadata": {}, |
| 458 | + "cell_type": "markdown", |
| 459 | + "source": [ |
| 460 | + "Let's now ask the model for a prediction at the `midframe[2]` time point. By\n", |
| 461 | + "calling `model.fit_predict` the model is fitted using all the available data,\n", |
| 462 | + "and a prediction is requested on the time provided as the argument. The\n", |
| 463 | + "B-Spline PET model employs uses a B-Spline-based interpolation method to\n", |
| 464 | + "estimate the data for the requested frame." |
| 465 | + ], |
| 466 | + "id": "cbd738998dd6ed1f" |
| 467 | + }, |
424 | 468 | { |
425 | 469 | "cell_type": "code", |
426 | 470 | "execution_count": 7, |
|
432 | 476 | "predicted = model.fit_predict(pet_dataset.midframe[index])" |
433 | 477 | ] |
434 | 478 | }, |
| 479 | + { |
| 480 | + "metadata": {}, |
| 481 | + "cell_type": "markdown", |
| 482 | + "source": [ |
| 483 | + "We now save the uncorrected and corrected data so that we can visualize the\n", |
| 484 | + "difference." |
| 485 | + ], |
| 486 | + "id": "17f3d61720ac0959" |
| 487 | + }, |
435 | 488 | { |
436 | 489 | "cell_type": "code", |
437 | 490 | "execution_count": 8, |
|
452 | 505 | "nifti_img_after.to_filename(output_path_after)" |
453 | 506 | ] |
454 | 507 | }, |
| 508 | + { |
| 509 | + "metadata": {}, |
| 510 | + "cell_type": "markdown", |
| 511 | + "source": [ |
| 512 | + "Let's now visualize a number of axial, sagittal and coronal slices of the\n", |
| 513 | + "uncorrected and corrected data." |
| 514 | + ], |
| 515 | + "id": "7126dd0b08f3d70e" |
| 516 | + }, |
455 | 517 | { |
456 | 518 | "cell_type": "code", |
457 | 519 | "execution_count": 10, |
|
2242 | 2304 | ] |
2243 | 2305 | }, |
2244 | 2306 | { |
2245 | | - "cell_type": "code", |
2246 | | - "execution_count": 13, |
2247 | | - "id": "78edfed2-8200-48be-9f58-8fb910fac299", |
2248 | 2307 | "metadata": {}, |
| 2308 | + "cell_type": "markdown", |
| 2309 | + "source": [ |
| 2310 | + "## Motion estimation\n", |
| 2311 | + "\n", |
| 2312 | + "We now want to have an estimate of the motion that the model corrects. We will\n", |
| 2313 | + "need to instantiate the `nifreeze.estimator.PETMotionEstimator`, which will\n", |
| 2314 | + "take an instance of the model. We will call `run` to get the parameters of the\n", |
| 2315 | + "affine transform estimation." |
| 2316 | + ], |
| 2317 | + "id": "44d029b581d72b55" |
| 2318 | + }, |
| 2319 | + { |
| 2320 | + "metadata": {}, |
| 2321 | + "cell_type": "code", |
2249 | 2322 | "outputs": [ |
2250 | 2323 | { |
2251 | 2324 | "name": "stderr", |
|
2255 | 2328 | ] |
2256 | 2329 | } |
2257 | 2330 | ], |
| 2331 | + "execution_count": 13, |
2258 | 2332 | "source": [ |
2259 | 2333 | "from nifreeze.estimator import PETMotionEstimator\n", |
2260 | 2334 | "\n", |
|
2265 | 2339 | " pet_dataset,\n", |
2266 | 2340 | " omp_nthreads=4,\n", |
2267 | 2341 | ")" |
2268 | | - ] |
| 2342 | + ], |
| 2343 | + "id": "af6ca1ccbce1e579" |
2269 | 2344 | }, |
2270 | 2345 | { |
2271 | 2346 | "cell_type": "code", |
|
2427 | 2502 | "affines" |
2428 | 2503 | ] |
2429 | 2504 | }, |
| 2505 | + { |
| 2506 | + "metadata": {}, |
| 2507 | + "cell_type": "markdown", |
| 2508 | + "source": [ |
| 2509 | + "Let's now visualize the estimated motion: we will plot the translation and\n", |
| 2510 | + "rotation components in the affine transform for each axis." |
| 2511 | + ], |
| 2512 | + "id": "79a4b84912aed9f9" |
| 2513 | + }, |
2430 | 2514 | { |
2431 | 2515 | "metadata": {}, |
2432 | 2516 | "cell_type": "code", |
|
2537 | 2621 | "\n", |
2538 | 2622 | "plt.show()" |
2539 | 2623 | ] |
2540 | | - }, |
2541 | | - { |
2542 | | - "cell_type": "code", |
2543 | | - "execution_count": null, |
2544 | | - "id": "14308ff4-d5b1-4270-aca2-0d7e9ccef27f", |
2545 | | - "metadata": {}, |
2546 | | - "outputs": [], |
2547 | | - "source": [] |
2548 | 2624 | } |
2549 | 2625 | ], |
2550 | 2626 | "metadata": { |
|
0 commit comments