|
7 | 7 | "metadata": {},
|
8 | 8 | "outputs": [],
|
9 | 9 | "source": [
|
10 |
| - "import numpy as np\n", |
11 |
| - "from pathlib import Path\n", |
12 |
| - "import shutil\n", |
13 |
| - "import warnings\n", |
14 | 10 | "from os import getenv\n",
|
| 11 | + "from pathlib import Path\n", |
15 | 12 | "\n",
|
16 |
| - "from nifreeze.data import pet\n", |
17 |
| - "from nifreeze.model import PETModel\n", |
18 |
| - "#from eddymotion.viz import plot_dwi\n", |
19 | 13 | "import nibabel as nib\n",
|
20 |
| - "from nifreeze.data.splitting import lovo_split\n", |
21 |
| - "from pathlib import Path" |
| 14 | + "\n", |
| 15 | + "from nifreeze.data import pet\n", |
| 16 | + "from nifreeze.model import PETModel" |
22 | 17 | ]
|
23 | 18 | },
|
24 | 19 | {
|
|
38 | 33 | "OUTPUT_DIR = WORKDIR / \"motion_estimation\"\n",
|
39 | 34 | "OUTPUT_DIR.mkdir(exist_ok=True, parents=True)\n",
|
40 | 35 | "\n",
|
41 |
| - "pet_file = DATA_PATH / \"pet_data\" / \"sub-02\" / \"ses-baseline\" / \"pet\" / \"sub-02_ses-baseline_pet.nii.gz\"\n", |
42 |
| - "json_file = DATA_PATH / \"pet_data\" / \"sub-02\" / \"ses-baseline\" / \"pet\" / \"sub-02_ses-baseline_pet.json\"\n", |
| 36 | + "pet_file = (\n", |
| 37 | + " DATA_PATH / \"pet_data\" / \"sub-02\" / \"ses-baseline\" / \"pet\" / \"sub-02_ses-baseline_pet.nii.gz\"\n", |
| 38 | + ")\n", |
| 39 | + "json_file = (\n", |
| 40 | + " DATA_PATH / \"pet_data\" / \"sub-02\" / \"ses-baseline\" / \"pet\" / \"sub-02_ses-baseline_pet.json\"\n", |
| 41 | + ")\n", |
43 | 42 | "\n",
|
44 | 43 | "pet_dataset = pet.PET.load(pet_file, json_file)"
|
45 | 44 | ]
|
|
450 | 449 | "source": [
|
451 | 450 | "# before\n",
|
452 | 451 | "nifti_img_before = nib.Nifti1Image(predicted, pet_dataset.affine)\n",
|
453 |
| - "output_path_before = 'before_mc.nii'\n", |
| 452 | + "output_path_before = \"before_mc.nii\"\n", |
454 | 453 | "nifti_img_before.to_filename(output_path_before)\n",
|
455 | 454 | "\n",
|
456 | 455 | "# after\n",
|
457 | 456 | "nifti_img_after = nib.Nifti1Image(data_test[0], pet_dataset.affine)\n",
|
458 |
| - "output_path_after = 'after_mc.nii'\n", |
| 457 | + "output_path_after = \"after_mc.nii\"\n", |
459 | 458 | "nifti_img_after.to_filename(output_path_after)"
|
460 | 459 | ]
|
461 | 460 | },
|
|
2237 | 2236 | ],
|
2238 | 2237 | "source": [
|
2239 | 2238 | "from niworkflows.viz.notebook import display\n",
|
2240 |
| - "import os\n", |
2241 |
| - "from IPython.display import SVG\n", |
2242 | 2239 | "\n",
|
2243 | 2240 | "moving_image = output_path_after\n",
|
2244 | 2241 | "fixed_image = output_path_before\n",
|
2245 |
| - "obj = display(fixed_image, moving_image, fixed_label='PET_before', moving_label='PET', )" |
| 2242 | + "obj = display(\n", |
| 2243 | + " fixed_image,\n", |
| 2244 | + " moving_image,\n", |
| 2245 | + " fixed_label=\"PET_before\",\n", |
| 2246 | + " moving_label=\"PET\",\n", |
| 2247 | + ")" |
2246 | 2248 | ]
|
2247 | 2249 | },
|
2248 | 2250 | {
|
|
2271 | 2273 | ],
|
2272 | 2274 | "source": [
|
2273 | 2275 | "# Instantiate with a PETModel or appropriate model instance\n",
|
2274 |
| - "model = PETModel(dataset=pet_dataset, timepoints=pet_dataset.midframe, xlim=pet_dataset.total_duration)\n", |
| 2276 | + "model = PETModel(\n", |
| 2277 | + " dataset=pet_dataset, timepoints=pet_dataset.midframe, xlim=pet_dataset.total_duration\n", |
| 2278 | + ")\n", |
2275 | 2279 | "estimator = PETMotionEstimator(model=model)\n",
|
2276 | 2280 | "\n",
|
2277 | 2281 | "# Run the estimator\n",
|
|
2452 | 2456 | "import numpy as np\n",
|
2453 | 2457 | "import pandas as pd\n",
|
2454 | 2458 | "\n",
|
| 2459 | + "\n", |
2455 | 2460 | "def extract_motion_parameters(affine):\n",
|
2456 | 2461 | " \"\"\"Extract translation (mm) and rotation (degrees) parameters from an affine matrix.\"\"\"\n",
|
2457 | 2462 | " translation = affine[:3, 3]\n",
|
2458 | 2463 | " rotation_rad = np.arctan2(\n",
|
2459 |
| - " [affine[2, 1], affine[0, 2], affine[1, 0]],\n", |
2460 |
| - " [affine[2, 2], affine[0, 0], affine[1, 1]]\n", |
| 2464 | + " [affine[2, 1], affine[0, 2], affine[1, 0]], [affine[2, 2], affine[0, 0], affine[1, 1]]\n", |
2461 | 2465 | " )\n",
|
2462 | 2466 | " rotation_deg = np.rad2deg(rotation_rad)\n",
|
2463 |
| - " return (*translation, *rotation_deg)\n", |
| 2467 | + " return *translation, *rotation_deg\n", |
| 2468 | + "\n", |
2464 | 2469 | "\n",
|
2465 | 2470 | "def compute_fd(motion_parameters):\n",
|
2466 | 2471 | " \"\"\"Compute Framewise Displacement from motion parameters.\"\"\"\n",
|
2467 | 2472 | " translations = motion_parameters[:, :3]\n",
|
2468 | 2473 | " rotations_deg = motion_parameters[:, 3:]\n",
|
2469 | 2474 | " rotations_rad = np.deg2rad(rotations_deg)\n",
|
2470 |
| - " \n", |
| 2475 | + "\n", |
2471 | 2476 | " # Compute differences between consecutive frames\n",
|
2472 | 2477 | " d_translations = np.vstack([np.zeros((1, 3)), np.diff(translations, axis=0)])\n",
|
2473 | 2478 | " d_rotations = np.vstack([np.zeros((1, 3)), np.diff(rotations_rad, axis=0)])\n",
|
2474 |
| - " \n", |
| 2479 | + "\n", |
2475 | 2480 | " # Convert rotations from radians to displacement on a sphere (radius 50 mm)\n",
|
2476 | 2481 | " radius = 50 # typical head radius in mm\n",
|
2477 | 2482 | " rotation_displacement = d_rotations * radius\n",
|
2478 |
| - " \n", |
| 2483 | + "\n", |
2479 | 2484 | " # Compute FD as sum of absolute differences\n",
|
2480 | 2485 | " fd = np.sum(np.abs(d_translations) + np.abs(rotation_displacement), axis=1)\n",
|
2481 | 2486 | " return fd\n",
|
2482 | 2487 | "\n",
|
| 2488 | + "\n", |
2483 | 2489 | "# Assume 'affines' is the list of affine matrices you computed earlier\n",
|
2484 | 2490 | "motion_parameters = []\n",
|
2485 | 2491 | "\n",
|
|
2491 | 2497 | "fd = compute_fd(motion_parameters)\n",
|
2492 | 2498 | "\n",
|
2493 | 2499 | "# Creating a DataFrame for better visualization\n",
|
2494 |
| - "df_motion = pd.DataFrame({\n", |
2495 |
| - " \"Frame\": np.arange(len(fd)),\n", |
2496 |
| - " \"Translation X\": motion_parameters[:, 0],\n", |
2497 |
| - " \"Translation Y\": motion_parameters[:, 1],\n", |
2498 |
| - " \"Translation Z\": motion_parameters[:, 2],\n", |
2499 |
| - " \"Rotation X\": motion_parameters[:, 3],\n", |
2500 |
| - " \"Rotation Y\": motion_parameters[:, 4],\n", |
2501 |
| - " \"Rotation Z\": motion_parameters[:, 5],\n", |
2502 |
| - " \"Framewise Displacement (mm)\": fd\n", |
2503 |
| - "})\n" |
| 2500 | + "df_motion = pd.DataFrame(\n", |
| 2501 | + " {\n", |
| 2502 | + " \"Frame\": np.arange(len(fd)),\n", |
| 2503 | + " \"Translation X\": motion_parameters[:, 0],\n", |
| 2504 | + " \"Translation Y\": motion_parameters[:, 1],\n", |
| 2505 | + " \"Translation Z\": motion_parameters[:, 2],\n", |
| 2506 | + " \"Rotation X\": motion_parameters[:, 3],\n", |
| 2507 | + " \"Rotation Y\": motion_parameters[:, 4],\n", |
| 2508 | + " \"Rotation Z\": motion_parameters[:, 5],\n", |
| 2509 | + " \"Framewise Displacement (mm)\": fd,\n", |
| 2510 | + " }\n", |
| 2511 | + ")" |
2504 | 2512 | ]
|
2505 | 2513 | },
|
2506 | 2514 | {
|
|
2522 | 2530 | "# Set up the matplotlib figure\n",
|
2523 | 2531 | "import matplotlib.pyplot as plt\n",
|
2524 | 2532 | "import seaborn as sns\n",
|
| 2533 | + "\n", |
2525 | 2534 | "plt.figure(figsize=(18, 10))\n",
|
2526 | 2535 | "\n",
|
2527 | 2536 | "# Translation plots\n",
|
2528 | 2537 | "plt.subplot(2, 3, 1)\n",
|
2529 |
| - "sns.lineplot(x='Frame', y='Translation X', data=df_motion)\n", |
2530 |
| - "plt.title('Translation X over Frames')\n", |
| 2538 | + "sns.lineplot(x=\"Frame\", y=\"Translation X\", data=df_motion)\n", |
| 2539 | + "plt.title(\"Translation X over Frames\")\n", |
2531 | 2540 | "\n",
|
2532 | 2541 | "plt.subplot(2, 3, 2)\n",
|
2533 |
| - "sns.lineplot(x='Frame', y='Translation Y', data=df_motion)\n", |
2534 |
| - "plt.title('Translation Y over Frames')\n", |
| 2542 | + "sns.lineplot(x=\"Frame\", y=\"Translation Y\", data=df_motion)\n", |
| 2543 | + "plt.title(\"Translation Y over Frames\")\n", |
2535 | 2544 | "\n",
|
2536 | 2545 | "plt.subplot(2, 3, 3)\n",
|
2537 |
| - "sns.lineplot(x='Frame', y='Translation Z', data=df_motion)\n", |
2538 |
| - "plt.title('Translation Z over Frames')\n", |
| 2546 | + "sns.lineplot(x=\"Frame\", y=\"Translation Z\", data=df_motion)\n", |
| 2547 | + "plt.title(\"Translation Z over Frames\")\n", |
2539 | 2548 | "\n",
|
2540 | 2549 | "# Rotation plots\n",
|
2541 | 2550 | "plt.subplot(2, 3, 4)\n",
|
2542 |
| - "sns.lineplot(x='Frame', y='Rotation X', data=df_motion)\n", |
2543 |
| - "plt.title('Rotation X over Frames')\n", |
| 2551 | + "sns.lineplot(x=\"Frame\", y=\"Rotation X\", data=df_motion)\n", |
| 2552 | + "plt.title(\"Rotation X over Frames\")\n", |
2544 | 2553 | "\n",
|
2545 | 2554 | "plt.subplot(2, 3, 5)\n",
|
2546 |
| - "sns.lineplot(x='Frame', y='Rotation Y', data=df_motion)\n", |
2547 |
| - "plt.title('Rotation Y over Frames')\n", |
| 2555 | + "sns.lineplot(x=\"Frame\", y=\"Rotation Y\", data=df_motion)\n", |
| 2556 | + "plt.title(\"Rotation Y over Frames\")\n", |
2548 | 2557 | "\n",
|
2549 | 2558 | "plt.subplot(2, 3, 6)\n",
|
2550 |
| - "sns.lineplot(x='Frame', y='Rotation Z', data=df_motion)\n", |
2551 |
| - "plt.title('Rotation Z over Frames')\n", |
| 2559 | + "sns.lineplot(x=\"Frame\", y=\"Rotation Z\", data=df_motion)\n", |
| 2560 | + "plt.title(\"Rotation Z over Frames\")\n", |
2552 | 2561 | "\n",
|
2553 | 2562 | "plt.tight_layout()\n",
|
2554 | 2563 | "plt.show()"
|
|
2571 | 2580 | ],
|
2572 | 2581 | "source": [
|
2573 | 2582 | "plt.figure(figsize=(18, 10))\n",
|
2574 |
| - "sns.lineplot(x='Frame', y='Framewise Displacement (mm)', data=df_motion)\n", |
2575 |
| - "plt.title('Framewise Displacement (mm)')\n", |
| 2583 | + "sns.lineplot(x=\"Frame\", y=\"Framewise Displacement (mm)\", data=df_motion)\n", |
| 2584 | + "plt.title(\"Framewise Displacement (mm)\")\n", |
2576 | 2585 | "\n",
|
2577 | 2586 | "plt.tight_layout()\n",
|
2578 | 2587 | "plt.show()"
|
|
0 commit comments