runStat.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. import statUtils
  2. import os
  3. import radiomics
  4. import SimpleITK
  5. import sys
  6. import json
  7. import numpy
  8. def main(parFile='../templates/statistics.json'):
  9. setup=statUtils.loadSetup(parFile)
  10. rFile='radiomics.json'
  11. #update threshold values if needed
  12. with open(rFile,'w') as f:
  13. f.write(json.dumps(setup['radiomics']))
  14. setup['db'],setup['fb']=statUtils.connectDB('onko-nix')
  15. users=statUtils.getUsers(setup['db'],setup['project'])
  16. qFilter=[]
  17. try:
  18. vList=';'.join(setup['participants'])
  19. qFilter.append({'variable':'ParticipantId','value':vList,'oper':'in'})
  20. except KeyError:
  21. pass
  22. try:
  23. vList=';'.join(setup['visits'])
  24. qFilter.append({'variable':'visitCode','value':vList,'oper':'in'})
  25. except KeyError:
  26. pass
  27. ds=setup['db'].selectRows(setup['project'],'study',setup['imagingDataset'],qFilter)
  28. if not os.path.isdir(setup['localDir']):
  29. os.mkdir(setup['localDir'])
  30. #select just the first row; debugging
  31. rows=ds['rows']
  32. setup['values']=['COM','MTV','TLG','SUVmean','SUVmax','voxelCount','SUVSD']
  33. #params=os.path.join('..','templates','radiomics.yaml')
  34. setup['featureExtractor']=radiomics.featureextractor.RadiomicsFeatureExtractor(rFile)
  35. n=setup.get('n',-1)
  36. if n>0:
  37. rows=rows[:n]
  38. for r in rows:
  39. #check if we have to do calculation
  40. setup['SUVdataset']='SUVanalysis_liver'
  41. liverDone=checkData(setup,r)
  42. setup['SUVdataset']='SUVanalysis_SUVmax'
  43. suvMaxDone=checkData(setup,r)
  44. if liverDone and suvMaxDone:
  45. print('Skipping {} {}'.format(r['ParticipantId'],r['visitCode']))
  46. continue
  47. #PET
  48. for q in ['petResampled']:
  49. localPath=statUtils.getImage(setup,r,q)
  50. if localPath=="NONE":
  51. continue
  52. pet=SimpleITK.ReadImage(localPath)
  53. #Seg
  54. segPaths=statUtils.getSegmentations(setup,r)
  55. if "NONE" in segPaths.values():
  56. os.remove(localPath)
  57. continue
  58. segKeys=list(segPaths.keys())
  59. for x in segPaths:
  60. print('Loaded {}/{}'.format(users[x],segPaths[x]))
  61. seg={x:SimpleITK.ReadImage(segPaths[x]) for x in segPaths}
  62. try:
  63. thr=setup['radiomics']['setting']['resegmentRange'][0]
  64. except KeyError:
  65. thr=None
  66. setup['radiomics']['setting']['resegmentRange']=None
  67. firstOrder=setup['radiomics']['featureClass']['firstorder']
  68. if 'Variance' not in firstOrder:
  69. firstOrder.append('Variance')
  70. #get value for maximum in organs or liver mean and std
  71. outputs=getValues(setup,r,pet,seg)
  72. setup['SUVdataset']='SUVanalysis'
  73. #uploadData(setup,r,outputs)
  74. print(outputs)
  75. default={'SUVmax':0,'SUVmean':0,'SUVSD':0}
  76. #liver threshold
  77. liverId=1
  78. liverThreshold={x:outputs[x].get(liverId,default)['SUVmean']
  79. +2*outputs[x].get(liverId,default)['SUVSD']
  80. for x in outputs}
  81. lesionId=4
  82. bmId=3
  83. suvMax={x:numpy.max([outputs[x].get(lesionId,default)['SUVmax'],
  84. outputs[x].get(bmId,default)['SUVmax']])
  85. for x in outputs}
  86. suvMaxThreshold={x:0.41*suvMax[x] for x in suvMax}
  87. print('thr[liver]={} thr(suvmax)={}'.format(liverThreshold,suvMaxThreshold))
  88. #thresholds are by user
  89. liverOutputs={}
  90. for s in liverThreshold:
  91. #update radiomics setting
  92. setup['radiomics']['setting']['resegmentRange']=[liverThreshold[s]]
  93. setup['radiomics']['setting']['resegmentShape']=True
  94. liverOutputs[s]=getValuesForSegmentation(setup,r,pet,seg[s])
  95. _=[liverOutputs[s][y].update({'threshold':liverThreshold[s]}) for y in liverOutputs[s]]
  96. setup['SUVdataset']='SUVanalysis_liver'
  97. uploadData(setup,r,liverOutputs)
  98. suvMaxOutputs={}
  99. for s in suvMaxThreshold:
  100. setup['radiomics']['setting']['resegmentRange']=[suvMaxThreshold[s]]
  101. setup['radiomics']['setting']['resegmentShape']=True
  102. suvMaxOutputs[s]=getValuesForSegmentation(setup,r,pet,seg[s])
  103. _=[suvMaxOutputs[s][y].update({'threshold':suvMaxThreshold[s]}) for y in suvMaxOutputs[s]]
  104. setup['SUVdataset']='SUVanalysis_SUVmax'
  105. uploadData(setup,r,suvMaxOutputs)
  106. #skip threshold of 4
  107. doThreshold4=False
  108. if doThreshold4:
  109. #threshold of 4
  110. setup['radiomics']['setting']['resegmentRange']=[4]
  111. setup['radiomics']['setting']['resegmentShape']=True
  112. outputs4=getValues(setup,r,pet,seg)
  113. setup['SUVdataset']='SUVanalysis_SUV4'
  114. uploadData(setup,r,outputs4)
  115. #outputs=getValues(setup,users,r,pet)
  116. #uploadData(setup,r,outputs)
  117. #cleanup
  118. os.remove(localPath)
  119. for x in segPaths:
  120. os.remove(segPaths[x])
  121. def getValues(setup,row,pet,seg):
  122. rFile='radiomics.json'
  123. with open(rFile,'w') as f:
  124. f.write(json.dumps(setup['radiomics']))
  125. setup['featureExtractor']=radiomics.featureextractor.RadiomicsFeatureExtractor(rFile)
  126. #find labels associated with each (non-overlaping) segmentation
  127. ids=statUtils.getSegments(list(seg.values())[0])
  128. outputs={x:{} for x in seg}
  129. for x in seg:
  130. for id in ids:
  131. print('{} {}'.format(id,ids[id]))
  132. try:
  133. output=statUtils.getRadiomicsComponentStats(setup,pet,seg[x],ids[id])
  134. except ValueError:
  135. continue
  136. outputs[x][ids[id]]=output
  137. os.remove(rFile)
  138. return outputs
  139. def getValuesForSegmentation(setup,row,pet,seg):
  140. rFile='radiomics.json'
  141. with open(rFile,'w') as f:
  142. f.write(json.dumps(setup['radiomics']))
  143. setup['featureExtractor']=radiomics.featureextractor.RadiomicsFeatureExtractor(rFile)
  144. #find labels associated with each (non-overlaping) segmentation
  145. ids=statUtils.getSegments(seg)
  146. outputs={}
  147. for id in ids:
  148. print('{} {}'.format(id,ids[id]))
  149. try:
  150. output=statUtils.getRadiomicsComponentStats(setup,pet,seg,ids[id])
  151. except ValueError:
  152. continue
  153. outputs[ids[id]]=output
  154. os.remove(rFile)
  155. return outputs
  156. def uploadData(setup,r,outputs):
  157. baseVar=['ParticipantId','SequenceNum','patientCode','visitCode']
  158. for x in outputs:
  159. for s in outputs[x]:
  160. output=outputs[x][s]
  161. output.update({x:r[x] for x in baseVar})
  162. output['User']=x
  163. output['segment']=s
  164. statUtils.updateDatasetRows(setup['db'],setup['project'],setup['SUVdataset'],[output])
  165. def checkData(setup,r):
  166. qFilter=[]
  167. qFilter.append({'variable':'ParticipantId','value':r['ParticipantId'],'oper':'eq'})
  168. qFilter.append({'variable':'visitCode','value':r['visitCode'],'oper':'eq'})
  169. ds=setup['db'].selectRows(setup['project'],'study',setup['SUVdataset'],qFilter)
  170. n=len(ds['rows'])
  171. print('[{}:{}/{}] got {} rows.'.format(setup['SUVdataset'],r['ParticipantId'],r['visitCode'],n))
  172. return n>0
  173. if __name__=='__main__':
  174. main(sys.argv[1])