示例#1
0
class XNATScenePackager(object):
    """Class containing methods for packaging scenes pertinent to the 
       Slicer-XNAT workflow.  The major feature of this class is that 
       it handles any shared nodes and 1) uploads them to a "shared" 
       folder on XNAT 2) eliminates them from scene packages sent to XNAT."""
       
    def __init__(self, browser = None):
        self.browser = browser
        self.viewer = self.browser.XNATView
        self.utils = XNATUtils()
        self.hostName = 'https://central.xnat.org'
    
    def determineSceneType(self):
        scene = slicer.app.mrmlScene()
        currURL = os.path.normpath(scene.GetURL())
        if currURL == None or currURL == '': return None
        elif currURL.find(self.utils.projectPath) == 0: return "XNATSlicerScene"
        else: return "LocalScene"                    
        return None
                                       
    def bundleScene(self, args):
            #
            # STEP 1: Init variables.
            #
            XNATCommunicator = args['XNATCommunicator'] 
            XNATDir = args['saveDir']
            XNATSharedDir = args['sharedDir']
            sceneName = args['fileName'] 
            metadata = args['metadata']      
            packageName = os.path.basename(sceneName.split(".")[0])              
            #
            # STEP 2: Analyzes the scene type.
            #
            #print self.utils.lf() +  "ANALYZING SCENE TYPE"
            sceneType = self.determineSceneType() 
            #print self.utils.lf() +  "SCENE TYPE: %s"%(sceneType)                     
            #   
            # STEP 3: Create a directory for packaging.
            #            
            tempDir = os.path.join(self.utils.tempUploadPath, packageName)
            #print self.utils.lf() +  "CREATE PACKAGE DIRECTORY: %s"%(tempDir)
            try:
                #print self.utils.lf() + ("%s does not exist. Making it."%(tempDir)) 
                self.utils.removeFilesInDir(tempDir)
                os.rmdir(tempDir)
            except Exception, e: pass 
            try: os.mkdir(tempDir)
            except Exception, e: pass
            #
            # STEP 4: Write according to scene type and if there's matching metadata.
            #
            #print self.utils.lf() +  "BEGINNING THE SCENE WRITE"
            self.browser.updateStatus(["", "Write all...", ""]) 
            #print self.utils.lf() +  "WRITING ALL!"
            self.writeScene_All(tempDir)            
            slicer.app.processEvents()              
           
            self.browser.updateStatus(["", "Finding mrml...", ""]) 
            mrml = None
            for root, dirs, files in os.walk(tempDir):
                for relFileName in files:
                    if relFileName.endswith("mrml"):
                        mrml = os.path.join(root, relFileName)
                        break
                    
            slicer.app.processEvents()
            self.browser.updateStatus(["", "Bundling scene.  Please wait...", ""])            
            return {'path':self.utils.adjustPathSlashes(tempDir), 
                    'mrml': self.utils.adjustPathSlashes(mrml)}

    # SOURCE OF FOLLOWING CODE: 
    # http://stackoverflow.com/questions/296499/how-do-i-zip-the-contents-of-a-folder-using-python-version-2-5
    #
    # NOTE: To be deprecated after MRB methods are put in place.
    def zipdir(self, basedir=None, zipArchive=None):
        assert os.path.isdir(basedir)
        with closing(ZipFile(zipArchive, "w", ZIP_DEFLATED)) as z:
            for root, dirs, files in os.walk(basedir):
                #NOTE: ignore empty directories
                for fn in files:
                    absfn = os.path.join(root, fn)
                    zfn = absfn[len(basedir)+len(os.sep):] #XXX: relative path
                    z.write(absfn, zfn)
    
    def packageDir(self, packageFilePath, sceneDir):
        #logic = slicer.app.applicationLogic()
        #logic.SaveSceneToSlicerDataBundleDirectory(sceneDir, None)
        slicer.app.applicationLogic().Zip(packageFilePath,sceneDir)
        
    def writeScene_All(self, saveDir):
        #slicer.app.processEvents()       
        if os.path.exists(saveDir): 
            self.utils.removeDirsAndFiles(saveDir)
                #slicer.app.processEvents()
        try: 
            os.makedirs(saveDir + "/Data")
        except Exception, e: 
            print self.utils.lf() +  "Likely the dir already exists: " + str(e)
        slicer.app.applicationLogic().SaveSceneToSlicerDataBundleDirectory(saveDir, None)
        slicer.app.processEvents()
示例#2
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}