generateFigures.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. import nibabel
  2. import os
  3. import json
  4. import sys
  5. import numpy
  6. import matplotlib.pyplot
  7. #import chardet
  8. def buildPath(server,project,imageDir,patientCode,visitCode,imageType):
  9. path='/'.join([server,'labkey/_webdav',project,'@files',imageDir,patientCode,visitCode])
  10. tail='_notCropped_2mmVoxel'
  11. if imageType=='Segm':
  12. tail='_v5'
  13. path+='/'+patientCode+'-'+visitCode+'_'+imageType+tail+'.nii.gz'
  14. return path
  15. def getCOWAxis(seg,val,axis):
  16. #returns center of weight for segmentation image where val is selected
  17. if axis==0:
  18. #2,1 or 1,1
  19. i1=2
  20. i2=1
  21. if axis==1:
  22. #0,1 or 2,0
  23. i1=2
  24. i2=0
  25. if axis==2:
  26. #0,0 or 1,0
  27. i1=1
  28. i2=0
  29. s=numpy.sum(numpy.sum(seg==val,i1),i2)
  30. x=numpy.arange(len(s))
  31. s0=0
  32. for i in x:
  33. if s[i]==0:
  34. continue
  35. s0=i
  36. break
  37. s1=len(s)
  38. for i in numpy.arange(s0,len(s)):
  39. if s[i]>0:
  40. continue
  41. s1=i
  42. break
  43. return [s0,numpy.average(x,weights=s),s1]
  44. def getGeometry(seg,val):
  45. #return center of weight of segmentation seg for segment val as a 3D vector
  46. return [getCOWAxis(seg,val,x) for x in [0,1,2]]
  47. def getCOW(geom):
  48. return [x[1] for x in geom]
  49. def getRange(geom):
  50. return [[x[0],x[2]] for x in geom]
  51. def plot(imgs,t,val,tempBase):
  52. segColors=[[0,0,0],[0.1,0.1,0.1],[0,0.2,0],[1,0,0],[0,0,1],[1,0,1]]
  53. #3-lungs 4-thyroid 5-bowel
  54. delta=20
  55. if val==4:
  56. delta=40
  57. window=350
  58. level=40
  59. geo=getGeometry(imgs['Segm'],val)
  60. cowF=getCOW(geo)
  61. rng=getRange(geo)
  62. #print(rng)
  63. cowI=[int(x) for x in cowF]
  64. segment=imgs['Segm']==val
  65. i0=rng[0][0]-delta
  66. if i0<0:
  67. i0=0
  68. i1=rng[0][1]+delta
  69. if i1>imgs['CT'].shape[0]:
  70. i1=imgs['CT'].shape[0]
  71. k0=rng[2][0]-delta
  72. if k0<0:
  73. k0=0
  74. k1=rng[2][1]+delta
  75. if k1>imgs['CT'].shape[2]:
  76. k1=imgs['CT'].shape[2]
  77. if t=='CT':
  78. v0=level-0.5*window
  79. v1=v0+window
  80. matplotlib.pyplot.imshow(imgs['CT'][i0:i1,cowI[1],k0:k1].transpose(),cmap='gray',vmin=v0,vmax=v1)
  81. if t=='PET':
  82. matplotlib.pyplot.imshow(imgs['PET'][i0:i1,cowI[1],k0:k1].transpose(),cmap='inferno')
  83. #blueish
  84. if t=='CT':
  85. rgb=segColors[val]
  86. if t=='PET':
  87. rgb=[1,1,1]
  88. colors = [rgb+[c] for c in numpy.linspace(0,1,100)]
  89. cmap = matplotlib.colors.LinearSegmentedColormap.from_list('mycmap', colors, N=5)
  90. matplotlib.pyplot.imshow(segment[i0:i1,cowI[1],k0:k1].transpose(), cmap=cmap, alpha=0.2)
  91. matplotlib.pyplot.gca().invert_yaxis()
  92. outfile=os.path.join(tempBase,'slice{}_{}.png'.format(t,val))
  93. matplotlib.pyplot.savefig(outfile)
  94. return outfile
  95. def main(parameterFile):
  96. #mask for segmentations
  97. setupJSON=os.path.join(os.path.expanduser('~'),'.labkey','setup.json')
  98. with open(setupJSON) as f:
  99. setup=json.load(f)
  100. sys.path.insert(0,setup["paths"]["nixWrapper"])
  101. import nixWrapper
  102. nixWrapper.loadLibrary("labkeyInterface")
  103. import labkeyInterface
  104. import labkeyDatabaseBrowser
  105. import labkeyFileBrowser
  106. fconfig=os.path.join(os.path.expanduser('~'),'.labkey','network.json')
  107. net=labkeyInterface.labkeyInterface()
  108. net.init(fconfig)
  109. db=labkeyDatabaseBrowser.labkeyDB(net)
  110. fb=labkeyFileBrowser.labkeyFileBrowser(net)
  111. tempBase=os.path.join(os.path.expanduser('~'),'temp')
  112. with open(parameterFile) as f:
  113. pars=json.load(f)
  114. project=pars['project']
  115. dataset=pars['targetQuery']
  116. schema=pars['targetSchema']
  117. reportSchema=pars['reportSchema']
  118. reportQuery=pars['reportQuery']
  119. participantField=pars['participantField']
  120. #all images from database
  121. ds=db.selectRows(project,schema,dataset,[])
  122. #input
  123. imageResampledField={"CT":"ctResampled","PET":"petResampled","patientmask":"ROImask"}
  124. rows=ds['rows']
  125. rows=[ds['rows'][0]]
  126. for r in rows:
  127. print(r)
  128. iTypes=['CT','PET','Segm']
  129. needToCalculate=False
  130. for t in ['CT','PET']:
  131. idFilter={'variable':participantField,'value':r[participantField],'oper':'eq'}
  132. visitFilter={'variable':'visitCode','value':r['visitCode'],'oper':'eq'}
  133. verFilter={'variable':'version','value':pars['version'],'oper':'eq'}
  134. typeFilter={'variable':'type','value':t,'oper':'eq'}
  135. ds2=db.selectRows(project,reportSchema,reportQuery,[idFilter,visitFilter,verFilter,typeFilter])
  136. if len(ds2['rows'])==0:
  137. #skip if row is present
  138. #there are in fact multiple rows for multiple organs...
  139. needToCalculate=True
  140. break
  141. if not needToCalculate:
  142. continue
  143. imgs={}
  144. for t in iTypes:
  145. try:
  146. imagePath=r['_labkeyurl_'+imageResampledField[t]]
  147. except KeyError:
  148. ds1=db.selectRows(project,pars['segmentationSchema'],pars['segmentationQuery'],\
  149. [idFilter,visitFilter,verFilter])
  150. imagePath=ds1['rows'][0]['_labkeyurl_segmentation']
  151. localPath=os.path.join(tempBase,'image'+t+'.nii.gz')
  152. if os.path.isfile(localPath):
  153. os.remove(localPath)
  154. fb.readFileToFile(imagePath,localPath)
  155. img=nibabel.load(localPath)
  156. imgs[t]=img.get_fdata()
  157. print('Loading completed')
  158. for t in ['CT','PET']:
  159. for val in [3,4,5]:
  160. outfile=plot(imgs,t,val,tempBase)
  161. remoteDir=fb.buildPathURL(project,[pars['imageDir'],r['patientCode'],r['visitCode']])
  162. imageFile=r['patientCode']+'-'+r['visitCode']+'_'+t+'_{}'.format(val)+'_'+pars['version']+'.png'
  163. remoteFile='/'.join([remoteDir,imageFile])
  164. fb.writeFileToFile(outfile,remoteFile)
  165. print('Uploaded {}'.format(remoteFile))
  166. os.remove(outfile)
  167. organFilter={'variable':'organ','value':'{}'.format(val),'oper':'eq'}
  168. typeFilter['value']=t
  169. ds3=db.selectRows(project,reportSchema,reportQuery,\
  170. [idFilter,visitFilter,verFilter,organFilter,typeFilter])
  171. if len(ds3['rows'])>0:
  172. mode='update'
  173. frow=ds3['rows'][0]
  174. else:
  175. mode='insert'
  176. frow={}
  177. for f in [participantField,'patientCode','visitCode']:
  178. frow[f]=r[f]
  179. frow['organ']='{}'.format(val)
  180. frow['type']=t
  181. frow['version']=pars['version']
  182. frow['file']=imageFile
  183. db.modifyRows(mode,project,reportSchema,reportQuery,[frow])
  184. print('Images uploaded')
  185. if __name__ == '__main__':
  186. main(sys.argv[1])