organ_percentile.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import numpy
  2. import sys
  3. import os
  4. import json
  5. import nibabel
  6. def organ_percentile(img, mask, level, p):
  7. #ORGAN_PERCENTILE - computes suv_x the pth percentile of the distribution of
  8. # image intensity values in img from within some ROI mask
  9. #
  10. # Inputs:
  11. # img - image. ndarray
  12. # mask - ROI mask. Must be same dimension as img. Must be binary ndarray
  13. # p - percentile. Between 0-100
  14. #
  15. # Outputs:
  16. # suv_x - percentile of distribution. Defined by:
  17. #
  18. # suv_x
  19. # p/100 = ∫ H(x) dx
  20. # 0
  21. #
  22. # where H(x) is the normalized distribution of image values within mask
  23. #img = np.array(img)
  24. #mask = np.array(mask)
  25. h = img[mask == level]
  26. suv_x = numpy.percentile(h, p)
  27. return suv_x
  28. def main(parameterFile):
  29. fhome=os.path.expanduser('~')
  30. with open(os.path.join(fhome,".labkey","setup.json")) as f:
  31. setup=json.load(f)
  32. sys.path.insert(0,setup["paths"]["nixWrapper"])
  33. import nixWrapper
  34. nixWrapper.loadLibrary("labkeyInterface")
  35. import labkeyInterface
  36. import labkeyDatabaseBrowser
  37. import labkeyFileBrowser
  38. fconfig=os.path.join(fhome,'.labkey','network.json')
  39. net=labkeyInterface.labkeyInterface()
  40. net.init(fconfig)
  41. db=labkeyDatabaseBrowser.labkeyDB(net)
  42. fb=labkeyFileBrowser.labkeyFileBrowser(net)
  43. with open(parameterFile) as f:
  44. pars=json.load(f)
  45. #segmentation layout
  46. project=pars['project']
  47. dataset=pars['targetQuery']
  48. schema=pars['targetSchema']
  49. segSchema=pars['segmentationSchema']
  50. segQuery=pars['segmentationQuery']
  51. qQuery=pars['percentileQuery']
  52. segVersion=pars['version']
  53. segVersionI=int(pars['versionNumber'])
  54. tempBase=pars['tempBase']
  55. if not os.path.isdir(tempBase):
  56. os.makedirs(tempBase)
  57. participantField=pars['participantField']
  58. #all images from database
  59. ds=db.selectRows(project,schema,dataset,[])
  60. petField=pars['images']['PET']['queryField']
  61. rows=ds['rows']
  62. #rows=[ds['rows'][0]]
  63. pv=numpy.concatenate((numpy.linspace(10,50,5),
  64. numpy.linspace(55,80,6),
  65. numpy.linspace(82,90,5),
  66. numpy.linspace(91,100,10)))
  67. for r in rows:
  68. localPET=os.path.join(tempBase,'PET.nii.gz')
  69. localSeg=os.path.join(tempBase,'Seg.nii.gz')
  70. for f in [localPET,localSeg]:
  71. if os.path.isfile(f):
  72. os.remove(f)
  73. #build image path
  74. remoteDir=fb.buildPathURL(project,[pars['imageDir'],\
  75. r['patientCode'],r['visitCode']])
  76. print('{}: {}'.format(petField,r[petField]))
  77. remotePET=remoteDir+'/'+r[petField]
  78. print('{}:{}'.format(remotePET,fb.entryExists(remotePET)))
  79. vFilter={'variable':'version','value':segVersion,'oper':'eq'}
  80. idFilter={'variable':'patientCode','value':r['patientCode'], 'oper':'eq'}
  81. visitFilter={'variable':'visitCode','value':r['visitCode'], 'oper':'eq'}
  82. dsSeg=db.selectRows(project,segSchema,segQuery,[idFilter,visitFilter,vFilter])
  83. if len(dsSeg['rows'])!=1:
  84. print('Failed to get segmentation for {}/{}'.format(r[participantField],segVersion))
  85. remoteSeg=remoteDir+'/'+dsSeg['rows'][0]['segmentation']
  86. print('{}:{}'.format(remoteSeg,fb.entryExists(remoteSeg)))
  87. fb.readFileToFile(remotePET,localPET)
  88. fb.readFileToFile(remoteSeg,localSeg)
  89. niPET=nibabel.load(localPET)
  90. niSeg=nibabel.load(localSeg)
  91. #3 lungs
  92. #4 thyroid
  93. #5 bowel
  94. for level in [3,4,5]:
  95. v=organ_percentile(niPET.get_fdata(),niSeg.get_fdata(),level,pv)
  96. for (x,y) in zip(pv,v):
  97. #get existing entry
  98. seqNum=r['SequenceNum']+0.0001*x+0.01*segVersionI
  99. print('[{:.8f}] {}/{}: {}/{}'.format(seqNum,r['patientCode'],r['visitCode'],x,y))
  100. sFilter={'variable':'SequenceNum','value':'{}'.format(seqNum),'oper':'eq'}
  101. oFilter={'variable':'organ','value':'{}'.format(level),'oper':'eq'}
  102. dsP=db.selectRows(project,schema,qQuery,[idFilter,sFilter,oFilter])
  103. mode='update'
  104. if len(dsP['rows'])==0:
  105. mode='insert'
  106. rowDSP={x:r[x] for x in [participantField,'patientCode','visitCode']}
  107. rowDSP['SequenceNum']=seqNum
  108. rowDSP['segmentationVersion']=segVersion
  109. else:
  110. rowDSP=dsP['rows'][0]
  111. rowDSP['percentile']=x
  112. rowDSP['value']=y
  113. rowDSP['organ']=level
  114. db.modifyRows(mode,project,schema,qQuery,[rowDSP])
  115. print('Done')
  116. if __name__ == '__main__':
  117. main(sys.argv[1])