Преглед изворни кода

Merge branch 'master' of wiscigt.powertheword.com:oil/iraemm

Andrej Studen пре 3 година
родитељ
комит
fc25bd8249

+ 137 - 0
pythonScripts/findCandidatesForSchedule.py

@@ -0,0 +1,137 @@
+#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])

+ 56 - 9
pythonScripts/populateImagingFromTransferList.py

@@ -1,5 +1,8 @@
 #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
@@ -13,7 +16,12 @@ def main(parameterFile):
     with open(fsetup,'r') as f:
         setup=json.load(f)
 
-    sys.path.insert(0,setup['paths']['labkeyInterface'])
+    sys.path.insert(0,setup['paths']['nixWrapper'])
+
+    import nixWrapper
+
+    nixWrapper.loadLibrary("labkeyInterface")
+
     import labkeyInterface
     import labkeyDatabaseBrowser
     import labkeyFileBrowser
@@ -48,17 +56,29 @@ def main(parameterFile):
     transferQuery=pars['Database']['transferQuery']
     dbParticipantField=pars['Database']['participantField']
 
-    #make a list of images
+    missingSchema=pars['Database']['missingImagesSchema']
+    missingQuery=pars['Database']['missingImagesQuery']
+
+    #make a list of images from transferQuery
     dsImage=db.selectRows(projectStudy,outputSchema,transferQuery,[])
 
     for im in dsImage['rows']:
-        idFilter={'variable':inputParticipantField,'value':im[dbParticipantField],\
-            'oper':'eq'}
+        inputIdFilter={'variable':inputParticipantField,\
+                'value':im[dbParticipantField],\
+                'oper':'eq'}
+
+        idFilter={'variable':dbParticipantField,\
+                'value':im[dbParticipantField],\
+                '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,[idFilter])
+        dsOrthanc=db.selectRows(projectOrthanc,inputSchema,inputQuery,[inputIdFilter])
+        #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') 
@@ -66,6 +86,7 @@ def main(parameterFile):
             dateYMD=date.strftime('%Y%m%d')
             if dateYMD!=im['imageDate']:
                 print('Rejecting mismatch: {}/{}'.format(dateYMD,im['imageDate']))
+                imageDateMismatch.append(dateYMD)
                 continue
         
             outvar='NONE'
@@ -84,10 +105,10 @@ def main(parameterFile):
 
             #figure out which row in output study to update
             filters=[]
-            idFilter={'variable':dbParticipantField,'value':im[dbParticipantField],'oper':'eq'}
             seqNum=im['imagingVisitId']
             seqFilter={'variable':'SequenceNum','value':str(seqNum),'oper':'eq'}
-            print('Participant {} Sequence number {}'.format(im[dbParticipantField],str(seqNum)))
+            print('Participant {} Sequence number {}'.\
+                    format(im[dbParticipantField],str(seqNum)))
             #ds1 are the matching outputs in target dataset
             ds1=db.selectRows(projectStudy,outputSchema,outputQuery,\
                 [idFilter,seqFilter])
@@ -95,6 +116,7 @@ def main(parameterFile):
             if len(ds1['rows'])>1:
                 print('ERROR: too many matches for {}/{}'.\
                     format(im[dbParticipantField],seqNum))
+                status="MULTIPLE MATCHES"
                 continue
 
             mode='update'
@@ -114,9 +136,34 @@ def main(parameterFile):
             outRow['imagingVisitId']=im['imagingVisitId']
             outRow['visitCode']='VISIT_'+str(im['imagingVisitId'])
 
-            status=db.modifyRows(mode,projectStudy,outputSchema,outputQuery,[outRow])
-            print('{}'.format(status))
+            modifyStatus=db.modifyRows(mode,projectStudy,outputSchema,\
+                    outputQuery,[outRow])
+            print('{}'.format(modifyStatus))
+            uploadStatus="LOADED"
         
+        if uploadStatus=="FAILED":
+            #standard spiel - find if already present; if so, skip, if not, add
+            imFilter={'variable':'imagingVisitId',
+                    'value':'{}'.format(im['imagingVisitId']),
+                    'oper':'eq'}
+            dsMissing=db.selectRows(projectStudy,missingSchema,\
+                    missingQuery,[idFilter,imFilter])
+
+            #already recorded
+            imageDateMismatch=list(set(imageDateMismatch))
+            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']=','.join(imageDateMismatch)
+            orow['failureDescription']='MISSING DICOM'
+            db.modifyRows(mode,projectStudy,missingSchema,\
+                    missingQuery,[orow])
+            
+       
     print("Done")
 
 if __name__=='__main__':

+ 1 - 1
pythonScripts/runPython.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-nohup python $@  0<&- &> $HOME/logs/runPython.log &
+nohup python3 -u $@  0<&- &> $HOME/logs/runPython.log &

+ 66 - 0
templates/segmentationPreproces.json

@@ -0,0 +1,66 @@
+{
+ "setVariables":["__tempBase__","__segBase__","__roiFile__","__petFile__","__ctFile__","__segFile__","__modelName__"],
+ "setVariablesComment":"this variables will get updated with local values like home and can be used to set variables further on",
+ "__tempBase__":"__home__/temp/segmentation",
+ "__segBase__":"/home/nixUser/software/src/irAEMM/segmentation",
+ "__roiFile__":"testMask.nii.gz",
+ "__ctFile__":"testCT.nii.gz",
+ "__petFile__":"testPET.nii.gz",
+ "__segFile__":"segmentation.nii.gz",
+ "__modelName__":"DM_defaults.DM_train_VISCERAL16_Fold1.final.2019-10-01.07.46.19.932616.model.ckpt",
+ "tempBase":"__tempBase__",
+ "model":"__model__",
+ "project":"IPNUMMprospektiva/Study",
+ "targetSchema":"study",
+ "targetQuery":"Imaging1",
+ "participantField":"ParticipantId",
+ "imageDir":"preprocessedImages",
+ "images":{
+	"CT":{
+		"queryField":"ctResampled",
+		"tempFile":"__ctFile__"},
+	"PET":{
+		"queryField":"petResampled",
+		"tempFile":"__petFile__"},
+	"patientmask":{
+		"queryField":"ROImask",
+		"tempFile":"__roiFile__"}
+ },
+ "replacePattern":{
+	 "__workDir__":"__tempBase__",
+	 "__roi__":"__tempBase__/__roiFile__",
+	 "__pet__":"__tempBase__/__petFile__",
+	 "__ct__":"__tempBase__/__ctFile__",
+	 "__seg__":"__tempBase__/__segFile__",
+	 "__model__":"__modelName__"
+ },
+ "deepmedic": {
+	 "config":{
+		 "model":{
+		 	"template":"__segBase__/model/modelConfig.cfg.template",
+		 	"out":"__tempBase__/modelConfig.cfg"
+	 	},
+	 	"test":{
+			"template":"__segBase__/test/testConfig.cfg.template",
+		 	"out":"__tempBase__/testConfig.cfg"
+	 	},
+		"predictions":{
+			"template":"__segBase__/test/testNamesOfPredictions.cfg.template",
+			"out":"__tempBase__/testNamesOfPredictions.cfg"
+		},
+		"CT":{
+			"template":"__segBase__/test/testChannels_CT.cfg.template",
+			"out":"__tempBase__/testChannels_CT.cfg"
+		},
+		"ROI":{
+			"template":"__segBase__/test/testRoiMasks.cfg.template",
+			"out":"__tempBase__/testRoiMasks.cfg"
+		}
+
+
+
+	 }
+ }
+
+
+}