예제 #1
0
class XNATSaveWorkflow(object):
    def __init__(self, browser, XNATCommunicator, sessionArgs):
        """ Parent class of any load workflow
        """
        self.browser = browser
        self.scenePackager = XNATScenePackager(self.browser)
        self.utils = XNATUtils()
        self.sessionArgs = sessionArgs
        self.XNATCommunicator = XNATCommunicator
        
    def saveScene(self):       
        #=======================================================================
        #     PACKAGE SCENE
        #
        #     NOTE: The scene packager refers to the .metadata file.     
        #======================================================================= 
        package = self.scenePackager.bundleScene(self.sessionArgs)
        projectDir =         package['path']
        mrmlFile =           package['mrml']  
        #=======================================================================
        #     ZIP PACKAGE
        #=======================================================================           
        self.browser.updateStatus(["Compressing package. Please wait...", "", ""]) 
        packageFileName = projectDir + self.utils.defaultPackageExtension
        if os.path.exists(packageFileName): 
            self.utils.removeFile(packageFileName) 
        self.scenePackager.packageDir(packageFileName, projectDir)
        
        self.browser.updateStatus(["Deleting temporary package.", "", ""])    
        self.utils.removeDirsAndFiles(projectDir)
        #=======================================================================
        #     UPLOAD PACKAGE
        #=======================================================================          
        self.browser.updateStatus(["Sending '%s' to XNAT. Please wait..."%
                                   (os.path.basename(packageFileName)), "", ""])
        #print ("UPLOADING HERE: " + self.sessionArgs['saveDir'] + "/" + os.path.basename(packageFileName))
        self.XNATCommunicator.upload(packageFileName, self.sessionArgs['saveDir'] + "/" + os.path.basename(packageFileName))
        slicer.app.processEvents()
        if self.sessionArgs['sharable']:
            self.browser.updateStatus(["", "Finished updating '%s' in XNAT."%
                                       (os.path.basename(packageFileName)), ""])
        else: self.browser.updateStatus(["", "Finished writing '%s' to XNAT."%
                                         (os.path.basename(packageFileName)), ""])                        
        #=======================================================================
        #     UPDATE VIEWER
        #=======================================================================
        self.sessionArgs['sessionType'] = "scene upload"
        self.browser.XNATView.startNewSession(self.sessionArgs)
        self.browser.XNATView.loadButton.setEnabled(True)
        self.browser.XNATView.deleteButton.setEnabled(True) 
        self.browser.XNATView.setCurrItemToChild(item = None, 
                                                 childFileName = os.path.basename(packageFileName))
        


    def determineSaveLocation(self, itemType, selectedDir, saveLevel = None):
        """ Method goes through various steps to determine the optimal XNAT 
            location to save the current scene.
        """
        #=======================================================================
        #     SET VARIABLES
        #=======================================================================
        print self.utils.lf() + "DETERMINE SAVE DIR"
        currDir = os.path.dirname(selectedDir)
        saveDir = ""
        
              
        #=======================================================================
        #     NONE HANDLER
        #=======================================================================
        if not saveLevel:                                                                     
            # This is where another analysis step could exist to determine where
            # the scene could be saved.                                             
            saveLevel = self.utils.defaultXNATSaveLevel               
        
        #=======================================================================
        #     CHECK SAVE LEVEL VALIDITY
        #=======================================================================
        else:
            findCount = False
            for key, value in self.utils.xnatDepthDict.iteritems():
                if value == saveLevel: 
                    findCount = True
            if not findCount:
                print (self.utils.lf() + 
                       "Couldn't find save level '%s'. Resorting to default: %s"%(saveLevel, self.utils.defaultXNATSaveLevel))
                saveLevel = self.utils.defaultXNATSaveLevel 
        #         Look at the sessionManager, reconcile save dir based on that
        #         and XNATSaveLevel
        if self.browser.XNATView.sessionManager.currSessionInfo:
            saveDir = self.utils.getSlicerDirAtLevel(self.browser.XNATView.sessionManager.currSessionInfo['RemoteURI'], saveLevel)
        else:
            return None            
        print "SAVEDIR: " + saveDir 

        otherRequiredDirs = []
        baseDir = saveDir.split(self.utils.slicerDirName)[0]
        for folderName in self.utils.requiredSlicerFolders:
            otherRequiredDirs.append("%s%s/files/"%(baseDir, folderName))
            
        return {'saveDir': saveDir, 'others': otherRequiredDirs}


                    
