populateImagingFromTransferList.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. continue
  70. #have to convert from datetime to %Y%m%d format
  71. #dateFilter={'variable':'imageDate','value':im['imageDate'],'oper':'eq'}
  72. dsOrthanc=db.selectRows(projectOrthanc,inputSchema,inputQuery,[inputIdFilter])
  73. #what if dsOrthanc['rows'] is empty?
  74. #this is part of QA and is reported in missingImages Schema/Query
  75. uploadStatus="FAILED"
  76. imageDateMismatch=[]
  77. for im1 in dsOrthanc['rows']:
  78. date=datetime.datetime.strptime(im1['studyDate'],'%Y/%m/%d %H:%M:%S')
  79. #convert date to %Y%m%d notation
  80. dateYMD=date.strftime('%Y%m%d')
  81. if dateYMD!=im['imageDate']:
  82. print('Rejecting mismatch: {}/{}'.format(dateYMD,im['imageDate']))
  83. imageDateMismatch.append(dateYMD)
  84. continue
  85. outvar='NONE'
  86. sd=im1['seriesDescription']
  87. if sd=='PET WB':
  88. outvar='PETWB_orthancId'
  89. print('Found PET: {}'.format(im1['orthancSeries']))
  90. if sd.find('CT WB')==0:
  91. if sd.find('fov')<0:
  92. outvar='CT_orthancId'
  93. print('Found CT: {}'.format(im1['orthancSeries']))
  94. #skip irrelevant series
  95. if outvar=='NONE':
  96. continue
  97. #figure out which row in output study to update
  98. filters=[]
  99. print('Participant {} Sequence number {}'.\
  100. format(im[dbParticipantField],str(seqNum)))
  101. mode='update'
  102. outRow={}
  103. if len(ds1['rows'])==0:
  104. mode='insert'
  105. outRow[dbParticipantField]=im[dbParticipantField]
  106. outRow['SequenceNum']=seqNum
  107. outRow['dicomStudy']=im1['dicomStudy']
  108. else:
  109. #never happens if we check for sd1 before matches are found
  110. outRow=ds1['rows'][0]
  111. outRow[outvar]=im1['orthancSeries']
  112. outRow['studyDate']=im1['studyDate']
  113. outRow['imagingVisitId']=im['imagingVisitId']
  114. outRow['visitCode']='VISIT_'+str(im['imagingVisitId'])
  115. modifyStatus=db.modifyRows(mode,projectStudy,outputSchema,\
  116. outputQuery,[outRow])
  117. print('{}'.format(modifyStatus))
  118. uploadStatus="LOADED"
  119. if uploadStatus=="FAILED":
  120. #standard spiel - find if already present; if so, skip, if not, add
  121. imFilter={'variable':'imagingVisitId',
  122. 'value':'{}'.format(im['imagingVisitId']),
  123. 'oper':'eq'}
  124. dsMissing=db.selectRows(projectStudy,missingSchema,\
  125. missingQuery,[idFilter,imFilter])
  126. #already recorded
  127. imageDateMismatch=list(set(imageDateMismatch))
  128. vals=[dbParticipantField,'imagingVisitId','imageDate']
  129. mode='insert'
  130. if len(dsMissing['rows'])>0:
  131. mode='update'
  132. orow=dsMissing['rows'][0]
  133. else:
  134. orow={v:im[v] for v in vals}
  135. orow['imageDateMismatch']=','.join(imageDateMismatch)
  136. orow['failureDescription']='MISSING DICOM'
  137. db.modifyRows(mode,projectStudy,missingSchema,\
  138. missingQuery,[orow])
  139. print("Done")
  140. if __name__=='__main__':
  141. main(sys.argv[1])