{ "cells": [ { "cell_type": "markdown", "id": "49964463", "metadata": {}, "source": [ "# RAMAC Example on Custom Volumetric images\n", "\n", "`RAMAC` repository is tailored for implementation of the algorithm on `Monaleesa` Computed Tomography (CT) data set as outlined in the below paper :\n", "**_Image registration based automated lesion correspondence pipeline for longitudinal CT data_**\n", "\n", "Hence users can use this tool for their own volumetric image dataset. \n", "The following function provides a convenient format for users to establish correspondence within their own volumetric image datasets. By simply providing the directory path containing the images and the corresponding Region of Interest (ROI) coordinate information, users can effortlessly establish the necessary correspondence.\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "6547a963", "metadata": {}, "outputs": [], "source": [ "import sys\n", "sys.path.append(\"../ramac\")\n", "from registration import *\n", "from correspondence_csv_input import *\n", "from transform_coordinates import *\n", "from merge_dataframe import *\n", "from phantominator import shepp_logan\n", "from plots import *\n", "from input_transform import *\n", "from preprocessing import mask_air\n", "from utils import *\n", "#import warnings\n", "import scipy\n", "import numpy as np\n", "import SimpleITK as sitk\n", "import pandas as pd\n", "import os" ] }, { "cell_type": "markdown", "id": "af1839fd", "metadata": {}, "source": [ "The below function is to perform a test using custom data.\n", "This function shows the process to load DICOM series for longitudinal image data at two timepoints, performs rigid 3D registration,perform adaaptive hungarian and saves result files, and plots triplanar views of the images." ] }, { "cell_type": "code", "execution_count": null, "id": "6ccc9a27", "metadata": {}, "outputs": [], "source": [ "def test_custom_data():\n", " \n", " ## Directory 1 = '/projects01/didsr-novartis/reference/Novartis_Monaleesa/Images/ML3_deid/1003003/Screening/CT - Chest - Abdomen - Pelvis - Venous - Spiral'\n", " ## Directory 2 = '/projects01/didsr-novartis/reference/Novartis_Monaleesa/Images/ML3_deid/1003003/Week 8/CT - Chest - Abdomen - Pelvis - Venous - Spiral'\n", " \n", " Screening_image = load_dicom_series('Directory 1') ## User needs to give the directory path\n", " Week_8_image = load_dicom_series('Directory 2')\n", " \n", " ## Preprocess the images if needed\n", " fixed_image = mask_air(Screening_image)\n", " moving_image = mask_air(Week_8_image)\n", " # # Apply the 3D rigid registration\n", " moving_resampled, [init_transform, final_transform] = registration_3d_rigid_series(fixed_image, moving_image)\n", "\n", " result_folder = \"monaleesa\"\n", " os.makedirs(result_folder, exist_ok=True) # Create the result folder if it doesn't exist\n", "\n", " # File paths for saving CSV files which contains the ROI coordinates as inputs in CSV format (to be placed by user)\n", " \n", " filename_fixed_R1 = os.path.join(result_folder, 'df_lesions_Screening_1.csv')\n", " filename_fixed_R2 = os.path.join(result_folder, 'df_lesions_Screening_2.csv')\n", " filename_moving_R1 = os.path.join(result_folder, 'df_lesions_Week_8_1.csv')\n", " filename_moving_R2 = os.path.join(result_folder, 'df_lesions_Week_8_2.csv')\n", "\n", " ## Apply Adaptive Hungarian\n", " threshold = 30\n", " correspondences_screening, unmatched_names_df1_screening, unmatched_names_df2_screening = process_lesion_timepoints(filename_fixed_R1, filename_fixed_R2, threshold)\n", " plot_lesion_correspondences_timepoints(filename_fixed_R1, filename_fixed_R2)\n", " final_df_screening = create_final_dataframe_timepoints(correspondences_screening, unmatched_names_df1_screening, unmatched_names_df2_screening, filename_fixed_R1, filename_fixed_R2)\n", "\n", " correspondences_week_8, unmatched_names_df1_week_8, unmatched_names_df2_week_8 = process_lesion_timepoints(filename_moving_R1, filename_moving_R2, threshold)\n", " plot_lesion_correspondences_timepoints(filename_moving_R1, filename_moving_R2)\n", " final_df_week_8 = create_final_dataframe_timepoints(correspondences_week_8, unmatched_names_df1_week_8, unmatched_names_df2_week_8, filename_moving_R1, filename_moving_R2)\n", "\n", " final_df_S = create_trim_dataframe(final_df_screening)\n", " final_df_8 = create_trim_dataframe(final_df_week_8)\n", " \n", " ## Save the dataframes of the ROI coordiantes in CSV format\n", " filename_fixed = os.path.join(result_folder, 'fixed_coordinates.csv')\n", " filename_moving = os.path.join(result_folder, 'moving_coordinates.csv')\n", " filename_registered = os.path.join(result_folder, 'registered_coordinates.csv')\n", " filename_correspondence = os.path.join(result_folder, 'correspondence_indices.csv')\n", "\n", " save_transformed_dataframe(final_df_S, filename_fixed)\n", " save_transformed_dataframe(final_df_8, filename_moving)\n", " ## Apply the transformation matrix on ROI cooridnates of moving image (Image B) to obtain registered ROI cooridnates\n", " final_transform_1 = final_transform.GetInverse()\n", "\n", " registered_coordinates = create_transformed_dataframe(filename_moving, final_transform_1)\n", " save_transformed_dataframe(registered_coordinates, filename_registered)\n", " \n", " ## Apply Adaptive Hungarian on the fixed ROI cooridnates and registered coordinates\n", " threshold = 30\n", " correspondences, unmatched_names_df1, unmatched_names_df2 = process_lesion_timepoints(filename_fixed, filename_registered, threshold)\n", " plot_lesion_correspondences_timepoints(filename_fixed, filename_registered)\n", " final_df = create_final_dataframe_timepoints(correspondences, unmatched_names_df1, unmatched_names_df2, filename_fixed, filename_registered)\n", " \n", " ## Saving the final correspondence thereby achieved in a CSV format\n", " df_transformed = merge_indices(final_df)\n", " df_transformed.to_csv(filename_correspondence, index=False)\n", " \n", " ## Transform the ROI coordinates from physical to voxel unit for plotting\n", "\n", " fixed_voxel = transform_physical_to_index(fixed_image, filename_fixed)\n", " fixed_voxel_tuples = voxel_tuples_from_dataframe(fixed_voxel)\n", " moving_voxel = transform_physical_to_index(moving_image, filename_moving)\n", " moving_voxel_tuples = voxel_tuples_from_dataframe(moving_voxel)\n", " registered_voxel = transform_physical_to_index(moving_resampled, filename_registered)\n", " registered_voxel_tuples = voxel_tuples_from_dataframe(registered_voxel)\n", " \n", " ## Triplanar visualization after registration\n", "\n", " window_level = 100\n", " window_width = 2000\n", "\n", " images = [fixed_image, moving_image, moving_resampled]\n", " voxel_tuples_list = [fixed_voxel_tuples, moving_voxel_tuples, registered_voxel_tuples]\n", " image_names = ['Fixed', 'Moving', 'Registered']\n", "\n", " for image, voxel_tuples, image_name in zip(images, voxel_tuples_list, image_names):\n", " plot_triplanar(image, voxel_tuples, window_level, window_width, image_name)\n", "\n", "\n", "test_custom_data()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.13" } }, "nbformat": 4, "nbformat_minor": 5 }