##// END OF EJS Templates
Update interval in send to server
Juan C. Espinoza -
r1301:fc107a2679d3
parent child
Show More
@@ -1,703 +1,704
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 buffering = True
151 buffering = True
152 __missing = 1E30
152 __missing = 1E30
153
153
154 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
154 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
155 'showprofile']
155 'showprofile']
156
156
157 def __init__(self):
157 def __init__(self):
158
158
159 Operation.__init__(self)
159 Operation.__init__(self)
160 self.isConfig = False
160 self.isConfig = False
161 self.isPlotConfig = False
161 self.isPlotConfig = False
162 self.save_counter = 1
162 self.save_counter = 1
163 self.sender_time = 0
163 self.sender_time = 0
164 self.data = None
164 self.data = None
165 self.firsttime = True
165 self.firsttime = True
166 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
166 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
167
167
168 def __fmtTime(self, x, pos):
168 def __fmtTime(self, x, pos):
169 '''
169 '''
170 '''
170 '''
171
171
172 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
172 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
173
173
174 def __setup(self, **kwargs):
174 def __setup(self, **kwargs):
175 '''
175 '''
176 Initialize variables
176 Initialize variables
177 '''
177 '''
178
178
179 self.figures = []
179 self.figures = []
180 self.axes = []
180 self.axes = []
181 self.cb_axes = []
181 self.cb_axes = []
182 self.localtime = kwargs.pop('localtime', True)
182 self.localtime = kwargs.pop('localtime', True)
183 self.show = kwargs.get('show', True)
183 self.show = kwargs.get('show', True)
184 self.save = kwargs.get('save', False)
184 self.save = kwargs.get('save', False)
185 self.save_period = kwargs.get('save_period', 1)
185 self.save_period = kwargs.get('save_period', 1)
186 self.ftp = kwargs.get('ftp', False)
186 self.ftp = kwargs.get('ftp', False)
187 self.colormap = kwargs.get('colormap', self.colormap)
187 self.colormap = kwargs.get('colormap', self.colormap)
188 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
188 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
189 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
189 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
190 self.colormaps = kwargs.get('colormaps', None)
190 self.colormaps = kwargs.get('colormaps', None)
191 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
191 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
192 self.showprofile = kwargs.get('showprofile', False)
192 self.showprofile = kwargs.get('showprofile', False)
193 self.title = kwargs.get('wintitle', self.CODE.upper())
193 self.title = kwargs.get('wintitle', self.CODE.upper())
194 self.cb_label = kwargs.get('cb_label', None)
194 self.cb_label = kwargs.get('cb_label', None)
195 self.cb_labels = kwargs.get('cb_labels', None)
195 self.cb_labels = kwargs.get('cb_labels', None)
196 self.labels = kwargs.get('labels', None)
196 self.labels = kwargs.get('labels', None)
197 self.xaxis = kwargs.get('xaxis', 'frequency')
197 self.xaxis = kwargs.get('xaxis', 'frequency')
198 self.zmin = kwargs.get('zmin', None)
198 self.zmin = kwargs.get('zmin', None)
199 self.zmax = kwargs.get('zmax', None)
199 self.zmax = kwargs.get('zmax', None)
200 self.zlimits = kwargs.get('zlimits', None)
200 self.zlimits = kwargs.get('zlimits', None)
201 self.xmin = kwargs.get('xmin', None)
201 self.xmin = kwargs.get('xmin', None)
202 self.xmax = kwargs.get('xmax', None)
202 self.xmax = kwargs.get('xmax', None)
203 self.xrange = kwargs.get('xrange', 24)
203 self.xrange = kwargs.get('xrange', 24)
204 self.xscale = kwargs.get('xscale', None)
204 self.xscale = kwargs.get('xscale', None)
205 self.ymin = kwargs.get('ymin', None)
205 self.ymin = kwargs.get('ymin', None)
206 self.ymax = kwargs.get('ymax', None)
206 self.ymax = kwargs.get('ymax', None)
207 self.yscale = kwargs.get('yscale', None)
207 self.yscale = kwargs.get('yscale', None)
208 self.xlabel = kwargs.get('xlabel', None)
208 self.xlabel = kwargs.get('xlabel', None)
209 self.attr_time = kwargs.get('attr_time', 'utctime')
209 self.attr_time = kwargs.get('attr_time', 'utctime')
210 self.decimation = kwargs.get('decimation', None)
210 self.decimation = kwargs.get('decimation', None)
211 self.showSNR = kwargs.get('showSNR', False)
211 self.showSNR = kwargs.get('showSNR', False)
212 self.oneFigure = kwargs.get('oneFigure', True)
212 self.oneFigure = kwargs.get('oneFigure', True)
213 self.width = kwargs.get('width', None)
213 self.width = kwargs.get('width', None)
214 self.height = kwargs.get('height', None)
214 self.height = kwargs.get('height', None)
215 self.colorbar = kwargs.get('colorbar', True)
215 self.colorbar = kwargs.get('colorbar', True)
216 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
216 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
217 self.channels = kwargs.get('channels', None)
217 self.channels = kwargs.get('channels', None)
218 self.titles = kwargs.get('titles', [])
218 self.titles = kwargs.get('titles', [])
219 self.polar = False
219 self.polar = False
220 self.type = kwargs.get('type', 'iq')
220 self.type = kwargs.get('type', 'iq')
221 self.grid = kwargs.get('grid', False)
221 self.grid = kwargs.get('grid', False)
222 self.pause = kwargs.get('pause', False)
222 self.pause = kwargs.get('pause', False)
223 self.save_code = kwargs.get('save_code', None)
223 self.save_code = kwargs.get('save_code', None)
224 self.realtime = kwargs.get('realtime', True)
224 self.realtime = kwargs.get('realtime', True)
225 self.throttle = kwargs.get('throttle', 0)
225 self.throttle = kwargs.get('throttle', 0)
226 self.exp_code = kwargs.get('exp_code', None)
226 self.exp_code = kwargs.get('exp_code', None)
227 self.plot_server = kwargs.get('plot_server', False)
227 self.plot_server = kwargs.get('plot_server', False)
228 self.sender_period = kwargs.get('sender_period', 60)
228 self.sender_period = kwargs.get('sender_period', 60)
229 self.height_index = kwargs.get('height_index', None)
229 self.height_index = kwargs.get('height_index', None)
230 self.__throttle_plot = apply_throttle(self.throttle)
230 self.__throttle_plot = apply_throttle(self.throttle)
231 self.data = PlotterData(
231 self.data = PlotterData(
232 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
232 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
233
233
234 if self.plot_server:
234 if self.plot_server:
235 if not self.plot_server.startswith('tcp://'):
235 if not self.plot_server.startswith('tcp://'):
236 self.plot_server = 'tcp://{}'.format(self.plot_server)
236 self.plot_server = 'tcp://{}'.format(self.plot_server)
237 log.success(
237 log.success(
238 'Sending to server: {}'.format(self.plot_server),
238 'Sending to server: {}'.format(self.plot_server),
239 self.name
239 self.name
240 )
240 )
241 if 'plot_name' in kwargs:
241 if 'plot_name' in kwargs:
242 self.plot_name = kwargs['plot_name']
242 self.plot_name = kwargs['plot_name']
243
243
244 def __setup_plot(self):
244 def __setup_plot(self):
245 '''
245 '''
246 Common setup for all figures, here figures and axes are created
246 Common setup for all figures, here figures and axes are created
247 '''
247 '''
248
248
249 self.setup()
249 self.setup()
250
250
251 self.time_label = 'LT' if self.localtime else 'UTC'
251 self.time_label = 'LT' if self.localtime else 'UTC'
252
252
253 if self.width is None:
253 if self.width is None:
254 self.width = 8
254 self.width = 8
255
255
256 self.figures = []
256 self.figures = []
257 self.axes = []
257 self.axes = []
258 self.cb_axes = []
258 self.cb_axes = []
259 self.pf_axes = []
259 self.pf_axes = []
260 self.cmaps = []
260 self.cmaps = []
261
261
262 size = '15%' if self.ncols == 1 else '30%'
262 size = '15%' if self.ncols == 1 else '30%'
263 pad = '4%' if self.ncols == 1 else '8%'
263 pad = '4%' if self.ncols == 1 else '8%'
264
264
265 if self.oneFigure:
265 if self.oneFigure:
266 if self.height is None:
266 if self.height is None:
267 self.height = 1.4 * self.nrows + 1
267 self.height = 1.4 * self.nrows + 1
268 fig = plt.figure(figsize=(self.width, self.height),
268 fig = plt.figure(figsize=(self.width, self.height),
269 edgecolor='k',
269 edgecolor='k',
270 facecolor='w')
270 facecolor='w')
271 self.figures.append(fig)
271 self.figures.append(fig)
272 for n in range(self.nplots):
272 for n in range(self.nplots):
273 ax = fig.add_subplot(self.nrows, self.ncols,
273 ax = fig.add_subplot(self.nrows, self.ncols,
274 n + 1, polar=self.polar)
274 n + 1, polar=self.polar)
275 ax.tick_params(labelsize=8)
275 ax.tick_params(labelsize=8)
276 ax.firsttime = True
276 ax.firsttime = True
277 ax.index = 0
277 ax.index = 0
278 ax.press = None
278 ax.press = None
279 self.axes.append(ax)
279 self.axes.append(ax)
280 if self.showprofile:
280 if self.showprofile:
281 cax = self.__add_axes(ax, size=size, pad=pad)
281 cax = self.__add_axes(ax, size=size, pad=pad)
282 cax.tick_params(labelsize=8)
282 cax.tick_params(labelsize=8)
283 self.pf_axes.append(cax)
283 self.pf_axes.append(cax)
284 else:
284 else:
285 if self.height is None:
285 if self.height is None:
286 self.height = 3
286 self.height = 3
287 for n in range(self.nplots):
287 for n in range(self.nplots):
288 fig = plt.figure(figsize=(self.width, self.height),
288 fig = plt.figure(figsize=(self.width, self.height),
289 edgecolor='k',
289 edgecolor='k',
290 facecolor='w')
290 facecolor='w')
291 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
291 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
292 ax.tick_params(labelsize=8)
292 ax.tick_params(labelsize=8)
293 ax.firsttime = True
293 ax.firsttime = True
294 ax.index = 0
294 ax.index = 0
295 ax.press = None
295 ax.press = None
296 self.figures.append(fig)
296 self.figures.append(fig)
297 self.axes.append(ax)
297 self.axes.append(ax)
298 if self.showprofile:
298 if self.showprofile:
299 cax = self.__add_axes(ax, size=size, pad=pad)
299 cax = self.__add_axes(ax, size=size, pad=pad)
300 cax.tick_params(labelsize=8)
300 cax.tick_params(labelsize=8)
301 self.pf_axes.append(cax)
301 self.pf_axes.append(cax)
302
302
303 for n in range(self.nrows):
303 for n in range(self.nrows):
304 if self.colormaps is not None:
304 if self.colormaps is not None:
305 cmap = plt.get_cmap(self.colormaps[n])
305 cmap = plt.get_cmap(self.colormaps[n])
306 else:
306 else:
307 cmap = plt.get_cmap(self.colormap)
307 cmap = plt.get_cmap(self.colormap)
308 cmap.set_bad(self.bgcolor, 1.)
308 cmap.set_bad(self.bgcolor, 1.)
309 self.cmaps.append(cmap)
309 self.cmaps.append(cmap)
310
310
311 def __add_axes(self, ax, size='30%', pad='8%'):
311 def __add_axes(self, ax, size='30%', pad='8%'):
312 '''
312 '''
313 Add new axes to the given figure
313 Add new axes to the given figure
314 '''
314 '''
315 divider = make_axes_locatable(ax)
315 divider = make_axes_locatable(ax)
316 nax = divider.new_horizontal(size=size, pad=pad)
316 nax = divider.new_horizontal(size=size, pad=pad)
317 ax.figure.add_axes(nax)
317 ax.figure.add_axes(nax)
318 return nax
318 return nax
319
319
320 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
320 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
321 '''
321 '''
322 Create a masked array for missing data
322 Create a masked array for missing data
323 '''
323 '''
324 if x_buffer.shape[0] < 2:
324 if x_buffer.shape[0] < 2:
325 return x_buffer, y_buffer, z_buffer
325 return x_buffer, y_buffer, z_buffer
326
326
327 deltas = x_buffer[1:] - x_buffer[0:-1]
327 deltas = x_buffer[1:] - x_buffer[0:-1]
328 x_median = numpy.median(deltas)
328 x_median = numpy.median(deltas)
329
329
330 index = numpy.where(deltas > 5 * x_median)
330 index = numpy.where(deltas > 5 * x_median)
331
331
332 if len(index[0]) != 0:
332 if len(index[0]) != 0:
333 z_buffer[::, index[0], ::] = self.__missing
333 z_buffer[::, index[0], ::] = self.__missing
334 z_buffer = numpy.ma.masked_inside(z_buffer,
334 z_buffer = numpy.ma.masked_inside(z_buffer,
335 0.99 * self.__missing,
335 0.99 * self.__missing,
336 1.01 * self.__missing)
336 1.01 * self.__missing)
337
337
338 return x_buffer, y_buffer, z_buffer
338 return x_buffer, y_buffer, z_buffer
339
339
340 def decimate(self):
340 def decimate(self):
341
341
342 # dx = int(len(self.x)/self.__MAXNUMX) + 1
342 # dx = int(len(self.x)/self.__MAXNUMX) + 1
343 dy = int(len(self.y) / self.decimation) + 1
343 dy = int(len(self.y) / self.decimation) + 1
344
344
345 # x = self.x[::dx]
345 # x = self.x[::dx]
346 x = self.x
346 x = self.x
347 y = self.y[::dy]
347 y = self.y[::dy]
348 z = self.z[::, ::, ::dy]
348 z = self.z[::, ::, ::dy]
349
349
350 return x, y, z
350 return x, y, z
351
351
352 def format(self):
352 def format(self):
353 '''
353 '''
354 Set min and max values, labels, ticks and titles
354 Set min and max values, labels, ticks and titles
355 '''
355 '''
356
356
357 if self.xmin is None:
357 if self.xmin is None:
358 xmin = self.data.min_time
358 xmin = self.data.min_time
359 else:
359 else:
360 if self.xaxis is 'time':
360 if self.xaxis is 'time':
361 dt = self.getDateTime(self.data.min_time)
361 dt = self.getDateTime(self.data.min_time)
362 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
362 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
363 datetime.datetime(1970, 1, 1)).total_seconds()
363 datetime.datetime(1970, 1, 1)).total_seconds()
364 if self.data.localtime:
364 if self.data.localtime:
365 xmin += time.timezone
365 xmin += time.timezone
366 else:
366 else:
367 xmin = self.xmin
367 xmin = self.xmin
368
368
369 if self.xmax is None:
369 if self.xmax is None:
370 xmax = xmin + self.xrange * 60 * 60
370 xmax = xmin + self.xrange * 60 * 60
371 else:
371 else:
372 if self.xaxis is 'time':
372 if self.xaxis is 'time':
373 dt = self.getDateTime(self.data.max_time)
373 dt = self.getDateTime(self.data.max_time)
374 xmax = self.xmax - 1
374 xmax = self.xmax - 1
375 xmax = (dt.replace(hour=int(xmax), minute=59, second=59) -
375 xmax = (dt.replace(hour=int(xmax), minute=59, second=59) -
376 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
376 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
377 if self.data.localtime:
377 if self.data.localtime:
378 xmax += time.timezone
378 xmax += time.timezone
379 else:
379 else:
380 xmax = self.xmax
380 xmax = self.xmax
381
381
382 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
382 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
383 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
383 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
384
384
385 for n, ax in enumerate(self.axes):
385 for n, ax in enumerate(self.axes):
386 if ax.firsttime:
386 if ax.firsttime:
387
387
388 dig = int(numpy.log10(ymax))
388 dig = int(numpy.log10(ymax))
389 if dig == 0:
389 if dig == 0:
390 digD = len(str(ymax)) - 2
390 digD = len(str(ymax)) - 2
391 ydec = ymax*(10**digD)
391 ydec = ymax*(10**digD)
392
392
393 dig = int(numpy.log10(ydec))
393 dig = int(numpy.log10(ydec))
394 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
394 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
395 ystep = ystep/5
395 ystep = ystep/5
396 ystep = ystep/(10**digD)
396 ystep = ystep/(10**digD)
397
397
398 else:
398 else:
399 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
399 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
400 ystep = ystep/5
400 ystep = ystep/5
401
401
402 if self.xaxis is not 'time':
402 if self.xaxis is not 'time':
403
403
404 dig = int(numpy.log10(xmax))
404 dig = int(numpy.log10(xmax))
405
405
406 if dig <= 0:
406 if dig <= 0:
407 digD = len(str(xmax)) - 2
407 digD = len(str(xmax)) - 2
408 xdec = xmax*(10**digD)
408 xdec = xmax*(10**digD)
409
409
410 dig = int(numpy.log10(xdec))
410 dig = int(numpy.log10(xdec))
411 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
411 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
412 xstep = xstep*0.5
412 xstep = xstep*0.5
413 xstep = xstep/(10**digD)
413 xstep = xstep/(10**digD)
414
414
415 else:
415 else:
416 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
416 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
417 xstep = xstep/5
417 xstep = xstep/5
418
418
419 ax.set_facecolor(self.bgcolor)
419 ax.set_facecolor(self.bgcolor)
420 ax.yaxis.set_major_locator(MultipleLocator(ystep))
420 ax.yaxis.set_major_locator(MultipleLocator(ystep))
421 if self.xscale:
421 if self.xscale:
422 ax.xaxis.set_major_formatter(FuncFormatter(
422 ax.xaxis.set_major_formatter(FuncFormatter(
423 lambda x, pos: '{0:g}'.format(x*self.xscale)))
423 lambda x, pos: '{0:g}'.format(x*self.xscale)))
424 if self.xscale:
424 if self.xscale:
425 ax.yaxis.set_major_formatter(FuncFormatter(
425 ax.yaxis.set_major_formatter(FuncFormatter(
426 lambda x, pos: '{0:g}'.format(x*self.yscale)))
426 lambda x, pos: '{0:g}'.format(x*self.yscale)))
427 if self.xaxis is 'time':
427 if self.xaxis is 'time':
428 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
428 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
429 ax.xaxis.set_major_locator(LinearLocator(9))
429 ax.xaxis.set_major_locator(LinearLocator(9))
430 else:
430 else:
431 ax.xaxis.set_major_locator(MultipleLocator(xstep))
431 ax.xaxis.set_major_locator(MultipleLocator(xstep))
432 if self.xlabel is not None:
432 if self.xlabel is not None:
433 ax.set_xlabel(self.xlabel)
433 ax.set_xlabel(self.xlabel)
434 ax.set_ylabel(self.ylabel)
434 ax.set_ylabel(self.ylabel)
435 ax.firsttime = False
435 ax.firsttime = False
436 if self.showprofile:
436 if self.showprofile:
437 self.pf_axes[n].set_ylim(ymin, ymax)
437 self.pf_axes[n].set_ylim(ymin, ymax)
438 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
438 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
439 self.pf_axes[n].set_xlabel('dB')
439 self.pf_axes[n].set_xlabel('dB')
440 self.pf_axes[n].grid(b=True, axis='x')
440 self.pf_axes[n].grid(b=True, axis='x')
441 [tick.set_visible(False)
441 [tick.set_visible(False)
442 for tick in self.pf_axes[n].get_yticklabels()]
442 for tick in self.pf_axes[n].get_yticklabels()]
443 if self.colorbar:
443 if self.colorbar:
444 ax.cbar = plt.colorbar(
444 ax.cbar = plt.colorbar(
445 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
445 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
446 ax.cbar.ax.tick_params(labelsize=8)
446 ax.cbar.ax.tick_params(labelsize=8)
447 ax.cbar.ax.press = None
447 ax.cbar.ax.press = None
448 if self.cb_label:
448 if self.cb_label:
449 ax.cbar.set_label(self.cb_label, size=8)
449 ax.cbar.set_label(self.cb_label, size=8)
450 elif self.cb_labels:
450 elif self.cb_labels:
451 ax.cbar.set_label(self.cb_labels[n], size=8)
451 ax.cbar.set_label(self.cb_labels[n], size=8)
452 else:
452 else:
453 ax.cbar = None
453 ax.cbar = None
454 if self.grid:
454 if self.grid:
455 ax.grid(True)
455 ax.grid(True)
456
456
457 if not self.polar:
457 if not self.polar:
458 ax.set_xlim(xmin, xmax)
458 ax.set_xlim(xmin, xmax)
459 ax.set_ylim(ymin, ymax)
459 ax.set_ylim(ymin, ymax)
460 ax.set_title('{} {} {}'.format(
460 ax.set_title('{} {} {}'.format(
461 self.titles[n],
461 self.titles[n],
462 self.getDateTime(self.data.max_time).strftime(
462 self.getDateTime(self.data.max_time).strftime(
463 '%Y-%m-%d %H:%M:%S'),
463 '%Y-%m-%d %H:%M:%S'),
464 self.time_label),
464 self.time_label),
465 size=8)
465 size=8)
466 else:
466 else:
467 ax.set_title('{}'.format(self.titles[n]), size=8)
467 ax.set_title('{}'.format(self.titles[n]), size=8)
468 ax.set_ylim(0, 90)
468 ax.set_ylim(0, 90)
469 ax.set_yticks(numpy.arange(0, 90, 20))
469 ax.set_yticks(numpy.arange(0, 90, 20))
470 ax.yaxis.labelpad = 40
470 ax.yaxis.labelpad = 40
471
471
472 if self.firsttime:
472 if self.firsttime:
473 for n, fig in enumerate(self.figures):
473 for n, fig in enumerate(self.figures):
474 fig.subplots_adjust(**self.plots_adjust)
474 fig.subplots_adjust(**self.plots_adjust)
475 self.firsttime = False
475 self.firsttime = False
476
476
477 def clear_figures(self):
477 def clear_figures(self):
478 '''
478 '''
479 Reset axes for redraw plots
479 Reset axes for redraw plots
480 '''
480 '''
481
481
482 for ax in self.axes+self.pf_axes+self.cb_axes:
482 for ax in self.axes+self.pf_axes+self.cb_axes:
483 ax.clear()
483 ax.clear()
484 ax.firsttime = True
484 ax.firsttime = True
485 if ax.cbar:
485 if ax.cbar:
486 ax.cbar.remove()
486 ax.cbar.remove()
487
487
488 def __plot(self):
488 def __plot(self):
489 '''
489 '''
490 Main function to plot, format and save figures
490 Main function to plot, format and save figures
491 '''
491 '''
492
492
493 self.plot()
493 self.plot()
494 self.format()
494 self.format()
495
495
496 for n, fig in enumerate(self.figures):
496 for n, fig in enumerate(self.figures):
497 if self.nrows == 0 or self.nplots == 0:
497 if self.nrows == 0 or self.nplots == 0:
498 log.warning('No data', self.name)
498 log.warning('No data', self.name)
499 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
499 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
500 fig.canvas.manager.set_window_title(self.CODE)
500 fig.canvas.manager.set_window_title(self.CODE)
501 continue
501 continue
502
502
503 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
503 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
504 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
504 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
505 fig.canvas.draw()
505 fig.canvas.draw()
506 if self.show:
506 if self.show:
507 fig.show()
507 fig.show()
508 figpause(0.01)
508 figpause(0.01)
509
509
510 if self.save:
510 if self.save:
511 self.save_figure(n)
511 self.save_figure(n)
512
512
513 if self.plot_server:
513 if self.plot_server:
514 self.send_to_server()
514 self.send_to_server()
515
515
516 def save_figure(self, n):
516 def save_figure(self, n):
517 '''
517 '''
518 '''
518 '''
519
519
520 if self.save_counter < self.save_period:
520 if self.save_counter < self.save_period:
521 self.save_counter += 1
521 self.save_counter += 1
522 return
522 return
523
523
524 self.save_counter = 1
524 self.save_counter = 1
525
525
526 fig = self.figures[n]
526 fig = self.figures[n]
527
527
528 if self.save_code:
528 if self.save_code:
529 if isinstance(self.save_code, str):
529 if isinstance(self.save_code, str):
530 labels = [self.save_code for x in self.figures]
530 labels = [self.save_code for x in self.figures]
531 else:
531 else:
532 labels = self.save_code
532 labels = self.save_code
533 else:
533 else:
534 labels = [self.CODE for x in self.figures]
534 labels = [self.CODE for x in self.figures]
535
535
536 figname = os.path.join(
536 figname = os.path.join(
537 self.save,
537 self.save,
538 labels[n],
538 labels[n],
539 '{}_{}.png'.format(
539 '{}_{}.png'.format(
540 labels[n],
540 labels[n],
541 self.getDateTime(self.data.max_time).strftime(
541 self.getDateTime(self.data.max_time).strftime(
542 '%Y%m%d_%H%M%S'
542 '%Y%m%d_%H%M%S'
543 ),
543 ),
544 )
544 )
545 )
545 )
546 log.log('Saving figure: {}'.format(figname), self.name)
546 log.log('Saving figure: {}'.format(figname), self.name)
547 if not os.path.isdir(os.path.dirname(figname)):
547 if not os.path.isdir(os.path.dirname(figname)):
548 os.makedirs(os.path.dirname(figname))
548 os.makedirs(os.path.dirname(figname))
549 fig.savefig(figname)
549 fig.savefig(figname)
550
550
551 if self.throttle == 0:
551 if self.throttle == 0:
552 figname = os.path.join(
552 figname = os.path.join(
553 self.save,
553 self.save,
554 '{}_{}.png'.format(
554 '{}_{}.png'.format(
555 labels[n],
555 labels[n],
556 self.getDateTime(self.data.min_time).strftime(
556 self.getDateTime(self.data.min_time).strftime(
557 '%Y%m%d'
557 '%Y%m%d'
558 ),
558 ),
559 )
559 )
560 )
560 )
561 fig.savefig(figname)
561 fig.savefig(figname)
562
562
563 def send_to_server(self):
563 def send_to_server(self):
564 '''
564 '''
565 '''
565 '''
566
566
567 if self.data.tm - self.sender_time < self.sender_period:
567 interval = self.data.tm - self.sender_time
568 if interval < self.sender_period:
568 return
569 return
569
570
570 self.sender_time = self.data.tm
571 self.sender_time = self.data.tm
571
572
572 attrs = ['titles', 'zmin', 'zmax']
573 attrs = ['titles', 'zmin', 'zmax']
573 for attr in attrs:
574 for attr in attrs:
574 self.data.meta[attr] = getattr(self, attr)
575 self.data.meta[attr] = getattr(self, attr)
575
576 self.data.meta['interval'] = int(interval)
576 retries = 2
577 retries = 2
577 while True:
578 while True:
578 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
579 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
579 socks = dict(self.poll.poll(5000))
580 socks = dict(self.poll.poll(5000))
580 if socks.get(self.socket) == zmq.POLLIN:
581 if socks.get(self.socket) == zmq.POLLIN:
581 reply = self.socket.recv_string()
582 reply = self.socket.recv_string()
582 if reply == 'ok':
583 if reply == 'ok':
583 log.log("Response from server ok", self.name)
584 log.log("Response from server ok", self.name)
584 break
585 break
585 else:
586 else:
586 log.warning(
587 log.warning(
587 "Malformed reply from server: {}".format(reply), self.name)
588 "Malformed reply from server: {}".format(reply), self.name)
588
589
589 else:
590 else:
590 log.warning(
591 log.warning(
591 "No response from server, retrying...", self.name)
592 "No response from server, retrying...", self.name)
592 self.socket.setsockopt(zmq.LINGER, 0)
593 self.socket.setsockopt(zmq.LINGER, 0)
593 self.socket.close()
594 self.socket.close()
594 self.poll.unregister(self.socket)
595 self.poll.unregister(self.socket)
595 retries -= 1
596 retries -= 1
596 if retries == 0:
597 if retries == 0:
597 log.error(
598 log.error(
598 "Server seems to be offline, abandoning", self.name)
599 "Server seems to be offline, abandoning", self.name)
599 self.socket = self.context.socket(zmq.REQ)
600 self.socket = self.context.socket(zmq.REQ)
600 self.socket.connect(self.plot_server)
601 self.socket.connect(self.plot_server)
601 self.poll.register(self.socket, zmq.POLLIN)
602 self.poll.register(self.socket, zmq.POLLIN)
602 time.sleep(1)
603 time.sleep(1)
603 break
604 break
604 self.socket = self.context.socket(zmq.REQ)
605 self.socket = self.context.socket(zmq.REQ)
605 self.socket.connect(self.plot_server)
606 self.socket.connect(self.plot_server)
606 self.poll.register(self.socket, zmq.POLLIN)
607 self.poll.register(self.socket, zmq.POLLIN)
607 time.sleep(0.5)
608 time.sleep(0.5)
608
609
609 def setup(self):
610 def setup(self):
610 '''
611 '''
611 This method should be implemented in the child class, the following
612 This method should be implemented in the child class, the following
612 attributes should be set:
613 attributes should be set:
613
614
614 self.nrows: number of rows
615 self.nrows: number of rows
615 self.ncols: number of cols
616 self.ncols: number of cols
616 self.nplots: number of plots (channels or pairs)
617 self.nplots: number of plots (channels or pairs)
617 self.ylabel: label for Y axes
618 self.ylabel: label for Y axes
618 self.titles: list of axes title
619 self.titles: list of axes title
619
620
620 '''
621 '''
621 raise NotImplementedError
622 raise NotImplementedError
622
623
623 def plot(self):
624 def plot(self):
624 '''
625 '''
625 Must be defined in the child class
626 Must be defined in the child class
626 '''
627 '''
627 raise NotImplementedError
628 raise NotImplementedError
628
629
629 def run(self, dataOut, **kwargs):
630 def run(self, dataOut, **kwargs):
630 '''
631 '''
631 Main plotting routine
632 Main plotting routine
632 '''
633 '''
633
634
634 if self.isConfig is False:
635 if self.isConfig is False:
635 self.__setup(**kwargs)
636 self.__setup(**kwargs)
636
637
637 t = getattr(dataOut, self.attr_time)
638 t = getattr(dataOut, self.attr_time)
638
639
639 if dataOut.useLocalTime:
640 if dataOut.useLocalTime:
640 self.getDateTime = datetime.datetime.fromtimestamp
641 self.getDateTime = datetime.datetime.fromtimestamp
641 if not self.localtime:
642 if not self.localtime:
642 t += time.timezone
643 t += time.timezone
643 else:
644 else:
644 self.getDateTime = datetime.datetime.utcfromtimestamp
645 self.getDateTime = datetime.datetime.utcfromtimestamp
645 if self.localtime:
646 if self.localtime:
646 t -= time.timezone
647 t -= time.timezone
647
648
648 if 'buffer' in self.plot_type:
649 if 'buffer' in self.plot_type:
649 if self.xmin is None:
650 if self.xmin is None:
650 self.tmin = t
651 self.tmin = t
651 self.xmin = self.getDateTime(t).hour
652 self.xmin = self.getDateTime(t).hour
652 else:
653 else:
653 self.tmin = (
654 self.tmin = (
654 self.getDateTime(t).replace(
655 self.getDateTime(t).replace(
655 hour=int(self.xmin),
656 hour=int(self.xmin),
656 minute=0,
657 minute=0,
657 second=0) - self.getDateTime(0)).total_seconds()
658 second=0) - self.getDateTime(0)).total_seconds()
658
659
659 self.data.setup()
660 self.data.setup()
660 self.isConfig = True
661 self.isConfig = True
661 if self.plot_server:
662 if self.plot_server:
662 self.context = zmq.Context()
663 self.context = zmq.Context()
663 self.socket = self.context.socket(zmq.REQ)
664 self.socket = self.context.socket(zmq.REQ)
664 self.socket.connect(self.plot_server)
665 self.socket.connect(self.plot_server)
665 self.poll = zmq.Poller()
666 self.poll = zmq.Poller()
666 self.poll.register(self.socket, zmq.POLLIN)
667 self.poll.register(self.socket, zmq.POLLIN)
667
668
668 tm = getattr(dataOut, self.attr_time)
669 tm = getattr(dataOut, self.attr_time)
669
670
670 if not dataOut.useLocalTime and self.localtime:
671 if not dataOut.useLocalTime and self.localtime:
671 tm -= time.timezone
672 tm -= time.timezone
672 if dataOut.useLocalTime and not self.localtime:
673 if dataOut.useLocalTime and not self.localtime:
673 tm += time.timezone
674 tm += time.timezone
674
675
675 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
676 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
676 self.save_counter = self.save_period
677 self.save_counter = self.save_period
677 self.__plot()
678 self.__plot()
678 self.xmin += self.xrange
679 self.xmin += self.xrange
679 if self.xmin >= 24:
680 if self.xmin >= 24:
680 self.xmin -= 24
681 self.xmin -= 24
681 self.tmin += self.xrange*60*60
682 self.tmin += self.xrange*60*60
682 self.data.setup()
683 self.data.setup()
683 self.clear_figures()
684 self.clear_figures()
684
685
685 self.data.update(dataOut, tm)
686 self.data.update(dataOut, tm)
686
687
687 if self.isPlotConfig is False:
688 if self.isPlotConfig is False:
688 self.__setup_plot()
689 self.__setup_plot()
689 self.isPlotConfig = True
690 self.isPlotConfig = True
690
691
691 if self.throttle == 0:
692 if self.throttle == 0:
692 self.__plot()
693 self.__plot()
693 else:
694 else:
694 self.__throttle_plot(self.__plot)#, coerce=coerce)
695 self.__throttle_plot(self.__plot)#, coerce=coerce)
695
696
696 def close(self):
697 def close(self):
697
698
698 if self.data and not self.data.flagNoData:
699 if self.data and not self.data.flagNoData:
699 self.save_counter = self.save_period
700 self.save_counter = self.save_period
700 self.__plot()
701 self.__plot()
701 if self.data and not self.data.flagNoData and self.pause:
702 if self.data and not self.data.flagNoData and self.pause:
702 figpause(10)
703 figpause(10)
703
704
General Comments 0
You need to be logged in to leave comments. Login now