#labkey/orthanc interface #scans the orthanc internal database and fills labkey table #"Orthanc" section expected in the configuration file, with #"queryName": query to be filled for each image #"demographicsQuery": query to be filled for every patient #"schemaName": the schema both queries are part of #"project": name of the project under labkey that collects Orthanc data, # typically named Orthanc or similar #"participantField": sorting participant field label in labkey study import os import json import re import sys 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 nixWrapper.loadLibrary('orthancInterface') import orthancInterface import orthancDatabaseBrowser fconfig=os.path.join(fhome,'.labkey','network.json') net=labkeyInterface.labkeyInterface() net.init(fconfig) db=labkeyDatabaseBrowser.labkeyDB(net) onet=orthancInterface.orthancInterface() onet.init(fconfig) odb=orthancDatabaseBrowser.orthancDB(onet) with open(parameterFile) as f: pars=json.load(f) i=0 opars=pars['Orthanc'] project=opars['project'] participantField=opars['participantField'] patients=odb.getPatients() n=len(patients) for p in patients: pdata=odb.getPatientData(p) dicom=pdata['MainDicomTags'] patientId=dicom['PatientID'] print("[{}/{}] Patient: {} ID: {}".format(i,n,p,patientId)) qfilter={'variable':participantField,'value':patientId,'oper':'eq'} ds=db.selectRows(project,opars['schemaName'],\ opars['demographicsQuery'],[qfilter]) if len(ds['rows'])==0: row={} row[participantField]=patientId row['birthDate']=dicom['PatientBirthDate'] row['PatientName']=dicom['PatientName'] row['OrthancId']=p db.modifyRows('insert',project,opars['schemaName'],\ opars['demographicsQuery'],[row]) for s in pdata['Studies']: sdata=odb.getStudyData(s) sdicom=sdata['MainDicomTags'] sid=sdicom['StudyInstanceUID'] #print('Data: {}'.format(sdata)) #this is try/except protetcted in previous version... sdate="19700101" try: sdate=sdicom['StudyDate'] except KeyError: pass #continue print('\tStudy[{}]: {}/{}'.format(sdate,s,sid)) for se in sdata['Series']: sedata=odb.getSeriesData(se) sedicom=sedata['MainDicomTags'] seid=sedicom['SeriesInstanceUID'] #print('Data: {}'.format(sedata)) seDesc="NONE" try: seDesc=sedicom['SeriesDescription'] except KeyError: pass #replace letters that might trip the database spanishOAcute=''.join([chr(3619),chr(3603)]) spanishAAcute=''.join([chr(3619),chr(3585)]) seDesc=re.sub(spanishOAcute,'o',seDesc) seDesc=re.sub(spanishAAcute,'a',seDesc) print('\t\tSeries[{}]: {}/{}'.format(seDesc,se,seid)) qfilter={'variable':'orthancSeries','value':se,'oper':'eq'} ds=db.selectRows(project,opars['schemaName'],\ opars['queryName'],[qfilter]) mode='insert' if len(ds['rows'])>0: mode='update' #use existing row data row=ds['rows'][0] else: #count existing entries for patient qfilter={'variable':participantField,'value':patientId,'oper':'eq'} ds=db.selectRows(project,opars['schemaName'],\ opars['queryName'],[qfilter]) seqNum=len(ds['rows']) #create new row row={} row[participantField]=patientId row['sequenceNum']=seqNum row['orthancSeries']=se row['dicomStudy']=sid row['orthancStudy']=s row['dicomSeries']=seid row['studyDate']=sdate row['seriesDescription']=seDesc db.modifyRows(mode,project,opars['schemaName'],\ opars['queryName'],[row]) i+=1 print("Done") if __name__=="__main__": main(sys.argv[1])