python animation

Concerning processing components: filters, file load/save, visualizations, communication ...
Post Reply
RadhaKumari
Posts: 27
Joined: Wed Nov 14, 2018 6:10 pm

python animation

Post by RadhaKumari »

I have a gauge animation indicating the power received. Ideally it should work in real-time. But, after initializing it and expecting it to change value as the program proceeds , I am stuck because the stimulations won't start until I close the figure(which was supposed to change values as the program proceeds). The code is below. I do not know how to get it to work in real-time. Also, is it possible for the figure to appear as part of the visualization window and not separately, it will be so convenient if this is possible for matplotlib figures to be embedded into the main visualization window:

Code: Select all

import os, sys
import matplotlib
from matplotlib import cm
from matplotlib import pyplot as plt
import numpy as np
import matplotlib.animation as animation
import time

from matplotlib.patches import Circle, Wedge, Rectangle
# let's define a new box class that inherits from OVBox
class MyOVBox(OVBox):
    def __init__(self):
        OVBox.__init__(self)
        # we add a new member to save the signal header information we will receive
        self.signalHeader = None
        self.threshold=0
        #stores the current chunk at anytime    
        self.chunk=[0]
        self.fig,self.ax=plt.subplots()
        
    def initialize(self):
        self.threshold=float(self.setting['Threshold'])
        ani=animation.FuncAnimation(self.fig,self.animate,interval=30) 
        plt.show()
        
    def animate(self,i):
        if (self.chunk[0]<=0.33*self.threshold):
                    self.ax.clear()
                    self.gauge(1)
        elif (self.chunk[0]<=0.66*self.threshold) and (self.chunk[0]>0.33*self.threshold):
                    self.ax.clear()
                    self.gauge(2)

        elif (self.chunk[0]<=self.threshold) and (self.chunk[0]>0.66*self.threshold):
                    self.ax.clear()
                    self.gauge(3)
        elif (self.chunk[0]<=1.33*self.threshold) and (self.chunk[0]>self.threshold):
                    self.ax.clear()
                    self.gauge(4)

        elif (self.chunk[0]<1.66*self.threshold) and (self.chunk[0]>1.33*self.threshold):
                    self.ax.clear()
                    self.gauge(5)

        else :
                    self.ax.clear()
                    self.gauge(6)
        
        
    def degree_range(self,n): 
        start = np.linspace(0,180,n+1, endpoint=True)[0:-1]
        end = np.linspace(0,180,n+1, endpoint=True)[1::]
        mid_points = start + ((end-start)/2.)
        return np.c_[start, end], mid_points

    def rot_text(self,ang): 
        rotation = np.degrees(np.radians(ang) * np.pi / np.pi - np.radians(90))
        return rotation

    def gauge(self,arrow=1): 
        #fixed stuff
        labels=['LOW','MEDIUM','HIGH','VERY HIGH','EXTREME','CRITICAL']
        colors='YlOrRd_r'
        title='ERD level'
        N = len(labels)
        #if colors is a string, we assume it's a matplotlib colormap and we discretize in N discrete colors 
        
        if isinstance(colors, str):
           cmap = cm.get_cmap(colors, N)
           cmap = cmap(np.arange(N))
           colors = cmap[::-1,:].tolist()
        if isinstance(colors, list): 
            if len(colors) == N:
                colors = colors[::-1]
            else: 
                raise Exception("\n\nnumber of colors {} not equal to number of categories{}\n".format(len(colors), N))

    
        ang_range, mid_points = self.degree_range(N)
        labels = labels[::-1]
        patches =[]
        for ang, c in zip(ang_range, colors): 
            # sectors
            patches.append(Wedge((0.,0.), .4, *ang, facecolor='w', lw=2))
            # arcs
            patches.append(Wedge((0.,0.), .4, *ang, width=0.10, facecolor=c, lw=2, alpha=0.5))
            [self.ax.add_patch(p) for p in patches]

        #set the labels (e.g. 'LOW','MEDIUM',...)
        for mid, lab in zip(mid_points, labels): 
            self.ax.text(0.35 * np.cos(np.radians(mid)), 0.35 * np.sin(np.radians(mid)), lab, horizontalalignment='center', verticalalignment='center', fontsize=14,             fontweight='bold', rotation = self.rot_text(mid))

        #set the bottom banner and the title
        r = Rectangle((-0.4,-0.1),0.8,0.1, facecolor='w', lw=2)
        self.ax.add_patch(r)
        self.ax.text(0, -0.05, title, horizontalalignment='center',verticalalignment='center', fontsize=22, fontweight='bold')
        #Arrow
        pos = mid_points[abs(arrow - N)]
        self.ax.arrow(0, 0, 0.225 * np.cos(np.radians(pos)), 0.225 * np.sin(np.radians(pos)),width=0.04, head_width=0.09, head_length=0.1, fc='k', ec='k')
        self.ax.add_patch(Circle((0, 0), radius=0.02, facecolor='k'))
        self.ax.add_patch(Circle((0, 0), radius=0.01, facecolor='w', zorder=11))
        #removes frame and ticks, and makes axis equal and tight
        self.ax.set_frame_on(False)
        self.ax.axes.set_xticks([])
        self.ax.axes.set_yticks([])
        self.ax.axis('equal')
        plt.tight_layout()
    
    def process(self):

        for chunkIndex in range( len(self.input[0]) ):
                            
            if(type(self.input[0][chunkIndex]) == OVSignalBuffer):
                self.chunk=self.input[0].pop()
                
            elif(type(self.input[0][chunkIndex]) == OVSignalEnd):
                print 'Signal end reached'

            else:
                self.chunk=self.input[0].pop()
                

# Finally, we notify openvibe that the box instance 'box' is now an instance of MyOVBox.
# Don't forget that step !!
box = MyOVBox()


Thibaut
Posts: 264
Joined: Wed Oct 31, 2018 9:14 am

Re: python animation

Post by Thibaut »

Hi,
I have never used matplotlib for animation, but I think it must be pretty heavy as a system. Personally, I made a system as you describe it, but I coded it in C ++ in a specific box. For visualizations, I think you should turn to the visualization box implementation. Or use existing ones by passing them the information calculated by your script.
If you go about the implementation of a box, the Graz visualization displays a blue bar that evolves according to the data received (input amplitude) it could help you.
Thibaut

Post Reply