Forráskód Böngészése

added all of the code necessery

arefks 3 hónapja
szülő
commit
13cb663094
5 módosított fájl, 257 hozzáadás és 34 törlés
  1. 1 1
      code/AIDAmri
  2. 6 0
      code/README.md
  3. 43 0
      code/mask2MTPL.py
  4. 70 33
      code/overlayPlot3D.py
  5. 137 0
      code/register_masks.py

+ 1 - 1
code/AIDAmri

@@ -1 +1 @@
-Subproject commit cc61e0643a7c47322513e133ab8beedfe62967f9
+Subproject commit 8e7f9d3597fecc6fa33093eca5fdd2855e7b22b4

+ 6 - 0
code/README.md

@@ -3,3 +3,9 @@
 This is the code used to process raw Bruker data and to apply transformations from the drawn masks to each individual subject. Note that this is a subdataset linked to the GitHub page of AIDAmri.
 
 The link to the exact branch of the code which was used for this process is: [AIDAmri - SND_Mask_trafu branch](https://github.com/Aswendt-Lab/AIDAmri/tree/SND_Mask_trafu).
+
+
+
+# Example usage of code
+
+`root@9c22c56092e5:/aida/DATA/code# python mask2MTPL.py -i /aida/DATA/output/Tract_Density -o /aida/DATA/output/Nifti_Tract_density_registered`

+ 43 - 0
code/mask2MTPL.py

@@ -0,0 +1,43 @@
+import os
+import argparse
+import subprocess
+
+def main():
+    parser = argparse.ArgumentParser(description="Resample multiple flo images using a reference image and an affine transformation file.")
+    parser.add_argument("-i", "--input", help="Input folder containing flo images", required=True)
+    parser.add_argument("-o", "--output", help="Output folder for resampled images", required=True)
+    args = parser.parse_args()
+
+    # Get the script's location
+    script_location = os.path.dirname(os.path.realpath(__file__))
+
+    # Construct paths to reference image and affine transformation file
+    ref_image_path = os.path.join(script_location, "..", "output", "C57BL6_mouse.iso_registerd.nii.gz")
+    affine_trafo_path = os.path.join(script_location, "..", "output", "affineTrafo.txt")
+
+    # Create the output folder if it doesn't exist
+    if not os.path.exists(args.output):
+        os.makedirs(args.output)
+
+    # List all flo images in the input folder
+    flo_images = [os.path.join(args.input, image) for image in os.listdir(args.input) if image.endswith(".nii")]
+
+    # Loop through flo images and perform resampling
+    for flo_image in flo_images:
+        output_filename = os.path.basename(flo_image).replace(".nii", "_registered.nii")
+        output_path = os.path.join(args.output, output_filename)
+
+        # Run the resample command
+        command = [
+            "reg_resample",
+            "-ref", ref_image_path,
+            "-flo", flo_image,
+            "-res", output_path,
+            "-trans", affine_trafo_path,
+            "-inter", "0"
+        ]
+
+        subprocess.run(command)
+
+if __name__ == "__main__":
+    main()

+ 70 - 33
code/overlayPlot3D.py

@@ -6,7 +6,7 @@ from scipy.ndimage import rotate
 # Define the file paths
 templateFilePath = r"C:\Users\aswen\Desktop\Code\2024_Ruthe_SND\input\average_template_50_from_website.nii.gz"
 densityFilePath = r"C:\Users\aswen\Desktop\Code\2024_Ruthe_SND\input\12_wks_coronal_100141780_50um_projection_density.nii.gz"
-maskFilePath = r"C:\Users\aswen\Desktop\Code\2024_Ruthe_SND\output\Nifti_Trakte_registered\CC_Mop_dilated_registered.nii.gz"
+maskFilePath = r"\\10.209.5.114\Projects\Student_projects\14_Aref_Kalantari_2021\Luca\CC_Mop_desnitymap_50um.nii.gz"
 
 # Load the NIfTI files
 templateNifti = nib.load(templateFilePath)
@@ -22,20 +22,64 @@ dpi = 400
 # Get the number of slices along each dimension
 num_slices_dim0, num_slices_dim1, num_slices_dim2 = templateNifti.shape
 
-# Create a 3D array to hold the overlay
-overlay_volume = np.zeros((num_slices_dim0, num_slices_dim1, num_slices_dim2, 4), dtype=np.uint8)
-
-# Loop through and overlay all slices
-for sliceIdx in range(num_slices_dim2):
-    # Extract the desired slice from the template, density, and mask
-    templateSlice = np.squeeze(templateNifti.get_fdata()[:, :, sliceIdx]).astype(np.uint16)
-    densitySlice = np.squeeze(densityNifti.get_fdata()[:, :, sliceIdx]).astype(np.double)
-    
-    mask_data = maskNifti.get_fdata()
-    mask_data = mask_data.swapaxes(0, 2)
-    mask_data = np.flip(mask_data, axis=0)
-
-    maskSlice = np.squeeze(mask_data[:, :, sliceIdx])
+# Set the slice step for display (every tenth slice)
+slice_step = 10
+
+# Choose the dimension for iteration (0, 1, or 2)
+iteration_dimension = 0  # Change this value to select the dimension
+
+# Calculate the number of rows and columns for the grid based on the selected dimension
+if iteration_dimension == 0:
+    num_slices = num_slices_dim0
+elif iteration_dimension == 1:
+    num_slices = num_slices_dim1
+else:
+    num_slices = num_slices_dim2
+
+grid_size = int(np.sqrt(num_slices // slice_step))
+if grid_size * grid_size < num_slices // slice_step:
+    grid_size += 1
+
+cm = 1/2.54
+# Adjust the figure size to be larger
+fig, axs = plt.subplots(grid_size, grid_size, figsize=(20, 20), dpi=dpi)
+
+# Hide axis numbers
+for ax_row in axs:
+    for ax in ax_row:
+        ax.axis('off')
+
+# Load the mask and perform necessary flips
+mask_data = np.squeeze(maskNifti.get_fdata())
+# Swap the mask over the x and y axes
+mask_data = mask_data.swapaxes(0, 2)
+mask_data = np.flip(mask_data, axis=0)
+
+# Create a new NIfTI image with the adjusted mask data
+adjusted_mask_nifti = nib.Nifti1Image(mask_data, maskNifti.affine)
+
+# Save the new NIfTI image with adjusted header
+output_mask_filepath = r"\\10.209.5.114\Projects\Student_projects\14_Aref_Kalantari_2021\Luca\CC_Mop_desnitymap_50um_reoriented.nii.gz"  # Specify the desired output file path
+nib.save(adjusted_mask_nifti, output_mask_filepath)
+
+# Loop through and display every nth slice as subplots along the selected dimension
+for i, sliceIdx in enumerate(range(0, num_slices, slice_step)):
+    row = i // grid_size
+    col = i % grid_size
+
+    # Extract the desired slice from the template and density based on the selected dimension
+    if iteration_dimension == 0:
+        templateSlice = np.squeeze(templateNifti.get_fdata()[sliceIdx, :, :]).astype(np.uint16)
+        densitySlice = np.squeeze(densityNifti.get_fdata()[sliceIdx, :, :]).astype(np.double)
+        maskSlice = np.squeeze(mask_data[sliceIdx, :, :])
+    elif iteration_dimension == 1:
+        templateSlice = np.squeeze(templateNifti.get_fdata()[:, sliceIdx, :]).astype(np.uint16)
+        densitySlice = np.squeeze(densityNifti.get_fdata()[:, sliceIdx, :]).astype(np.double)
+        maskSlice = np.squeeze(mask_data[:, sliceIdx, :])
+    else:
+        templateSlice = np.squeeze(templateNifti.get_fdata()[:, :, sliceIdx]).astype(np.uint16)
+        densitySlice = np.squeeze(densityNifti.get_fdata()[:, :, sliceIdx]).astype(np.double)
+        maskSlice = np.squeeze(mask_data[:, :, sliceIdx])
 
     # Normalize the templateSlice to [0, 1] for visualization
     templateSlice = (templateSlice - np.min(templateSlice)) / (np.max(templateSlice) - np.min(templateSlice))
@@ -43,25 +87,18 @@ for sliceIdx in range(num_slices_dim2):
     # Overlay the density and mask onto the template slice
     overlayedImage = templateSlice + densitySlice + maskSlice
 
-    # Normalize the overlay to [0, 1]
-    overlayedImage = (overlayedImage - np.min(overlayedImage)) / (np.max(overlayedImage) - np.min(overlayedImage))
-
-    # Convert the overlay image to RGBA format (4 channels for transparency)
-    overlay_image_rgba = plt.cm.gray(overlayedImage)
-    overlay_image_rgba[:, :, 3] = (overlayedImage * 255).astype(np.uint8)  # Set alpha channel based on intensity
-
-    # Update the 3D overlay volume
-    overlay_volume[:, :, sliceIdx, :] = overlay_image_rgba
-
-# Create a figure for the 3D visualization
-fig = plt.figure(figsize=(10, 10), dpi=dpi)
-ax = fig.add_subplot(111, projection='3d')
+    # Display the overlaid image in the corresponding subplot
+    axs[row, col].imshow(templateSlice, cmap='gray')
+    axs[row, col].imshow(densitySlice, cmap='hot', alpha=0.4)
+    axs[row, col].imshow(maskSlice, cmap='hot', alpha=0.2)  # Apply "hot" colormap to the mask
+  # Apply "cool" colormap to the mask
 
-# Plot the 3D overlay volume
-ax.voxels(overlay_volume[:, :, :, 0] > 0, facecolors=overlay_volume[:, :, :, :3] / 255., edgecolor='k')
+# Remove empty subplots if necessary
+for i in range(num_slices // slice_step, grid_size * grid_size):
+    fig.delaxes(axs.flatten()[i])
 
-# Set the aspect ratio to be equal for all dimensions
-ax.set_box_aspect([1, 1, 1])
+# Adjust spacing between subplots
+plt.tight_layout()
 
-# Show the 3D plot
+# Show the plot
 plt.show()

+ 137 - 0
code/register_masks.py

@@ -0,0 +1,137 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri Jan 12 18:22:18 2024
+
+@author: arefks
+"""
+
+import argparse
+import subprocess
+import shlex
+import os
+import glob
+import csv
+import nibabel as nib
+import numpy as np
+def main():
+    parser = argparse.ArgumentParser(description="Image Registration and Resampling")
+    
+    parser.add_argument("-i", "--input", required=True, help="Path to main folder of the nii Converted Data that are already processed with AIDAmri, e.g proc_data")
+    parser.add_argument("-m", "--masks", required=True, help="Path to the folder containing the drawn masks. They should be in the MTPL space!")
+    
+    args = parser.parse_args()
+    
+    missing_matrix_paths = []
+
+    # Parsing for all BiasBet.nii.gz files in T2w folders after a given input path.
+    T2BetPath = os.path.join(args.input,"**","T2w","*BiasBet.nii.gz")
+    T2BetFiles = glob.glob(T2BetPath,recursive=True)
+    
+    # Parsing for all given masks.
+    FloatingMasksPath = os.path.join(args.masks, "*.nii*")
+    FloatingMasksFiles = glob.glob(FloatingMasksPath)
+    
+    for ff in T2BetFiles:
+        for mm in FloatingMasksFiles:
+            MaskName = os.path.basename(mm).replace(".nii","").replace(".gz","")
+            NewMaskName = MaskName + "_T2w" + ".nii.gz"
+            NewMaskFolder = os.path.join(os.path.dirname(ff),"RegisteredTractMasks")
+            NewMaskAddress = os.path.join(NewMaskFolder,NewMaskName)
+            if not os.path.exists(NewMaskFolder):
+                os.makedirs(NewMaskFolder)
+
+            Affine_matrix_files = glob.glob(os.path.join(os.path.dirname(ff),"*MatrixAff.txt"))
+            if not Affine_matrix_files:
+                missing_matrix_paths.append(os.path.dirname(ff))
+                continue
+            Affine_matrix = Affine_matrix_files[0]
+
+            # Execute the command
+            command = f"reg_resample -ref {ff} -flo {mm} -res {NewMaskAddress} -trans {Affine_matrix} -inter 0"        
+            command_args = shlex.split(command)
+
+            try:
+                result = subprocess.run(command_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                print(f"Output:\n{result.stdout.decode()}")
+                print(f"Errors:\n{result.stderr.decode()}")
+            except Exception as e:
+                print(f"An error occurred: {e}")
+    
+    print("Registered all masks to t2w space of individual mice: DONE\n")
+    
+    # Parsing for all SmoothMicoBet.nii.gz files in DTI folders after a given input path.
+    DTIBetPath = os.path.join(args.input,"**","DTI*","*SmoothMicoBet.nii.gz")
+    DTIBetFiles = glob.glob(DTIBetPath,recursive=True)
+    
+    for ff in DTIBetFiles:
+        temp = os.path.dirname(os.path.dirname(ff))
+        t2MasksPath = os.path.join(temp,"T2w","RegisteredTractMasks","*nii.gz")
+        FloatingMasksFiles = glob.glob(t2MasksPath)
+        for mm in FloatingMasksFiles:
+            MaskName = os.path.basename(mm).replace("T2w","DTI")
+            NewMaskName = MaskName
+            NewMaskFolder = os.path.join(os.path.dirname(ff),"RegisteredTractMasks")
+            NewMaskAddress = os.path.join(NewMaskFolder,NewMaskName)
+            if not os.path.exists(NewMaskFolder):
+                os.makedirs(NewMaskFolder)
+
+            Affine_matrix_files = glob.glob(os.path.join(os.path.dirname(ff),"*MatrixAff.txt"))
+            if not Affine_matrix_files:
+                missing_matrix_paths.append(os.path.dirname(ff))
+                continue
+            Affine_matrix = Affine_matrix_files[0]
+
+            command = f"reg_resample -ref {ff} -flo {mm} -res {NewMaskAddress} -trans {Affine_matrix} -inter 0"        
+            command_args = shlex.split(command)
+
+            try:
+                result = subprocess.run(command_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                print(f"Output:\n{result.stdout.decode()}")
+                print(f"Errors:\n{result.stderr.decode()}")
+            except Exception as e:
+                print(f"An error occurred: {e}")
+    
+    # Adjust by flipping for the fa0 and ad files
+    # Locate all files in the "RegisteredTractMasks" folder
+    registered_masks_path = os.path.join(args.input,"**","RegisteredTractMasks", "*.nii.gz")
+    registered_masks_files = glob.glob(registered_masks_path, recursive=True)
+
+    for mask_file in registered_masks_files:
+        # Load the mask file
+        mask_nifti = nib.load(mask_file)
+        mask_data = mask_nifti.get_fdata()
+
+        # Flip the mask along the Y and Z axes
+        #flipped_mask = np.flip(np.flip(mask_data, axis=1), axis=2)
+        flipped_mask = np.flip(mask_data, axis=2)
+        
+
+        # Determine the directory to save the adjusted mask
+        mask_dir = os.path.dirname(os.path.dirname(mask_file))
+        adjusted_masks_dir = os.path.join(mask_dir, "DSI_studio", "RegisteredTractMasks_adjusted")
+
+        # Create the directory if it doesn't exist
+        if not os.path.exists(adjusted_masks_dir):
+            os.makedirs(adjusted_masks_dir)
+
+        # Define the new file name and save the flipped mask
+        adjusted_mask_file = os.path.join(adjusted_masks_dir, os.path.basename(mask_file).replace(".nii.gz","_flipped.nii.gz"))
+        nib.save(nib.Nifti1Image(flipped_mask, mask_nifti.affine), adjusted_mask_file)
+
+        print("Flipping of RegisteredTractMasks and saving to RegisteredTractMasks_adjusted: DONE\n")
+
+    # Save the missing matrix paths to a CSV file
+    missing_matrix_csv_path = os.path.join(args.input, "missing_matrix_paths.csv")
+    with open(missing_matrix_csv_path, mode='w', newline='') as file:
+        writer = csv.writer(file)
+        if not missing_matrix_paths:
+            writer.writerow(["All folders contained an Affine transformation matrix"])
+        else:
+            for path in missing_matrix_paths:
+                writer.writerow([path])
+    
+    print("Saved missing matrix paths to CSV: DONE\n")
+
+        
+if __name__ == "__main__":
+    main()