Optimization line plotting

Usually, in order to optimize (accelerate) your code, you must vectorize as much as possible, and avoid for loops.

Numpy does that great and allow you to manipulate matrix without the need of a for loop.

But sometimes, I have been surprised. I wanted to draw a « thick » line in a graph. I needed to have all the coordinates, and I thought that directly plotting them was a good idea to see if I had an error.

So on the code below, you may see an example of vectorized generation of 2D matrix (the xx and yy) : I did not use any loop, just adding « vertical » matrix (generated with numpy.vstack) and « horizontal » matrix.
and then I show 3 syntax to plot them, producing exactly the same graph . I was really surprised by the 2 first. The for loop is here more that 300 times faster than plotting directly « xx, yy ». I really had existential questions like « do I understand really vectorization ? » « am I completely stupid or matplotlib is weird programmed? ».

I finally found the right way to do « vectorized plotting » : transpose the matrix to have long dimension (here the length) as the first index. And actually, if I did not specified the color of my line (with plot argument ‘r-‘) I would have directly seen what’s was going on : I plotted 20000 lines with a length of 20… instead of ploting 20 long lines!

So you have seen the difference between the 2nd and the 3rd way to plot : the « T » which mean « transpose » in numpy, and accelerate the plot time by a factor bigger than 300 and is even 10% better than the for loop (first method). So now everything is reasonable again : vectorialization is faster than for loop 🙂

 

#### Optimization drawings ####
import numpy as np
from time import clock
from matplotlib import pyplot as plt

width = 20
theta = 1.
length = 20000

fig, ax = plt.subplots()

i = np.vstack(np.linspace(-width/2.,width/2.,width))
xx = 10 + np.linspace(0, length * np.cos(theta), length) - i*np.sin(theta)
yy = 10 + np.linspace(0, length * np.sin(theta), length) + i*np.cos(theta)

timeStart = clock()
for j in range(width):
    ax.plot(xx[j],yy[j],'r-')
print "plot 1 in : " + str(clock()-timeStart) + "s"

timeStart = clock()
ax.plot(xx,yy,'r-')
print "plot 2 in : " + str(clock()-timeStart) + "s"

timeStart = clock()
ax.plot(xx.T,yy.T,'r-')
print "plot 3 in : " + str(clock()-timeStart) + "s"