def initialzeVisualisation(self):
     '''
     
     '''        
     # to be changed
     self.loadVascularNetwork()
     # find min max pressures and apply it to LUT
     self.findMinMaxPressure()
     # create LUT      
     self.cLUT = LUT(self.quantitiyMaxima) 
     # creat 3d vessel representations
     
     self.createVessel3D()
     start = time.clock()
     # apply number total timesteps
     self.timeStepsTotal = len(self.vascularNetwork.vessels[self.vascularNetwork.root].Psol)
     
     # evaluate maximum area factor
     self.findMaximumAreaFactor()
     
     # evaluate visualisation time step
     self.evaluateUpdateRate()
     
     # small stuff
     self.set_caption(self.vascularNetwork.name)
     
     self.networkName = self.vascularNetwork.name   
     # evaluate movie count from already saved movies:
     for dirName, dirNames, fileNames in os.walk(self.movieSaveDirectory):
         for fileName in fileNames:
             if self.networkName in fileName:
                 try:
                     number = int(fileName.split('_')[-1].split(self.movieFileType)[0])
                     self.movieNumber = max(self.movieNumber,1 + number)
                 except: pass
     # evaluate the screenshot count from already saved screenshots
     for dirName, dirNames, fileNames in os.walk(self.screenShotDataDirectory):
         for fileName in fileNames:
             if self.networkName in fileName:
                 try: 
                     number = int(fileName.split('_')[-1].split('.png')[0])
                     self.screenShotNumber = max(self.screenShotNumber,1 + number)
                 except: pass
