123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- import os
- import json
- import re
- import subprocess
- import nibabel
- import shutil
- import sys
- import pathlib
- import numpy
- #nothing gets done if you do import
- def getPatientLabel(row,participantField='PatientId'):
- return row[participantField].replace('/','_')
- def getVisitLabel(row):
- return 'VISIT_'+str(int(row['SequenceNum']))
- def getStudyLabel(row,participantField='PatientId'):
- return getPatientLabel(row,participantField)+'-'+getVisitLabel(row)
- def updateRow(project,dataset,row,imageResampledField,gzFileNames,\
- participantField='PatientId'):
- row['patientCode']=getPatientLabel(row,participantField)
- row['visitCode']=getVisitLabel(row)
- for im in imageResampledField:
- row[imageResampledField[im]]=gzFileNames[im]
- db.modifyRows('update',project,'study',dataset,[row])
-
- def replacePatterns(infile,outfile,replacePatterns):
- of=open(outfile,'w')
- with open(infile,'r') as f:
- data=f.read()
- for p in replacePatterns:
- val=replacePatterns[p]
- data=re.sub(p,val,data)
- of.write(data)
- of.close()
-
- def valueSubstitution(pars,val):
- if val.find('__home__')>-1:
- val=re.sub(r'__home__',os.path.expanduser('~'),val)
- return path
- def getSuffix(tempFile):
- p=pathlib.Path(tempFile)
- return ''.join(p.suffixes)
- def getSegmImagePath(tempFile):
- sfx=getSuffix(tempFile)
- return re.sub(sfx,'_Segm'+sfx,tempFile)
- def addVersion(tempFile,version):
- sfx=getSuffix(tempFile)
- return re.sub(sfx,'_'+version+sfx,tempFile)
- def addnnUNetCode(tempFile,fileNumber=0):
- sfx=getSuffix(tempFile)
- return re.sub(sfx,'_'+'{:04d}'.format(fileNumber)+sfx,tempFile)
- def runnnUNet(setup,pars):
- args=[]
- #set the environment
- args.append(setup['paths']['nnUNetRunInference'])
- #location of input images
- args.extend(['-i',os.path.join(pars['tempBase'],'CT')])
- #output path is segmentations
- args.extend(['-o',os.path.join(pars['tempBase'],'segmentations')])
- #modelid, nnUNet internal rules.
- args.extend(['-t',pars['nnUNet']['ModelId']])
- #specify configuration (3d_fullres)
- args.extend(['-m',pars['nnUNet']['configuration']])
- print(args)
- my_env = os.environ
- for key in pars['nnUNet']['env']:
- my_env[key]=pars['nnUNet']['env'][key]
-
- print(subprocess.run(args,env=my_env,check=True,stdout=subprocess.PIPE).stdout)
- def getSegmentationFile(pars):
- #this is how deep medic stores files
- return os.path.join(pars['tempBase'],'segmentations',\
- pars['images']['CT']['tempFile'])
-
- def runSegmentation(fb,row,pars,setup):
-
-
- #download to temp file (could be a fixed name)
- project=pars['project']
- images=pars['images']
- participantField=pars['participantField']
- baseDir=fb.formatPathURL(project,pars['imageDir']+'/'+\
- getPatientLabel(row,participantField)+'/'+\
- getVisitLabel(row))
-
- #download CT
- ctDir=os.path.join(pars['tempBase'],'CT')
- if not os.path.isdir(ctDir):
- os.mkdir(ctDir)
- fullFile=os.path.join(ctDir,images['CT']['tempFile'])
- fullFile=addnnUNetCode(fullFile)
- fb.readFileToFile(baseDir+'/'+row[images['CT']['queryField']],fullFile)
-
- #debug
- #run deep medic
- runnnUNet(setup,pars)
- #processed file is
- segFile=getSegmentationFile(pars)
- #SimpleITK.WriteImage(outImg,segFile)
- return segFile
-
- def test(parameterFile):
-
- fhome=os.path.expanduser('~')
-
- with open(os.path.join(fhome,".labkey","setup.json")) as f:
- setup=json.load(f)
- sys.path.insert(0,setup["paths"]["nixWrapper"])
-
- import nixWrapper
-
- nixWrapper.loadLibrary("labkeyInterface")#force reload
- import labkeyInterface
- import labkeyDatabaseBrowser
- import labkeyFileBrowser
- nixWrapper.loadLibrary("parseConfig")
- import parseConfig
- with open(parameterFile) as f:
- pars=json.load(f)
-
- pars=parseConfig.convert(pars)
- pars=parseConfig.convertValues(pars)
- #print(pars)
-
- def doSegmentation(parameterFile):
- fhome=os.path.expanduser('~')
-
- with open(os.path.join(fhome,".labkey","setup.json")) as f:
- setup=json.load(f)
- sys.path.insert(0,setup["paths"]["nixWrapper"])
-
- import nixWrapper
-
- nixWrapper.loadLibrary("labkeyInterface")#force reload
- import labkeyInterface
- import labkeyDatabaseBrowser
- import labkeyFileBrowser
- nixWrapper.loadLibrary("parseConfig")
- import parseConfig
- with open(parameterFile) as f:
- pars=json.load(f)
-
- pars=parseConfig.convert(pars)
- pars=parseConfig.convertValues(pars)
-
- project=pars['project']
- dataset=pars['targetQuery']
- schema=pars['targetSchema']
- view=pars['viewName']
- participantField=pars['participantField']
- tempBase=pars['tempBase']
- if not os.path.isdir(tempBase):
- os.makedirs(tempBase)
- #start the database interface
- fconfig=os.path.join(fhome,'.labkey','network.json')
- net=labkeyInterface.labkeyInterface()
- net.init(fconfig)
- db=labkeyDatabaseBrowser.labkeyDB(net)
- fb=labkeyFileBrowser.labkeyFileBrowser(net)
- #all images from database
- ds=db.selectRows(project,schema,dataset,[],view)
-
- #input
- #use webdav to transfer file (even though it is localhost)
-
- i=0
- #for debugging
- rows=[ds['rows'][0]]
- #production mode
- rows=ds['rows']
- for row in rows:
-
- ctField=row[pars['images']['CT']['queryField']]
- if ctField==None:
- print('{}/{}: missing resampled CT'.format(row[participantField],row['SequenceNum']))
- continue
- #build file name
- sfx=pars['images']['segmentation']['suffix']
- outpath=fb.buildPathURL(pars['project'],\
- [pars['imageDir'],row['patientCode'],row['visitCode']])
- outName=addVersion(\
- getSegmImagePath(\
- getStudyLabel(row,pars['participantField'])+sfx),\
- pars['version'])
- outFile=outpath+'/'+outName
- #check if file is there
- if not fb.entryExists(outFile):
-
- segFile=getSegmentationFile(pars)
- #remove existing file
- if os.path.isfile(segFile):
- os.remove(segFile)
-
- segFile=runSegmentation(fb,row,pars,setup)
- #copy file to file
- #normally I would update the targetQuery, but it contains previously set images
- #copy to labkey
- fb.writeFileToFile(segFile,outFile)
- print(segFile)
- #debug
- #update database
- copyFields=[pars['participantField'],'SequenceNum','patientCode','visitCode']
- row['SequenceNum']+=0.001*float(pars['versionNumber'])
- filters=[{'variable':v,'value':str(row[v]),'oper':'eq'} for v in copyFields]
- filters.append({'variable':'Version','value':pars['version'],'oper':'eq'})
- ds1=db.selectRows(pars['project'],pars['segmentationSchema'],pars['segmentationQuery'],filters)
- if len(ds1['rows'])>0:
- mode='update'
- outRow=ds1['rows'][0]
- else:
- mode='insert'
- outRow={v:row[v] for v in copyFields}
- outRow['Version']= pars['version']
- outRow['Segmentation']= outName
- print(db.modifyRows(mode,pars['project'],pars['segmentationSchema'],pars['segmentationQuery'],[outRow]))
- #push results back to LabKey
- print("Done")
- if __name__ == '__main__':
- #test(sys.argv[1])
- doSegmentation(sys.argv[1])
- #sys.exit()
|