Skip to content

Commit f2f0d67

Browse files
authored
Add files via upload
1 parent 2b8286c commit f2f0d67

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed

radiomics2.py

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
#rBatch-run radiomics module inside Slicer using a parameter file
2+
#Usage: Set variables in slicer console according to local file paths and execute python file. For example:
3+
#base_directory = r"C:\Users\urs\Desktop\hoedha_radiomics\test"
4+
#paramfilepath = r"C:\urs\urs\Desktop\hoedha_radiomics\Params_radiomics.yaml"
5+
#pythonfile = r"C:\Users\urs\Desktop\hoedha_radiomics\radiomics.py"
6+
#exec(open(pythonfile).read())
7+
8+
import SlicerRadiomics
9+
import re
10+
import pandas as pd
11+
import openpyxl
12+
import os
13+
14+
################################SET PARAMETERS###########################################
15+
#define regex patterns to find correct volumes in scene
16+
pattern_T1C = r'^(?=.*(?:T1|t1|T1W))(?=.*CE)' #T1C works
17+
pattern_ADC = r'^\d+:\s.*ADC.*' #works ADC
18+
pattern_T1 = r'^\d+:\s(T1|t1|T1W)(?!.*CE)' #works T1
19+
pattern_T2 = r'^\d+:\s(?!(.*FLAIR.*|.*dark-fluid.*))(T2|t2|T2W)'
20+
pattern_FLAIR = r'^\d+:\s(FLAIR|.*dark-fluid.*)' #works FLAIR
21+
22+
23+
################# Get a list of subfolders in the base directory####################
24+
#'base_directory' path is set in the slicer python console
25+
subfolders = [os.path.join(base_directory, folder) for folder in os.listdir(base_directory) if os.path.isdir(os.path.join(base_directory, folder))]
26+
27+
# Print the full paths of the subfolders
28+
print('Processing the following folders:')
29+
for folder in subfolders:
30+
print(folder)
31+
32+
##############################FUNCTIONS################################
33+
#function to find first mrb files in each patient folder
34+
def find_file_with_extension(directory, extension):
35+
for root, dirs, files in os.walk(directory):
36+
for file in files:
37+
if file.endswith(extension):
38+
return os.path.join(root, file)
39+
return None # If no file with the given extension is found
40+
41+
##########################export table to csv##############################
42+
def savecsvandxlsx(nodename,outname):
43+
result = getNode(nodename)
44+
rad_outputFilename = subfolders[Index]+'\\Tables\\'+outname+'.csv' #TAKES i from index of mainloop!
45+
print(rad_outputFilename)
46+
delayDisplay("Export results to CSV file: "+rad_outputFilename,3000)
47+
slicer.util.exportNode(result,rad_outputFilename)
48+
# Read the csv file into a pandas DataFrame for export to xlsx
49+
df = pd.read_csv(rad_outputFilename, sep=',')
50+
excel_file_path =re.sub(r'\.csv$', '.xlsx', rad_outputFilename)# Define the Excel file path where you want to save the data
51+
# Write the DataFrame to an Excel file
52+
df.to_excel(excel_file_path, index=False)
53+
os.remove(rad_outputFilename)#remove original csv file if desired
54+
55+
#savecsvandxlsx('ADC_radiomics','ADC_radiomics')
56+
57+
#################PROCESS ADC VOLUME - find volume using regex#################
58+
def process_ADC():
59+
volnames_original = []
60+
#loop through names of volumes in original volume folder and test regex rules:
61+
children = vtk.vtkIdList()
62+
shNode.GetItemChildren(originalvols, children) #
63+
for j in range(children.GetNumberOfIds()):
64+
child = children.GetId(j)
65+
#print(child)
66+
print(shNode.GetItemDataNode(child).GetName())# print items in folder
67+
volnames_original.append(shNode.GetItemDataNode(child).GetName())
68+
for k in range(0,len(volnames_original)):
69+
if re.search(pattern_ADC, volnames_original[k]):
70+
print(f'matched volume at {volnames_original[k]} ')
71+
refvol = getNode(volnames_original[k])#if match is found
72+
else:
73+
print('not target volume...')
74+
#################################RUN RADIOMICS for ADC Original######################33
75+
segmentation = getNode('Segmentation')
76+
table = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLTableNode',f'{refvol.GetName()}_radiomics')
77+
print(f'applying radiomics to following volume: {refvol.GetName()}')
78+
delayDisplay(f"applying radiomics to following volume: {refvol.GetName()}")
79+
logic = SlicerRadiomics.SlicerRadiomicsLogic()
80+
logic.__init__()
81+
logic.runSync = True
82+
logic.runCLIWithParameterFile(refvol,segmentation,table,paramfilepath,callback=lambda: savecsvandxlsx(f'{refvol.GetName()}_radiomics','ADC_radiomics'))
83+
84+
##############RADIOMICS - coreg-skullstripped volumes- isolate relevent volume using regex###################
85+
def process_coregskullstripped():
86+
volnames_skullstripped = []
87+
#loop through names of volumes in 'skullstripped' folder and test regex rules:
88+
children = vtk.vtkIdList()
89+
shNode.GetItemChildren(subjectItemID, children) # Add a third argument with value True for recursive query
90+
for L in range(children.GetNumberOfIds()):
91+
child = children.GetId(L)
92+
print(child)
93+
print(shNode.GetItemDataNode(child).GetName())# print items in folder
94+
volnames_skullstripped.append(shNode.GetItemDataNode(child).GetName())
95+
patterns_skullstripped = [pattern_FLAIR,pattern_T1,pattern_T2,pattern_T1C]#list of regext patterns to find volumes #,pattern_T2
96+
#################3MAKE TABLES FOR RADIOMICS
97+
for pattern in patterns_skullstripped:#go through and match each of the patterns to obtain correct reference volume
98+
for M in range(0,len(volnames_skullstripped)):
99+
if re.search(pattern, volnames_skullstripped[M]):
100+
print(f'matched volume at {volnames_skullstripped[M]} ')
101+
refvol = getNode(volnames_skullstripped[M])#if match is found
102+
#skullstripvolnamelist.append(volnames_skullstripped[M])
103+
global table
104+
table = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLTableNode',f'{volnames_skullstripped[M]}_radiomics' )
105+
logic = SlicerRadiomics.SlicerRadiomicsLogic()
106+
logic.__init__()
107+
logic.runSync = True
108+
logic.runCLIWithParameterFile(refvol,segmentation,table,paramfilepath, callback = exportskullstriptable)
109+
#tablenames.append(table.GetName())
110+
else:
111+
print('not target volume...')
112+
113+
114+
#export tables from the coreg-skullstrip group
115+
def exportskullstriptable():
116+
nm = table.GetName()
117+
if re.search(pattern_T1, nm):############export tables that match the correct
118+
savecsvandxlsx(nm,'T1_radiomics')
119+
print(f'exported {nm} as T1_radiomics')
120+
elif re.search(pattern_T2, nm):
121+
savecsvandxlsx(nm,'T2_radiomics')
122+
print(f'exported {nm} as T2_radiomics')
123+
elif re.search(pattern_FLAIR, nm):
124+
savecsvandxlsx(nm,'FLAIR_radiomics')
125+
print(f'exported {nm} as FLAIR_radiomics')
126+
elif re.search(pattern_T1C, nm):
127+
savecsvandxlsx(nm,'T1C_radiomics')
128+
print(f'exported {nm} as T1C_radiomics')
129+
else:
130+
print("No match")
131+
132+
##############################LOOP THROUGH PATIENT FILES#############
133+
def mainloop():
134+
for i in range(0,len(subfolders)):
135+
global Index
136+
Index = i #used in savecsvandxlsx() function
137+
# Construct the complete path to the new subfolder
138+
table_folder = os.path.join(subfolders[i], "Tables")
139+
# Create the subfolder
140+
if not os.path.exists(table_folder):
141+
os.mkdir(table_folder)
142+
#find_first mrb file
143+
scenefile = find_file_with_extension(subfolders[i],'mrb')
144+
print(f'searching for scene file in {subfolders[i]}')
145+
#print(i)
146+
print(f'opening scenefile: {scenefile}')
147+
#load scene file
148+
slicer.util.loadScene(scenefile)
149+
print(f'opened {scenefile}')
150+
###################################################Segment statistics export#####################################################################
151+
import SegmentStatistics
152+
segmentationNode = getNode('Segmentation')
153+
segStatLogic = SegmentStatistics.SegmentStatisticsLogic()
154+
segStatLogic.getParameterNode().SetParameter("Segmentation", segmentationNode.GetID())
155+
segStatLogic.computeStatistics()
156+
#stats = segStatLogic.getStatistics()
157+
resultsTableNode = slicer.vtkMRMLTableNode()
158+
slicer.mrmlScene.AddNode(resultsTableNode)
159+
resultsTableNode.SetName('Segment_statistics')
160+
segStatLogic.exportToTable(resultsTableNode)
161+
segStatLogic.showTable(resultsTableNode)
162+
outputFilename = subfolders[i]+'\\Tables\\'+'CalcVolumes.csv'
163+
delayDisplay("Export results to CSV file: "+outputFilename)
164+
segStatLogic.exportToCSVFile(outputFilename)
165+
# Read the csv file into a pandas DataFrame
166+
df = pd.read_csv(outputFilename, sep=',')
167+
excel_file_path =re.sub(r'\.csv$', '.xlsx', outputFilename)# Define the Excel file path where you want to save the data
168+
# Write the DataFrame to an Excel file
169+
df.to_excel(excel_file_path, index=False) # Set index=False if you don't want to save the row indices
170+
os.remove(outputFilename)#remove original csv file if desired
171+
################RADIOMICS##########################################################################################
172+
#For Radiomics: We will employ the "Radiomics" module.
173+
#Input Image Volumes are as follows:
174+
#a. Original ADC
175+
#b. Coregistered-skullstripped T1
176+
#c. Coregistered-skullstripped T2
177+
#d. Coregistered-skullstripped FLAIR
178+
#e. Coregistered-skullstripped T1C
179+
#access segmentation node (should be the only segmentation, named 'Segmentation' across all mrb files)
180+
global segmentation
181+
segmentation = getNode('Segmentation')
182+
##################access folder hierarchy###############################
183+
global shNode
184+
shNode = slicer.mrmlScene.GetSubjectHierarchyNode()
185+
# Get folder named 'skullstripped'
186+
global sceneItemID
187+
sceneItemID = shNode.GetSceneItemID()
188+
global subjectItemID
189+
subjectItemID = shNode.GetItemChildWithName(sceneItemID, "skullstripped")#################coreg-skullstripped volumes
190+
#for access to original ADC:
191+
global levelunderscened
192+
levelunderscened = shNode.GetItemByPositionUnderParent(sceneItemID,0)
193+
global originalvols
194+
originalvols = shNode.GetItemByPositionUnderParent(levelunderscened,0)######################original volumes
195+
process_ADC()
196+
process_coregskullstripped()
197+
sceneSaveFilename = subfolders[i] + "\\saved-scene-AIAA segmentation_Tables" + time.strftime("%Y%m%d-%H%M%S") + ".mrb"
198+
if slicer.util.saveScene(sceneSaveFilename):
199+
logging.info("Scene saved to: {0}".format(sceneSaveFilename))
200+
print(f'scene file exported: {sceneSaveFilename}')
201+
else:
202+
logging.error("Scene saving failed")
203+
os.remove(scenefile)
204+
slicer.mrmlScene.Clear (0)#clear scene
205+
del Index
206+
207+
208+
mainloop()
209+
210+
211+
212+
213+
214+

0 commit comments

Comments
 (0)