예제 #2
0
class XNATMRMLParser(object):
    """XNATMRMLParser is the class that parses and changes strings in a given .mrml file
    """
    def __init__(self, browser=None):         
        self.browser = browser
        self.utils = XNATUtils()
        
        self.useCache = True
        self.useCacheMsgBox = None
        self.resetUseCacheMsgBox()
        
        self.tempLocalFileMap = None
        self.tempNewFilename = None
        self.cacheList = None
        
        self.TESTWRITE = False
                    
    def changeValues(self, filename, newFilename, replaceValues, 
                     otherReplaceValues, removeOriginalFile = False, 
                     debug = True):
        self.browser.updateStatus(["Changing values in the mrml.", "", ""]) 
        #print (self.utils.lf() + " MRML PARSER CHANGE VALUES!")
        #=======================================================================
        # CONCATENATE ALL REPLACE VALUES
        #=======================================================================
        dicoms = []
        compLines = []
        if otherReplaceValues:
            replaceValues.update(otherReplaceValues)
          
        #=======================================================================
        # CREATE NEW MRML, BACKUP OLD
        #=======================================================================
        if filename == newFilename:
            bkpFN = filename.split(".")[0] + ".BKP"
            shutil.copy(filename,bkpFN)
            self.utils.removeFile(filename)
            slicer.app.processEvents()
            filename = bkpFN
       
        #=======================================================================
        # INIT XML PARSER
        #=======================================================================
        elementTree = ET.parse(codecs.open(filename, encoding="UTF-8"))
        root = elementTree.getroot()
        iterator = root.getiterator()
        for subelement in iterator:
            if subelement.keys():
                for name, value in subelement.items():
                    #===========================================================
                    # if no strings to be changed, at least make sure filepaths are relative
                    #===========================================================
                    if replaceValues == {}:
                        if os.path.basename(os.path.dirname(value)).lower() == "data":
                            #print self.utils.lf() + " CHANGING NAME WITH DATA FORMAT: %s\tOLD: %s\tNEW:%s"%(subelement.attrib[name], value, "./Data/" + os.path.basename(value))
                            subelement.attrib[name] = "./Data/%s"%(os.path.basename(value))
        self.browser.updateStatus(["Writing a new element tree in the mrml.", "", ""])
        #=======================================================================
        # write new mrml
        #=======================================================================
        elementTree.write(newFilename)        
        ### For testing purposes #############################################################
        #if self.TESTWRITE:
        #    z = open(filename,"r")
        #    oldlines = z.readlines()
        #    z.close()
        #    self.makeMrmlReadable(str(newFilename).split(".")[0]+"BEFORE", oldlines)
        #    self.makeMrmlReadable(str(newFilename).split(".")[0]+"AFTER", lines)      
        ######################################################################################

        #=======================================================================
        # return the dicom files, if necessary
        #=======================================================================
        self.browser.updateStatus(["Done writing new mrml!", "", ""])
        return {"dicoms": dicoms}        
                            
        
    def localizeRemoteMRMLLinks(self, filename, downloadRemoteLinks = True):   
        """Used for the 'load' workflow.  This changes remote URIs (ones with the 
           http and https perefixes) .  
        """
        #=======================================================================
        # INIT DICTIONARY
        #=======================================================================
        self.cacheList = []
        fileNameKey = "fileName"
        fileListMemberKey = "fileListMember"
        remoteLocalFileMap = {}     
        compLines = []
        
        #=======================================================================
        # BEGIN MRML PARSING
        #=======================================================================
        elementTree = ET.parse(codecs.open(filename, encoding="UTF-8"))
        root = elementTree.getroot()
        iterator = root.getiterator()
        for subelement in iterator:
            if subelement.keys():
                for name, value in subelement.items():              
                    #===========================================================
                    # if the URI has a remote prefix, begin algorithm
                    #===========================================================            
                    if ("http://" in value) or ("https://" in value):
                        print self.utils.lf() +  "\t\tName: '%s', Value: '%s'"%(name, value)  
                        #=======================================================
                        # removes the https://www.host.*** prefix
                        #=======================================================
                        _localURI =  self.utils.adjustPathSlashes("%s%s"%(self.utils.remoteFilePath,
                                                                          str(qt.QUrl(value).path()).split('archive')[1]))                 
                        print (self.utils.lf() +  "GIVEN URL: " + value + 
                               " INITIAL PATH VALUE: " + _localURI)
                        #=======================================================
                        # creates a new local URI based on the module cache paths
                        #=======================================================
                        tempFileInfo = XNATFileInfo(remoteURI = value, localURI = _localURI)
                        newValue = tempFileInfo.localURI
                        #=======================================================
                        # special case for handling .raw files
                        #=======================================================
                        if _localURI.endswith("raw"): #special case                
                            newValue = os.path.join(os.path.join(tempFileInfo.localDirName, 
                                                                 tempFileInfo.basenameNoExtension), 
                                                    tempFileInfo.basename)                      
                            print (self.utils.lf() + "FOUND RAW: " + self.utils.adjustPathSlashes(newValue))
                        #=======================================================
                        # makes sure path slashes are all forward
                        #=======================================================
                        newValue = self.utils.adjustPathSlashes(newValue)
                        if "win" in sys.platform: 
                            newValue = newValue.replace('\\', '/')                                                                           
                        #=======================================================
                        # if the value does not exist in the map...
                        #=======================================================
                        if not value in remoteLocalFileMap: 
                            #===================================================
                            # if no map value, create raw file map values
                            #===================================================
                            print (self.utils.lf() +  ("DICTIONARY: Adding new val."))
                            if tempFileInfo.localURI.endswith('raw'):
                               print self.utils.lf() +  "RAW EXTENSION"                               
                               remoteLocalFileMap[value] = "%s/%s/%s"%(tempFileInfo.localDirName,  
                                                                       os.path.basename(tempFileInfo.localURI).split(".")[0],
                                                                       os.path.basename(tempFileInfo.localURI)) 
                               remoteLocalFileMap[value + ".gz"] = "%s/%s%s"%(tempFileInfo.localDirName,  
                                                                              os.path.basename(tempFileInfo.localURI).split(".")[0], 
                                                                              ".raw.gz")
                            #===================================================
                            # for nodes other than raw files, define its map value 
                            #===================================================
                            else:
                               print self.utils.lf() +  "OTHER EXTENSION"
                               remoteLocalFileMap[value] = tempFileInfo.localURI
                               tempFN = os.path.basename(tempFileInfo.localURI).split(".")[0]
                               tempFolder = os.path.basename(os.path.dirname(tempFileInfo.localURI))
                               print self.utils.lf() +  "TEMPFN %s TEMPFOLDER %s"%(tempFN, tempFolder)
                               if tempFN == tempFolder:
                                   remoteLocalFileMap[value] = "%s%s"%(os.path.dirname(tempFileInfo.localURI), 
                                                                       os.path.basename(tempFileInfo.localURI).split(".")[1])
                            #===================================================
                            # debugging calls
                            #===================================================
                            print self.utils.lf() +  "VALUE: %s and LOCAL %s"%(value, remoteLocalFileMap[value])                      
                            compLines.append("OLDWORD - READ1: '" + value + "'")
                            compLines.append("NEWWORD - READ1: '" + remoteLocalFileMap[value]+ "'\n")
                        #=======================================================
                        # set new mrml values
                        #=======================================================
                        subelement.attrib[name] = remoteLocalFileMap[value]
                    #===========================================================
                    # If there's a local prefix to the string, and it's in the data directory
                    # of the scene...    
                    #===========================================================
                    elif os.path.basename(os.path.dirname(value)).lower() == 'data':
                        ext = os.path.basename(value).split(".")[1]                   
                        newValue = "./Data/%s"%(os.path.basename(value))                
                        compLines.append("DATAOLD - READ2: '" + value + "'")
                        compLines.append("DATANEW - READ2: '" + newValue + "'\n")
                        subelement.attrib[name] = newValue
        #=======================================================================
        # GENERATE NEW FILENAME
        #=======================================================================
        newFilename = filename.replace("-remotized.mrml", self.utils.localizedMRMLExtension + ".mrml") 
        newFilename = os.path.normpath(newFilename)
        #=======================================================================
        # CHANGES DIRECTOR CHARS FOR WINDOWS
        #=======================================================================
        if sys.platform.find("win") > -1:
            newFilename.replace('\\', '/')
        #=======================================================================
        # PRINT LINES FOR DEBUGGING
        #=======================================================================
        for line in compLines:
            print self.utils.lf() +  "COMPLINE: " + line
        #=======================================================================
        # WRITE NEW MRML
        #=======================================================================
        slicer.app.processEvents()      
        elementTree.write(newFilename) 
        slicer.app.processEvents()
        
        #=======================================================================
        # MAKE, RETURN NEW FILENAMES
        #=======================================================================
        self.currLoadManager.newMRMLFile = newFilename
        print self.utils.lf() +  "MRML PARSE FILENAME: " + filename     
        print "*****************" + self.utils.lf() + "MRML PARSER: " + str(remoteLocalFileMap)
        return newFilename, remoteLocalFileMap
                            
    
    def resetUseCacheMsgBox(self):
        """Message box workflow for using the cached files instead of redownloading."""
        self.useCacheMsgBox = qt.QMessageBox()
        self.useCacheMsgBox.setText("It appears that some of the DICOM images in this scene are locally cached.  "+
                                    "Would you like the widget to use them when possible?");
        self.useCacheMsgBox.setInformativeText("NOTE: This will potentially save you load time.");
        self.useCacheMsgBox.setStandardButtons(qt.QMessageBox.Yes | qt.QMessageBox.No)
        self.useCacheMsgBox.setDefaultButton(qt.QMessageBox.Yes)
        

    def toggleUseCache(self, button):
        """Toggles the "use cache" yes/no window."""
        newDict = {}
        if button.text.lower().find('yes') > -1: 
            self.useCache = True
        elif button.text.lower().find('no') > -1: self.useCache = False
        text = "User opted to use cache." if self.useCache else "User selected to opt out of using cache."
        print self.utils.lf() + (text)

        for item in self.cacheList:
            self.tempLocalFileMap[str(item)] = None
        self.downloadRemoteURIs(self.tempLocalFileMap, self.tempNewFilename)



    def makeMrmlReadable(self, filename, lines = None):
        """Makes MRML files more readable to humans (i.e. linebreaks).
        """
        if not lines:
            z = open(filename,"r")
            lines = z.readlines()
            z.close()
            
        f = open(filename,'w' )
        for line in lines:
            words = line.split()
            for word in words:
                word = word.rstrip()
                if len(word)>0:     
                    #word = word.strip() 
                    f.write(word + '\n')
        f.close()
