plotting_quantitative_dti_values.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Mon Nov 4 17:54:46 2024
  4. @author: arefk
  5. """
  6. import os
  7. import pandas as pd
  8. import seaborn as sns
  9. import matplotlib.pyplot as plt
  10. import statsmodels.formula.api as smf
  11. from statsmodels.stats.multicomp import MultiComparison
  12. from itertools import combinations
  13. import statsmodels
  14. import scipy
  15. from scipy.stats import dunnett
  16. # Set up warning suppression for convergence
  17. import warnings
  18. warnings.simplefilter(action='ignore')
  19. # Define user settings for the analysis
  20. selected_dialation_amount = 3 # Set dilation amount
  21. selected_qtype = "fa" # Set Qtype value
  22. selected_mask_names = ["L_cst_784_AMBA",
  23. "CRuT_MOp-RN_ipsilesional_CCcut",
  24. "CRuT_MOp-RN_contralesional_mirrored_CCcut",
  25. "CReT_MOp-TRN_ipsilesional_CCcut",
  26. "CReT_MOp-TRN_contralesional_CCcut",
  27. "CST_MOp-int-py_ipsilesional_selfdrawnROA+CCcut",
  28. "CST_MOp-int-py_contralesional_selfdrawnROA+CCcut",
  29. "TC_DORsm-SSp_ll+SSp_ul_ipsilesional_END+higherstepsize_",
  30. "TC_DORsm-SSp_ll+SSp_ul_contralesional_END+higherstepsize",
  31. "CC_MOp-MOp_cut",
  32. "OT_och-lgn_lgncut"
  33. ] # Set mask names to be used
  34. # Define simple anatomical names for the masks
  35. mask_name_mapping = {
  36. "CRuT_MOp-RN_ipsilesional_CCcut": "Rubropsinal (Ipsilesional)",
  37. "CRuT_MOp-RN_contralesional_mirrored_CCcut": "Rubropsinal (Contralesional)",
  38. "CReT_MOp-TRN_ipsilesional_CCcut": "Reticulospinal (Ipsilesional)",
  39. "CReT_MOp-TRN_contralesional_CCcut": "Reticulospinal (Contralesional)",
  40. "CST_MOp-int-py_ipsilesional_selfdrawnROA+CCcut": "Corticospinal (Ipsilesional)",
  41. "CST_MOp-int-py_contralesional_selfdrawnROA+CCcut": "Corticospinal (Contralesional)",
  42. "TC_DORsm-SSp_ll+SSp_ul_ipsilesional_END+higherstepsize_": "Thalamocortical (Ipsilesional)",
  43. "TC_DORsm-SSp_ll+SSp_ul_contralesional_END+higherstepsize": "Thalamocortical (Contralesional)",
  44. "CC_MOp-MOp_cut": "Corpus Callosum",
  45. "OT_och-lgn_lgncut": "Optic"
  46. }
  47. # Define the PlotBoxplot function
  48. def PlotBoxplot(filtered_df, qq, mm, dd, output_folder, sig):
  49. """
  50. Plot boxplots for filtered dataframe and save as images.
  51. Parameters:
  52. filtered_df (DataFrame): Filtered dataframe based on "Qtype" and "mask_name".
  53. qq (str): Qtype value.
  54. mm (str): Mask_name value.
  55. output_folder (str): Path to the output folder to save images.
  56. """
  57. # Set the color palette to grey
  58. sns.set_palette("rocket")
  59. # Set the figure size to 18 cm in width
  60. plt.figure(figsize=(18/2.54, 4)) # Convert 18 cm to inches
  61. # Create a boxplot
  62. sns.boxplot(data=filtered_df, hue="Group", y="Value", x="merged_timepoint",
  63. fliersize=3, flierprops={"marker": "o"}, palette="rocket")
  64. # Set title and labels
  65. mask_label = mask_name_mapping.get(mm, mm)
  66. plt.title(f'{qq}_{mask_label}_{dd}')
  67. plt.xlabel('Timepoint')
  68. plt.ylabel(qq + "(n.a)")
  69. # Show legend without title and frame
  70. plt.legend(title=None, frameon=False, bbox_to_anchor=(1.05, 1), loc='best')
  71. plt.tight_layout()
  72. # Save the plot as an image
  73. if sig:
  74. output_path = os.path.join(output_folder, f'{qq}_{mm}_{dd}_mixedlm_significant.png')
  75. else:
  76. output_path = os.path.join(fa_over_time_plots_dir, f'{mm}.png')
  77. plt.savefig(output_path, dpi=100)
  78. # Close the plot to avoid displaying it
  79. plt.show()
  80. plt.close()
  81. # Get the directory where the code file is located
  82. code_dir = os.path.dirname(os.path.abspath(__file__))
  83. # Get the parent directory of the code directory
  84. parent_dir = os.path.dirname(code_dir)
  85. # Define the path for the input CSV file
  86. input_file_path = os.path.join(parent_dir, 'output', "Quantitative_outputs", 'Quantitative_results_from_dwi_processing_only_in_stroke_slices.csv.csv')
  87. # Define the path for the output folder to save plots
  88. plots_output_dir = os.path.join(parent_dir, 'output', 'Figures', 'pythonFigs')
  89. fa_over_time_plots_dir = os.path.join(parent_dir, 'output', 'Figures', 'fa_over_time_plots')
  90. os.makedirs(fa_over_time_plots_dir, exist_ok=True)
  91. os.makedirs(plots_output_dir, exist_ok=True)
  92. # Load the CSV file into a dataframe
  93. df = pd.read_csv(input_file_path)
  94. #df = df[df["cluster ii"]=="High ii"]
  95. df = df.drop_duplicates()
  96. df = df[df["merged_timepoint"].isin([0,3,7,14,21, 28])]
  97. # Create lists to store results and terminal output
  98. results = []
  99. # Iterate over the user-defined "dialation_amount", "Qtype", and "mask_name"
  100. for dd in [selected_dialation_amount]:
  101. for qq in [selected_qtype]:
  102. for mm in selected_mask_names:
  103. # Filter the dataframe based on current "Qtype", "mask_name", and "dialation_amount"
  104. filtered_df = df[(df["Qtype"] == qq) & (df["mask_name"] == mm) & (df["dialation_amount"] == dd)]
  105. # Check if the filtered dataframe is not empty
  106. if not filtered_df.empty:
  107. # Plot the boxplot for the filtered dataframe
  108. # Assuming `sig` is a boolean that indicates statistical significance (set to False for now)
  109. sig = False
  110. PlotBoxplot(filtered_df, qq, mm, dd, plots_output_dir, sig)
  111. # Print the list of results (currently empty as calculations are not included)
  112. print(results) # Replace this with actual results dataframe if available