##// END OF EJS Templates
Optimize plots
jespinoza -
r1269:ad3b2d103f49
parent child
Show More
@@ -1,810 +1,803
1
1
2 import os
2 import os
3 import sys
3 import sys
4 import zmq
4 import zmq
5 import time
5 import time
6 import numpy
6 import numpy
7 import datetime
7 import datetime
8 from functools import wraps
8 from functools import wraps
9 from threading import Thread
9 from threading import Thread
10 import matplotlib
10 import matplotlib
11
11
12 if 'BACKEND' in os.environ:
12 if 'BACKEND' in os.environ:
13 matplotlib.use(os.environ['BACKEND'])
13 matplotlib.use(os.environ['BACKEND'])
14 elif 'linux' in sys.platform:
14 elif 'linux' in sys.platform:
15 matplotlib.use("TkAgg")
15 matplotlib.use("TkAgg")
16 elif 'darwin' in sys.platform:
16 elif 'darwin' in sys.platform:
17 matplotlib.use('WxAgg')
17 matplotlib.use('WxAgg')
18 else:
18 else:
19 from schainpy.utils import log
19 from schainpy.utils import log
20 log.warning('Using default Backend="Agg"', 'INFO')
20 log.warning('Using default Backend="Agg"', 'INFO')
21 matplotlib.use('Agg')
21 matplotlib.use('Agg')
22
22
23 import matplotlib.pyplot as plt
23 import matplotlib.pyplot as plt
24 from matplotlib.patches import Polygon
24 from matplotlib.patches import Polygon
25 from mpl_toolkits.axes_grid1 import make_axes_locatable
25 from mpl_toolkits.axes_grid1 import make_axes_locatable
26 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
26 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
27
27
28 from schainpy.model.data.jrodata import PlotterData
28 from schainpy.model.data.jrodata import PlotterData
29 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
29 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
30 from schainpy.utils import log
30 from schainpy.utils import log
31
31
32 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
32 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
33 blu_values = matplotlib.pyplot.get_cmap(
33 blu_values = matplotlib.pyplot.get_cmap(
34 'seismic_r', 20)(numpy.arange(20))[10:15]
34 'seismic_r', 20)(numpy.arange(20))[10:15]
35 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
35 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
36 'jro', numpy.vstack((blu_values, jet_values)))
36 'jro', numpy.vstack((blu_values, jet_values)))
37 matplotlib.pyplot.register_cmap(cmap=ncmap)
37 matplotlib.pyplot.register_cmap(cmap=ncmap)
38
38
39 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
39 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
40 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
40 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
41
41
42 EARTH_RADIUS = 6.3710e3
42 EARTH_RADIUS = 6.3710e3
43
43
44 def ll2xy(lat1, lon1, lat2, lon2):
44 def ll2xy(lat1, lon1, lat2, lon2):
45
45
46 p = 0.017453292519943295
46 p = 0.017453292519943295
47 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
47 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
48 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
48 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
49 r = 12742 * numpy.arcsin(numpy.sqrt(a))
49 r = 12742 * numpy.arcsin(numpy.sqrt(a))
50 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
50 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
51 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
51 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
52 theta = -theta + numpy.pi/2
52 theta = -theta + numpy.pi/2
53 return r*numpy.cos(theta), r*numpy.sin(theta)
53 return r*numpy.cos(theta), r*numpy.sin(theta)
54
54
55
55
56 def km2deg(km):
56 def km2deg(km):
57 '''
57 '''
58 Convert distance in km to degrees
58 Convert distance in km to degrees
59 '''
59 '''
60
60
61 return numpy.rad2deg(km/EARTH_RADIUS)
61 return numpy.rad2deg(km/EARTH_RADIUS)
62
62
63
63
64 def figpause(interval):
64 def figpause(interval):
65 backend = plt.rcParams['backend']
65 backend = plt.rcParams['backend']
66 if backend in matplotlib.rcsetup.interactive_bk:
66 if backend in matplotlib.rcsetup.interactive_bk:
67 figManager = matplotlib._pylab_helpers.Gcf.get_active()
67 figManager = matplotlib._pylab_helpers.Gcf.get_active()
68 if figManager is not None:
68 if figManager is not None:
69 canvas = figManager.canvas
69 canvas = figManager.canvas
70 if canvas.figure.stale:
70 if canvas.figure.stale:
71 canvas.draw()
71 canvas.draw()
72 try:
72 try:
73 canvas.start_event_loop(interval)
73 canvas.start_event_loop(interval)
74 except:
74 except:
75 pass
75 pass
76 return
76 return
77
77
78
78
79 def popup(message):
79 def popup(message):
80 '''
80 '''
81 '''
81 '''
82
82
83 fig = plt.figure(figsize=(12, 8), facecolor='r')
83 fig = plt.figure(figsize=(12, 8), facecolor='r')
84 text = '\n'.join([s.strip() for s in message.split(':')])
84 text = '\n'.join([s.strip() for s in message.split(':')])
85 fig.text(0.01, 0.5, text, ha='left', va='center',
85 fig.text(0.01, 0.5, text, ha='left', va='center',
86 size='20', weight='heavy', color='w')
86 size='20', weight='heavy', color='w')
87 fig.show()
87 fig.show()
88 figpause(1000)
88 figpause(1000)
89
89
90
90
91 class Throttle(object):
91 class Throttle(object):
92 '''
92 '''
93 Decorator that prevents a function from being called more than once every
93 Decorator that prevents a function from being called more than once every
94 time period.
94 time period.
95 To create a function that cannot be called more than once a minute, but
95 To create a function that cannot be called more than once a minute, but
96 will sleep until it can be called:
96 will sleep until it can be called:
97 @Throttle(minutes=1)
97 @Throttle(minutes=1)
98 def foo():
98 def foo():
99 pass
99 pass
100
100
101 for i in range(10):
101 for i in range(10):
102 foo()
102 foo()
103 print "This function has run %s times." % i
103 print "This function has run %s times." % i
104 '''
104 '''
105
105
106 def __init__(self, seconds=0, minutes=0, hours=0):
106 def __init__(self, seconds=0, minutes=0, hours=0):
107 self.throttle_period = datetime.timedelta(
107 self.throttle_period = datetime.timedelta(
108 seconds=seconds, minutes=minutes, hours=hours
108 seconds=seconds, minutes=minutes, hours=hours
109 )
109 )
110
110
111 self.time_of_last_call = datetime.datetime.min
111 self.time_of_last_call = datetime.datetime.min
112
112
113 def __call__(self, fn):
113 def __call__(self, fn):
114 @wraps(fn)
114 @wraps(fn)
115 def wrapper(*args, **kwargs):
115 def wrapper(*args, **kwargs):
116 coerce = kwargs.pop('coerce', None)
116 coerce = kwargs.pop('coerce', None)
117 if coerce:
117 if coerce:
118 self.time_of_last_call = datetime.datetime.now()
118 self.time_of_last_call = datetime.datetime.now()
119 return fn(*args, **kwargs)
119 return fn(*args, **kwargs)
120 else:
120 else:
121 now = datetime.datetime.now()
121 now = datetime.datetime.now()
122 time_since_last_call = now - self.time_of_last_call
122 time_since_last_call = now - self.time_of_last_call
123 time_left = self.throttle_period - time_since_last_call
123 time_left = self.throttle_period - time_since_last_call
124
124
125 if time_left > datetime.timedelta(seconds=0):
125 if time_left > datetime.timedelta(seconds=0):
126 return
126 return
127
127
128 self.time_of_last_call = datetime.datetime.now()
128 self.time_of_last_call = datetime.datetime.now()
129 return fn(*args, **kwargs)
129 return fn(*args, **kwargs)
130
130
131 return wrapper
131 return wrapper
132
132
133 def apply_throttle(value):
133 def apply_throttle(value):
134
134
135 @Throttle(seconds=value)
135 @Throttle(seconds=value)
136 def fnThrottled(fn):
136 def fnThrottled(fn):
137 fn()
137 fn()
138
138
139 return fnThrottled
139 return fnThrottled
140
140
141
141
142 @MPDecorator
142 @MPDecorator
143 class Plot(Operation):
143 class Plot(Operation):
144 '''
144 '''
145 Base class for Schain plotting operations
145 Base class for Schain plotting operations
146 '''
146 '''
147
147
148 CODE = 'Figure'
148 CODE = 'Figure'
149 colormap = 'jet'
149 colormap = 'jet'
150 bgcolor = 'white'
150 bgcolor = 'white'
151 __missing = 1E30
151 __missing = 1E30
152
152
153 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
153 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
154 'zlimits', 'xlabel', 'ylabel', 'xaxis', 'cb_label', 'title',
154 'zlimits', 'xlabel', 'ylabel', 'xaxis', 'cb_label', 'title',
155 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
155 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
156 'showprofile', 'decimation', 'pause']
156 'showprofile', 'decimation', 'pause']
157
157
158 def __init__(self):
158 def __init__(self):
159
159
160 Operation.__init__(self)
160 Operation.__init__(self)
161 self.isConfig = False
161 self.isConfig = False
162 self.isPlotConfig = False
162 self.isPlotConfig = False
163 self.save_counter = 1
163 self.save_counter = 1
164 self.sender_counter = 1
164 self.sender_counter = 1
165 self.data = None
165 self.data = None
166
166
167 def __fmtTime(self, x, pos):
167 def __fmtTime(self, x, pos):
168 '''
168 '''
169 '''
169 '''
170
170
171 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
171 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
172
172
173 def __setup(self, **kwargs):
173 def __setup(self, **kwargs):
174 '''
174 '''
175 Initialize variables
175 Initialize variables
176 '''
176 '''
177
177
178 self.figures = []
178 self.figures = []
179 self.axes = []
179 self.axes = []
180 self.cb_axes = []
180 self.cb_axes = []
181 self.localtime = kwargs.pop('localtime', True)
181 self.localtime = kwargs.pop('localtime', True)
182 self.show = kwargs.get('show', True)
182 self.show = kwargs.get('show', True)
183 self.save = kwargs.get('save', False)
183 self.save = kwargs.get('save', False)
184 self.save_period = kwargs.get('save_period', 1)
184 self.save_period = kwargs.get('save_period', 1)
185 self.ftp = kwargs.get('ftp', False)
185 self.ftp = kwargs.get('ftp', False)
186 self.colormap = kwargs.get('colormap', self.colormap)
186 self.colormap = kwargs.get('colormap', self.colormap)
187 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
187 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
188 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
188 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
189 self.colormaps = kwargs.get('colormaps', None)
189 self.colormaps = kwargs.get('colormaps', None)
190 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
190 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
191 self.showprofile = kwargs.get('showprofile', False)
191 self.showprofile = kwargs.get('showprofile', False)
192 self.title = kwargs.get('wintitle', self.CODE.upper())
192 self.title = kwargs.get('wintitle', self.CODE.upper())
193 self.cb_label = kwargs.get('cb_label', None)
193 self.cb_label = kwargs.get('cb_label', None)
194 self.cb_labels = kwargs.get('cb_labels', None)
194 self.cb_labels = kwargs.get('cb_labels', None)
195 self.labels = kwargs.get('labels', None)
195 self.labels = kwargs.get('labels', None)
196 self.xaxis = kwargs.get('xaxis', 'frequency')
196 self.xaxis = kwargs.get('xaxis', 'frequency')
197 self.zmin = kwargs.get('zmin', None)
197 self.zmin = kwargs.get('zmin', None)
198 self.zmax = kwargs.get('zmax', None)
198 self.zmax = kwargs.get('zmax', None)
199 self.zlimits = kwargs.get('zlimits', None)
199 self.zlimits = kwargs.get('zlimits', None)
200 self.xmin = kwargs.get('xmin', None)
200 self.xmin = kwargs.get('xmin', None)
201 self.xmax = kwargs.get('xmax', None)
201 self.xmax = kwargs.get('xmax', None)
202 self.xrange = kwargs.get('xrange', 24)
202 self.xrange = kwargs.get('xrange', 24)
203 self.xscale = kwargs.get('xscale', None)
203 self.xscale = kwargs.get('xscale', None)
204 self.ymin = kwargs.get('ymin', None)
204 self.ymin = kwargs.get('ymin', None)
205 self.ymax = kwargs.get('ymax', None)
205 self.ymax = kwargs.get('ymax', None)
206 self.yscale = kwargs.get('yscale', None)
206 self.yscale = kwargs.get('yscale', None)
207 self.xlabel = kwargs.get('xlabel', None)
207 self.xlabel = kwargs.get('xlabel', None)
208 self.attr_time = kwargs.get('attr_time', 'utctime')
208 self.decimation = kwargs.get('decimation', None)
209 self.decimation = kwargs.get('decimation', None)
209 self.showSNR = kwargs.get('showSNR', False)
210 self.showSNR = kwargs.get('showSNR', False)
210 self.oneFigure = kwargs.get('oneFigure', True)
211 self.oneFigure = kwargs.get('oneFigure', True)
211 self.width = kwargs.get('width', None)
212 self.width = kwargs.get('width', None)
212 self.height = kwargs.get('height', None)
213 self.height = kwargs.get('height', None)
213 self.colorbar = kwargs.get('colorbar', True)
214 self.colorbar = kwargs.get('colorbar', True)
214 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
215 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
215 self.channels = kwargs.get('channels', None)
216 self.channels = kwargs.get('channels', None)
216 self.titles = kwargs.get('titles', [])
217 self.titles = kwargs.get('titles', [])
217 self.polar = False
218 self.polar = False
218 self.type = kwargs.get('type', 'iq')
219 self.type = kwargs.get('type', 'iq')
219 self.grid = kwargs.get('grid', False)
220 self.grid = kwargs.get('grid', False)
220 self.pause = kwargs.get('pause', False)
221 self.pause = kwargs.get('pause', False)
221 self.save_labels = kwargs.get('save_labels', None)
222 self.save_labels = kwargs.get('save_labels', None)
222 self.realtime = kwargs.get('realtime', True)
223 self.realtime = kwargs.get('realtime', True)
223 self.buffering = kwargs.get('buffering', True)
224 self.buffering = kwargs.get('buffering', True)
224 self.throttle = kwargs.get('throttle', 2)
225 self.throttle = kwargs.get('throttle', 2)
225 self.exp_code = kwargs.get('exp_code', None)
226 self.exp_code = kwargs.get('exp_code', None)
226 self.plot_server = kwargs.get('plot_server', False)
227 self.plot_server = kwargs.get('plot_server', False)
227 self.sender_period = kwargs.get('sender_period', 1)
228 self.sender_period = kwargs.get('sender_period', 1)
228 self.__throttle_plot = apply_throttle(self.throttle)
229 self.__throttle_plot = apply_throttle(self.throttle)
229 self.data = PlotterData(
230 self.data = PlotterData(
230 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
231 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
231
232
232 if self.plot_server:
233 if self.plot_server:
233 if not self.plot_server.startswith('tcp://'):
234 if not self.plot_server.startswith('tcp://'):
234 self.plot_server = 'tcp://{}'.format(self.plot_server)
235 self.plot_server = 'tcp://{}'.format(self.plot_server)
235 log.success(
236 log.success(
236 'Sending to server: {}'.format(self.plot_server),
237 'Sending to server: {}'.format(self.plot_server),
237 self.name
238 self.name
238 )
239 )
239 if 'plot_name' in kwargs:
240 if 'plot_name' in kwargs:
240 self.plot_name = kwargs['plot_name']
241 self.plot_name = kwargs['plot_name']
241
242
242 def __setup_plot(self):
243 def __setup_plot(self):
243 '''
244 '''
244 Common setup for all figures, here figures and axes are created
245 Common setup for all figures, here figures and axes are created
245 '''
246 '''
246
247
247 self.setup()
248 self.setup()
248
249
249 self.time_label = 'LT' if self.localtime else 'UTC'
250 self.time_label = 'LT' if self.localtime else 'UTC'
250
251
251 if self.width is None:
252 if self.width is None:
252 self.width = 8
253 self.width = 8
253
254
254 self.figures = []
255 self.figures = []
255 self.axes = []
256 self.axes = []
256 self.cb_axes = []
257 self.cb_axes = []
257 self.pf_axes = []
258 self.pf_axes = []
258 self.cmaps = []
259 self.cmaps = []
259
260
260 size = '15%' if self.ncols == 1 else '30%'
261 size = '15%' if self.ncols == 1 else '30%'
261 pad = '4%' if self.ncols == 1 else '8%'
262 pad = '4%' if self.ncols == 1 else '8%'
262
263
263 if self.oneFigure:
264 if self.oneFigure:
264 if self.height is None:
265 if self.height is None:
265 self.height = 1.4 * self.nrows + 1
266 self.height = 1.4 * self.nrows + 1
266 fig = plt.figure(figsize=(self.width, self.height),
267 fig = plt.figure(figsize=(self.width, self.height),
267 edgecolor='k',
268 edgecolor='k',
268 facecolor='w')
269 facecolor='w')
269 self.figures.append(fig)
270 self.figures.append(fig)
270 for n in range(self.nplots):
271 for n in range(self.nplots):
271 ax = fig.add_subplot(self.nrows, self.ncols,
272 ax = fig.add_subplot(self.nrows, self.ncols,
272 n + 1, polar=self.polar)
273 n + 1, polar=self.polar)
273 ax.tick_params(labelsize=8)
274 ax.tick_params(labelsize=8)
274 ax.firsttime = True
275 ax.firsttime = True
275 ax.index = 0
276 ax.index = 0
276 ax.press = None
277 ax.press = None
277 self.axes.append(ax)
278 self.axes.append(ax)
278 if self.showprofile:
279 if self.showprofile:
279 cax = self.__add_axes(ax, size=size, pad=pad)
280 cax = self.__add_axes(ax, size=size, pad=pad)
280 cax.tick_params(labelsize=8)
281 cax.tick_params(labelsize=8)
281 self.pf_axes.append(cax)
282 self.pf_axes.append(cax)
282 else:
283 else:
283 if self.height is None:
284 if self.height is None:
284 self.height = 3
285 self.height = 3
285 for n in range(self.nplots):
286 for n in range(self.nplots):
286 fig = plt.figure(figsize=(self.width, self.height),
287 fig = plt.figure(figsize=(self.width, self.height),
287 edgecolor='k',
288 edgecolor='k',
288 facecolor='w')
289 facecolor='w')
289 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
290 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
290 ax.tick_params(labelsize=8)
291 ax.tick_params(labelsize=8)
291 ax.firsttime = True
292 ax.firsttime = True
292 ax.index = 0
293 ax.index = 0
293 ax.press = None
294 ax.press = None
294 self.figures.append(fig)
295 self.figures.append(fig)
295 self.axes.append(ax)
296 self.axes.append(ax)
296 if self.showprofile:
297 if self.showprofile:
297 cax = self.__add_axes(ax, size=size, pad=pad)
298 cax = self.__add_axes(ax, size=size, pad=pad)
298 cax.tick_params(labelsize=8)
299 cax.tick_params(labelsize=8)
299 self.pf_axes.append(cax)
300 self.pf_axes.append(cax)
300
301
301 for n in range(self.nrows):
302 for n in range(self.nrows):
302 if self.colormaps is not None:
303 if self.colormaps is not None:
303 cmap = plt.get_cmap(self.colormaps[n])
304 cmap = plt.get_cmap(self.colormaps[n])
304 else:
305 else:
305 cmap = plt.get_cmap(self.colormap)
306 cmap = plt.get_cmap(self.colormap)
306 cmap.set_bad(self.bgcolor, 1.)
307 cmap.set_bad(self.bgcolor, 1.)
307 self.cmaps.append(cmap)
308 self.cmaps.append(cmap)
308
309
309 for fig in self.figures:
310 for fig in self.figures:
310 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
311 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
311 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
312 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
312 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
313 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
313 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
314 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
314 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
315 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
315
316
316 def OnKeyPress(self, event):
317 def OnKeyPress(self, event):
317 '''
318 '''
318 Event for pressing keys (up, down) change colormap
319 Event for pressing keys (up, down) change colormap
319 '''
320 '''
320 ax = event.inaxes
321 ax = event.inaxes
321 if ax in self.axes:
322 if ax in self.axes:
322 if event.key == 'down':
323 if event.key == 'down':
323 ax.index += 1
324 ax.index += 1
324 elif event.key == 'up':
325 elif event.key == 'up':
325 ax.index -= 1
326 ax.index -= 1
326 if ax.index < 0:
327 if ax.index < 0:
327 ax.index = len(CMAPS) - 1
328 ax.index = len(CMAPS) - 1
328 elif ax.index == len(CMAPS):
329 elif ax.index == len(CMAPS):
329 ax.index = 0
330 ax.index = 0
330 cmap = CMAPS[ax.index]
331 cmap = CMAPS[ax.index]
331 ax.cbar.set_cmap(cmap)
332 ax.cbar.set_cmap(cmap)
332 ax.cbar.draw_all()
333 ax.cbar.draw_all()
333 ax.plt.set_cmap(cmap)
334 ax.plt.set_cmap(cmap)
334 ax.cbar.patch.figure.canvas.draw()
335 ax.cbar.patch.figure.canvas.draw()
335 self.colormap = cmap.name
336 self.colormap = cmap.name
336
337
337 def OnBtnScroll(self, event):
338 def OnBtnScroll(self, event):
338 '''
339 '''
339 Event for scrolling, scale figure
340 Event for scrolling, scale figure
340 '''
341 '''
341 cb_ax = event.inaxes
342 cb_ax = event.inaxes
342 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
343 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
343 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
344 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
344 pt = ax.cbar.ax.bbox.get_points()[:, 1]
345 pt = ax.cbar.ax.bbox.get_points()[:, 1]
345 nrm = ax.cbar.norm
346 nrm = ax.cbar.norm
346 vmin, vmax, p0, p1, pS = (
347 vmin, vmax, p0, p1, pS = (
347 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
348 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
348 scale = 2 if event.step == 1 else 0.5
349 scale = 2 if event.step == 1 else 0.5
349 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
350 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
350 ax.cbar.norm.vmin = point - scale * (point - vmin)
351 ax.cbar.norm.vmin = point - scale * (point - vmin)
351 ax.cbar.norm.vmax = point - scale * (point - vmax)
352 ax.cbar.norm.vmax = point - scale * (point - vmax)
352 ax.plt.set_norm(ax.cbar.norm)
353 ax.plt.set_norm(ax.cbar.norm)
353 ax.cbar.draw_all()
354 ax.cbar.draw_all()
354 ax.cbar.patch.figure.canvas.draw()
355 ax.cbar.patch.figure.canvas.draw()
355
356
356 def onBtnPress(self, event):
357 def onBtnPress(self, event):
357 '''
358 '''
358 Event for mouse button press
359 Event for mouse button press
359 '''
360 '''
360 cb_ax = event.inaxes
361 cb_ax = event.inaxes
361 if cb_ax is None:
362 if cb_ax is None:
362 return
363 return
363
364
364 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
365 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
365 cb_ax.press = event.x, event.y
366 cb_ax.press = event.x, event.y
366 else:
367 else:
367 cb_ax.press = None
368 cb_ax.press = None
368
369
369 def onMotion(self, event):
370 def onMotion(self, event):
370 '''
371 '''
371 Event for move inside colorbar
372 Event for move inside colorbar
372 '''
373 '''
373 cb_ax = event.inaxes
374 cb_ax = event.inaxes
374 if cb_ax is None:
375 if cb_ax is None:
375 return
376 return
376 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
377 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
377 return
378 return
378 if cb_ax.press is None:
379 if cb_ax.press is None:
379 return
380 return
380
381
381 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
382 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
382 xprev, yprev = cb_ax.press
383 xprev, yprev = cb_ax.press
383 dx = event.x - xprev
384 dx = event.x - xprev
384 dy = event.y - yprev
385 dy = event.y - yprev
385 cb_ax.press = event.x, event.y
386 cb_ax.press = event.x, event.y
386 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
387 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
387 perc = 0.03
388 perc = 0.03
388
389
389 if event.button == 1:
390 if event.button == 1:
390 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
391 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
391 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
392 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
392 elif event.button == 3:
393 elif event.button == 3:
393 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
394 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
394 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
395 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
395
396
396 ax.cbar.draw_all()
397 ax.cbar.draw_all()
397 ax.plt.set_norm(ax.cbar.norm)
398 ax.plt.set_norm(ax.cbar.norm)
398 ax.cbar.patch.figure.canvas.draw()
399 ax.cbar.patch.figure.canvas.draw()
399
400
400 def onBtnRelease(self, event):
401 def onBtnRelease(self, event):
401 '''
402 '''
402 Event for mouse button release
403 Event for mouse button release
403 '''
404 '''
404 cb_ax = event.inaxes
405 cb_ax = event.inaxes
405 if cb_ax is not None:
406 if cb_ax is not None:
406 cb_ax.press = None
407 cb_ax.press = None
407
408
408 def __add_axes(self, ax, size='30%', pad='8%'):
409 def __add_axes(self, ax, size='30%', pad='8%'):
409 '''
410 '''
410 Add new axes to the given figure
411 Add new axes to the given figure
411 '''
412 '''
412 divider = make_axes_locatable(ax)
413 divider = make_axes_locatable(ax)
413 nax = divider.new_horizontal(size=size, pad=pad)
414 nax = divider.new_horizontal(size=size, pad=pad)
414 ax.figure.add_axes(nax)
415 ax.figure.add_axes(nax)
415 return nax
416 return nax
416
417
417 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
418 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
418 '''
419 '''
419 Create a masked array for missing data
420 Create a masked array for missing data
420 '''
421 '''
421 if x_buffer.shape[0] < 2:
422 if x_buffer.shape[0] < 2:
422 return x_buffer, y_buffer, z_buffer
423 return x_buffer, y_buffer, z_buffer
423
424
424 deltas = x_buffer[1:] - x_buffer[0:-1]
425 deltas = x_buffer[1:] - x_buffer[0:-1]
425 x_median = numpy.median(deltas)
426 x_median = numpy.median(deltas)
426
427
427 index = numpy.where(deltas > 5 * x_median)
428 index = numpy.where(deltas > 5 * x_median)
428
429
429 if len(index[0]) != 0:
430 if len(index[0]) != 0:
430 z_buffer[::, index[0], ::] = self.__missing
431 z_buffer[::, index[0], ::] = self.__missing
431 z_buffer = numpy.ma.masked_inside(z_buffer,
432 z_buffer = numpy.ma.masked_inside(z_buffer,
432 0.99 * self.__missing,
433 0.99 * self.__missing,
433 1.01 * self.__missing)
434 1.01 * self.__missing)
434
435
435 return x_buffer, y_buffer, z_buffer
436 return x_buffer, y_buffer, z_buffer
436
437
437 def decimate(self):
438 def decimate(self):
438
439
439 # dx = int(len(self.x)/self.__MAXNUMX) + 1
440 # dx = int(len(self.x)/self.__MAXNUMX) + 1
440 dy = int(len(self.y) / self.decimation) + 1
441 dy = int(len(self.y) / self.decimation) + 1
441
442
442 # x = self.x[::dx]
443 # x = self.x[::dx]
443 x = self.x
444 x = self.x
444 y = self.y[::dy]
445 y = self.y[::dy]
445 z = self.z[::, ::, ::dy]
446 z = self.z[::, ::, ::dy]
446
447
447 return x, y, z
448 return x, y, z
448
449
449 def format(self):
450 def format(self):
450 '''
451 '''
451 Set min and max values, labels, ticks and titles
452 Set min and max values, labels, ticks and titles
452 '''
453 '''
453
454
454 if self.xmin is None:
455 if self.xmin is None:
455 xmin = self.data.min_time
456 xmin = self.data.min_time
456 else:
457 else:
457 if self.xaxis is 'time':
458 if self.xaxis is 'time':
458 dt = self.getDateTime(self.data.min_time)
459 dt = self.getDateTime(self.data.min_time)
459 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
460 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
460 datetime.datetime(1970, 1, 1)).total_seconds()
461 datetime.datetime(1970, 1, 1)).total_seconds()
461 if self.data.localtime:
462 if self.data.localtime:
462 xmin += time.timezone
463 xmin += time.timezone
463 else:
464 else:
464 xmin = self.xmin
465 xmin = self.xmin
465
466
466 if self.xmax is None:
467 if self.xmax is None:
467 xmax = xmin + self.xrange * 60 * 60
468 xmax = xmin + self.xrange * 60 * 60
468 else:
469 else:
469 if self.xaxis is 'time':
470 if self.xaxis is 'time':
470 dt = self.getDateTime(self.data.max_time)
471 dt = self.getDateTime(self.data.max_time)
471 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
472 xmax = self.xmax - 1
473 xmax = (dt.replace(hour=int(xmax), minute=59, second=59) -
472 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
474 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
473 if self.data.localtime:
475 if self.data.localtime:
474 xmax += time.timezone
476 xmax += time.timezone
475 else:
477 else:
476 xmax = self.xmax
478 xmax = self.xmax
477
479
478 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
480 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
479 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
481 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
480 #Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000])
481
482 #i = 1 if numpy.where(
483 # abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
484 #ystep = Y[i] / 10.
485 dig = int(numpy.log10(ymax))
486 if dig == 0:
487 digD = len(str(ymax)) - 2
488 ydec = ymax*(10**digD)
489
490 dig = int(numpy.log10(ydec))
491 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
492 ystep = ystep/5
493 ystep = ystep/(10**digD)
494
495 else:
496 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
497 ystep = ystep/5
498
499 if self.xaxis is not 'time':
500
501 dig = int(numpy.log10(xmax))
502
503 if dig <= 0:
504 digD = len(str(xmax)) - 2
505 xdec = xmax*(10**digD)
506
507 dig = int(numpy.log10(xdec))
508 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
509 xstep = xstep*0.5
510 xstep = xstep/(10**digD)
511
512 else:
513 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
514 xstep = xstep/5
515
482
516 for n, ax in enumerate(self.axes):
483 for n, ax in enumerate(self.axes):
517 if ax.firsttime:
484 if ax.firsttime:
485
486 dig = int(numpy.log10(ymax))
487 if dig == 0:
488 digD = len(str(ymax)) - 2
489 ydec = ymax*(10**digD)
490
491 dig = int(numpy.log10(ydec))
492 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
493 ystep = ystep/5
494 ystep = ystep/(10**digD)
495
496 else:
497 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
498 ystep = ystep/5
499
500 if self.xaxis is not 'time':
501
502 dig = int(numpy.log10(xmax))
503
504 if dig <= 0:
505 digD = len(str(xmax)) - 2
506 xdec = xmax*(10**digD)
507
508 dig = int(numpy.log10(xdec))
509 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
510 xstep = xstep*0.5
511 xstep = xstep/(10**digD)
512
513 else:
514 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
515 xstep = xstep/5
516
518 ax.set_facecolor(self.bgcolor)
517 ax.set_facecolor(self.bgcolor)
519 ax.yaxis.set_major_locator(MultipleLocator(ystep))
518 ax.yaxis.set_major_locator(MultipleLocator(ystep))
520 if self.xscale:
519 if self.xscale:
521 ax.xaxis.set_major_formatter(FuncFormatter(
520 ax.xaxis.set_major_formatter(FuncFormatter(
522 lambda x, pos: '{0:g}'.format(x*self.xscale)))
521 lambda x, pos: '{0:g}'.format(x*self.xscale)))
523 if self.xscale:
522 if self.xscale:
524 ax.yaxis.set_major_formatter(FuncFormatter(
523 ax.yaxis.set_major_formatter(FuncFormatter(
525 lambda x, pos: '{0:g}'.format(x*self.yscale)))
524 lambda x, pos: '{0:g}'.format(x*self.yscale)))
526 if self.xaxis is 'time':
525 if self.xaxis is 'time':
527 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
526 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
528 ax.xaxis.set_major_locator(LinearLocator(9))
527 ax.xaxis.set_major_locator(LinearLocator(9))
529 else:
528 else:
530 ax.xaxis.set_major_locator(MultipleLocator(xstep))
529 ax.xaxis.set_major_locator(MultipleLocator(xstep))
531 if self.xlabel is not None:
530 if self.xlabel is not None:
532 ax.set_xlabel(self.xlabel)
531 ax.set_xlabel(self.xlabel)
533 ax.set_ylabel(self.ylabel)
532 ax.set_ylabel(self.ylabel)
534 ax.firsttime = False
533 ax.firsttime = False
535 if self.showprofile:
534 if self.showprofile:
536 self.pf_axes[n].set_ylim(ymin, ymax)
535 self.pf_axes[n].set_ylim(ymin, ymax)
537 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
536 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
538 self.pf_axes[n].set_xlabel('dB')
537 self.pf_axes[n].set_xlabel('dB')
539 self.pf_axes[n].grid(b=True, axis='x')
538 self.pf_axes[n].grid(b=True, axis='x')
540 [tick.set_visible(False)
539 [tick.set_visible(False)
541 for tick in self.pf_axes[n].get_yticklabels()]
540 for tick in self.pf_axes[n].get_yticklabels()]
542 if self.colorbar:
541 if self.colorbar:
543 ax.cbar = plt.colorbar(
542 ax.cbar = plt.colorbar(
544 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
543 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
545 ax.cbar.ax.tick_params(labelsize=8)
544 ax.cbar.ax.tick_params(labelsize=8)
546 ax.cbar.ax.press = None
545 ax.cbar.ax.press = None
547 if self.cb_label:
546 if self.cb_label:
548 ax.cbar.set_label(self.cb_label, size=8)
547 ax.cbar.set_label(self.cb_label, size=8)
549 elif self.cb_labels:
548 elif self.cb_labels:
550 ax.cbar.set_label(self.cb_labels[n], size=8)
549 ax.cbar.set_label(self.cb_labels[n], size=8)
551 else:
550 else:
552 ax.cbar = None
551 ax.cbar = None
553 if self.grid:
552 if self.grid:
554 ax.grid(True)
553 ax.grid(True)
555
554
556 if not self.polar:
555 if not self.polar:
557 ax.set_xlim(xmin, xmax)
556 ax.set_xlim(xmin, xmax)
558 ax.set_ylim(ymin, ymax)
557 ax.set_ylim(ymin, ymax)
559 ax.set_title('{} {} {}'.format(
558 ax.set_title('{} {} {}'.format(
560 self.titles[n],
559 self.titles[n],
561 self.getDateTime(self.data.max_time).strftime(
560 self.getDateTime(self.data.max_time).strftime(
562 '%Y-%m-%d %H:%M:%S'),
561 '%Y-%m-%d %H:%M:%S'),
563 self.time_label),
562 self.time_label),
564 size=8)
563 size=8)
565 else:
564 else:
566 ax.set_title('{}'.format(self.titles[n]), size=8)
565 ax.set_title('{}'.format(self.titles[n]), size=8)
567 ax.set_ylim(0, 90)
566 ax.set_ylim(0, 90)
568 ax.set_yticks(numpy.arange(0, 90, 20))
567 ax.set_yticks(numpy.arange(0, 90, 20))
569 ax.yaxis.labelpad = 40
568 ax.yaxis.labelpad = 40
570
569
571 def clear_figures(self):
570 def clear_figures(self):
572 '''
571 '''
573 Reset axes for redraw plots
572 Reset axes for redraw plots
574 '''
573 '''
575
574
576 for ax in self.axes:
575 for ax in self.axes:
577 ax.clear()
576 ax.clear()
578 ax.firsttime = True
577 ax.firsttime = True
579 if ax.cbar:
578 if ax.cbar:
580 ax.cbar.remove()
579 ax.cbar.remove()
581
580
582 def __plot(self):
581 def __plot(self):
583 '''
582 '''
584 Main function to plot, format and save figures
583 Main function to plot, format and save figures
585 '''
584 '''
586
585
587 try:
586 try:
588 self.plot()
587 self.plot()
589 self.format()
588 self.format()
590 except Exception as e:
589 except Exception as e:
591 log.warning('{} Plot could not be updated... check data'.format(
590 log.warning('{} Plot could not be updated... check data'.format(
592 self.CODE), self.name)
591 self.CODE), self.name)
593 log.error(str(e), '')
592 log.error(str(e), '')
594 return
593 return
595
594
596 for n, fig in enumerate(self.figures):
595 for n, fig in enumerate(self.figures):
597 if self.nrows == 0 or self.nplots == 0:
596 if self.nrows == 0 or self.nplots == 0:
598 log.warning('No data', self.name)
597 log.warning('No data', self.name)
599 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
598 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
600 fig.canvas.manager.set_window_title(self.CODE)
599 fig.canvas.manager.set_window_title(self.CODE)
601 continue
600 continue
602
601
603 fig.tight_layout()
602 fig.tight_layout()
604 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
603 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
605 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
604 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
606 fig.canvas.draw()
605 fig.canvas.draw()
607 if self.show:
606 if self.show:
608 fig.show()
607 fig.show()
609 figpause(0.1)
608 # figpause(0.1)
610
609
611 if self.save:
610 if self.save:
612 self.save_figure(n)
611 self.save_figure(n)
613
612
614 if self.plot_server:
613 if self.plot_server:
615 self.send_to_server()
614 self.send_to_server()
616 # t = Thread(target=self.send_to_server)
617 # t.start()
618
615
619 def save_figure(self, n):
616 def save_figure(self, n):
620 '''
617 '''
621 '''
618 '''
622
619
623 if self.save_counter < self.save_period:
620 if self.save_counter < self.save_period:
624 self.save_counter += 1
621 self.save_counter += 1
625 return
622 return
626
623
627 self.save_counter = 1
624 self.save_counter = 1
628
625
629 fig = self.figures[n]
626 fig = self.figures[n]
630
627
631 if self.save_labels:
628 if self.save_labels:
632 labels = self.save_labels
629 labels = self.save_labels
633 else:
630 else:
634 labels = list(range(self.nrows))
631 labels = list(range(self.nrows))
635
632
636 if self.oneFigure:
633 if self.oneFigure:
637 label = ''
634 label = ''
638 else:
635 else:
639 label = '-{}'.format(labels[n])
636 label = '-{}'.format(labels[n])
640 figname = os.path.join(
637 figname = os.path.join(
641 self.save,
638 self.save,
642 self.CODE,
639 self.CODE,
643 '{}{}_{}.png'.format(
640 '{}{}_{}.png'.format(
644 self.CODE,
641 self.CODE,
645 label,
642 label,
646 self.getDateTime(self.data.max_time).strftime(
643 self.getDateTime(self.data.max_time).strftime(
647 '%Y%m%d_%H%M%S'
644 '%Y%m%d_%H%M%S'
648 ),
645 ),
649 )
646 )
650 )
647 )
651 log.log('Saving figure: {}'.format(figname), self.name)
648 log.log('Saving figure: {}'.format(figname), self.name)
652 if not os.path.isdir(os.path.dirname(figname)):
649 if not os.path.isdir(os.path.dirname(figname)):
653 os.makedirs(os.path.dirname(figname))
650 os.makedirs(os.path.dirname(figname))
654 fig.savefig(figname)
651 fig.savefig(figname)
655
652
656 if self.realtime:
653 if self.realtime:
657 figname = os.path.join(
654 figname = os.path.join(
658 self.save,
655 self.save,
659 '{}{}_{}.png'.format(
656 '{}{}_{}.png'.format(
660 self.CODE,
657 self.CODE,
661 label,
658 label,
662 self.getDateTime(self.data.min_time).strftime(
659 self.getDateTime(self.data.min_time).strftime(
663 '%Y%m%d'
660 '%Y%m%d'
664 ),
661 ),
665 )
662 )
666 )
663 )
667 fig.savefig(figname)
664 fig.savefig(figname)
668
665
669 def send_to_server(self):
666 def send_to_server(self):
670 '''
667 '''
671 '''
668 '''
672
669
673 if self.sender_counter < self.sender_period:
670 if self.sender_counter < self.sender_period:
674 self.sender_counter += 1
671 self.sender_counter += 1
675 return
672 return
676
673
677 self.sender_counter = 1
674 self.sender_counter = 1
678 self.data.meta['titles'] = self.titles
675 self.data.meta['titles'] = self.titles
679 retries = 2
676 retries = 2
680 while True:
677 while True:
681 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
678 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
682 socks = dict(self.poll.poll(5000))
679 socks = dict(self.poll.poll(5000))
683 if socks.get(self.socket) == zmq.POLLIN:
680 if socks.get(self.socket) == zmq.POLLIN:
684 reply = self.socket.recv_string()
681 reply = self.socket.recv_string()
685 if reply == 'ok':
682 if reply == 'ok':
686 log.log("Response from server ok", self.name)
683 log.log("Response from server ok", self.name)
687 break
684 break
688 else:
685 else:
689 log.warning(
686 log.warning(
690 "Malformed reply from server: {}".format(reply), self.name)
687 "Malformed reply from server: {}".format(reply), self.name)
691
688
692 else:
689 else:
693 log.warning(
690 log.warning(
694 "No response from server, retrying...", self.name)
691 "No response from server, retrying...", self.name)
695 self.socket.setsockopt(zmq.LINGER, 0)
692 self.socket.setsockopt(zmq.LINGER, 0)
696 self.socket.close()
693 self.socket.close()
697 self.poll.unregister(self.socket)
694 self.poll.unregister(self.socket)
698 retries -= 1
695 retries -= 1
699 if retries == 0:
696 if retries == 0:
700 log.error(
697 log.error(
701 "Server seems to be offline, abandoning", self.name)
698 "Server seems to be offline, abandoning", self.name)
702 self.socket = self.context.socket(zmq.REQ)
699 self.socket = self.context.socket(zmq.REQ)
703 self.socket.connect(self.plot_server)
700 self.socket.connect(self.plot_server)
704 self.poll.register(self.socket, zmq.POLLIN)
701 self.poll.register(self.socket, zmq.POLLIN)
705 time.sleep(1)
702 time.sleep(1)
706 break
703 break
707 self.socket = self.context.socket(zmq.REQ)
704 self.socket = self.context.socket(zmq.REQ)
708 self.socket.connect(self.plot_server)
705 self.socket.connect(self.plot_server)
709 self.poll.register(self.socket, zmq.POLLIN)
706 self.poll.register(self.socket, zmq.POLLIN)
710 time.sleep(0.5)
707 time.sleep(0.5)
711
708
712 def setup(self):
709 def setup(self):
713 '''
710 '''
714 This method should be implemented in the child class, the following
711 This method should be implemented in the child class, the following
715 attributes should be set:
712 attributes should be set:
716
713
717 self.nrows: number of rows
714 self.nrows: number of rows
718 self.ncols: number of cols
715 self.ncols: number of cols
719 self.nplots: number of plots (channels or pairs)
716 self.nplots: number of plots (channels or pairs)
720 self.ylabel: label for Y axes
717 self.ylabel: label for Y axes
721 self.titles: list of axes title
718 self.titles: list of axes title
722
719
723 '''
720 '''
724 raise NotImplementedError
721 raise NotImplementedError
725
722
726 def plot(self):
723 def plot(self):
727 '''
724 '''
728 Must be defined in the child class
725 Must be defined in the child class
729 '''
726 '''
730 raise NotImplementedError
727 raise NotImplementedError
731
728
732 def run(self, dataOut, **kwargs):
729 def run(self, dataOut, **kwargs):
733 '''
730 '''
734 Main plotting routine
731 Main plotting routine
735 '''
732 '''
736
733
737 if self.isConfig is False:
734 if self.isConfig is False:
738 self.__setup(**kwargs)
735 self.__setup(**kwargs)
739 if dataOut.type == 'Parameters':
736
740 t = dataOut.utctimeInit
737 t = getattr(dataOut, self.attr_time)
741 else:
742 t = dataOut.utctime
743
738
744 if dataOut.useLocalTime:
739 if dataOut.useLocalTime:
745 self.getDateTime = datetime.datetime.fromtimestamp
740 self.getDateTime = datetime.datetime.fromtimestamp
746 if not self.localtime:
741 if not self.localtime:
747 t += time.timezone
742 t += time.timezone
748 else:
743 else:
749 self.getDateTime = datetime.datetime.utcfromtimestamp
744 self.getDateTime = datetime.datetime.utcfromtimestamp
750 if self.localtime:
745 if self.localtime:
751 t -= time.timezone
746 t -= time.timezone
752
747
753 if 'buffer' in self.plot_type:
748 if 'buffer' in self.plot_type:
754 if self.xmin is None:
749 if self.xmin is None:
755 self.tmin = t
750 self.tmin = t
751 self.xmin = self.getDateTime(t).hour
756 else:
752 else:
757 self.tmin = (
753 self.tmin = (
758 self.getDateTime(t).replace(
754 self.getDateTime(t).replace(
759 hour=self.xmin,
755 hour=int(self.xmin),
760 minute=0,
756 minute=0,
761 second=0) - self.getDateTime(0)).total_seconds()
757 second=0) - self.getDateTime(0)).total_seconds()
762
758
763 self.data.setup()
759 self.data.setup()
764 self.isConfig = True
760 self.isConfig = True
765 if self.plot_server:
761 if self.plot_server:
766 self.context = zmq.Context()
762 self.context = zmq.Context()
767 self.socket = self.context.socket(zmq.REQ)
763 self.socket = self.context.socket(zmq.REQ)
768 self.socket.connect(self.plot_server)
764 self.socket.connect(self.plot_server)
769 self.poll = zmq.Poller()
765 self.poll = zmq.Poller()
770 self.poll.register(self.socket, zmq.POLLIN)
766 self.poll.register(self.socket, zmq.POLLIN)
771
767
772 if dataOut.type == 'Parameters':
768 tm = getattr(dataOut, self.attr_time)
773 tm = dataOut.utctimeInit
774 else:
775 tm = dataOut.utctime
776
769
777 if not dataOut.useLocalTime and self.localtime:
770 if not dataOut.useLocalTime and self.localtime:
778 tm -= time.timezone
771 tm -= time.timezone
779 if dataOut.useLocalTime and not self.localtime:
772 if dataOut.useLocalTime and not self.localtime:
780 tm += time.timezone
773 tm += time.timezone
781
774
782 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
775 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
783 self.save_counter = self.save_period
776 self.save_counter = self.save_period
784 self.__plot()
777 self.__plot()
785 self.xmin += self.xrange
778 self.xmin += self.xrange
786 if self.xmin >= 24:
779 if self.xmin >= 24:
787 self.xmin -= 24
780 self.xmin -= 24
788 self.tmin += self.xrange*60*60
781 self.tmin += self.xrange*60*60
789 self.data.setup()
782 self.data.setup()
790 self.clear_figures()
783 self.clear_figures()
791
784
792 self.data.update(dataOut, tm)
785 self.data.update(dataOut, tm)
793
786
794 if self.isPlotConfig is False:
787 if self.isPlotConfig is False:
795 self.__setup_plot()
788 self.__setup_plot()
796 self.isPlotConfig = True
789 self.isPlotConfig = True
797
790
798 if self.realtime:
791 if self.realtime:
799 self.__plot()
792 self.__plot()
800 else:
793 else:
801 self.__throttle_plot(self.__plot)#, coerce=coerce)
794 self.__throttle_plot(self.__plot)#, coerce=coerce)
802
795
803 def close(self):
796 def close(self):
804
797
805 if self.data:
798 if self.data:
806 self.save_counter = self.save_period
799 self.save_counter = self.save_period
807 self.__plot()
800 self.__plot()
808 if self.data and self.pause:
801 if self.data and self.pause:
809 figpause(10)
802 figpause(10)
810
803
General Comments 0
You need to be logged in to leave comments. Login now