Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: Plotting numerous disconnected line segments with different colors

I have a set of data records like this:

(s1, t1), (u1, v1), color1 (s2, t2), (u2, v2), color2 . . . (sN, tN), (uN, vN), colorN 

In any record, the first two values are the end-points of a line segment, the third value is the color of that line segment. More specifically, (sn, tn) are the x-y coordinates of the first end-point, (un, vn) are the x-y coordinates of the second-endpoint. Also, color is an rgb with alpha value.

In general, any two line segments are disconnected (meaning that their end-points do not necessarily coincide).

How to plot this data using matplotlib with a single plot call (or as few as possible) as there could be potentially thousands of records.

Attempts

Preparing the data in one big list and calling plot against it is way too slow. For example the following code couldn't finish in a reasonable amount of time:

import numpy as np import matplotlib.pyplot as plt  data = [] for _ in xrange(60000):     data.append((np.random.rand(), np.random.rand()))     data.append((np.random.rand(), np.random.rand()))     data.append('r')  print 'now plotting...' # from now on, takes too long plt.plot(*data) print 'done' #plt.show() 

I was able to speed-up the plot rendering by using the None insertion trick as follows:

import numpy as np import matplotlib.pyplot as plt from timeit import timeit  N = 60000 _s = np.random.rand(N) _t = np.random.rand(N) _u = np.random.rand(N) _v = np.random.rand(N) x = [] y = [] for s, t, u, v in zip(_s, _t, _u, _v):     x.append(s)     x.append(u)     x.append(None)     y.append(t)     y.append(v)     y.append(None) print timeit(lambda:plt.plot(x, y), number=1) 

This executes in under a second on my machine. I still have to figure out how to embed the color values (RGB with alpha channel).

like image 866
Rabih Kodeih Avatar asked Jan 25 '14 15:01

Rabih Kodeih


2 Answers

function plot allows to draw multiple lines in one call, if your data is just in a list, just unpack it when passing it to plot:

In [315]: data=[(1, 1), (2, 3), 'r', #assuming points are (1,2) (1,3) actually and,                                      #here they are in form of (x1, x2), (y1, y2)      ...: (2, 2), (4, 5), 'g',      ...: (5, 5), (6, 7), 'b',]  In [316]: plot(*data) Out[316]:  [<matplotlib.lines.Line2D at 0x8752870>,  <matplotlib.lines.Line2D at 0x8752a30>,  <matplotlib.lines.Line2D at 0x8752db0>] 

enter image description here

like image 37
zhangxaochen Avatar answered Oct 03 '22 05:10

zhangxaochen


use LineCollection:

import numpy as np import pylab as pl from matplotlib import collections  as mc  lines = [[(0, 1), (1, 1)], [(2, 3), (3, 3)], [(1, 2), (1, 3)]] c = np.array([(1, 0, 0, 1), (0, 1, 0, 1), (0, 0, 1, 1)])  lc = mc.LineCollection(lines, colors=c, linewidths=2) fig, ax = pl.subplots() ax.add_collection(lc) ax.autoscale() ax.margins(0.1) 

here is the output:

enter image description here

like image 110
HYRY Avatar answered Oct 03 '22 07:10

HYRY