1 __author__="fccoelho@gmail.com"
2 __date__ ="$26/02/2009 10:44:29$"
3 __docformat__ = "restructuredtext en"
4 import Gnuplot
5 import numpy
6 import pylab as P
7 from SimpleXMLRPCServer import SimpleXMLRPCServer
8 from multiprocessing import Process
9
10 Gnuplot.GnuplotOpts.prefer_inline_data = 1
11 Gnuplot.GnuplotOpts.prefer_fifo_data = 0
12
13
14 __ports_used = []
15
17 '''
18 Real time plotting class based on Gnuplot
19 '''
21 self.gp = Gnuplot.Gnuplot(persist = persist, debug=debug)
22 self.plots = []
23
25 '''
26 Clears the figure.
27 '''
28 self.plots = []
29
32
33 - def scatter(self,x,y,names=[],title='',style='points', jitter = True):
34 """
35 Makes scatter plots from numpy arrays.
36 if arrays are multidimensional, multiple scatter plots will be generated, pairing rows.
37 """
38 if jitter:
39 jt = numpy.random.normal(1, 1e-4, 1)[0]
40 else:
41 jt = 1
42 if isinstance(x, numpy.ndarray):
43 if not isinstance(y, numpy.ndarray):
44 raise TypeError("If x is a numpy array, y must also be an array.")
45 if x.shape != y.shape:
46 raise ValueError("x, %s and y, %s arrays must have the same shape."%(x.shape,y.shape))
47 if names:
48 if len(names) != x.shape[0]:
49 raise ValueError("names list must have exactly %s items, but has %s."%(x.shape[0],len(names)))
50 else:
51 x = numpy.array(x)
52 y = numpy.array(y)
53
54
55 self.gp('set title "%s"'%title)
56 if not names:
57 names = ['s%s'%i for i in range(x.shape[0])]
58 if len(x.shape) > 1 and len(x.shape) <= 2:
59 i = 0
60 for n in range(x.shape[0]):
61 self.plots.append(Gnuplot.PlotItems.Data(x[n]*jt,y[n]*jt,title=names[i],with_=style))
62 i += 1
63 self.gp.plot(*tuple(self.plots))
64 elif len(x.shape) >2:
65 pass
66 else:
67
68 self.plots.append(Gnuplot.PlotItems.Data(x*jt,y*jt,title=names[0],with_=style))
69 self.gp.plot(*tuple(self.plots))
70
71 - def plotlines(self, data, x=None, names=[],title='',style='lines', multiplot=0):
72 '''
73 Create a single/multiple line plot from a numpy array or record array.
74
75 :Parameters:
76 - `data`: must be a numpy array or a list of lists,or record array, with series as rows
77 - `x`: x values for the series: numpy array
78 - `names`: is a list of strings to serve as legend labels
79 - `title`: Figure Title.
80 - `style`: plot styles from gnuplot: lines, boxes, points, linespoints, etc.
81 - `multiplot`: Whether to make multiple subplots
82 '''
83
84 if multiplot:
85 sq = numpy.sqrt(len(data))
86 r= numpy.floor(sq);c=numpy.ceil(sq)
87 if len(data) == 3:
88 r=3;c=1
89 self.gp('set multiplot layout %s,%s title "%s"'%(r, c, title))
90 else:
91 self.gp('set title "%s"'%title)
92
93 if isinstance (data, list):
94 data = numpy.array(data)
95 if isinstance(data,numpy.core.records.recarray):
96 return self._linesFromRA(data,x, style)
97 if len(data.shape) > 1 and len(data.shape) <= 2:
98 i = 0
99 for row in data:
100 if x== None:
101 x = numpy.arange(len(row))
102 if names:
103 self.plots.append(Gnuplot.PlotItems.Data(x, row,title=names[i], with_=style))
104 else:
105 self.plots.append(Gnuplot.PlotItems.Data(x, row, with_=style))
106 i += 1
107 if not multiplot:
108 self.gp.plot(*tuple(self.plots))
109 else:
110 [self.gp.plot(pl) for pl in self.plots]
111 elif len(data.shape) >2:
112 pass
113 else:
114
115 if x==None:
116 x = numpy.arange(len(data))
117 self.plots.append(Gnuplot.PlotItems.Data(x,data,title=names[0],with_=style))
118 if not multiplot:
119 self.gp.plot(*tuple(self.plots))
120 else:
121 [self.gp.plot(pl) for pl in self.plots]
122
124 '''
125 Record-array specific code
126 '''
127 for n in data.dtype.names:
128 if len(data.shape) > 1 and len(data.shape) <= 2:
129 i = 0
130 for row in data[n]:
131 if x == None:
132 x = numpy.arange(len(row))
133 self.plots.append(Gnuplot.PlotItems.Data(x, row,title=n+':%s'%i,with_=style))
134 i += 1
135 elif len(data.shape) >2:
136 pass
137
138 else:
139 self.plots.append(Gnuplot.PlotItems.Data(x, data[n],title=n,with_=style))
140 self.gp.plot(*tuple(self.plots))
141
142 - def plothist(self,data, title='', names=[], multiplot=0):
143 '''
144 Create a sinlge/multiple Histogram plot from a numpy array or record array.
145
146 :Parameters:
147 - `data`: must be a numpy array or record array, with series as rows
148 - `names`: is a list of strings to serve as legend labels
149 '''
150 if multiplot:
151 sq = numpy.sqrt(len(data))
152 r= numpy.floor(sq);c=numpy.ceil(sq)
153 if len(data) == 3:
154 r=3;c=1
155 self.gp('set multiplot layout %s,%s title "%s"'%(r, c, title))
156 else:
157 self.gp('set title "%s"'%title)
158 self.gp('set style data boxes')
159
160 if isinstance (data, list):
161 data = numpy.array(data)
162 if isinstance(data,numpy.core.records.recarray):
163 return self._histFromRA(data)
164 if not names:
165 names = ['s%s'%i for i in range(data.shape[0])]
166 if len(data.shape) > 1 and len(data.shape) <= 2:
167 for n,row in enumerate(data):
168 m,bins = numpy.histogram(row,normed=True,bins=50)
169 d = zip(bins[:-1],m)
170 self.plots.append(Gnuplot.PlotItems.Data(d,title=names[n]))
171 [self.gp.plot(pl) for pl in self.plots]
172 elif len(data.shape) >2:
173 pass
174 else:
175 m,bins = numpy.histogram(data,normed=True,bins=50)
176 d = zip(bins[:-1],m)
177 self.plots.append(Gnuplot.PlotItems.Data(d,title=names[0]))
178 [self.gp.plot(pl) for pl in self.plots]
179
181 '''
182 Record-array specific code
183 '''
184 for n in data.dtype.names:
185 if len(data.shape) > 1 and len(data.shape) <= 2:
186 i = 0
187 for row in data[n]:
188 m,bins = numpy.histogram(row,normed=True,bins=50)
189 d = zip(bins[:-1],m)
190 self.plots.append(Gnuplot.PlotItems.Data(d,title=n+':%s'%i))
191 i += 1
192 elif len(data.shape) > 2:
193 pass
194 else:
195 m,bins = numpy.histogram(data[n],normed=True,bins=50)
196 d = zip(bins[:-1],m)
197 self.plots.append(Gnuplot.PlotItems.Data(d,title=n))
198 self.gp.plot(*tuple(self.plots))
199
201 """
202 Creates an animated plot based on pylab
203 """
204 - def __init__(self, nseries=1, leng =10, names=['l'], title = ""):
205 self.nseries = nseries
206 self.leng = leng
207 self.names = names
208 self.title = title
209 self.lines = []
210 self.started = False
211
213 self.ax = P.subplot(111)
214 self.canvas = self.ax.figure.canvas
215 for i in range(self.nseries):
216 line, = P.plot(numpy.arange(self.leng), [1]*self.leng,label=self.names[i], title=self.title, animated=True)
217 self.lines.append(line)
218 P.legend(loc=0)
219 P.grid()
220 P.show()
221 self.started = True
223 if not self.started:
224 self._setup()
225 nlines = data.shape[0]
226 assert nlines == self.nseries
227 for i, d in enumerate(data):
228 background = self.canvas.copy_from_bbox(self.ax.bbox)
229 self.lines[i].set_ydata(d)
230 self.ax.draw_artist(self.lines[i])
231 self.canvas.blit(self.ax.bbox)
232
233
235 server.register_instance(RTplot(persist=0))
236 server.register_introspection_functions()
237 server.serve_forever()
238
239
241 """
242 XML RPC plot server factory function
243 returns port if server successfully started or 0
244 """
245 if port == None:
246 po = 10001
247 while 1:
248 if po not in __ports_used:break
249 po += 1
250 port = po
251 try:
252 server = SimpleXMLRPCServer(("localhost", port),logRequests=False, allow_none=True)
253 server.register_introspection_functions()
254 p = Process(target=start_server, args=(server, ))
255 p.daemon = True
256 p.start()
257 except:
258 return 0
259 __ports_used.append(port)
260 return port
261
262
263
264
265
266 if __name__ == "__main__":
267 gp = RTplot()
268 gp.plotlines([range(10), range(10)], range(10, 20),['a', 'b'], 'multi', 'lines', 1 )
269