Vizard 8 » Tutorials & Examples » Python Programming » Addons » matplotlib
8.1

matplotlib

Matplotlib is a library with a very 'Matlab' like environment for generating publication quality figures. You can output to raster formats (e.g., PNG, TIFF, JPG) immediately in a pop-up window or to vector (e.g, EPS, PS) formats that are saved as files. The style of graphs and syntax for creating them will be very familiar to users of Matlab, especially when combined with the added Python language constructs through NumPy.

Installation

Matplotlib requires the installation of a few 3rd party packages before it can be used with Vizard.

Use matplotlib

Two common ways to use matplotlib with Vizard are to:

Example: Save data to file

The following example script creates a graph using Vizard data and saves this to a PDF file:

'''
A matplotlib figure will be saved as a PDF file in the
current directory. Wait for the script to close automatically
after 10 seconds.
'''

import viz
import vizinfo
import viztask
import vizact

viz.setMultiSample(4)
viz.fov(60)
viz.go()

info = vizinfo.InfoPanel()

#set sample rate in hz
SAMPLE_RATE = 60

#set max number of samples
MAX_SIZE_OF_ARRAY = 600

#create arrays to store data and fill with zeros
array_time, array_height = [],[]
 
for i in range(0,MAX_SIZE_OF_ARRAY):
    array_time.append(0)
    array_height.append(0)

###---physics simulation---###
viz.phys.enable()
ball = viz.addChild('beachball.osgb', pos=(0,10,6))
ballphys = ball.collideSphere(bounce = 1.5)
ground = viz.addChild('sky_day.osgb')
ground.collidePlane()

#task function that adds to ball height and time arrays every frame
import time
starttime = time.time()
def getData():

    for i in range (0,MAX_SIZE_OF_ARRAY):
        array_time[i] = time.time() - starttime
        array_height[i] = ball.getPosition()[1]
        yield viztask.waitTime(1.0/SAMPLE_RATE) #wait at least a frame before setting new data points
            
#call our task function
data = viztask.schedule(getData())

#take the arrays and create a simple plot of time and ball height and save it as a
#PDF file in the current script directory
from pylab import *
def savePlot():
    
    plot(array_time, array_height, linewidth=1.0)
    axis([0,10,0,10])
    xlabel('time (s)')
    ylabel('height (m)')
    title('matplotlib and Vizard')
    grid(True)
    savefig( "Vizard_Plot.pdf", format='pdf' )
    viz.quit()

vizact.ontimer2(10,0,savePlot)

Example: Plot data in real-time

The following example applies a matplotlib figure to a vizmatplot texture and plots data in real-time:

import viz
import vizact
import viztask
import vizmatplot

import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt

viz.setMultiSample(8)
viz.fov(60)
viz.go()

import vizinfo
vizinfo.InfoPanel('Press the <space bar> to restart the simulation')

# Time duration of plot
PLOT_DURATION = 10.0

# Rate to sample data in hz
SAMPLE_RATE = 60.0

# Rate to redraw plot in hz
REDRAW_RATE = 20.0

# Create arrays to store data
array_time, array_height, array_velocity = [], [], []

# Create a matplotlib figure
fig = plt.figure()

# Create subplot for ball height
ax_height = fig.add_subplot(111)    #create axes
ax_height.axis([0,PLOT_DURATION,0,10])  #set axis limits

# Create a subplot for ball velocity
# Make new plot that shares the x-axis with ax_height. the y-axis is independent and have different tick marks on left and right y-axis
ax_velocity = ax_height.twinx()
ax_velocity.axis([0,PLOT_DURATION,-15,15])

# Create yellow line for height plot
line_height, = ax_height.plot(array_time, array_height, 'y')

# Create blue line for velocity plot
line_velocity, = ax_velocity.plot(array_time, array_velocity, 'b')

# Create labels for figure
plt.grid() # Display grid lines
plt.title('Y-Coord and Velocity of Ball')
plt.xlabel('Time in Seconds')
ax_height.set_ylabel('y coord in meters')
ax_velocity.set_ylabel('velocity in meters per sec')

# Create texture for displaying figure
fig_texture = vizmatplot.Texture(fig)

# Create quad to render plot texture
quad = viz.addTexQuad(texture=fig_texture, pos=(0,1.8,1))
quad.alpha(0.5)

# Create simulation models
viz.phys.enable()
ball = viz.addChild('beachball.osgb', pos=(0,10,10))
ball.collideSphere(bounce=1.5)

ground = viz.addChild('ground.osgb')
ground.collidePlane()

# Create global params
params = viz.Data(startTime=viz.tick())

def CollectData():
    """Collects data for plotting"""
    elapsed = viz.tick() - params.startTime
    if elapsed <= PLOT_DURATION:
        array_time.append(elapsed)
        array_height.append(ball.getPosition()[1]) #store position data of ball in array
        array_velocity.append(ball.getVelocity()[1]) #store velocity data of ball in array

vizact.ontimer(1.0 / SAMPLE_RATE, CollectData)

def PlotTask():
    """Task that updates plot with latest data and redraws texture"""
    while True:

        yield viztask.waitTime(1.0 / REDRAW_RATE)

        elapsed = viz.tick() - params.startTime
        if elapsed <= PLOT_DURATION:

            # Update plot data
            line_height.set_data(array_time, array_height)
            line_velocity.set_data(array_time, array_velocity)

            # Wait for redraw
            yield fig_texture.waitRedraw()

viztask.schedule(PlotTask())

def Reset():
    """Reset plot data and ball position"""
    del array_time[:]
    del array_height[:]
    del array_velocity[:]
    ball.setPosition([0,10,10])
    ball.reset()
    params.startTime = viz.tick()

vizact.onkeydown(' ', Reset)