##// END OF EJS Templates
test for localtime plotting issues
Juan C. Espinoza -
r1218:afa054b492c7
parent child
Show More
@@ -1,802 +1,799
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
166
166 def __fmtTime(self, x, pos):
167 def __fmtTime(self, x, pos):
167 '''
168 '''
168 '''
169 '''
169
170
170 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
171 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
171
172
172 def __setup(self, **kwargs):
173 def __setup(self, **kwargs):
173 '''
174 '''
174 Initialize variables
175 Initialize variables
175 '''
176 '''
176
177
177 self.figures = []
178 self.figures = []
178 self.axes = []
179 self.axes = []
179 self.cb_axes = []
180 self.cb_axes = []
180 self.localtime = kwargs.pop('localtime', True)
181 self.localtime = kwargs.pop('localtime', True)
181 self.show = kwargs.get('show', True)
182 self.show = kwargs.get('show', True)
182 self.save = kwargs.get('save', False)
183 self.save = kwargs.get('save', False)
183 self.save_period = kwargs.get('save_period', 2)
184 self.save_period = kwargs.get('save_period', 2)
184 self.ftp = kwargs.get('ftp', False)
185 self.ftp = kwargs.get('ftp', False)
185 self.colormap = kwargs.get('colormap', self.colormap)
186 self.colormap = kwargs.get('colormap', self.colormap)
186 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
187 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
187 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
188 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
188 self.colormaps = kwargs.get('colormaps', None)
189 self.colormaps = kwargs.get('colormaps', None)
189 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
190 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
190 self.showprofile = kwargs.get('showprofile', False)
191 self.showprofile = kwargs.get('showprofile', False)
191 self.title = kwargs.get('wintitle', self.CODE.upper())
192 self.title = kwargs.get('wintitle', self.CODE.upper())
192 self.cb_label = kwargs.get('cb_label', None)
193 self.cb_label = kwargs.get('cb_label', None)
193 self.cb_labels = kwargs.get('cb_labels', None)
194 self.cb_labels = kwargs.get('cb_labels', None)
194 self.labels = kwargs.get('labels', None)
195 self.labels = kwargs.get('labels', None)
195 self.xaxis = kwargs.get('xaxis', 'frequency')
196 self.xaxis = kwargs.get('xaxis', 'frequency')
196 self.zmin = kwargs.get('zmin', None)
197 self.zmin = kwargs.get('zmin', None)
197 self.zmax = kwargs.get('zmax', None)
198 self.zmax = kwargs.get('zmax', None)
198 self.zlimits = kwargs.get('zlimits', None)
199 self.zlimits = kwargs.get('zlimits', None)
199 self.xmin = kwargs.get('xmin', None)
200 self.xmin = kwargs.get('xmin', None)
200 self.xmax = kwargs.get('xmax', None)
201 self.xmax = kwargs.get('xmax', None)
201 self.xrange = kwargs.get('xrange', 24)
202 self.xrange = kwargs.get('xrange', 24)
202 self.xscale = kwargs.get('xscale', None)
203 self.xscale = kwargs.get('xscale', None)
203 self.ymin = kwargs.get('ymin', None)
204 self.ymin = kwargs.get('ymin', None)
204 self.ymax = kwargs.get('ymax', None)
205 self.ymax = kwargs.get('ymax', None)
205 self.yscale = kwargs.get('yscale', None)
206 self.yscale = kwargs.get('yscale', None)
206 self.xlabel = kwargs.get('xlabel', None)
207 self.xlabel = kwargs.get('xlabel', None)
207 self.decimation = kwargs.get('decimation', None)
208 self.decimation = kwargs.get('decimation', None)
208 self.showSNR = kwargs.get('showSNR', False)
209 self.showSNR = kwargs.get('showSNR', False)
209 self.oneFigure = kwargs.get('oneFigure', True)
210 self.oneFigure = kwargs.get('oneFigure', True)
210 self.width = kwargs.get('width', None)
211 self.width = kwargs.get('width', None)
211 self.height = kwargs.get('height', None)
212 self.height = kwargs.get('height', None)
212 self.colorbar = kwargs.get('colorbar', True)
213 self.colorbar = kwargs.get('colorbar', True)
213 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
214 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
214 self.channels = kwargs.get('channels', None)
215 self.channels = kwargs.get('channels', None)
215 self.titles = kwargs.get('titles', [])
216 self.titles = kwargs.get('titles', [])
216 self.polar = False
217 self.polar = False
217 self.type = kwargs.get('type', 'iq')
218 self.type = kwargs.get('type', 'iq')
218 self.grid = kwargs.get('grid', False)
219 self.grid = kwargs.get('grid', False)
219 self.pause = kwargs.get('pause', False)
220 self.pause = kwargs.get('pause', False)
220 self.save_labels = kwargs.get('save_labels', None)
221 self.save_labels = kwargs.get('save_labels', None)
221 self.realtime = kwargs.get('realtime', True)
222 self.realtime = kwargs.get('realtime', True)
222 self.buffering = kwargs.get('buffering', True)
223 self.buffering = kwargs.get('buffering', True)
223 self.throttle = kwargs.get('throttle', 2)
224 self.throttle = kwargs.get('throttle', 2)
224 self.exp_code = kwargs.get('exp_code', None)
225 self.exp_code = kwargs.get('exp_code', None)
225 self.plot_server = kwargs.get('plot_server', False)
226 self.plot_server = kwargs.get('plot_server', False)
226 self.sender_period = kwargs.get('sender_period', 2)
227 self.sender_period = kwargs.get('sender_period', 2)
227 self.__throttle_plot = apply_throttle(self.throttle)
228 self.__throttle_plot = apply_throttle(self.throttle)
228 self.data = PlotterData(
229 self.data = PlotterData(
229 self.CODE, self.throttle, self.exp_code, self.buffering)
230 self.CODE, self.throttle, self.exp_code, self.buffering)
230
231
231 if self.plot_server:
232 if self.plot_server:
232 if not self.plot_server.startswith('tcp://'):
233 if not self.plot_server.startswith('tcp://'):
233 self.plot_server = 'tcp://{}'.format(self.plot_server)
234 self.plot_server = 'tcp://{}'.format(self.plot_server)
234 log.success(
235 log.success(
235 'Sending to server: {}'.format(self.plot_server),
236 'Sending to server: {}'.format(self.plot_server),
236 self.name
237 self.name
237 )
238 )
238
239
239 def __setup_plot(self):
240 def __setup_plot(self):
240 '''
241 '''
241 Common setup for all figures, here figures and axes are created
242 Common setup for all figures, here figures and axes are created
242 '''
243 '''
243
244
244 self.setup()
245 self.setup()
245
246
246 self.time_label = 'LT' if self.localtime else 'UTC'
247 self.time_label = 'LT' if self.localtime else 'UTC'
247 if self.data.localtime:
248 self.getDateTime = datetime.datetime.fromtimestamp
249 else:
250 self.getDateTime = datetime.datetime.utcfromtimestamp
251
248
252 if self.width is None:
249 if self.width is None:
253 self.width = 8
250 self.width = 8
254
251
255 self.figures = []
252 self.figures = []
256 self.axes = []
253 self.axes = []
257 self.cb_axes = []
254 self.cb_axes = []
258 self.pf_axes = []
255 self.pf_axes = []
259 self.cmaps = []
256 self.cmaps = []
260
257
261 size = '15%' if self.ncols == 1 else '30%'
258 size = '15%' if self.ncols == 1 else '30%'
262 pad = '4%' if self.ncols == 1 else '8%'
259 pad = '4%' if self.ncols == 1 else '8%'
263
260
264 if self.oneFigure:
261 if self.oneFigure:
265 if self.height is None:
262 if self.height is None:
266 self.height = 1.4 * self.nrows + 1
263 self.height = 1.4 * self.nrows + 1
267 fig = plt.figure(figsize=(self.width, self.height),
264 fig = plt.figure(figsize=(self.width, self.height),
268 edgecolor='k',
265 edgecolor='k',
269 facecolor='w')
266 facecolor='w')
270 self.figures.append(fig)
267 self.figures.append(fig)
271 for n in range(self.nplots):
268 for n in range(self.nplots):
272 ax = fig.add_subplot(self.nrows, self.ncols,
269 ax = fig.add_subplot(self.nrows, self.ncols,
273 n + 1, polar=self.polar)
270 n + 1, polar=self.polar)
274 ax.tick_params(labelsize=8)
271 ax.tick_params(labelsize=8)
275 ax.firsttime = True
272 ax.firsttime = True
276 ax.index = 0
273 ax.index = 0
277 ax.press = None
274 ax.press = None
278 self.axes.append(ax)
275 self.axes.append(ax)
279 if self.showprofile:
276 if self.showprofile:
280 cax = self.__add_axes(ax, size=size, pad=pad)
277 cax = self.__add_axes(ax, size=size, pad=pad)
281 cax.tick_params(labelsize=8)
278 cax.tick_params(labelsize=8)
282 self.pf_axes.append(cax)
279 self.pf_axes.append(cax)
283 else:
280 else:
284 if self.height is None:
281 if self.height is None:
285 self.height = 3
282 self.height = 3
286 for n in range(self.nplots):
283 for n in range(self.nplots):
287 fig = plt.figure(figsize=(self.width, self.height),
284 fig = plt.figure(figsize=(self.width, self.height),
288 edgecolor='k',
285 edgecolor='k',
289 facecolor='w')
286 facecolor='w')
290 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
287 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
291 ax.tick_params(labelsize=8)
288 ax.tick_params(labelsize=8)
292 ax.firsttime = True
289 ax.firsttime = True
293 ax.index = 0
290 ax.index = 0
294 ax.press = None
291 ax.press = None
295 self.figures.append(fig)
292 self.figures.append(fig)
296 self.axes.append(ax)
293 self.axes.append(ax)
297 if self.showprofile:
294 if self.showprofile:
298 cax = self.__add_axes(ax, size=size, pad=pad)
295 cax = self.__add_axes(ax, size=size, pad=pad)
299 cax.tick_params(labelsize=8)
296 cax.tick_params(labelsize=8)
300 self.pf_axes.append(cax)
297 self.pf_axes.append(cax)
301
298
302 for n in range(self.nrows):
299 for n in range(self.nrows):
303 if self.colormaps is not None:
300 if self.colormaps is not None:
304 cmap = plt.get_cmap(self.colormaps[n])
301 cmap = plt.get_cmap(self.colormaps[n])
305 else:
302 else:
306 cmap = plt.get_cmap(self.colormap)
303 cmap = plt.get_cmap(self.colormap)
307 cmap.set_bad(self.bgcolor, 1.)
304 cmap.set_bad(self.bgcolor, 1.)
308 self.cmaps.append(cmap)
305 self.cmaps.append(cmap)
309
306
310 for fig in self.figures:
307 for fig in self.figures:
311 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
308 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
312 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
309 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
313 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
310 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
314 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
311 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
315 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
312 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
316 if self.show:
313 if self.show:
317 fig.show()
314 fig.show()
318
315
319 def OnKeyPress(self, event):
316 def OnKeyPress(self, event):
320 '''
317 '''
321 Event for pressing keys (up, down) change colormap
318 Event for pressing keys (up, down) change colormap
322 '''
319 '''
323 ax = event.inaxes
320 ax = event.inaxes
324 if ax in self.axes:
321 if ax in self.axes:
325 if event.key == 'down':
322 if event.key == 'down':
326 ax.index += 1
323 ax.index += 1
327 elif event.key == 'up':
324 elif event.key == 'up':
328 ax.index -= 1
325 ax.index -= 1
329 if ax.index < 0:
326 if ax.index < 0:
330 ax.index = len(CMAPS) - 1
327 ax.index = len(CMAPS) - 1
331 elif ax.index == len(CMAPS):
328 elif ax.index == len(CMAPS):
332 ax.index = 0
329 ax.index = 0
333 cmap = CMAPS[ax.index]
330 cmap = CMAPS[ax.index]
334 ax.cbar.set_cmap(cmap)
331 ax.cbar.set_cmap(cmap)
335 ax.cbar.draw_all()
332 ax.cbar.draw_all()
336 ax.plt.set_cmap(cmap)
333 ax.plt.set_cmap(cmap)
337 ax.cbar.patch.figure.canvas.draw()
334 ax.cbar.patch.figure.canvas.draw()
338 self.colormap = cmap.name
335 self.colormap = cmap.name
339
336
340 def OnBtnScroll(self, event):
337 def OnBtnScroll(self, event):
341 '''
338 '''
342 Event for scrolling, scale figure
339 Event for scrolling, scale figure
343 '''
340 '''
344 cb_ax = event.inaxes
341 cb_ax = event.inaxes
345 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
342 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
346 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
343 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
347 pt = ax.cbar.ax.bbox.get_points()[:, 1]
344 pt = ax.cbar.ax.bbox.get_points()[:, 1]
348 nrm = ax.cbar.norm
345 nrm = ax.cbar.norm
349 vmin, vmax, p0, p1, pS = (
346 vmin, vmax, p0, p1, pS = (
350 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
347 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
351 scale = 2 if event.step == 1 else 0.5
348 scale = 2 if event.step == 1 else 0.5
352 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
349 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
353 ax.cbar.norm.vmin = point - scale * (point - vmin)
350 ax.cbar.norm.vmin = point - scale * (point - vmin)
354 ax.cbar.norm.vmax = point - scale * (point - vmax)
351 ax.cbar.norm.vmax = point - scale * (point - vmax)
355 ax.plt.set_norm(ax.cbar.norm)
352 ax.plt.set_norm(ax.cbar.norm)
356 ax.cbar.draw_all()
353 ax.cbar.draw_all()
357 ax.cbar.patch.figure.canvas.draw()
354 ax.cbar.patch.figure.canvas.draw()
358
355
359 def onBtnPress(self, event):
356 def onBtnPress(self, event):
360 '''
357 '''
361 Event for mouse button press
358 Event for mouse button press
362 '''
359 '''
363 cb_ax = event.inaxes
360 cb_ax = event.inaxes
364 if cb_ax is None:
361 if cb_ax is None:
365 return
362 return
366
363
367 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
364 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
368 cb_ax.press = event.x, event.y
365 cb_ax.press = event.x, event.y
369 else:
366 else:
370 cb_ax.press = None
367 cb_ax.press = None
371
368
372 def onMotion(self, event):
369 def onMotion(self, event):
373 '''
370 '''
374 Event for move inside colorbar
371 Event for move inside colorbar
375 '''
372 '''
376 cb_ax = event.inaxes
373 cb_ax = event.inaxes
377 if cb_ax is None:
374 if cb_ax is None:
378 return
375 return
379 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
376 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
380 return
377 return
381 if cb_ax.press is None:
378 if cb_ax.press is None:
382 return
379 return
383
380
384 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
381 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
385 xprev, yprev = cb_ax.press
382 xprev, yprev = cb_ax.press
386 dx = event.x - xprev
383 dx = event.x - xprev
387 dy = event.y - yprev
384 dy = event.y - yprev
388 cb_ax.press = event.x, event.y
385 cb_ax.press = event.x, event.y
389 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
386 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
390 perc = 0.03
387 perc = 0.03
391
388
392 if event.button == 1:
389 if event.button == 1:
393 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
390 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
394 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
391 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
395 elif event.button == 3:
392 elif event.button == 3:
396 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
393 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
397 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
394 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
398
395
399 ax.cbar.draw_all()
396 ax.cbar.draw_all()
400 ax.plt.set_norm(ax.cbar.norm)
397 ax.plt.set_norm(ax.cbar.norm)
401 ax.cbar.patch.figure.canvas.draw()
398 ax.cbar.patch.figure.canvas.draw()
402
399
403 def onBtnRelease(self, event):
400 def onBtnRelease(self, event):
404 '''
401 '''
405 Event for mouse button release
402 Event for mouse button release
406 '''
403 '''
407 cb_ax = event.inaxes
404 cb_ax = event.inaxes
408 if cb_ax is not None:
405 if cb_ax is not None:
409 cb_ax.press = None
406 cb_ax.press = None
410
407
411 def __add_axes(self, ax, size='30%', pad='8%'):
408 def __add_axes(self, ax, size='30%', pad='8%'):
412 '''
409 '''
413 Add new axes to the given figure
410 Add new axes to the given figure
414 '''
411 '''
415 divider = make_axes_locatable(ax)
412 divider = make_axes_locatable(ax)
416 nax = divider.new_horizontal(size=size, pad=pad)
413 nax = divider.new_horizontal(size=size, pad=pad)
417 ax.figure.add_axes(nax)
414 ax.figure.add_axes(nax)
418 return nax
415 return nax
419
416
420 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
417 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
421 '''
418 '''
422 Create a masked array for missing data
419 Create a masked array for missing data
423 '''
420 '''
424 if x_buffer.shape[0] < 2:
421 if x_buffer.shape[0] < 2:
425 return x_buffer, y_buffer, z_buffer
422 return x_buffer, y_buffer, z_buffer
426
423
427 deltas = x_buffer[1:] - x_buffer[0:-1]
424 deltas = x_buffer[1:] - x_buffer[0:-1]
428 x_median = numpy.median(deltas)
425 x_median = numpy.median(deltas)
429
426
430 index = numpy.where(deltas > 5 * x_median)
427 index = numpy.where(deltas > 5 * x_median)
431
428
432 if len(index[0]) != 0:
429 if len(index[0]) != 0:
433 z_buffer[::, index[0], ::] = self.__missing
430 z_buffer[::, index[0], ::] = self.__missing
434 z_buffer = numpy.ma.masked_inside(z_buffer,
431 z_buffer = numpy.ma.masked_inside(z_buffer,
435 0.99 * self.__missing,
432 0.99 * self.__missing,
436 1.01 * self.__missing)
433 1.01 * self.__missing)
437
434
438 return x_buffer, y_buffer, z_buffer
435 return x_buffer, y_buffer, z_buffer
439
436
440 def decimate(self):
437 def decimate(self):
441
438
442 # dx = int(len(self.x)/self.__MAXNUMX) + 1
439 # dx = int(len(self.x)/self.__MAXNUMX) + 1
443 dy = int(len(self.y) / self.decimation) + 1
440 dy = int(len(self.y) / self.decimation) + 1
444
441
445 # x = self.x[::dx]
442 # x = self.x[::dx]
446 x = self.x
443 x = self.x
447 y = self.y[::dy]
444 y = self.y[::dy]
448 z = self.z[::, ::, ::dy]
445 z = self.z[::, ::, ::dy]
449
446
450 return x, y, z
447 return x, y, z
451
448
452 def format(self):
449 def format(self):
453 '''
450 '''
454 Set min and max values, labels, ticks and titles
451 Set min and max values, labels, ticks and titles
455 '''
452 '''
456
453
457 if self.xmin is None:
454 if self.xmin is None:
458 xmin = self.data.min_time
455 xmin = self.data.min_time
459 else:
456 else:
460 if self.xaxis is 'time':
457 if self.xaxis is 'time':
461 dt = self.getDateTime(self.data.min_time)
458 dt = self.getDateTime(self.data.min_time)
462 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
459 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
463 datetime.datetime(1970, 1, 1)).total_seconds()
460 datetime.datetime(1970, 1, 1)).total_seconds()
464 if self.data.localtime:
461 if self.data.localtime:
465 xmin += time.timezone
462 xmin += time.timezone
466 else:
463 else:
467 xmin = self.xmin
464 xmin = self.xmin
468
465
469 if self.xmax is None:
466 if self.xmax is None:
470 xmax = xmin + self.xrange * 60 * 60
467 xmax = xmin + self.xrange * 60 * 60
471 else:
468 else:
472 if self.xaxis is 'time':
469 if self.xaxis is 'time':
473 dt = self.getDateTime(self.data.max_time)
470 dt = self.getDateTime(self.data.max_time)
474 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
471 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
475 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
472 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
476 if self.data.localtime:
473 if self.data.localtime:
477 xmax += time.timezone
474 xmax += time.timezone
478 else:
475 else:
479 xmax = self.xmax
476 xmax = self.xmax
480
477
481 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
478 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
482 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
479 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
483 #Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000])
480 #Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000])
484
481
485 #i = 1 if numpy.where(
482 #i = 1 if numpy.where(
486 # abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
483 # abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
487 #ystep = Y[i] / 10.
484 #ystep = Y[i] / 10.
488 dig = int(numpy.log10(ymax))
485 dig = int(numpy.log10(ymax))
489 if dig == 0:
486 if dig == 0:
490 digD = len(str(ymax)) - 2
487 digD = len(str(ymax)) - 2
491 ydec = ymax*(10**digD)
488 ydec = ymax*(10**digD)
492
489
493 dig = int(numpy.log10(ydec))
490 dig = int(numpy.log10(ydec))
494 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
491 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
495 ystep = ystep/5
492 ystep = ystep/5
496 ystep = ystep/(10**digD)
493 ystep = ystep/(10**digD)
497
494
498 else:
495 else:
499 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
496 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
500 ystep = ystep/5
497 ystep = ystep/5
501
498
502 if self.xaxis is not 'time':
499 if self.xaxis is not 'time':
503
500
504 dig = int(numpy.log10(xmax))
501 dig = int(numpy.log10(xmax))
505
502
506 if dig <= 0:
503 if dig <= 0:
507 digD = len(str(xmax)) - 2
504 digD = len(str(xmax)) - 2
508 xdec = xmax*(10**digD)
505 xdec = xmax*(10**digD)
509
506
510 dig = int(numpy.log10(xdec))
507 dig = int(numpy.log10(xdec))
511 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
508 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
512 xstep = xstep*0.5
509 xstep = xstep*0.5
513 xstep = xstep/(10**digD)
510 xstep = xstep/(10**digD)
514
511
515 else:
512 else:
516 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
513 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
517 xstep = xstep/5
514 xstep = xstep/5
518
515
519 for n, ax in enumerate(self.axes):
516 for n, ax in enumerate(self.axes):
520 if ax.firsttime:
517 if ax.firsttime:
521 ax.set_facecolor(self.bgcolor)
518 ax.set_facecolor(self.bgcolor)
522 ax.yaxis.set_major_locator(MultipleLocator(ystep))
519 ax.yaxis.set_major_locator(MultipleLocator(ystep))
523 if self.xscale:
520 if self.xscale:
524 ax.xaxis.set_major_formatter(FuncFormatter(
521 ax.xaxis.set_major_formatter(FuncFormatter(
525 lambda x, pos: '{0:g}'.format(x*self.xscale)))
522 lambda x, pos: '{0:g}'.format(x*self.xscale)))
526 if self.xscale:
523 if self.xscale:
527 ax.yaxis.set_major_formatter(FuncFormatter(
524 ax.yaxis.set_major_formatter(FuncFormatter(
528 lambda x, pos: '{0:g}'.format(x*self.yscale)))
525 lambda x, pos: '{0:g}'.format(x*self.yscale)))
529 if self.xaxis is 'time':
526 if self.xaxis is 'time':
530 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
527 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
531 ax.xaxis.set_major_locator(LinearLocator(9))
528 ax.xaxis.set_major_locator(LinearLocator(9))
532 else:
529 else:
533 ax.xaxis.set_major_locator(MultipleLocator(xstep))
530 ax.xaxis.set_major_locator(MultipleLocator(xstep))
534 if self.xlabel is not None:
531 if self.xlabel is not None:
535 ax.set_xlabel(self.xlabel)
532 ax.set_xlabel(self.xlabel)
536 ax.set_ylabel(self.ylabel)
533 ax.set_ylabel(self.ylabel)
537 ax.firsttime = False
534 ax.firsttime = False
538 if self.showprofile:
535 if self.showprofile:
539 self.pf_axes[n].set_ylim(ymin, ymax)
536 self.pf_axes[n].set_ylim(ymin, ymax)
540 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
537 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
541 self.pf_axes[n].set_xlabel('dB')
538 self.pf_axes[n].set_xlabel('dB')
542 self.pf_axes[n].grid(b=True, axis='x')
539 self.pf_axes[n].grid(b=True, axis='x')
543 [tick.set_visible(False)
540 [tick.set_visible(False)
544 for tick in self.pf_axes[n].get_yticklabels()]
541 for tick in self.pf_axes[n].get_yticklabels()]
545 if self.colorbar:
542 if self.colorbar:
546 ax.cbar = plt.colorbar(
543 ax.cbar = plt.colorbar(
547 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
544 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
548 ax.cbar.ax.tick_params(labelsize=8)
545 ax.cbar.ax.tick_params(labelsize=8)
549 ax.cbar.ax.press = None
546 ax.cbar.ax.press = None
550 if self.cb_label:
547 if self.cb_label:
551 ax.cbar.set_label(self.cb_label, size=8)
548 ax.cbar.set_label(self.cb_label, size=8)
552 elif self.cb_labels:
549 elif self.cb_labels:
553 ax.cbar.set_label(self.cb_labels[n], size=8)
550 ax.cbar.set_label(self.cb_labels[n], size=8)
554 else:
551 else:
555 ax.cbar = None
552 ax.cbar = None
556 if self.grid:
553 if self.grid:
557 ax.grid(True)
554 ax.grid(True)
558
555
559 if not self.polar:
556 if not self.polar:
560 ax.set_xlim(xmin, xmax)
557 ax.set_xlim(xmin, xmax)
561 ax.set_ylim(ymin, ymax)
558 ax.set_ylim(ymin, ymax)
562 ax.set_title('{} {} {}'.format(
559 ax.set_title('{} {} {}'.format(
563 self.titles[n],
560 self.titles[n],
564 self.getDateTime(self.data.max_time).strftime(
561 self.getDateTime(self.data.max_time).strftime(
565 '%Y-%m-%d %H:%M:%S'),
562 '%Y-%m-%d %H:%M:%S'),
566 self.time_label),
563 self.time_label),
567 size=8)
564 size=8)
568 else:
565 else:
569 ax.set_title('{}'.format(self.titles[n]), size=8)
566 ax.set_title('{}'.format(self.titles[n]), size=8)
570 ax.set_ylim(0, 90)
567 ax.set_ylim(0, 90)
571 ax.set_yticks(numpy.arange(0, 90, 20))
568 ax.set_yticks(numpy.arange(0, 90, 20))
572 ax.yaxis.labelpad = 40
569 ax.yaxis.labelpad = 40
573
570
574 def clear_figures(self):
571 def clear_figures(self):
575 '''
572 '''
576 Reset axes for redraw plots
573 Reset axes for redraw plots
577 '''
574 '''
578
575
579 for ax in self.axes:
576 for ax in self.axes:
580 ax.clear()
577 ax.clear()
581 ax.firsttime = True
578 ax.firsttime = True
582 if ax.cbar:
579 if ax.cbar:
583 ax.cbar.remove()
580 ax.cbar.remove()
584
581
585 def __plot(self):
582 def __plot(self):
586 '''
583 '''
587 Main function to plot, format and save figures
584 Main function to plot, format and save figures
588 '''
585 '''
589
586
590 try:
587 try:
591 self.plot()
588 self.plot()
592 self.format()
589 self.format()
593 except Exception as e:
590 except Exception as e:
594 log.warning('{} Plot could not be updated... check data'.format(
591 log.warning('{} Plot could not be updated... check data'.format(
595 self.CODE), self.name)
592 self.CODE), self.name)
596 log.error(str(e), '')
593 log.error(str(e), '')
597 return
594 return
598
595
599 for n, fig in enumerate(self.figures):
596 for n, fig in enumerate(self.figures):
600 if self.nrows == 0 or self.nplots == 0:
597 if self.nrows == 0 or self.nplots == 0:
601 log.warning('No data', self.name)
598 log.warning('No data', self.name)
602 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
599 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
603 fig.canvas.manager.set_window_title(self.CODE)
600 fig.canvas.manager.set_window_title(self.CODE)
604 continue
601 continue
605
602
606 fig.tight_layout()
603 fig.tight_layout()
607 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
604 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
608 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
605 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
609 fig.canvas.draw()
606 fig.canvas.draw()
610
607
611 if self.save:
608 if self.save:
612 self.save_figure(n)
609 self.save_figure(n)
613
610
614 if self.plot_server:
611 if self.plot_server:
615 self.send_to_server()
612 self.send_to_server()
616 # t = Thread(target=self.send_to_server)
613 # t = Thread(target=self.send_to_server)
617 # t.start()
614 # 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
672
676 self.sender_counter = 1
673 self.sender_counter = 1
677
674
678 retries = 2
675 retries = 2
679 while True:
676 while True:
680 self.socket.send_string(self.data.jsonify())
677 self.socket.send_string(self.data.jsonify())
681 socks = dict(self.poll.poll(5000))
678 socks = dict(self.poll.poll(5000))
682 if socks.get(self.socket) == zmq.POLLIN:
679 if socks.get(self.socket) == zmq.POLLIN:
683 reply = self.socket.recv_string()
680 reply = self.socket.recv_string()
684 if reply == 'ok':
681 if reply == 'ok':
685 log.log("Response from server ok", self.name)
682 log.log("Response from server ok", self.name)
686 break
683 break
687 else:
684 else:
688 log.warning(
685 log.warning(
689 "Malformed reply from server: {}".format(reply), self.name)
686 "Malformed reply from server: {}".format(reply), self.name)
690
687
691 else:
688 else:
692 log.warning(
689 log.warning(
693 "No response from server, retrying...", self.name)
690 "No response from server, retrying...", self.name)
694 self.socket.setsockopt(zmq.LINGER, 0)
691 self.socket.setsockopt(zmq.LINGER, 0)
695 self.socket.close()
692 self.socket.close()
696 self.poll.unregister(self.socket)
693 self.poll.unregister(self.socket)
697 retries -= 1
694 retries -= 1
698 if retries == 0:
695 if retries == 0:
699 log.error(
696 log.error(
700 "Server seems to be offline, abandoning", self.name)
697 "Server seems to be offline, abandoning", self.name)
701 self.socket = self.context.socket(zmq.REQ)
698 self.socket = self.context.socket(zmq.REQ)
702 self.socket.connect(self.plot_server)
699 self.socket.connect(self.plot_server)
703 self.poll.register(self.socket, zmq.POLLIN)
700 self.poll.register(self.socket, zmq.POLLIN)
704 time.sleep(1)
701 time.sleep(1)
705 break
702 break
706 self.socket = self.context.socket(zmq.REQ)
703 self.socket = self.context.socket(zmq.REQ)
707 self.socket.connect(self.plot_server)
704 self.socket.connect(self.plot_server)
708 self.poll.register(self.socket, zmq.POLLIN)
705 self.poll.register(self.socket, zmq.POLLIN)
709 time.sleep(0.5)
706 time.sleep(0.5)
710
707
711 def setup(self):
708 def setup(self):
712 '''
709 '''
713 This method should be implemented in the child class, the following
710 This method should be implemented in the child class, the following
714 attributes should be set:
711 attributes should be set:
715
712
716 self.nrows: number of rows
713 self.nrows: number of rows
717 self.ncols: number of cols
714 self.ncols: number of cols
718 self.nplots: number of plots (channels or pairs)
715 self.nplots: number of plots (channels or pairs)
719 self.ylabel: label for Y axes
716 self.ylabel: label for Y axes
720 self.titles: list of axes title
717 self.titles: list of axes title
721
718
722 '''
719 '''
723 raise NotImplementedError
720 raise NotImplementedError
724
721
725 def plot(self):
722 def plot(self):
726 '''
723 '''
727 Must be defined in the child class
724 Must be defined in the child class
728 '''
725 '''
729 raise NotImplementedError
726 raise NotImplementedError
730
727
731 def run(self, dataOut, **kwargs):
728 def run(self, dataOut, **kwargs):
732
729 '''
733 if dataOut.error:
730 Main plotting routine
734 coerce = True
731 '''
735 else:
736 coerce = False
737
732
738 if self.isConfig is False:
733 if self.isConfig is False:
739 self.__setup(**kwargs)
734 self.__setup(**kwargs)
740 if dataOut.type == 'Parameters':
735 if dataOut.type == 'Parameters':
741 self.tmin = dataOut.utctimeInit
736 t = dataOut.utctimeInit
742 else:
737 else:
743 self.tmin = dataOut.utctime
738 t = dataOut.utctime
744
739
745 if dataOut.useLocalTime:
740 if dataOut.useLocalTime:
746 if not self.localtime:
741 self.getDateTime = datetime.datetime.fromtimestamp
747 self.tmin += time.timezone
748 else:
742 else:
749 if self.localtime:
743 self.getDateTime = datetime.datetime.utcfromtimestamp
750 self.tmin -= time.timezone
744
745 if self.xmin is None:
746 self.tmin = t
747 else:
748 self.tmin = (self.getDateTime(t).replace(hour=self.xmin, minute=0, second=0) - datetime.datetime(1970, 1, 1)).total_seconds()
749
751 self.data.setup()
750 self.data.setup()
752 self.isConfig = True
751 self.isConfig = True
753 if self.plot_server:
752 if self.plot_server:
754 self.context = zmq.Context()
753 self.context = zmq.Context()
755 self.socket = self.context.socket(zmq.REQ)
754 self.socket = self.context.socket(zmq.REQ)
756 self.socket.connect(self.plot_server)
755 self.socket.connect(self.plot_server)
757 self.poll = zmq.Poller()
756 self.poll = zmq.Poller()
758 self.poll.register(self.socket, zmq.POLLIN)
757 self.poll.register(self.socket, zmq.POLLIN)
759
758
760 if dataOut.type == 'Parameters':
759 if dataOut.type == 'Parameters':
761 tm = dataOut.utctimeInit
760 tm = dataOut.utctimeInit
762 else:
761 else:
763 tm = dataOut.utctime
762 tm = dataOut.utctime
764
763
765 if dataOut.useLocalTime:
764 if not dataOut.useLocalTime and self.localtime:
766 if not self.localtime:
767 tm += time.timezone
768 else:
769 if self.localtime:
770 tm -= time.timezone
765 tm -= time.timezone
766 if dataOut.useLocalTime and not self.localtime:
767 tm += time.timezone
771
768
772 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
769 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
773 self.save_counter = self.save_period
770 self.save_counter = self.save_period
774 self.__plot()
771 self.__plot()
775 self.xmin += self.xrange
772 self.xmin += self.xrange
776 if self.xmin >= 24:
773 if self.xmin >= 24:
777 self.xmin -= 24
774 self.xmin -= 24
778 self.tmin += self.xrange*60*60
775 self.tmin += self.xrange*60*60
779 self.data.setup()
776 self.data.setup()
780 self.clear_figures()
777 self.clear_figures()
781
778
782 self.data.update(dataOut, tm)
779 self.data.update(dataOut, tm)
783
780
784 if self.isPlotConfig is False:
781 if self.isPlotConfig is False:
785 self.__setup_plot()
782 self.__setup_plot()
786 self.isPlotConfig = True
783 self.isPlotConfig = True
787
784
788 if self.realtime:
785 if self.realtime:
789 self.__plot()
786 self.__plot()
790 else:
787 else:
791 self.__throttle_plot(self.__plot, coerce=coerce)
788 self.__throttle_plot(self.__plot)#, coerce=coerce)
792
789
793 figpause(0.01)
790 figpause(0.01)
794
791
795 def close(self):
792 def close(self):
796
793
797 if self.data:
794 if self.data:
798 self.save_counter = self.save_period
795 self.save_counter = self.save_period
799 self.__plot()
796 self.__plot()
800 if self.data and self.pause:
797 if self.data and self.pause:
801 figpause(10)
798 figpause(10)
802
799
General Comments 0
You need to be logged in to leave comments. Login now