예제 #3
0
class XNATCommunicator(object):
    def __init__(self, browser, 
                       server, 
                       user, 
                       password, 
                       cachedir):
        self.browser = browser
        self.server = server
        self.user = user
        self.password = password
        self.cachedir = cachedir
        self.utils = XNATUtils()
        self.XNAT = None
        self.progDialog = None
        self.setup()
    
        self.totalDLSize = 0
        self.downloadedBytes = 0
        
    def setup(self):
        pass
    
    def getFiles_URL(self, srcDstMap, withProgressBar = True, fileOrFolder = None):     
        #=======================================================================
        # GET TOTAL SIZE OF DOWNLOADS FOR ALL FILES
        #=======================================================================
        self.totalDLSize = 0
        self.downloadedBytes = 0
        downloadFolders = []
        #=======================================================================
        # REMOVE EXISTING DST FILES
        #=======================================================================
        for src, dst in srcDstMap.iteritems(): 
            if os.path.exists(dst): self.utils.removeFile(dst)
        timeStart = time.time()
        #=======================================================================
        # DOWNLOAD THE FILES
        #=======================================================================
        if fileOrFolder == "file":
            for src, dst in srcDstMap.iteritems():
                #print("FILE DOWNLOAD src:%s\tdst:%s"%(src, dst))
                self.totalDLSize = int(self.XNAT.select(self.cleanSelectString(src)).size())
                if withProgressBar: self.urllib2GetWithProgress(self.cleanSelectString(src), dst)
                else: f.get(dst)                 
        elif fileOrFolder == "folder":
            import tempfile
            xnatFileFolders = []
            #=======================================================================
            # DETERMINE SOURCE FOLDERS, CREATE NEW DICT BASED ON BASENAME
            #=======================================================================
            for src, dst in srcDstMap.iteritems():
                #print("FOLDER D/L src:%s\tdst:%s"%(src, dst))
                srcFolder = os.path.dirname(src)
                if not srcFolder in xnatFileFolders:
                    xnatFileFolders.append(srcFolder)
            #=======================================================================
            # GET THE 'FILEOBJECTS'
            #=======================================================================
            fObjs = []
            for f in xnatFileFolders:
                #print("FOLDER DOWNLOAD %s"%(f))
                fObjs = self.XNAT.select(self.cleanSelectString(os.path.dirname(f))).files().get('~/tmp/files')
                for fO in fObjs:
                    self.totalDLSize += int(fO.size())                    
            for f in xnatFileFolders:
                if withProgressBar: 
                    src = self.cleanSelectString(f + "?format=zip")                 
                    dst = tempfile.mktemp('', 'XNATDownload', self.utils.tempPath) + ".zip"
                    downloadFolders.append(self.utils.adjustPathSlashes(dst))
                    if os.path.exists(dst): self.utils.removeFile(dst)
                    #print("DOWNLOADING %s to %s"%(src, dst))
                    self.urllib2GetWithProgress(src, dst)
                   
        timeEnd = time.time()
        totalTime = (timeEnd-timeStart)
        bps = self.totalDLSize/totalTime

        #print "DOWNLOAD FOLDERS: " + str(downloadFolders)
        return downloadFolders
        #qt.QMessageBox.warning(None, "Time", "Total time: %s. Bps: %s"%(totalTime, str(bps)))
    
    def getFolderContents(self):
        pass
    
    def getItemValue(self):
        pass
    
    def makeDir(self):
        pass

    def upload(self):
        pass

    def delete(self):
        pass
    
    def getSize(self):
        pass
    
    def downloadFailed(self, windowTitle, msg):
            qt.QMessageBox.warning(None, windowTitle, msg)

    def buffer_read(self, response, fileToWrite, dialog=None, buffer_size=8192):
        try:
            itemSize = response.info().getheader('Content-Length').strip()
            itemSize = int(itemSize)
        except Exception, e:
            #print ("ITEM SIZE ERROR %s"%(e))
            pass
        while 1:
            buffer = response.read(buffer_size)
            self.downloadedBytes += len(buffer)
            fileToWrite.write(buffer)
            if not buffer:
                break 
            
            percent = (float(self.downloadedBytes) / self.totalDLSize)
            percent = round(percent*100, 2)
            if percent == 100:
                self.browser.updateStatus(["", "Loading, please wait...", ""])
                self.browser.generalProgressBar.setVisible(False)
            dialog.setValue(percent)
        
        return self.downloadedBytes