extract_suv_from_mask.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Thu Sep 29 14:51:09 2022
  4. @author: katja
  5. """
  6. import numpy
  7. import os
  8. import pandas as pd
  9. import nibabel
  10. import csv
  11. import matplotlib.pyplot as plt
  12. def organ_percentile(img, mask, level, p):
  13. #ORGAN_PERCENTILE - computes suv_x the pth percentile of the distribution of
  14. # image intensity values in img from within some ROI mask
  15. #
  16. # Inputs:
  17. # img - image. ndarray
  18. # mask - ROI mask. Must be same dimension as img. Must be binary ndarray
  19. # p - percentile. Between 0-100
  20. #
  21. # Outputs:
  22. # suv_x - percentile of distribution. Defined by:
  23. #
  24. # suv_x
  25. # p/100 = ∫ H(x) dx
  26. # 0
  27. #
  28. # where H(x) is the normalized distribution of image values within mask
  29. #img = np.array(img)
  30. #mask = np.array(mask)
  31. h = img[mask == level]
  32. print("Extracting SUV% for organ", level)
  33. #histo=[]
  34. # col=["red", "green", "yellow","pink", "brown", "darkblue", "black", "purple"]
  35. # i=level
  36. # plt.hist(h, color= col[i-1],bins=50, range=(0,6))
  37. # plt.title("Histogram of SUV values for "+ str(level))
  38. # plt.show()
  39. suv_x = numpy.percentile(h, p)
  40. return suv_x
  41. def main():
  42. # Get the current script's directory
  43. current_dir = os.path.dirname(os.path.abspath(__file__))
  44. inputCSV = os.path.join(current_dir, "..", 'data', 'cases_retroMManon.csv') #input csv file that has the path to each patient image
  45. #Returns concatinated sequnces of evenly spaced numbers over a specified interval - for SUV percentile
  46. pv=numpy.concatenate((numpy.linspace(10,50,5),
  47. numpy.linspace(55,80,6),
  48. numpy.linspace(82,90,5),
  49. numpy.linspace(91,100,10)))
  50. pvi=pv.astype(int) #have to be indigers to be able to append to name
  51. col_names = ["SUV" + str(x) for x in pvi]
  52. flists = []
  53. with open(inputCSV, 'r') as inFile: #goes trough the whole csv file and makes an flist (list)
  54. cr = csv.DictReader(inFile, lineterminator='\n')
  55. flists = [row for row in cr]
  56. alldata=[]
  57. histo=[]
  58. for idx, entry in enumerate(flists, start=1): #
  59. PET = entry['Image']
  60. Seg = entry['Mask']
  61. Visit = entry['Visit']
  62. ID = entry['ID']
  63. #open PET image and segmentation
  64. niPET=nibabel.load(PET)
  65. niSeg=nibabel.load(Seg)
  66. print(" Processing Patient, Visit , (Image: , Mask:)", idx, len(flists), Visit, entry['Image'], entry['Mask'])
  67. #In nnU-Net (organ segmentation are numbered):
  68. #1 liver #DM
  69. #2 spleen #DM
  70. #3 lungs #DM
  71. #4 thyroid #DM
  72. #5 bowel # DM 16
  73. #6 pancreas
  74. #7 bladder
  75. #8 kidneys
  76. #extract SUV percentiles from PET image with mask - segmentation
  77. for level in [1,2,3,4,5,6,7,8]:
  78. v=organ_percentile(niPET.get_fdata(),niSeg.get_fdata(),level,pv)
  79. mat=[level,ID, Visit]
  80. mat=numpy.concatenate((mat,v))
  81. alldata.append(mat)
  82. # plt.hist(histo, bins=5, range=(0,6))
  83. # plt.title("Histogram of SUV values for Spleen")
  84. # plt.show()
  85. #print("Percentile, value: ", mat)
  86. #print(alldata)
  87. # plt.hist(h, bins=50, range=(0,6))
  88. # plt.show()
  89. Names=["Organ", "PatientID", "Visit"]
  90. Names=numpy.concatenate((Names,col_names))
  91. #make a dataframe to write the data than in excel - that can be read by another script
  92. df=pd.DataFrame(alldata,columns=Names)
  93. df.to_excel('..\\data\\percentilesAnon.xlsx', index=None) #path to where you want to save excel
  94. print("Done.")
  95. if __name__ == '__main__':
  96. main()