class Visualisation3D(Visualisation3DGUI):
    '''
    This class defines the 3D visualisation
    it is an inheritance of Visualisation3DGui which defines the GUI
    '''
    def __init__(self, networkName = None, dataSetNumber = None, connect = False):
        
        Visualisation3DGUI.__init__(self)
        
        # load functions
        self.networkName = networkName
        self.dataSetNumber = dataSetNumber
        self.connect = connect
               
        # vascularNewtor Instance
        self.vascularNetwork = None
        
        # dictionary with 3D vessels
        self.vessels3D = {}
        self.nPointsPerCircle = 8  # points for the circle at one gridpoint should bee around 8-16-32
        
        # vessel area/wall 
        self.areaFactor         = [2]
        self.areaFactorMaximum  = 200
        self.wallMovement       = [True]
            
        # look up table 
        self.pressureMaxima      = None
        self.pressureMaximaSplit = None
        self.cLUT = None # color look up table class
        self.quantityLUT = ['Pressure'] 
                
        # enable waveSplit LUT
        self.waveSplit = [False] # us an array as it is behaving like a pointer
        
        # simulation timing and update 
        self.updateTime = 1./60.
        self.totalTime = 0
        self.timeStepsTotal     = 50 # get this from solution length e.g. len(area)
        self.timeStepCurrent    = 0
        self.timeStepIncrement  = 1 # time step increment from [1, ... self.totalTimeSteps-1 ]
                
        ## create movie
        self.recordMovieData = False
        self.movieCount = 0
        self.movieCount = 0
        
        self.templateMovDataDirectory = ''.join([cur,'/.movieTemplateData'])
        self.movieSaveDirectory = ''.join([cur+'/Movies'])
        try: os.mkdir(self.movieSaveDirectory)
        except: pass
        self.movieNumber = 0
        self.movieFileType = '.mp4'
        
        ## create screen shot
        self.screenShotNumber = 0 
        self.screenShotDataDirectory = ''.join([cur,'/screenShots'])
                
        self.initialzeVisualisation()
        
    
    #--- functions for initialisation
    def initialzeVisualisation(self):
        '''
        
        '''        
        # to be changed
        self.loadVascularNetwork()
        # find min max pressures and apply it to LUT
        self.findMinMaxPressure()
        # create LUT      
        self.cLUT = LUT(self.quantitiyMaxima) 
        # creat 3d vessel representations
        
        self.createVessel3D()
        start = time.clock()
        # apply number total timesteps
        self.timeStepsTotal = len(self.vascularNetwork.vessels[self.vascularNetwork.root].Psol)
        
        # evaluate maximum area factor
        self.findMaximumAreaFactor()
        
        # evaluate visualisation time step
        self.evaluateUpdateRate()
        
        # small stuff
        self.set_caption(self.vascularNetwork.name)
        
        self.networkName = self.vascularNetwork.name   
        # evaluate movie count from already saved movies:
        for dirName, dirNames, fileNames in os.walk(self.movieSaveDirectory):
            for fileName in fileNames:
                if self.networkName in fileName:
                    try:
                        number = int(fileName.split('_')[-1].split(self.movieFileType)[0])
                        self.movieNumber = max(self.movieNumber,1 + number)
                    except: pass
        # evaluate the screenshot count from already saved screenshots
        for dirName, dirNames, fileNames in os.walk(self.screenShotDataDirectory):
            for fileName in fileNames:
                if self.networkName in fileName:
                    try: 
                        number = int(fileName.split('_')[-1].split('.png')[0])
                        self.screenShotNumber = max(self.screenShotNumber,1 + number)
                    except: pass
        
    def loadVascularNetwork(self):

        '''
        load vascularNetwork inclusiv all solution data
        from solution data set
        
        uses local variables networkName and dataSetNumber
        saves vascularNetwork instance in self.vascularNetwork
        '''
        if self.networkName and self.dataSetNumber:
            vascularNetwork, solutionDataSets, simulationCaseDescriptions = loadSolutionDataFile(self.networkName, self.dataSetNumber) 
            self.vascularNetwork = vascularNetwork    
        
    def createVessel3D(self):

        '''
        method to create a Vessel3D instance for each vessel in the current
        vascularNetwork and stores it in self.vessels3D = {vesselId: vessel3D}
        '''
        if self.vascularNetwork is not None:  
            for vesselId,vessel in self.vascularNetwork.vessels.iteritems():
                self.vessels3D[vesselId] = Vessel3D( vessel,
                                                     self.batch,
                                                     self.nPointsPerCircle,
                                                     self.wallMovement,
                                                     self.areaFactor,
                                                     self.cLUT,
                                                     self.quantityLUT,
                                                     self.waveSplit)
       
    #--- functions for update                 
    def updateVisualisation(self, dt):

        ''' 
        method to update the visualisation of the 
        network depending on the timeStep
        this method is call continously if the "play button is clicked"
        '''
        timeStepCurrent = self.timeStepCurrent     
        ## update all visualisations of all vessel3D instances   
        # update vessel Positions, 3dgeometry and colour of vertices
        for vesselId in self.vascularNetwork.treeTraverseList:
            self.vessels3D[vesselId].update3Dposition(timeStepCurrent,None, None)
        
        # update the time step for next call
        self.timeStepCurrent = self.timeStepCurrent+self.timeStepIncrement
        # restart simulation if end reached
        if self.timeStepCurrent >= self.timeStepsTotal:
            self.timeStepCurrent = 0
            self.timeElapsed = 0
        
        # record movie data
        if self.recordMovieData == True:
            ## save screenshots
            self.switch_to()
            pyglet.image.get_buffer_manager().get_color_buffer().save(''.join([self.templateMovDataDirectory,'/.screenShot',str(self.movieCount),'.png']))
            self.movieCount = self.movieCount + 1 
        
    def recordMovie(self):
        '''
        start end end recording movies
        '''
        # start recording
        if self.recordMovieData == False:
                       
            try: os.mkdir(self.templateMovDataDirectory)
            except: pass
            
            self.movieCount = 0
            self.recordMovieData = True
            
        else: # create movie out of recorded data 
            self.recordMovieData = False
            self.createMovie()
            filelist = [ f for f in os.listdir(self.templateMovDataDirectory) if  f.endswith(".png")]
            for f in filelist:
                os.remove(''.join([self.templateMovDataDirectory,'/',f]))
        
    def saveScreenShot(self):
        '''
        save screenshot to disk
        '''
        try: os.mkdir(self.screenShotDataDirectory)
        except: pass
        self.switch_to()
        pyglet.image.get_buffer_manager().get_color_buffer().save(''.join([self.screenShotDataDirectory,'/',self.networkName,'_',str(self.screenShotNumber),'.png']))
        self.screenShotNumber = self.screenShotNumber +1 
             
        
    def createMovie(self):
        '''
        open all movie-template-*.png's and create a movie out of it
        '''
        print "createMovie(): writing image data"
        
        frameSizeImage = read_png(''.join([self.templateMovDataDirectory,'/.screenShot',str(0),'.png']))
        frameSize = (np.shape(frameSizeImage)[1],np.shape(frameSizeImage)[0])
        
        try:   FFMpegWriter = animation.writers['mencoder']
        except: print "ERROR: Visualisation3D.createMovie(): mencoder libary is not installed, could not create movie!"; return
                
        try:
            fileName = ''.join([self.movieSaveDirectory,'/',self.networkName,'_',str(self.movieNumber),self.movieFileType])
            imageName = ''.join(['mf://',self.templateMovDataDirectory,'/.screenShot%d.png'])
            imageType = ''.join(['type=png:w=',str(frameSize[0]),':h=',str(frameSize[1]),':fps=24'])
            command = ('mencoder',
                       imageName,
                       '-mf',
                       imageType,
                       '-ovc',
                       'lavc',
                       '-lavcopts',
                       'vcodec=mpeg4',
                       '-oac',
                       'copy',
                       '-o',
                       fileName)
            os.spawnvp(os.P_WAIT, 'mencoder', command)
            self.movieNumber = self.movieNumber+1
            print "createMovie(): created movie sucessfull"
        except:
            print "ERROR: Visualisation3D.createMovie(): mencoder libary is not installed, could not create movie!"; return
               
        
        
    #--- functions for the visualisation speed
    def evaluateUpdateRate(self):
        '''
        evaluate the visualisation update rate and the timeStepIncrement
        to get realtime visualisation i.e. synchronise update times
        '''
        maxFrameRate = 60.
        minFrameRate = 24.
        numberOfUpdates = 50.
        
        dtSim     = self.vascularNetwork.dt
        timeSteps = len(self.vessels3D[self.vessels3D.keys()[0]].Psol)-1 # number of dt is one less then number of solutions
        totalTime = timeSteps*dtSim
        
        # approximate frame rate
        timeSolverSolve = []
        self.timeStepCurrent = int(self.timeStepsTotal/2.)
        for i in xrange(int(numberOfUpdates)):
            timeSolverSolveStart = time.clock()
            self.updateVisualisation(0.0)
            timeSolverSolve.append(time.clock()-timeSolverSolveStart)
         
        approximatedFrameRateUpdate = (1./(sum(timeSolverSolve[2::])/(numberOfUpdates-2)))-1
        
        if maxFrameRate < approximatedFrameRateUpdate: minFrameRate = maxFrameRate
        else: minFrameRate = approximatedFrameRateUpdate
                        
        x = 1./(dtSim*minFrameRate)
        x = int(np.ceil(x))+1
        frameRate = 1.0/(dtSim*x)
        
        self.numberOfCalls     = timeSteps/x
        self.timeStepIncrement = x
        self.timeStepIncrementRealTime = x
        self.updateTime = totalTime/self.numberOfCalls
        self.totalTime = totalTime
        
        # reset initial state
        self.timeStepCurrent = 0
        self.updateVisualisation(0.0)
        self.timeStepCurrent = self.timeStepIncrement    
    
    def visualisationSpeedHalfTime(self):
        self.timeStepIncrement = int(self.timeStepIncrementRealTime/2.)
    
    def visualisationSpeedRealTime(self):
        self.timeStepIncrement = int(self.timeStepIncrementRealTime)
        
    def visualisationSpeedUp(self):
        self.timeStepIncrement = min(int(self.timeStepIncrement+1),int(self.timeStepIncrementRealTime))
    
    def visualisationSpeedDown(self):
        self.timeStepIncrement = max(int(self.timeStepIncrement-1),1)
    
    def setVisualisationSpeed(self, value):
        self.timeStepIncrement = max(int(self.timeStepIncrementRealTime*value),1)
    
    #--- functions for the area movement
    def setAreaFactor(self,value):
        self.areaFactor[0] = np.min([np.max([1,value*self.areaFactorMaximum]),self.areaFactorMaximum])
        
    def enableWallMovement(self):
        self.wallMovement[0] = [True,False][self.wallMovement[0]]
    
    def findMaximumAreaFactor(self):
        '''
        Function to find the maximum area factor
        that r is allways greater then 0.2 * r0
        '''
        rfmax = 5000
        for vessel in self.vascularNetwork.vessels.itervalues():
            A0 = vessel.Asol[0]
            devisor = ((vessel.Asol[1::]-A0))
            devisor[devisor==0] = 1
            rf = ((0.1*vessel.Asol[1::]-A0))/ devisor
            ## take out values close to -inf
            rf[rf<0] = 5000
            rf = np.min(rf)           
            rfmax = np.min([rfmax,rf])
        self.areaFactorMaximum = rfmax
        self.areaFactor[0] = 1
                
    #--- functions for the look up tables  
    def changeColorTable(self):
        self.cLUT.changeColorTable()
    
    def changeQuantityLUT(self, quantity):
        self.quantityLUT[0] = quantity
        self.cLUT.changeLUTquantity(quantity)
    
    def enableWaveSplitLookUp(self):
        self.waveSplit[0] = [True,False][self.waveSplit[0]]
        self.cLUT.enableWaveSplitLookUp()
                        
    def enableLeftRightColoring(self):
        self.cLUT.enableLeftRightColoring()
    
    def findMinMaxPressure(self):
        maximaP = [1.e20, 0]
        maximaQ = [1.e20, 0]
        for vessel in self.vascularNetwork.vessels.itervalues():
            # maximum
            maximaP[1] = np.max([maximaP[1], np.max(vessel.Psol)])
            maximaQ[1] = np.max([maximaQ[1], np.max(vessel.Qsol)])
            # minimum
            maximaP[0] = np.min([maximaP[0], np.min(vessel.Psol)])
            maximaQ[0] = np.min([maximaQ[0], np.min(vessel.Qsol)])
            
        self.quantitiyMaxima = {'Pressure':maximaP, 'Flow':maximaQ}