populateImagingFromTransferList.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #date sorts studies from orthanc dataset into target study dataset
  2. #takes transferQuery as the list of images that should be available on orthanc
  3. import os
  4. import json
  5. import re
  6. import sys
  7. import datetime
  8. import re
  9. def main(parameterFile):
  10. fhome=os.path.expanduser('~')
  11. fsetup=os.path.join(fhome,'.labkey','setup.json')
  12. with open(fsetup,'r') as f:
  13. setup=json.load(f)
  14. sys.path.insert(0,setup['paths']['nixWrapper'])
  15. import nixWrapper
  16. nixWrapper.loadLibrary("labkeyInterface")
  17. import labkeyInterface
  18. import labkeyDatabaseBrowser
  19. import labkeyFileBrowser
  20. fconfig=os.path.join(fhome,'.labkey','network.json')
  21. net=labkeyInterface.labkeyInterface()
  22. net.init(fconfig)
  23. db=labkeyDatabaseBrowser.labkeyDB(net)
  24. fb=labkeyFileBrowser.labkeyFileBrowser(net)
  25. with open(parameterFile,'r') as f:
  26. pars=json.load(f)
  27. i=0
  28. #from orthancDatabase/Imaging dataset
  29. projectOrthanc=pars['Orthanc']['project']
  30. inputQuery=pars['Orthanc']['queryName']
  31. inputSchema=pars['Orthanc']['schemaName']
  32. inputParticipantField=pars['Orthanc']['participantField']
  33. #to target project dataset
  34. projectStudy=pars['Database']['project']
  35. #'iPNUMMretro/Study'
  36. #for prospective, set
  37. #projectStudy='IPNUMMprospektiva/Study'
  38. outputQuery=pars['Database']['queryName']
  39. outputSchema=pars['Database']['schemaName']
  40. #select patientId that are contained in the demographics dataset
  41. transferQuery=pars['Database']['transferQuery']
  42. dbParticipantField=pars['Database']['participantField']
  43. missingSchema=pars['Database']['missingImagesSchema']
  44. missingQuery=pars['Database']['missingImagesQuery']
  45. #make a list of images from transferQuery
  46. dsImage=db.selectRows(projectStudy,outputSchema,transferQuery,[])
  47. for im in dsImage['rows']:
  48. #for orthanc
  49. inputIdFilter={'variable':inputParticipantField,\
  50. 'value':im[dbParticipantField],\
  51. 'oper':'eq'}
  52. #for database
  53. idFilter={'variable':dbParticipantField,\
  54. 'value':im[dbParticipantField],\
  55. 'oper':'eq'}
  56. seqNum=im['imagingVisitId']
  57. seqFilter={'variable':'SequenceNum','value':str(seqNum),'oper':'eq'}
  58. #for speedup one should check if a match was already done in Database/queryName
  59. #ds1 are the matching outputs in target dataset
  60. ds1=db.selectRows(projectStudy,outputSchema,outputQuery,\
  61. [idFilter,seqFilter])
  62. if len(ds1['rows'])>1:
  63. #never happens (idFilter and seqFilter)
  64. print('ERROR: too many matches in {} for {}/{}'.\
  65. format(outputQuery,im[dbParticipantField],seqNum))
  66. continue
  67. if len(ds1['rows'])>0:
  68. #just the one match, fine
  69. print('Entry for {}/{} already resolved'.\
  70. format(im[dbParticipantField],seqNum))
  71. continue
  72. #have to convert from datetime to %Y%m%d format
  73. #dateFilter={'variable':'imageDate','value':im['imageDate'],'oper':'eq'}
  74. dsOrthanc=db.selectRows(projectOrthanc,inputSchema,inputQuery,[inputIdFilter])
  75. #what if dsOrthanc['rows'] is empty?
  76. #this is part of QA and is reported in missingImages Schema/Query
  77. uploadStatus="FAILED"
  78. imageDateMismatch=[]
  79. for im1 in dsOrthanc['rows']:
  80. date=datetime.datetime.strptime(im1['studyDate'],'%Y/%m/%d %H:%M:%S')
  81. #convert date to %Y%m%d notation
  82. dateYMD=date.strftime('%Y%m%d')
  83. if dateYMD!=im['imageDate']:
  84. print('Rejecting mismatch: {}/{}'.format(dateYMD,im['imageDate']))
  85. imageDateMismatch.append(dateYMD)
  86. continue
  87. outvar='NONE'
  88. sd=im1['seriesDescription']
  89. if sd=='PET WB':
  90. outvar='PETWB_orthancId'
  91. print('Found PET: {}'.format(im1['orthancSeries']))
  92. if sd.find('CT WB')==0:
  93. if sd.find('fov')<0:
  94. outvar='CT_orthancId'
  95. print('Found CT: {}'.format(im1['orthancSeries']))
  96. #skip irrelevant series
  97. if outvar=='NONE':
  98. continue
  99. #figure out which row in output study to update
  100. filters=[]
  101. print('Participant {} Sequence number {}'.\
  102. format(im[dbParticipantField],str(seqNum)))
  103. mode='update'
  104. outRow={}
  105. if len(ds1['rows'])==0:
  106. mode='insert'
  107. outRow[dbParticipantField]=im[dbParticipantField]
  108. outRow['SequenceNum']=seqNum
  109. outRow['dicomStudy']=im1['dicomStudy']
  110. else:
  111. #never happens if we check for sd1 before matches are found
  112. outRow=ds1['rows'][0]
  113. outRow[outvar]=im1['orthancSeries']
  114. outRow['studyDate']=im1['studyDate']
  115. outRow['imagingVisitId']=im['imagingVisitId']
  116. outRow['visitCode']='VISIT_'+str(im['imagingVisitId'])
  117. modifyStatus=db.modifyRows(mode,projectStudy,outputSchema,\
  118. outputQuery,[outRow])
  119. print('{}'.format(modifyStatus))
  120. uploadStatus="LOADED"
  121. if uploadStatus=="FAILED":
  122. #standard spiel - find if already present; if so, skip, if not, add
  123. imFilter={'variable':'imagingVisitId',
  124. 'value':'{}'.format(im['imagingVisitId']),
  125. 'oper':'eq'}
  126. dsMissing=db.selectRows(projectStudy,missingSchema,\
  127. missingQuery,[idFilter,imFilter])
  128. #already recorded
  129. imageDateMismatch=list(set(imageDateMismatch))
  130. vals=[dbParticipantField,'imagingVisitId','imageDate']
  131. mode='insert'
  132. if len(dsMissing['rows'])>0:
  133. mode='update'
  134. orow=dsMissing['rows'][0]
  135. else:
  136. orow={v:im[v] for v in vals}
  137. orow['imageDateMismatch']=','.join(imageDateMismatch)
  138. orow['failureDescription']='MISSING DICOM'
  139. db.modifyRows(mode,projectStudy,missingSchema,\
  140. missingQuery,[orow])
  141. print("Done")
  142. if __name__=='__main__':
  143. main(sys.argv[1])