#date sorts studies from orthanc dataset into target study dataset #takes transferQuery as the list of images that should be available on orthanc import os import json import re import sys import datetime import re def main(parameterFile): fhome=os.path.expanduser('~') fsetup=os.path.join(fhome,'.labkey','setup.json') with open(fsetup,'r') as f: setup=json.load(f) sys.path.insert(0,setup['paths']['nixWrapper']) import nixWrapper nixWrapper.loadLibrary("labkeyInterface") import labkeyInterface import labkeyDatabaseBrowser import labkeyFileBrowser fconfig=os.path.join(fhome,'.labkey','network.json') net=labkeyInterface.labkeyInterface() net.init(fconfig) db=labkeyDatabaseBrowser.labkeyDB(net) fb=labkeyFileBrowser.labkeyFileBrowser(net) with open(parameterFile,'r') as f: pars=json.load(f) i=0 #from orthancDatabase/Imaging dataset projectOrthanc=pars['Orthanc']['project'] inputQuery=pars['Orthanc']['queryName'] inputSchema=pars['Orthanc']['schemaName'] inputParticipantField=pars['Orthanc']['participantField'] #to target project dataset projectStudy=pars['Database']['project'] #'iPNUMMretro/Study' #for prospective, set #projectStudy='IPNUMMprospektiva/Study' outputQuery=pars['Database']['queryName'] outputSchema=pars['Database']['schemaName'] #test for schedule entries which are scheduled scheduleCutOffDate=pars['Database']['scheduleCutOffDate']#format YYYY-MM-DD scheduleQuery=pars['Database']['scheduleQuery'] scheduleToleranceDays=int(pars['Database']['scheduleToleranceDays']) dbParticipantField=pars['Database']['participantField'] missingSchema=pars['Database']['missingImagesSchema'] missingQuery=pars['Database']['missingImagesQuery'] #make a list of images from transferQuery cutOffFilter={'variable':'actionDate','value':scheduleCutOffDate,'oper':'datelt'} #status of 1 is scheduled statusFilter={'variable':'actionStatus','value':'1','oper':'eq'} dsImage=db.selectRows(projectStudy,outputSchema,scheduleQuery,[cutOffFilter,statusFilter]) #clear entries from missing list failureFilter={'variable':'failureDescription','value':'MISSING FORM','oper':'eq'} dsDelete=db.selectRows(projectStudy,missingSchema,missingQuery,[failureFilter]) db.modifyRows('delete',projectStudy,missingSchema,missingQuery,dsDelete['rows']) for im in dsImage['rows']: print('{}: {} {}'.format(im[dbParticipantField],im['actionDate'],im['actionStatus'])) im['imagingVisitId']=im['visitId'] actionDate=datetime.datetime.strptime(im['actionDate'],'%Y/%m/%d %H:%M:%S') actionDateYMD=actionDate.strftime('%Y%m%d') im['imageDate']=actionDateYMD #this is still to be configured inputIdFilter={'variable':inputParticipantField,\ 'value':im[dbParticipantField],\ 'oper':'eq'} idFilter={'variable':dbParticipantField,\ 'value':im[dbParticipantField],\ 'oper':'eq'} #filter on series descripton - for PET, we should have 'PET WB' sdFilter={'variable':'seriesDescription','value':'PET WB','oper':'eq'} #have to convert from datetime to %Y%m%d format #dateFilter={'variable':'imageDate','value':im['imageDate'],'oper':'eq'} dsOrthanc=db.selectRows(projectOrthanc,inputSchema,inputQuery,[inputIdFilter,sdFilter]) #what if dsOrthanc['rows'] is empty? #this is part of QA and is reported in missingImages Schema/Query uploadStatus="FAILED" imageDateMismatch=[] for im1 in dsOrthanc['rows']: date=datetime.datetime.strptime(im1['studyDate'],'%Y/%m/%d %H:%M:%S') dt=date-actionDate if (abs(dt.days)>scheduleToleranceDays): continue #convert date to %Y%m%d notation dateYMD=date.strftime('%Y%m%d') #enter this time difference to a list imFilter={'variable':'imagingVisitId', 'value':'{}'.format(im['imagingVisitId']), 'oper':'eq'} dsMissing=db.selectRows(projectStudy,missingSchema,\ missingQuery,[idFilter,imFilter]) #already recorded vals=[dbParticipantField,'imagingVisitId','imageDate'] mode='insert' if len(dsMissing['rows'])>0: mode='update' orow=dsMissing['rows'][0] else: orow={v:im[v] for v in vals} orow['imageDateMismatch']=dateYMD orow['failureDescription']='MISSING FORM' db.modifyRows(mode,projectStudy,missingSchema,\ missingQuery,[orow]) print("Done: {}".format(len(dsImage['rows']))) if __name__=='__main__': main(sys.argv[1])