populateImagingFromTransferList.py 5.8 KB

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