Drawing chart dynamically with Python and Matplotlib 7

A while back my friend asked me if I could make him a dynamic chart for his thesis presentation. At first I didn’t know which tool I should use, but then a classmate suggested me to try matplot lib. As it turned out, it is quite easy to draw fancy dynamic chart with it … Here is demo of final chart:



First you need to install matplotlib. Here you can find instructions on how to do that.

Now, let take a look at how to plot that chart :) . First I needed to read data from .csv file into an array. Matplotlib takes in data in form of numpy array.

print "Read data ..."
lines = [line.strip() for line in open('data.csv')]

time = []
vol = []
for i, x in enumerate(lines):
    t, v = x.split(',')
    time.append(t)
    vol.append(v)

final = []
final.append(time[:650])
final.append(vol[:650])

# create numpy array
data = np.array(final)

All you have to do now is configure matplotlib.pyplot to draw chart the way you want.

fig1 = plt.figure()
plt.xlim(0, 70) # limit on X axis (modify to fit your data)
plt.ylim(0, 150) # limit on Y axis (modify to fit your data
plt.xlabel('Time')
plt.ylabel('Volume')
plt.title('The volume as a function of time')

Before we take a look at the interesting part, I would like to point out the following line

l, = plt.plot([], [], 'r-')

Normally we pass data to plot function as array of points ([X], [Y]), but in the case of dynamic chart, we pass it empty arrays because we draw points dynamically. The third argument is string which determines how the points are drawn. First char means color, second char the representation of a point. “-” means line, but you can choose whatever char you want. Here you can read more about plot function.

Ok, so far we haven’t seen anything special. Now let’s take a look at the part that does the magic. Matplotlib offers a FuncAnimation function to support animation of a chart. Animation is achieved by FuncAnimation repeatedly calling a function func.

def update_line(num, data, line):
    line.set_data(data[0, :num], data[1,:num])
    return lines

line_ani = animation.FuncAnimation(fig1, update_line, 5000, fargs=(data, l), interval=50, blit=True, repeat=False)

print "Starting drawing chart..."
plt.show()

As you can see, we pass the function update_line to FuncAnimation and arguments to update_line which takes 3 arguments. The num argument represents sequence number, which we don’t need to pass explicitly. Each iteration we draw points from 0 to num, which animates our chart. So, that all, if your goal is to draw only lines for one type of data. But what if you want to have 2 different data types for Y axis? Let’s take a look how you can implement that. First you have to define two sets of data and two different axis:

print "Prepare data and chart..."
data = np.array(final)
data2 = np.array(final2)

fig = plt.figure()
# add subplot to chart
ax = fig.add_subplot(111)
# first line is red
l, = ax.plot([], [], 'r-', label="Volume")

# define second axis
ax2 = ax.twinx()

#and set line color to blue
k, = ax2.plot([], [], 'b-', label="Temperature")

ax.legend([l,k], [l.get_label(), k.get_label()], loc=0)

plt.title('Volume and temperature in function with time.')
ax.set_xlabel("Time [seconds]")
ax.set_ylabel("Volume [liter]")
ax.set_ylim(0,150)
ax.set_xlim(0, 70)
ax2.set_ylabel("Temperature [Degrees celsius]")
ax2.set_ylim(0, 45)
ax2.set_xlim(0, 70)

I believe the above code shouldn’t give you trouble, because there were just some minor changes made. The main difference is that we add a subplot to the plot and set data to its ax. We define its color and label just like before. Then we specify second ax and repeat…

OK, we are almost there. The last thing we need to do is to modify our update_line function in a way that it accepts four parameters and pass them in FuncAnimation’s fargs argument.

def update_line(num, data, line, data2, line2):
    line.set_data(data[0, :num], data[1,:num])
    line2.set_data(data2[0, :num], data2[1, :num])
    return line, line2

# pass all data in fargs argument
line_ani = animation.FuncAnimation(fig, update_line, 5000, fargs=(data, l, data2, k), interval=50, blit=True, repeat=False)

And that is it. :) Just in case if you have any problem with putting it all together, here is the full source

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def update_line(num, data, line, data2, line2):
    line.set_data(data[0, :num], data[1,:num])
    line2.set_data(data2[0, :num], data2[1, :num])
    return line, line2

print "Read data ..."
lines = [line.strip() for line in open('data.csv')]
linesTemp = [line.strip() for line in open('cas_temp_ok.csv')]

pressure = []
time = []
for i, x in enumerate(lines):
    line = x.split(',')
    pressure.append(line[1])
    time.append(line[0])


temp = []
for i, x in enumerate(linesTemp):
    line = x.split(',')
    temp.append(line[1])



final = []
final.append(time)
final.append(pressure)

final2 = []
final2.append(time)
final2.append(temp)


print "Prepare data and chart..."
data = np.array(final)
data2 = np.array(final2)

fig = plt.figure()
# add subplot to chart
ax = fig.add_subplot(111)
# first line is red
l, = ax.plot([], [], 'r-', label="Volume")

# define second axis
ax2 = ax.twinx()

#and set line color to blue
k, = ax2.plot([], [], 'b-', label="Temperature")

ax.legend([l,k], [l.get_label(), k.get_label()], loc=0)

ax.set_xlabel("Time [seconds]")
ax.set_ylabel("Volume [liter]")
ax.set_ylim(0,150)
ax.set_xlim(0, 70)
ax2.set_ylabel("Temperature [Degrees celsius]")
ax2.set_ylim(0, 45)
ax2.set_xlim(0, 70)
plt.title('Volume and temperature in function with time.')

line_ani = animation.FuncAnimation(fig, update_line, 5000, fargs=(data, l, data2, k), interval=50, blit=True, repeat=False)
print "Starting drawing chart..."
plt.show()

7 thoughts on “Drawing chart dynamically with Python and Matplotlib

  1. Reply J Lam Jun 10, 2014 5:19 PM

    Thanks for the post. How would one output that to a movie file from Matplotlib?

  2. Reply DanB Jun 13, 2014 12:06 PM

    Hello,

    Interesting demo: I would like to get the input data file….

    I haven’t seen any link to download it ???

    Thank you,

    D.

  3. Reply Matic Balantič Jun 13, 2014 12:11 PM

    @J Lam Sori for late response. I tried playing with functions python offers to save that to a movie file, but weren’t successful. Since I was in a hurry I just recorded it with some program for recording computer desktop …

  4. Reply Matic Balantič Jun 13, 2014 12:17 PM

    @DanB The file is simple. For one line you need x and y coordinate. Each in its own line. So in my case I had two files. One for volume and one for temperature if I remember correctly. Example file would look something like this:

    0,60
    1,62
    2,64

    Hope it helps

  5. Reply DanB Jun 13, 2014 1:00 PM

    Hello Matic,

    Working fine with my own CSV….
    Thanks for the “LightSpeed” answer… ;-)

    D.

  6. Reply Tian Zhi Nov 1, 2014 3:58 PM

    There appears to be a mistake.
    At third line of the fourth code block,I think it should be “line” rather than “lines”.

  7. Reply huzaifa Dec 5, 2014 7:56 AM

    hey can anyone help me if i am not taking data from a csv file but instead i am recieving it serially through matlab but i want the same way to plot that data

Leave a Reply