##// END OF EJS Templates
Add decimation to jsonify data to web & fix typo KM
jespinoza -
r1122:f7735fe71c79
parent child
Show More
@@ -1,965 +1,965
1
1
2 import os
2 import os
3 import time
3 import time
4 import glob
4 import glob
5 import datetime
5 import datetime
6 from multiprocessing import Process
6 from multiprocessing import Process
7
7
8 import zmq
8 import zmq
9 import numpy
9 import numpy
10 import matplotlib
10 import matplotlib
11 import matplotlib.pyplot as plt
11 import matplotlib.pyplot as plt
12 from mpl_toolkits.axes_grid1 import make_axes_locatable
12 from mpl_toolkits.axes_grid1 import make_axes_locatable
13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
14
14
15 from schainpy.model.proc.jroproc_base import Operation
15 from schainpy.model.proc.jroproc_base import Operation
16 from schainpy.utils import log
16 from schainpy.utils import log
17
17
18 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
18 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
19 blu_values = matplotlib.pyplot.get_cmap(
19 blu_values = matplotlib.pyplot.get_cmap(
20 'seismic_r', 20)(numpy.arange(20))[10:15]
20 'seismic_r', 20)(numpy.arange(20))[10:15]
21 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
21 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
22 'jro', numpy.vstack((blu_values, jet_values)))
22 'jro', numpy.vstack((blu_values, jet_values)))
23 matplotlib.pyplot.register_cmap(cmap=ncmap)
23 matplotlib.pyplot.register_cmap(cmap=ncmap)
24
24
25 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis', 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
25 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis', 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
26
26
27
27
28 def figpause(interval):
28 def figpause(interval):
29 backend = plt.rcParams['backend']
29 backend = plt.rcParams['backend']
30 if backend in matplotlib.rcsetup.interactive_bk:
30 if backend in matplotlib.rcsetup.interactive_bk:
31 figManager = matplotlib._pylab_helpers.Gcf.get_active()
31 figManager = matplotlib._pylab_helpers.Gcf.get_active()
32 if figManager is not None:
32 if figManager is not None:
33 canvas = figManager.canvas
33 canvas = figManager.canvas
34 if canvas.figure.stale:
34 if canvas.figure.stale:
35 canvas.draw()
35 canvas.draw()
36 canvas.start_event_loop(interval)
36 canvas.start_event_loop(interval)
37 return
37 return
38
38
39
39
40 class PlotData(Operation, Process):
40 class PlotData(Operation, Process):
41 '''
41 '''
42 Base class for Schain plotting operations
42 Base class for Schain plotting operations
43 '''
43 '''
44
44
45 CODE = 'Figure'
45 CODE = 'Figure'
46 colormap = 'jro'
46 colormap = 'jro'
47 bgcolor = 'white'
47 bgcolor = 'white'
48 CONFLATE = False
48 CONFLATE = False
49 __missing = 1E30
49 __missing = 1E30
50
50
51 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
51 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
52 'zlimits', 'xlabel', 'ylabel', 'xaxis','cb_label', 'title',
52 'zlimits', 'xlabel', 'ylabel', 'xaxis','cb_label', 'title',
53 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
53 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
54 'showprofile', 'decimation']
54 'showprofile', 'decimation']
55
55
56 def __init__(self, **kwargs):
56 def __init__(self, **kwargs):
57
57
58 Operation.__init__(self, plot=True, **kwargs)
58 Operation.__init__(self, plot=True, **kwargs)
59 Process.__init__(self)
59 Process.__init__(self)
60
60
61 self.kwargs['code'] = self.CODE
61 self.kwargs['code'] = self.CODE
62 self.mp = False
62 self.mp = False
63 self.data = None
63 self.data = None
64 self.isConfig = False
64 self.isConfig = False
65 self.figures = []
65 self.figures = []
66 self.axes = []
66 self.axes = []
67 self.cb_axes = []
67 self.cb_axes = []
68 self.localtime = kwargs.pop('localtime', True)
68 self.localtime = kwargs.pop('localtime', True)
69 self.show = kwargs.get('show', True)
69 self.show = kwargs.get('show', True)
70 self.save = kwargs.get('save', False)
70 self.save = kwargs.get('save', False)
71 self.colormap = kwargs.get('colormap', self.colormap)
71 self.colormap = kwargs.get('colormap', self.colormap)
72 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
72 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
73 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
73 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
74 self.colormaps = kwargs.get('colormaps', None)
74 self.colormaps = kwargs.get('colormaps', None)
75 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
75 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
76 self.showprofile = kwargs.get('showprofile', False)
76 self.showprofile = kwargs.get('showprofile', False)
77 self.title = kwargs.get('wintitle', self.CODE.upper())
77 self.title = kwargs.get('wintitle', self.CODE.upper())
78 self.cb_label = kwargs.get('cb_label', None)
78 self.cb_label = kwargs.get('cb_label', None)
79 self.cb_labels = kwargs.get('cb_labels', None)
79 self.cb_labels = kwargs.get('cb_labels', None)
80 self.xaxis = kwargs.get('xaxis', 'frequency')
80 self.xaxis = kwargs.get('xaxis', 'frequency')
81 self.zmin = kwargs.get('zmin', None)
81 self.zmin = kwargs.get('zmin', None)
82 self.zmax = kwargs.get('zmax', None)
82 self.zmax = kwargs.get('zmax', None)
83 self.zlimits = kwargs.get('zlimits', None)
83 self.zlimits = kwargs.get('zlimits', None)
84 self.xmin = kwargs.get('xmin', None)
84 self.xmin = kwargs.get('xmin', None)
85 self.xmax = kwargs.get('xmax', None)
85 self.xmax = kwargs.get('xmax', None)
86 self.xrange = kwargs.get('xrange', 24)
86 self.xrange = kwargs.get('xrange', 24)
87 self.ymin = kwargs.get('ymin', None)
87 self.ymin = kwargs.get('ymin', None)
88 self.ymax = kwargs.get('ymax', None)
88 self.ymax = kwargs.get('ymax', None)
89 self.xlabel = kwargs.get('xlabel', None)
89 self.xlabel = kwargs.get('xlabel', None)
90 self.decimation = kwargs.get('decimation', None)
90 self.decimation = kwargs.get('decimation', None)
91 self.showSNR = kwargs.get('showSNR', False)
91 self.showSNR = kwargs.get('showSNR', False)
92 self.oneFigure = kwargs.get('oneFigure', True)
92 self.oneFigure = kwargs.get('oneFigure', True)
93 self.width = kwargs.get('width', None)
93 self.width = kwargs.get('width', None)
94 self.height = kwargs.get('height', None)
94 self.height = kwargs.get('height', None)
95 self.colorbar = kwargs.get('colorbar', True)
95 self.colorbar = kwargs.get('colorbar', True)
96 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
96 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
97 self.titles = kwargs.get('titles', [])
97 self.titles = kwargs.get('titles', [])
98 self.polar = False
98 self.polar = False
99
99
100 def __fmtTime(self, x, pos):
100 def __fmtTime(self, x, pos):
101 '''
101 '''
102 '''
102 '''
103
103
104 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
104 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
105
105
106 def __setup(self):
106 def __setup(self):
107 '''
107 '''
108 Common setup for all figures, here figures and axes are created
108 Common setup for all figures, here figures and axes are created
109 '''
109 '''
110
110
111 if self.CODE not in self.data:
111 if self.CODE not in self.data:
112 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
112 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
113 self.name))
113 self.name))
114
114
115 self.setup()
115 self.setup()
116
116
117 self.time_label = 'LT' if self.localtime else 'UTC'
117 self.time_label = 'LT' if self.localtime else 'UTC'
118 if self.data.localtime:
118 if self.data.localtime:
119 self.getDateTime = datetime.datetime.fromtimestamp
119 self.getDateTime = datetime.datetime.fromtimestamp
120 else:
120 else:
121 self.getDateTime = datetime.datetime.utcfromtimestamp
121 self.getDateTime = datetime.datetime.utcfromtimestamp
122
122
123 if self.width is None:
123 if self.width is None:
124 self.width = 8
124 self.width = 8
125
125
126 self.figures = []
126 self.figures = []
127 self.axes = []
127 self.axes = []
128 self.cb_axes = []
128 self.cb_axes = []
129 self.pf_axes = []
129 self.pf_axes = []
130 self.cmaps = []
130 self.cmaps = []
131
131
132 size = '15%' if self.ncols == 1 else '30%'
132 size = '15%' if self.ncols == 1 else '30%'
133 pad = '4%' if self.ncols == 1 else '8%'
133 pad = '4%' if self.ncols == 1 else '8%'
134
134
135 if self.oneFigure:
135 if self.oneFigure:
136 if self.height is None:
136 if self.height is None:
137 self.height = 1.4 * self.nrows + 1
137 self.height = 1.4 * self.nrows + 1
138 fig = plt.figure(figsize=(self.width, self.height),
138 fig = plt.figure(figsize=(self.width, self.height),
139 edgecolor='k',
139 edgecolor='k',
140 facecolor='w')
140 facecolor='w')
141 self.figures.append(fig)
141 self.figures.append(fig)
142 for n in range(self.nplots):
142 for n in range(self.nplots):
143 ax = fig.add_subplot(self.nrows, self.ncols,
143 ax = fig.add_subplot(self.nrows, self.ncols,
144 n + 1, polar=self.polar)
144 n + 1, polar=self.polar)
145 ax.tick_params(labelsize=8)
145 ax.tick_params(labelsize=8)
146 ax.firsttime = True
146 ax.firsttime = True
147 ax.index = 0
147 ax.index = 0
148 ax.press = None
148 ax.press = None
149 self.axes.append(ax)
149 self.axes.append(ax)
150 if self.showprofile:
150 if self.showprofile:
151 cax = self.__add_axes(ax, size=size, pad=pad)
151 cax = self.__add_axes(ax, size=size, pad=pad)
152 cax.tick_params(labelsize=8)
152 cax.tick_params(labelsize=8)
153 self.pf_axes.append(cax)
153 self.pf_axes.append(cax)
154 else:
154 else:
155 if self.height is None:
155 if self.height is None:
156 self.height = 3
156 self.height = 3
157 for n in range(self.nplots):
157 for n in range(self.nplots):
158 fig = plt.figure(figsize=(self.width, self.height),
158 fig = plt.figure(figsize=(self.width, self.height),
159 edgecolor='k',
159 edgecolor='k',
160 facecolor='w')
160 facecolor='w')
161 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
161 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
162 ax.tick_params(labelsize=8)
162 ax.tick_params(labelsize=8)
163 ax.firsttime = True
163 ax.firsttime = True
164 ax.index = 0
164 ax.index = 0
165 ax.press = None
165 ax.press = None
166 self.figures.append(fig)
166 self.figures.append(fig)
167 self.axes.append(ax)
167 self.axes.append(ax)
168 if self.showprofile:
168 if self.showprofile:
169 cax = self.__add_axes(ax, size=size, pad=pad)
169 cax = self.__add_axes(ax, size=size, pad=pad)
170 cax.tick_params(labelsize=8)
170 cax.tick_params(labelsize=8)
171 self.pf_axes.append(cax)
171 self.pf_axes.append(cax)
172
172
173 for n in range(self.nrows):
173 for n in range(self.nrows):
174 if self.colormaps is not None:
174 if self.colormaps is not None:
175 cmap = plt.get_cmap(self.colormaps[n])
175 cmap = plt.get_cmap(self.colormaps[n])
176 else:
176 else:
177 cmap = plt.get_cmap(self.colormap)
177 cmap = plt.get_cmap(self.colormap)
178 cmap.set_bad(self.bgcolor, 1.)
178 cmap.set_bad(self.bgcolor, 1.)
179 self.cmaps.append(cmap)
179 self.cmaps.append(cmap)
180
180
181 for fig in self.figures:
181 for fig in self.figures:
182 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
182 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
183 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
183 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
184 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
184 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
185 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
185 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
186 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
186 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
187 if self.show:
187 if self.show:
188 fig.show()
188 fig.show()
189
189
190 def OnKeyPress(self, event):
190 def OnKeyPress(self, event):
191 '''
191 '''
192 Event for pressing keys (up, down) change colormap
192 Event for pressing keys (up, down) change colormap
193 '''
193 '''
194 ax = event.inaxes
194 ax = event.inaxes
195 if ax in self.axes:
195 if ax in self.axes:
196 if event.key == 'down':
196 if event.key == 'down':
197 ax.index += 1
197 ax.index += 1
198 elif event.key == 'up':
198 elif event.key == 'up':
199 ax.index -= 1
199 ax.index -= 1
200 if ax.index < 0:
200 if ax.index < 0:
201 ax.index = len(CMAPS) - 1
201 ax.index = len(CMAPS) - 1
202 elif ax.index == len(CMAPS):
202 elif ax.index == len(CMAPS):
203 ax.index = 0
203 ax.index = 0
204 cmap = CMAPS[ax.index]
204 cmap = CMAPS[ax.index]
205 ax.cbar.set_cmap(cmap)
205 ax.cbar.set_cmap(cmap)
206 ax.cbar.draw_all()
206 ax.cbar.draw_all()
207 ax.plt.set_cmap(cmap)
207 ax.plt.set_cmap(cmap)
208 ax.cbar.patch.figure.canvas.draw()
208 ax.cbar.patch.figure.canvas.draw()
209 self.colormap = cmap.name
209 self.colormap = cmap.name
210
210
211 def OnBtnScroll(self, event):
211 def OnBtnScroll(self, event):
212 '''
212 '''
213 Event for scrolling, scale figure
213 Event for scrolling, scale figure
214 '''
214 '''
215 cb_ax = event.inaxes
215 cb_ax = event.inaxes
216 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
216 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
217 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
217 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
218 pt = ax.cbar.ax.bbox.get_points()[:, 1]
218 pt = ax.cbar.ax.bbox.get_points()[:, 1]
219 nrm = ax.cbar.norm
219 nrm = ax.cbar.norm
220 vmin, vmax, p0, p1, pS = (
220 vmin, vmax, p0, p1, pS = (
221 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
221 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
222 scale = 2 if event.step == 1 else 0.5
222 scale = 2 if event.step == 1 else 0.5
223 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
223 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
224 ax.cbar.norm.vmin = point - scale * (point - vmin)
224 ax.cbar.norm.vmin = point - scale * (point - vmin)
225 ax.cbar.norm.vmax = point - scale * (point - vmax)
225 ax.cbar.norm.vmax = point - scale * (point - vmax)
226 ax.plt.set_norm(ax.cbar.norm)
226 ax.plt.set_norm(ax.cbar.norm)
227 ax.cbar.draw_all()
227 ax.cbar.draw_all()
228 ax.cbar.patch.figure.canvas.draw()
228 ax.cbar.patch.figure.canvas.draw()
229
229
230 def onBtnPress(self, event):
230 def onBtnPress(self, event):
231 '''
231 '''
232 Event for mouse button press
232 Event for mouse button press
233 '''
233 '''
234 cb_ax = event.inaxes
234 cb_ax = event.inaxes
235 if cb_ax is None:
235 if cb_ax is None:
236 return
236 return
237
237
238 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
238 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
239 cb_ax.press = event.x, event.y
239 cb_ax.press = event.x, event.y
240 else:
240 else:
241 cb_ax.press = None
241 cb_ax.press = None
242
242
243 def onMotion(self, event):
243 def onMotion(self, event):
244 '''
244 '''
245 Event for move inside colorbar
245 Event for move inside colorbar
246 '''
246 '''
247 cb_ax = event.inaxes
247 cb_ax = event.inaxes
248 if cb_ax is None:
248 if cb_ax is None:
249 return
249 return
250 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
250 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
251 return
251 return
252 if cb_ax.press is None:
252 if cb_ax.press is None:
253 return
253 return
254
254
255 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
255 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
256 xprev, yprev = cb_ax.press
256 xprev, yprev = cb_ax.press
257 dx = event.x - xprev
257 dx = event.x - xprev
258 dy = event.y - yprev
258 dy = event.y - yprev
259 cb_ax.press = event.x, event.y
259 cb_ax.press = event.x, event.y
260 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
260 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
261 perc = 0.03
261 perc = 0.03
262
262
263 if event.button == 1:
263 if event.button == 1:
264 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
264 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
265 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
265 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
266 elif event.button == 3:
266 elif event.button == 3:
267 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
267 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
268 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
268 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
269
269
270 ax.cbar.draw_all()
270 ax.cbar.draw_all()
271 ax.plt.set_norm(ax.cbar.norm)
271 ax.plt.set_norm(ax.cbar.norm)
272 ax.cbar.patch.figure.canvas.draw()
272 ax.cbar.patch.figure.canvas.draw()
273
273
274 def onBtnRelease(self, event):
274 def onBtnRelease(self, event):
275 '''
275 '''
276 Event for mouse button release
276 Event for mouse button release
277 '''
277 '''
278 cb_ax = event.inaxes
278 cb_ax = event.inaxes
279 if cb_ax is not None:
279 if cb_ax is not None:
280 cb_ax.press = None
280 cb_ax.press = None
281
281
282 def __add_axes(self, ax, size='30%', pad='8%'):
282 def __add_axes(self, ax, size='30%', pad='8%'):
283 '''
283 '''
284 Add new axes to the given figure
284 Add new axes to the given figure
285 '''
285 '''
286 divider = make_axes_locatable(ax)
286 divider = make_axes_locatable(ax)
287 nax = divider.new_horizontal(size=size, pad=pad)
287 nax = divider.new_horizontal(size=size, pad=pad)
288 ax.figure.add_axes(nax)
288 ax.figure.add_axes(nax)
289 return nax
289 return nax
290
290
291 self.setup()
291 self.setup()
292
292
293 def setup(self):
293 def setup(self):
294 '''
294 '''
295 This method should be implemented in the child class, the following
295 This method should be implemented in the child class, the following
296 attributes should be set:
296 attributes should be set:
297
297
298 self.nrows: number of rows
298 self.nrows: number of rows
299 self.ncols: number of cols
299 self.ncols: number of cols
300 self.nplots: number of plots (channels or pairs)
300 self.nplots: number of plots (channels or pairs)
301 self.ylabel: label for Y axes
301 self.ylabel: label for Y axes
302 self.titles: list of axes title
302 self.titles: list of axes title
303
303
304 '''
304 '''
305 raise(NotImplementedError, 'Implement this method in child class')
305 raise(NotImplementedError, 'Implement this method in child class')
306
306
307 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
307 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
308 '''
308 '''
309 Create a masked array for missing data
309 Create a masked array for missing data
310 '''
310 '''
311 if x_buffer.shape[0] < 2:
311 if x_buffer.shape[0] < 2:
312 return x_buffer, y_buffer, z_buffer
312 return x_buffer, y_buffer, z_buffer
313
313
314 deltas = x_buffer[1:] - x_buffer[0:-1]
314 deltas = x_buffer[1:] - x_buffer[0:-1]
315 x_median = numpy.median(deltas)
315 x_median = numpy.median(deltas)
316
316
317 index = numpy.where(deltas > 5 * x_median)
317 index = numpy.where(deltas > 5 * x_median)
318
318
319 if len(index[0]) != 0:
319 if len(index[0]) != 0:
320 z_buffer[::, index[0], ::] = self.__missing
320 z_buffer[::, index[0], ::] = self.__missing
321 z_buffer = numpy.ma.masked_inside(z_buffer,
321 z_buffer = numpy.ma.masked_inside(z_buffer,
322 0.99 * self.__missing,
322 0.99 * self.__missing,
323 1.01 * self.__missing)
323 1.01 * self.__missing)
324
324
325 return x_buffer, y_buffer, z_buffer
325 return x_buffer, y_buffer, z_buffer
326
326
327 def decimate(self):
327 def decimate(self):
328
328
329 # dx = int(len(self.x)/self.__MAXNUMX) + 1
329 # dx = int(len(self.x)/self.__MAXNUMX) + 1
330 dy = int(len(self.y) / self.decimation) + 1
330 dy = int(len(self.y) / self.decimation) + 1
331
331
332 # x = self.x[::dx]
332 # x = self.x[::dx]
333 x = self.x
333 x = self.x
334 y = self.y[::dy]
334 y = self.y[::dy]
335 z = self.z[::, ::, ::dy]
335 z = self.z[::, ::, ::dy]
336
336
337 return x, y, z
337 return x, y, z
338
338
339 def format(self):
339 def format(self):
340 '''
340 '''
341 Set min and max values, labels, ticks and titles
341 Set min and max values, labels, ticks and titles
342 '''
342 '''
343
343
344 if self.xmin is None:
344 if self.xmin is None:
345 xmin = self.min_time
345 xmin = self.min_time
346 else:
346 else:
347 if self.xaxis is 'time':
347 if self.xaxis is 'time':
348 dt = self.getDateTime(self.min_time)
348 dt = self.getDateTime(self.min_time)
349 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
349 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
350 datetime.datetime(1970, 1, 1)).total_seconds()
350 datetime.datetime(1970, 1, 1)).total_seconds()
351 if self.data.localtime:
351 if self.data.localtime:
352 xmin += time.timezone
352 xmin += time.timezone
353 else:
353 else:
354 xmin = self.xmin
354 xmin = self.xmin
355
355
356 if self.xmax is None:
356 if self.xmax is None:
357 xmax = xmin + self.xrange * 60 * 60
357 xmax = xmin + self.xrange * 60 * 60
358 else:
358 else:
359 if self.xaxis is 'time':
359 if self.xaxis is 'time':
360 dt = self.getDateTime(self.max_time)
360 dt = self.getDateTime(self.max_time)
361 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
361 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
362 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
362 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
363 if self.data.localtime:
363 if self.data.localtime:
364 xmax += time.timezone
364 xmax += time.timezone
365 else:
365 else:
366 xmax = self.xmax
366 xmax = self.xmax
367
367
368 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
368 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
369 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
369 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
370
370
371 Y = numpy.array([5, 10, 20, 50, 100, 200, 500, 1000, 2000])
371 Y = numpy.array([5, 10, 20, 50, 100, 200, 500, 1000, 2000])
372 i = 1 if numpy.where(ymax-ymin < Y)[0][0] < 0 else numpy.where(ymax-ymin < Y)[0][0]
372 i = 1 if numpy.where(ymax-ymin < Y)[0][0] < 0 else numpy.where(ymax-ymin < Y)[0][0]
373 ystep = Y[i] / 5
373 ystep = Y[i] / 5
374
374
375 for n, ax in enumerate(self.axes):
375 for n, ax in enumerate(self.axes):
376 if ax.firsttime:
376 if ax.firsttime:
377 ax.set_facecolor(self.bgcolor)
377 ax.set_facecolor(self.bgcolor)
378 ax.yaxis.set_major_locator(MultipleLocator(ystep))
378 ax.yaxis.set_major_locator(MultipleLocator(ystep))
379 if self.xaxis is 'time':
379 if self.xaxis is 'time':
380 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
380 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
381 ax.xaxis.set_major_locator(LinearLocator(9))
381 ax.xaxis.set_major_locator(LinearLocator(9))
382 if self.xlabel is not None:
382 if self.xlabel is not None:
383 ax.set_xlabel(self.xlabel)
383 ax.set_xlabel(self.xlabel)
384 ax.set_ylabel(self.ylabel)
384 ax.set_ylabel(self.ylabel)
385 ax.firsttime = False
385 ax.firsttime = False
386 if self.showprofile:
386 if self.showprofile:
387 self.pf_axes[n].set_ylim(ymin, ymax)
387 self.pf_axes[n].set_ylim(ymin, ymax)
388 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
388 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
389 self.pf_axes[n].set_xlabel('dB')
389 self.pf_axes[n].set_xlabel('dB')
390 self.pf_axes[n].grid(b=True, axis='x')
390 self.pf_axes[n].grid(b=True, axis='x')
391 [tick.set_visible(False)
391 [tick.set_visible(False)
392 for tick in self.pf_axes[n].get_yticklabels()]
392 for tick in self.pf_axes[n].get_yticklabels()]
393 if self.colorbar:
393 if self.colorbar:
394 ax.cbar = plt.colorbar(
394 ax.cbar = plt.colorbar(
395 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
395 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
396 ax.cbar.ax.tick_params(labelsize=8)
396 ax.cbar.ax.tick_params(labelsize=8)
397 ax.cbar.ax.press = None
397 ax.cbar.ax.press = None
398 if self.cb_label:
398 if self.cb_label:
399 ax.cbar.set_label(self.cb_label, size=8)
399 ax.cbar.set_label(self.cb_label, size=8)
400 elif self.cb_labels:
400 elif self.cb_labels:
401 ax.cbar.set_label(self.cb_labels[n], size=8)
401 ax.cbar.set_label(self.cb_labels[n], size=8)
402 else:
402 else:
403 ax.cbar = None
403 ax.cbar = None
404
404
405 if not self.polar:
405 if not self.polar:
406 ax.set_xlim(xmin, xmax)
406 ax.set_xlim(xmin, xmax)
407 ax.set_ylim(ymin, ymax)
407 ax.set_ylim(ymin, ymax)
408 ax.set_title('{} - {} {}'.format(
408 ax.set_title('{} - {} {}'.format(
409 self.titles[n],
409 self.titles[n],
410 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
410 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
411 self.time_label),
411 self.time_label),
412 size=8)
412 size=8)
413 else:
413 else:
414 ax.set_title('{}'.format(self.titles[n]), size=8)
414 ax.set_title('{}'.format(self.titles[n]), size=8)
415 ax.set_ylim(0, 90)
415 ax.set_ylim(0, 90)
416 ax.set_yticks(numpy.arange(0, 90, 20))
416 ax.set_yticks(numpy.arange(0, 90, 20))
417 ax.yaxis.labelpad = 40
417 ax.yaxis.labelpad = 40
418
418
419 def __plot(self):
419 def __plot(self):
420 '''
420 '''
421 '''
421 '''
422 log.success('Plotting', self.name)
422 log.success('Plotting', self.name)
423
423
424 try:
424 try:
425 self.plot()
425 self.plot()
426 self.format()
426 self.format()
427 except:
427 except:
428 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
428 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
429
429
430 for n, fig in enumerate(self.figures):
430 for n, fig in enumerate(self.figures):
431 if self.nrows == 0 or self.nplots == 0:
431 if self.nrows == 0 or self.nplots == 0:
432 log.warning('No data', self.name)
432 log.warning('No data', self.name)
433 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
433 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
434 fig.canvas.manager.set_window_title(self.CODE)
434 fig.canvas.manager.set_window_title(self.CODE)
435 continue
435 continue
436
436
437 fig.tight_layout()
437 fig.tight_layout()
438 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
438 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
439 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
439 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
440 fig.canvas.draw()
440 fig.canvas.draw()
441
441
442 if self.save and self.data.ended:
442 if self.save and self.data.ended:
443 channels = range(self.nrows)
443 channels = range(self.nrows)
444 if self.oneFigure:
444 if self.oneFigure:
445 label = ''
445 label = ''
446 else:
446 else:
447 label = '_{}'.format(channels[n])
447 label = '_{}'.format(channels[n])
448 figname = os.path.join(
448 figname = os.path.join(
449 self.save,
449 self.save,
450 '{}{}_{}.png'.format(
450 '{}{}_{}.png'.format(
451 self.CODE,
451 self.CODE,
452 label,
452 label,
453 self.getDateTime(self.saveTime).strftime(
453 self.getDateTime(self.saveTime).strftime(
454 '%y%m%d_%H%M%S'),
454 '%Y%m%d_%H%M%S'),
455 )
455 )
456 )
456 )
457 log.log('Saving figure: {}'.format(figname), self.name)
457 log.log('Saving figure: {}'.format(figname), self.name)
458 fig.savefig(figname)
458 fig.savefig(figname)
459
459
460 def plot(self):
460 def plot(self):
461 '''
461 '''
462 '''
462 '''
463 raise(NotImplementedError, 'Implement this method in child class')
463 raise(NotImplementedError, 'Implement this method in child class')
464
464
465 def run(self):
465 def run(self):
466
466
467 log.success('Starting', self.name)
467 log.success('Starting', self.name)
468
468
469 context = zmq.Context()
469 context = zmq.Context()
470 receiver = context.socket(zmq.SUB)
470 receiver = context.socket(zmq.SUB)
471 receiver.setsockopt(zmq.SUBSCRIBE, '')
471 receiver.setsockopt(zmq.SUBSCRIBE, '')
472 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
472 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
473
473
474 if 'server' in self.kwargs['parent']:
474 if 'server' in self.kwargs['parent']:
475 receiver.connect(
475 receiver.connect(
476 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
476 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
477 else:
477 else:
478 receiver.connect("ipc:///tmp/zmq.plots")
478 receiver.connect("ipc:///tmp/zmq.plots")
479
479
480 while True:
480 while True:
481 try:
481 try:
482 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
482 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
483 if self.data.localtime and self.localtime:
483 if self.data.localtime and self.localtime:
484 self.times = self.data.times
484 self.times = self.data.times
485 elif self.data.localtime and not self.localtime:
485 elif self.data.localtime and not self.localtime:
486 self.times = self.data.times + time.timezone
486 self.times = self.data.times + time.timezone
487 elif not self.data.localtime and self.localtime:
487 elif not self.data.localtime and self.localtime:
488 self.times = self.data.times - time.timezone
488 self.times = self.data.times - time.timezone
489 else:
489 else:
490 self.times = self.data.times
490 self.times = self.data.times
491
491
492 self.min_time = self.times[0]
492 self.min_time = self.times[0]
493 self.max_time = self.times[-1]
493 self.max_time = self.times[-1]
494
494
495 if self.isConfig is False:
495 if self.isConfig is False:
496 self.__setup()
496 self.__setup()
497 self.isConfig = True
497 self.isConfig = True
498
498
499 self.__plot()
499 self.__plot()
500
500
501 except zmq.Again as e:
501 except zmq.Again as e:
502 log.log('Waiting for data...')
502 log.log('Waiting for data...')
503 if self.data:
503 if self.data:
504 figpause(self.data.throttle)
504 figpause(self.data.throttle)
505 else:
505 else:
506 time.sleep(2)
506 time.sleep(2)
507
507
508 def close(self):
508 def close(self):
509 if self.data:
509 if self.data:
510 self.__plot()
510 self.__plot()
511
511
512
512
513 class PlotSpectraData(PlotData):
513 class PlotSpectraData(PlotData):
514 '''
514 '''
515 Plot for Spectra data
515 Plot for Spectra data
516 '''
516 '''
517
517
518 CODE = 'spc'
518 CODE = 'spc'
519 colormap = 'jro'
519 colormap = 'jro'
520
520
521 def setup(self):
521 def setup(self):
522 self.nplots = len(self.data.channels)
522 self.nplots = len(self.data.channels)
523 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
523 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
524 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
524 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
525 self.width = 3.4 * self.ncols
525 self.width = 3.4 * self.ncols
526 self.height = 3 * self.nrows
526 self.height = 3 * self.nrows
527 self.cb_label = 'dB'
527 self.cb_label = 'dB'
528 if self.showprofile:
528 if self.showprofile:
529 self.width += 0.8 * self.ncols
529 self.width += 0.8 * self.ncols
530
530
531 self.ylabel = 'Range [Km]'
531 self.ylabel = 'Range [km]'
532
532
533 def plot(self):
533 def plot(self):
534 if self.xaxis == "frequency":
534 if self.xaxis == "frequency":
535 x = self.data.xrange[0]
535 x = self.data.xrange[0]
536 self.xlabel = "Frequency (kHz)"
536 self.xlabel = "Frequency (kHz)"
537 elif self.xaxis == "time":
537 elif self.xaxis == "time":
538 x = self.data.xrange[1]
538 x = self.data.xrange[1]
539 self.xlabel = "Time (ms)"
539 self.xlabel = "Time (ms)"
540 else:
540 else:
541 x = self.data.xrange[2]
541 x = self.data.xrange[2]
542 self.xlabel = "Velocity (m/s)"
542 self.xlabel = "Velocity (m/s)"
543
543
544 if self.CODE == 'spc_mean':
544 if self.CODE == 'spc_mean':
545 x = self.data.xrange[2]
545 x = self.data.xrange[2]
546 self.xlabel = "Velocity (m/s)"
546 self.xlabel = "Velocity (m/s)"
547
547
548 self.titles = []
548 self.titles = []
549
549
550 y = self.data.heights
550 y = self.data.heights
551 self.y = y
551 self.y = y
552 z = self.data['spc']
552 z = self.data['spc']
553
553
554 for n, ax in enumerate(self.axes):
554 for n, ax in enumerate(self.axes):
555 noise = self.data['noise'][n][-1]
555 noise = self.data['noise'][n][-1]
556 if self.CODE == 'spc_mean':
556 if self.CODE == 'spc_mean':
557 mean = self.data['mean'][n][-1]
557 mean = self.data['mean'][n][-1]
558 if ax.firsttime:
558 if ax.firsttime:
559 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
559 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
560 self.xmin = self.xmin if self.xmin else -self.xmax
560 self.xmin = self.xmin if self.xmin else -self.xmax
561 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
561 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
562 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
562 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
563 ax.plt = ax.pcolormesh(x, y, z[n].T,
563 ax.plt = ax.pcolormesh(x, y, z[n].T,
564 vmin=self.zmin,
564 vmin=self.zmin,
565 vmax=self.zmax,
565 vmax=self.zmax,
566 cmap=plt.get_cmap(self.colormap)
566 cmap=plt.get_cmap(self.colormap)
567 )
567 )
568
568
569 if self.showprofile:
569 if self.showprofile:
570 ax.plt_profile = self.pf_axes[n].plot(
570 ax.plt_profile = self.pf_axes[n].plot(
571 self.data['rti'][n][-1], y)[0]
571 self.data['rti'][n][-1], y)[0]
572 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
572 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
573 color="k", linestyle="dashed", lw=1)[0]
573 color="k", linestyle="dashed", lw=1)[0]
574 if self.CODE == 'spc_mean':
574 if self.CODE == 'spc_mean':
575 ax.plt_mean = ax.plot(mean, y, color='k')[0]
575 ax.plt_mean = ax.plot(mean, y, color='k')[0]
576 else:
576 else:
577 ax.plt.set_array(z[n].T.ravel())
577 ax.plt.set_array(z[n].T.ravel())
578 if self.showprofile:
578 if self.showprofile:
579 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
579 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
580 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
580 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
581 if self.CODE == 'spc_mean':
581 if self.CODE == 'spc_mean':
582 ax.plt_mean.set_data(mean, y)
582 ax.plt_mean.set_data(mean, y)
583
583
584 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
584 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
585 self.saveTime = self.max_time
585 self.saveTime = self.max_time
586
586
587
587
588 class PlotCrossSpectraData(PlotData):
588 class PlotCrossSpectraData(PlotData):
589
589
590 CODE = 'cspc'
590 CODE = 'cspc'
591 zmin_coh = None
591 zmin_coh = None
592 zmax_coh = None
592 zmax_coh = None
593 zmin_phase = None
593 zmin_phase = None
594 zmax_phase = None
594 zmax_phase = None
595
595
596 def setup(self):
596 def setup(self):
597
597
598 self.ncols = 4
598 self.ncols = 4
599 self.nrows = len(self.data.pairs)
599 self.nrows = len(self.data.pairs)
600 self.nplots = self.nrows * 4
600 self.nplots = self.nrows * 4
601 self.width = 3.4 * self.ncols
601 self.width = 3.4 * self.ncols
602 self.height = 3 * self.nrows
602 self.height = 3 * self.nrows
603 self.ylabel = 'Range [Km]'
603 self.ylabel = 'Range [km]'
604 self.showprofile = False
604 self.showprofile = False
605
605
606 def plot(self):
606 def plot(self):
607
607
608 if self.xaxis == "frequency":
608 if self.xaxis == "frequency":
609 x = self.data.xrange[0]
609 x = self.data.xrange[0]
610 self.xlabel = "Frequency (kHz)"
610 self.xlabel = "Frequency (kHz)"
611 elif self.xaxis == "time":
611 elif self.xaxis == "time":
612 x = self.data.xrange[1]
612 x = self.data.xrange[1]
613 self.xlabel = "Time (ms)"
613 self.xlabel = "Time (ms)"
614 else:
614 else:
615 x = self.data.xrange[2]
615 x = self.data.xrange[2]
616 self.xlabel = "Velocity (m/s)"
616 self.xlabel = "Velocity (m/s)"
617
617
618 self.titles = []
618 self.titles = []
619
619
620 y = self.data.heights
620 y = self.data.heights
621 self.y = y
621 self.y = y
622 spc = self.data['spc']
622 spc = self.data['spc']
623 cspc = self.data['cspc']
623 cspc = self.data['cspc']
624
624
625 for n in range(self.nrows):
625 for n in range(self.nrows):
626 noise = self.data['noise'][n][-1]
626 noise = self.data['noise'][n][-1]
627 pair = self.data.pairs[n]
627 pair = self.data.pairs[n]
628 ax = self.axes[4 * n]
628 ax = self.axes[4 * n]
629 ax3 = self.axes[4 * n + 3]
629 ax3 = self.axes[4 * n + 3]
630 if ax.firsttime:
630 if ax.firsttime:
631 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
631 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
632 self.xmin = self.xmin if self.xmin else -self.xmax
632 self.xmin = self.xmin if self.xmin else -self.xmax
633 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
633 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
634 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
634 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
635 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
635 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
636 vmin=self.zmin,
636 vmin=self.zmin,
637 vmax=self.zmax,
637 vmax=self.zmax,
638 cmap=plt.get_cmap(self.colormap)
638 cmap=plt.get_cmap(self.colormap)
639 )
639 )
640 else:
640 else:
641 ax.plt.set_array(spc[pair[0]].T.ravel())
641 ax.plt.set_array(spc[pair[0]].T.ravel())
642 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
642 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
643
643
644 ax = self.axes[4 * n + 1]
644 ax = self.axes[4 * n + 1]
645 if ax.firsttime:
645 if ax.firsttime:
646 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
646 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
647 vmin=self.zmin,
647 vmin=self.zmin,
648 vmax=self.zmax,
648 vmax=self.zmax,
649 cmap=plt.get_cmap(self.colormap)
649 cmap=plt.get_cmap(self.colormap)
650 )
650 )
651 else:
651 else:
652 ax.plt.set_array(spc[pair[1]].T.ravel())
652 ax.plt.set_array(spc[pair[1]].T.ravel())
653 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
653 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
654
654
655 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
655 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
656 coh = numpy.abs(out)
656 coh = numpy.abs(out)
657 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
657 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
658
658
659 ax = self.axes[4 * n + 2]
659 ax = self.axes[4 * n + 2]
660 if ax.firsttime:
660 if ax.firsttime:
661 ax.plt = ax.pcolormesh(x, y, coh.T,
661 ax.plt = ax.pcolormesh(x, y, coh.T,
662 vmin=0,
662 vmin=0,
663 vmax=1,
663 vmax=1,
664 cmap=plt.get_cmap(self.colormap_coh)
664 cmap=plt.get_cmap(self.colormap_coh)
665 )
665 )
666 else:
666 else:
667 ax.plt.set_array(coh.T.ravel())
667 ax.plt.set_array(coh.T.ravel())
668 self.titles.append(
668 self.titles.append(
669 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
669 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
670
670
671 ax = self.axes[4 * n + 3]
671 ax = self.axes[4 * n + 3]
672 if ax.firsttime:
672 if ax.firsttime:
673 ax.plt = ax.pcolormesh(x, y, phase.T,
673 ax.plt = ax.pcolormesh(x, y, phase.T,
674 vmin=-180,
674 vmin=-180,
675 vmax=180,
675 vmax=180,
676 cmap=plt.get_cmap(self.colormap_phase)
676 cmap=plt.get_cmap(self.colormap_phase)
677 )
677 )
678 else:
678 else:
679 ax.plt.set_array(phase.T.ravel())
679 ax.plt.set_array(phase.T.ravel())
680 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
680 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
681
681
682 self.saveTime = self.max_time
682 self.saveTime = self.max_time
683
683
684
684
685 class PlotSpectraMeanData(PlotSpectraData):
685 class PlotSpectraMeanData(PlotSpectraData):
686 '''
686 '''
687 Plot for Spectra and Mean
687 Plot for Spectra and Mean
688 '''
688 '''
689 CODE = 'spc_mean'
689 CODE = 'spc_mean'
690 colormap = 'jro'
690 colormap = 'jro'
691
691
692
692
693 class PlotRTIData(PlotData):
693 class PlotRTIData(PlotData):
694 '''
694 '''
695 Plot for RTI data
695 Plot for RTI data
696 '''
696 '''
697
697
698 CODE = 'rti'
698 CODE = 'rti'
699 colormap = 'jro'
699 colormap = 'jro'
700
700
701 def setup(self):
701 def setup(self):
702 self.xaxis = 'time'
702 self.xaxis = 'time'
703 self.ncols = 1
703 self.ncols = 1
704 self.nrows = len(self.data.channels)
704 self.nrows = len(self.data.channels)
705 self.nplots = len(self.data.channels)
705 self.nplots = len(self.data.channels)
706 self.ylabel = 'Range [Km]'
706 self.ylabel = 'Range [km]'
707 self.cb_label = 'dB'
707 self.cb_label = 'dB'
708 self.titles = ['{} Channel {}'.format(
708 self.titles = ['{} Channel {}'.format(
709 self.CODE.upper(), x) for x in range(self.nrows)]
709 self.CODE.upper(), x) for x in range(self.nrows)]
710
710
711 def plot(self):
711 def plot(self):
712 self.x = self.times
712 self.x = self.times
713 self.y = self.data.heights
713 self.y = self.data.heights
714 self.z = self.data[self.CODE]
714 self.z = self.data[self.CODE]
715 self.z = numpy.ma.masked_invalid(self.z)
715 self.z = numpy.ma.masked_invalid(self.z)
716
716
717 if self.decimation is None:
717 if self.decimation is None:
718 x, y, z = self.fill_gaps(self.x, self.y, self.z)
718 x, y, z = self.fill_gaps(self.x, self.y, self.z)
719 else:
719 else:
720 x, y, z = self.fill_gaps(*self.decimate())
720 x, y, z = self.fill_gaps(*self.decimate())
721
721
722 for n, ax in enumerate(self.axes):
722 for n, ax in enumerate(self.axes):
723 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
723 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
724 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
724 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
725 if ax.firsttime:
725 if ax.firsttime:
726 ax.plt = ax.pcolormesh(x, y, z[n].T,
726 ax.plt = ax.pcolormesh(x, y, z[n].T,
727 vmin=self.zmin,
727 vmin=self.zmin,
728 vmax=self.zmax,
728 vmax=self.zmax,
729 cmap=plt.get_cmap(self.colormap)
729 cmap=plt.get_cmap(self.colormap)
730 )
730 )
731 if self.showprofile:
731 if self.showprofile:
732 ax.plot_profile = self.pf_axes[n].plot(
732 ax.plot_profile = self.pf_axes[n].plot(
733 self.data['rti'][n][-1], self.y)[0]
733 self.data['rti'][n][-1], self.y)[0]
734 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
734 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
735 color="k", linestyle="dashed", lw=1)[0]
735 color="k", linestyle="dashed", lw=1)[0]
736 else:
736 else:
737 ax.collections.remove(ax.collections[0])
737 ax.collections.remove(ax.collections[0])
738 ax.plt = ax.pcolormesh(x, y, z[n].T,
738 ax.plt = ax.pcolormesh(x, y, z[n].T,
739 vmin=self.zmin,
739 vmin=self.zmin,
740 vmax=self.zmax,
740 vmax=self.zmax,
741 cmap=plt.get_cmap(self.colormap)
741 cmap=plt.get_cmap(self.colormap)
742 )
742 )
743 if self.showprofile:
743 if self.showprofile:
744 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
744 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
745 ax.plot_noise.set_data(numpy.repeat(
745 ax.plot_noise.set_data(numpy.repeat(
746 self.data['noise'][n][-1], len(self.y)), self.y)
746 self.data['noise'][n][-1], len(self.y)), self.y)
747
747
748 self.saveTime = self.min_time
748 self.saveTime = self.min_time
749
749
750
750
751 class PlotCOHData(PlotRTIData):
751 class PlotCOHData(PlotRTIData):
752 '''
752 '''
753 Plot for Coherence data
753 Plot for Coherence data
754 '''
754 '''
755
755
756 CODE = 'coh'
756 CODE = 'coh'
757
757
758 def setup(self):
758 def setup(self):
759 self.xaxis = 'time'
759 self.xaxis = 'time'
760 self.ncols = 1
760 self.ncols = 1
761 self.nrows = len(self.data.pairs)
761 self.nrows = len(self.data.pairs)
762 self.nplots = len(self.data.pairs)
762 self.nplots = len(self.data.pairs)
763 self.ylabel = 'Range [Km]'
763 self.ylabel = 'Range [km]'
764 if self.CODE == 'coh':
764 if self.CODE == 'coh':
765 self.cb_label = ''
765 self.cb_label = ''
766 self.titles = [
766 self.titles = [
767 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
767 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
768 else:
768 else:
769 self.cb_label = 'Degrees'
769 self.cb_label = 'Degrees'
770 self.titles = [
770 self.titles = [
771 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
771 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
772
772
773
773
774 class PlotPHASEData(PlotCOHData):
774 class PlotPHASEData(PlotCOHData):
775 '''
775 '''
776 Plot for Phase map data
776 Plot for Phase map data
777 '''
777 '''
778
778
779 CODE = 'phase'
779 CODE = 'phase'
780 colormap = 'seismic'
780 colormap = 'seismic'
781
781
782
782
783 class PlotNoiseData(PlotData):
783 class PlotNoiseData(PlotData):
784 '''
784 '''
785 Plot for noise
785 Plot for noise
786 '''
786 '''
787
787
788 CODE = 'noise'
788 CODE = 'noise'
789
789
790 def setup(self):
790 def setup(self):
791 self.xaxis = 'time'
791 self.xaxis = 'time'
792 self.ncols = 1
792 self.ncols = 1
793 self.nrows = 1
793 self.nrows = 1
794 self.nplots = 1
794 self.nplots = 1
795 self.ylabel = 'Intensity [dB]'
795 self.ylabel = 'Intensity [dB]'
796 self.titles = ['Noise']
796 self.titles = ['Noise']
797 self.colorbar = False
797 self.colorbar = False
798
798
799 def plot(self):
799 def plot(self):
800
800
801 x = self.times
801 x = self.times
802 xmin = self.min_time
802 xmin = self.min_time
803 xmax = xmin + self.xrange * 60 * 60
803 xmax = xmin + self.xrange * 60 * 60
804 Y = self.data[self.CODE]
804 Y = self.data[self.CODE]
805
805
806 if self.axes[0].firsttime:
806 if self.axes[0].firsttime:
807 for ch in self.data.channels:
807 for ch in self.data.channels:
808 y = Y[ch]
808 y = Y[ch]
809 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
809 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
810 plt.legend()
810 plt.legend()
811 else:
811 else:
812 for ch in self.data.channels:
812 for ch in self.data.channels:
813 y = Y[ch]
813 y = Y[ch]
814 self.axes[0].lines[ch].set_data(x, y)
814 self.axes[0].lines[ch].set_data(x, y)
815
815
816 self.ymin = numpy.nanmin(Y) - 5
816 self.ymin = numpy.nanmin(Y) - 5
817 self.ymax = numpy.nanmax(Y) + 5
817 self.ymax = numpy.nanmax(Y) + 5
818 self.saveTime = self.min_time
818 self.saveTime = self.min_time
819
819
820
820
821 class PlotSNRData(PlotRTIData):
821 class PlotSNRData(PlotRTIData):
822 '''
822 '''
823 Plot for SNR Data
823 Plot for SNR Data
824 '''
824 '''
825
825
826 CODE = 'snr'
826 CODE = 'snr'
827 colormap = 'jet'
827 colormap = 'jet'
828
828
829
829
830 class PlotDOPData(PlotRTIData):
830 class PlotDOPData(PlotRTIData):
831 '''
831 '''
832 Plot for DOPPLER Data
832 Plot for DOPPLER Data
833 '''
833 '''
834
834
835 CODE = 'dop'
835 CODE = 'dop'
836 colormap = 'jet'
836 colormap = 'jet'
837
837
838
838
839 class PlotSkyMapData(PlotData):
839 class PlotSkyMapData(PlotData):
840 '''
840 '''
841 Plot for meteors detection data
841 Plot for meteors detection data
842 '''
842 '''
843
843
844 CODE = 'param'
844 CODE = 'param'
845
845
846 def setup(self):
846 def setup(self):
847
847
848 self.ncols = 1
848 self.ncols = 1
849 self.nrows = 1
849 self.nrows = 1
850 self.width = 7.2
850 self.width = 7.2
851 self.height = 7.2
851 self.height = 7.2
852 self.nplots = 1
852 self.nplots = 1
853 self.xlabel = 'Zonal Zenith Angle (deg)'
853 self.xlabel = 'Zonal Zenith Angle (deg)'
854 self.ylabel = 'Meridional Zenith Angle (deg)'
854 self.ylabel = 'Meridional Zenith Angle (deg)'
855 self.polar = True
855 self.polar = True
856 self.ymin = -180
856 self.ymin = -180
857 self.ymax = 180
857 self.ymax = 180
858 self.colorbar = False
858 self.colorbar = False
859
859
860 def plot(self):
860 def plot(self):
861
861
862 arrayParameters = numpy.concatenate(self.data['param'])
862 arrayParameters = numpy.concatenate(self.data['param'])
863 error = arrayParameters[:, -1]
863 error = arrayParameters[:, -1]
864 indValid = numpy.where(error == 0)[0]
864 indValid = numpy.where(error == 0)[0]
865 finalMeteor = arrayParameters[indValid, :]
865 finalMeteor = arrayParameters[indValid, :]
866 finalAzimuth = finalMeteor[:, 3]
866 finalAzimuth = finalMeteor[:, 3]
867 finalZenith = finalMeteor[:, 4]
867 finalZenith = finalMeteor[:, 4]
868
868
869 x = finalAzimuth * numpy.pi / 180
869 x = finalAzimuth * numpy.pi / 180
870 y = finalZenith
870 y = finalZenith
871
871
872 ax = self.axes[0]
872 ax = self.axes[0]
873
873
874 if ax.firsttime:
874 if ax.firsttime:
875 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
875 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
876 else:
876 else:
877 ax.plot.set_data(x, y)
877 ax.plot.set_data(x, y)
878
878
879 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
879 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
880 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
880 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
881 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
881 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
882 dt2,
882 dt2,
883 len(x))
883 len(x))
884 self.titles[0] = title
884 self.titles[0] = title
885 self.saveTime = self.max_time
885 self.saveTime = self.max_time
886
886
887
887
888 class PlotParamData(PlotRTIData):
888 class PlotParamData(PlotRTIData):
889 '''
889 '''
890 Plot for data_param object
890 Plot for data_param object
891 '''
891 '''
892
892
893 CODE = 'param'
893 CODE = 'param'
894 colormap = 'seismic'
894 colormap = 'seismic'
895
895
896 def setup(self):
896 def setup(self):
897 self.xaxis = 'time'
897 self.xaxis = 'time'
898 self.ncols = 1
898 self.ncols = 1
899 self.nrows = self.data.shape(self.CODE)[0]
899 self.nrows = self.data.shape(self.CODE)[0]
900 self.nplots = self.nrows
900 self.nplots = self.nrows
901 if self.showSNR:
901 if self.showSNR:
902 self.nrows += 1
902 self.nrows += 1
903 self.nplots += 1
903 self.nplots += 1
904
904
905 self.ylabel = 'Height [Km]'
905 self.ylabel = 'Height [km]'
906 if not self.titles:
906 if not self.titles:
907 self.titles = self.data.parameters \
907 self.titles = self.data.parameters \
908 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
908 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
909 if self.showSNR:
909 if self.showSNR:
910 self.titles.append('SNR')
910 self.titles.append('SNR')
911
911
912 def plot(self):
912 def plot(self):
913 self.data.normalize_heights()
913 self.data.normalize_heights()
914 self.x = self.times
914 self.x = self.times
915 self.y = self.data.heights
915 self.y = self.data.heights
916 if self.showSNR:
916 if self.showSNR:
917 self.z = numpy.concatenate(
917 self.z = numpy.concatenate(
918 (self.data[self.CODE], self.data['snr'])
918 (self.data[self.CODE], self.data['snr'])
919 )
919 )
920 else:
920 else:
921 self.z = self.data[self.CODE]
921 self.z = self.data[self.CODE]
922
922
923 self.z = numpy.ma.masked_invalid(self.z)
923 self.z = numpy.ma.masked_invalid(self.z)
924
924
925 if self.decimation is None:
925 if self.decimation is None:
926 x, y, z = self.fill_gaps(self.x, self.y, self.z)
926 x, y, z = self.fill_gaps(self.x, self.y, self.z)
927 else:
927 else:
928 x, y, z = self.fill_gaps(*self.decimate())
928 x, y, z = self.fill_gaps(*self.decimate())
929
929
930 for n, ax in enumerate(self.axes):
930 for n, ax in enumerate(self.axes):
931
931
932 self.zmax = self.zmax if self.zmax is not None else numpy.max(
932 self.zmax = self.zmax if self.zmax is not None else numpy.max(
933 self.z[n])
933 self.z[n])
934 self.zmin = self.zmin if self.zmin is not None else numpy.min(
934 self.zmin = self.zmin if self.zmin is not None else numpy.min(
935 self.z[n])
935 self.z[n])
936
936
937 if ax.firsttime:
937 if ax.firsttime:
938 if self.zlimits is not None:
938 if self.zlimits is not None:
939 self.zmin, self.zmax = self.zlimits[n]
939 self.zmin, self.zmax = self.zlimits[n]
940
940
941 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
941 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
942 vmin=self.zmin,
942 vmin=self.zmin,
943 vmax=self.zmax,
943 vmax=self.zmax,
944 cmap=self.cmaps[n]
944 cmap=self.cmaps[n]
945 )
945 )
946 else:
946 else:
947 if self.zlimits is not None:
947 if self.zlimits is not None:
948 self.zmin, self.zmax = self.zlimits[n]
948 self.zmin, self.zmax = self.zlimits[n]
949 ax.collections.remove(ax.collections[0])
949 ax.collections.remove(ax.collections[0])
950 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
950 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
951 vmin=self.zmin,
951 vmin=self.zmin,
952 vmax=self.zmax,
952 vmax=self.zmax,
953 cmap=self.cmaps[n]
953 cmap=self.cmaps[n]
954 )
954 )
955
955
956 self.saveTime = self.min_time
956 self.saveTime = self.min_time
957
957
958
958
959 class PlotOutputData(PlotParamData):
959 class PlotOutputData(PlotParamData):
960 '''
960 '''
961 Plot data_output object
961 Plot data_output object
962 '''
962 '''
963
963
964 CODE = 'output'
964 CODE = 'output'
965 colormap = 'seismic'
965 colormap = 'seismic'
@@ -1,627 +1,631
1 '''
1 '''
2 @author: Juan C. Espinoza
2 @author: Juan C. Espinoza
3 '''
3 '''
4
4
5 import time
5 import time
6 import json
6 import json
7 import numpy
7 import numpy
8 import paho.mqtt.client as mqtt
8 import paho.mqtt.client as mqtt
9 import zmq
9 import zmq
10 import datetime
10 import datetime
11 from zmq.utils.monitor import recv_monitor_message
11 from zmq.utils.monitor import recv_monitor_message
12 from functools import wraps
12 from functools import wraps
13 from threading import Thread
13 from threading import Thread
14 from multiprocessing import Process
14 from multiprocessing import Process
15
15
16 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
16 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
17 from schainpy.model.data.jrodata import JROData
17 from schainpy.model.data.jrodata import JROData
18 from schainpy.utils import log
18 from schainpy.utils import log
19
19
20 MAXNUMX = 100
20 MAXNUMX = 100
21 MAXNUMY = 100
21 MAXNUMY = 100
22
22
23 class PrettyFloat(float):
23 class PrettyFloat(float):
24 def __repr__(self):
24 def __repr__(self):
25 return '%.2f' % self
25 return '%.2f' % self
26
26
27 def roundFloats(obj):
27 def roundFloats(obj):
28 if isinstance(obj, list):
28 if isinstance(obj, list):
29 return map(roundFloats, obj)
29 return map(roundFloats, obj)
30 elif isinstance(obj, float):
30 elif isinstance(obj, float):
31 return round(obj, 2)
31 return round(obj, 2)
32
32
33 def decimate(z, MAXNUMY):
33 def decimate(z, MAXNUMY):
34 dy = int(len(z[0])/MAXNUMY) + 1
34 dy = int(len(z[0])/MAXNUMY) + 1
35
35
36 return z[::, ::dy]
36 return z[::, ::dy]
37
37
38 class throttle(object):
38 class throttle(object):
39 '''
39 '''
40 Decorator that prevents a function from being called more than once every
40 Decorator that prevents a function from being called more than once every
41 time period.
41 time period.
42 To create a function that cannot be called more than once a minute, but
42 To create a function that cannot be called more than once a minute, but
43 will sleep until it can be called:
43 will sleep until it can be called:
44 @throttle(minutes=1)
44 @throttle(minutes=1)
45 def foo():
45 def foo():
46 pass
46 pass
47
47
48 for i in range(10):
48 for i in range(10):
49 foo()
49 foo()
50 print "This function has run %s times." % i
50 print "This function has run %s times." % i
51 '''
51 '''
52
52
53 def __init__(self, seconds=0, minutes=0, hours=0):
53 def __init__(self, seconds=0, minutes=0, hours=0):
54 self.throttle_period = datetime.timedelta(
54 self.throttle_period = datetime.timedelta(
55 seconds=seconds, minutes=minutes, hours=hours
55 seconds=seconds, minutes=minutes, hours=hours
56 )
56 )
57
57
58 self.time_of_last_call = datetime.datetime.min
58 self.time_of_last_call = datetime.datetime.min
59
59
60 def __call__(self, fn):
60 def __call__(self, fn):
61 @wraps(fn)
61 @wraps(fn)
62 def wrapper(*args, **kwargs):
62 def wrapper(*args, **kwargs):
63 coerce = kwargs.pop('coerce', None)
63 coerce = kwargs.pop('coerce', None)
64 if coerce:
64 if coerce:
65 self.time_of_last_call = datetime.datetime.now()
65 self.time_of_last_call = datetime.datetime.now()
66 return fn(*args, **kwargs)
66 return fn(*args, **kwargs)
67 else:
67 else:
68 now = datetime.datetime.now()
68 now = datetime.datetime.now()
69 time_since_last_call = now - self.time_of_last_call
69 time_since_last_call = now - self.time_of_last_call
70 time_left = self.throttle_period - time_since_last_call
70 time_left = self.throttle_period - time_since_last_call
71
71
72 if time_left > datetime.timedelta(seconds=0):
72 if time_left > datetime.timedelta(seconds=0):
73 return
73 return
74
74
75 self.time_of_last_call = datetime.datetime.now()
75 self.time_of_last_call = datetime.datetime.now()
76 return fn(*args, **kwargs)
76 return fn(*args, **kwargs)
77
77
78 return wrapper
78 return wrapper
79
79
80 class Data(object):
80 class Data(object):
81 '''
81 '''
82 Object to hold data to be plotted
82 Object to hold data to be plotted
83 '''
83 '''
84
84
85 def __init__(self, plottypes, throttle_value, exp_code):
85 def __init__(self, plottypes, throttle_value, exp_code):
86 self.plottypes = plottypes
86 self.plottypes = plottypes
87 self.throttle = throttle_value
87 self.throttle = throttle_value
88 self.exp_code = exp_code
88 self.exp_code = exp_code
89 self.ended = False
89 self.ended = False
90 self.localtime = False
90 self.localtime = False
91 self.__times = []
91 self.__times = []
92 self.__heights = []
92 self.__heights = []
93
93
94 def __str__(self):
94 def __str__(self):
95 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
95 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
96 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
96 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
97
97
98 def __len__(self):
98 def __len__(self):
99 return len(self.__times)
99 return len(self.__times)
100
100
101 def __getitem__(self, key):
101 def __getitem__(self, key):
102 if key not in self.data:
102 if key not in self.data:
103 raise KeyError(log.error('Missing key: {}'.format(key)))
103 raise KeyError(log.error('Missing key: {}'.format(key)))
104
104
105 if 'spc' in key:
105 if 'spc' in key:
106 ret = self.data[key]
106 ret = self.data[key]
107 else:
107 else:
108 ret = numpy.array([self.data[key][x] for x in self.times])
108 ret = numpy.array([self.data[key][x] for x in self.times])
109 if ret.ndim > 1:
109 if ret.ndim > 1:
110 ret = numpy.swapaxes(ret, 0, 1)
110 ret = numpy.swapaxes(ret, 0, 1)
111 return ret
111 return ret
112
112
113 def __contains__(self, key):
113 def __contains__(self, key):
114 return key in self.data
114 return key in self.data
115
115
116 def setup(self):
116 def setup(self):
117 '''
117 '''
118 Configure object
118 Configure object
119 '''
119 '''
120
120
121 self.ended = False
121 self.ended = False
122 self.data = {}
122 self.data = {}
123 self.__times = []
123 self.__times = []
124 self.__heights = []
124 self.__heights = []
125 self.__all_heights = set()
125 self.__all_heights = set()
126 for plot in self.plottypes:
126 for plot in self.plottypes:
127 if 'snr' in plot:
127 if 'snr' in plot:
128 plot = 'snr'
128 plot = 'snr'
129 self.data[plot] = {}
129 self.data[plot] = {}
130
130
131 def shape(self, key):
131 def shape(self, key):
132 '''
132 '''
133 Get the shape of the one-element data for the given key
133 Get the shape of the one-element data for the given key
134 '''
134 '''
135
135
136 if len(self.data[key]):
136 if len(self.data[key]):
137 if 'spc' in key:
137 if 'spc' in key:
138 return self.data[key].shape
138 return self.data[key].shape
139 return self.data[key][self.__times[0]].shape
139 return self.data[key][self.__times[0]].shape
140 return (0,)
140 return (0,)
141
141
142 def update(self, dataOut, tm):
142 def update(self, dataOut, tm):
143 '''
143 '''
144 Update data object with new dataOut
144 Update data object with new dataOut
145 '''
145 '''
146
146
147 if tm in self.__times:
147 if tm in self.__times:
148 return
148 return
149
149
150 self.parameters = getattr(dataOut, 'parameters', [])
150 self.parameters = getattr(dataOut, 'parameters', [])
151 if hasattr(dataOut, 'pairsList'):
151 if hasattr(dataOut, 'pairsList'):
152 self.pairs = dataOut.pairsList
152 self.pairs = dataOut.pairsList
153 self.channels = dataOut.channelList
153 self.channels = dataOut.channelList
154 self.interval = dataOut.getTimeInterval()
154 self.interval = dataOut.getTimeInterval()
155 self.localtime = dataOut.useLocalTime
155 self.localtime = dataOut.useLocalTime
156 if 'spc' in self.plottypes or 'cspc' in self.plottypes:
156 if 'spc' in self.plottypes or 'cspc' in self.plottypes:
157 self.xrange = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
157 self.xrange = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
158 self.__heights.append(dataOut.heightList)
158 self.__heights.append(dataOut.heightList)
159 self.__all_heights.update(dataOut.heightList)
159 self.__all_heights.update(dataOut.heightList)
160 self.__times.append(tm)
160 self.__times.append(tm)
161
161
162 for plot in self.plottypes:
162 for plot in self.plottypes:
163 if plot == 'spc':
163 if plot == 'spc':
164 z = dataOut.data_spc/dataOut.normFactor
164 z = dataOut.data_spc/dataOut.normFactor
165 self.data[plot] = 10*numpy.log10(z)
165 self.data[plot] = 10*numpy.log10(z)
166 if plot == 'cspc':
166 if plot == 'cspc':
167 self.data[plot] = dataOut.data_cspc
167 self.data[plot] = dataOut.data_cspc
168 if plot == 'noise':
168 if plot == 'noise':
169 self.data[plot][tm] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
169 self.data[plot][tm] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
170 if plot == 'rti':
170 if plot == 'rti':
171 self.data[plot][tm] = dataOut.getPower()
171 self.data[plot][tm] = dataOut.getPower()
172 if plot == 'snr_db':
172 if plot == 'snr_db':
173 self.data['snr'][tm] = dataOut.data_SNR
173 self.data['snr'][tm] = dataOut.data_SNR
174 if plot == 'snr':
174 if plot == 'snr':
175 self.data[plot][tm] = 10*numpy.log10(dataOut.data_SNR)
175 self.data[plot][tm] = 10*numpy.log10(dataOut.data_SNR)
176 if plot == 'dop':
176 if plot == 'dop':
177 self.data[plot][tm] = 10*numpy.log10(dataOut.data_DOP)
177 self.data[plot][tm] = 10*numpy.log10(dataOut.data_DOP)
178 if plot == 'mean':
178 if plot == 'mean':
179 self.data[plot][tm] = dataOut.data_MEAN
179 self.data[plot][tm] = dataOut.data_MEAN
180 if plot == 'std':
180 if plot == 'std':
181 self.data[plot][tm] = dataOut.data_STD
181 self.data[plot][tm] = dataOut.data_STD
182 if plot == 'coh':
182 if plot == 'coh':
183 self.data[plot][tm] = dataOut.getCoherence()
183 self.data[plot][tm] = dataOut.getCoherence()
184 if plot == 'phase':
184 if plot == 'phase':
185 self.data[plot][tm] = dataOut.getCoherence(phase=True)
185 self.data[plot][tm] = dataOut.getCoherence(phase=True)
186 if plot == 'output':
186 if plot == 'output':
187 self.data[plot][tm] = dataOut.data_output
187 self.data[plot][tm] = dataOut.data_output
188 if plot == 'param':
188 if plot == 'param':
189 self.data[plot][tm] = dataOut.data_param
189 self.data[plot][tm] = dataOut.data_param
190
190
191 def normalize_heights(self):
191 def normalize_heights(self):
192 '''
192 '''
193 Ensure same-dimension of the data for different heighList
193 Ensure same-dimension of the data for different heighList
194 '''
194 '''
195
195
196 H = numpy.array(list(self.__all_heights))
196 H = numpy.array(list(self.__all_heights))
197 H.sort()
197 H.sort()
198 for key in self.data:
198 for key in self.data:
199 shape = self.shape(key)[:-1] + H.shape
199 shape = self.shape(key)[:-1] + H.shape
200 for tm, obj in self.data[key].items():
200 for tm, obj in self.data[key].items():
201 h = self.__heights[self.__times.index(tm)]
201 h = self.__heights[self.__times.index(tm)]
202 if H.size == h.size:
202 if H.size == h.size:
203 continue
203 continue
204 index = numpy.where(numpy.in1d(H, h))[0]
204 index = numpy.where(numpy.in1d(H, h))[0]
205 dummy = numpy.zeros(shape) + numpy.nan
205 dummy = numpy.zeros(shape) + numpy.nan
206 if len(shape) == 2:
206 if len(shape) == 2:
207 dummy[:, index] = obj
207 dummy[:, index] = obj
208 else:
208 else:
209 dummy[index] = obj
209 dummy[index] = obj
210 self.data[key][tm] = dummy
210 self.data[key][tm] = dummy
211
211
212 self.__heights = [H for tm in self.__times]
212 self.__heights = [H for tm in self.__times]
213
213
214 def jsonify(self, decimate=False):
214 def jsonify(self, decimate=False):
215 '''
215 '''
216 Convert data to json
216 Convert data to json
217 '''
217 '''
218
218
219 data = {}
219 data = {}
220 tm = self.times[-1]
220 tm = self.times[-1]
221
221
222 for key in self.data:
222 for key in self.data:
223 if key in ('spc', 'cspc'):
223 if key in ('spc', 'cspc'):
224 data[key] = roundFloats(self.data[key].tolist())
224 dx = int(self.data[key].shape[1]/MAXNUMX) + 1
225 dy = int(self.data[key].shape[2]/MAXNUMY) + 1
226 data[key] = roundFloats(self.data[key][::, ::dx, ::dy].tolist())
225 else:
227 else:
226 data[key] = roundFloats(self.data[key][tm].tolist())
228 data[key] = roundFloats(self.data[key][tm].tolist())
227
229
228 ret = {'data': data}
230 ret = {'data': data}
229 ret['exp_code'] = self.exp_code
231 ret['exp_code'] = self.exp_code
230 ret['time'] = tm
232 ret['time'] = tm
231 ret['interval'] = self.interval
233 ret['interval'] = self.interval
232 ret['ymin'] = self.heights[0]
234 ret['localtime'] = self.localtime
233 ret['ymax'] = self.heights[-1]
235 ret['yrange'] = roundFloats(self.heights.tolist())
234 ret['ystep'] = self.heights[1] - self.heights[0]
236 if key in ('spc', 'cspc'):
235
237 ret['xrange'] = roundFloats(self.xrange[2][::dx].tolist())
238 if hasattr(self, 'pairs'):
239 ret['pairs'] = self.pairs
236 return json.dumps(ret)
240 return json.dumps(ret)
237
241
238 @property
242 @property
239 def times(self):
243 def times(self):
240 '''
244 '''
241 Return the list of times of the current data
245 Return the list of times of the current data
242 '''
246 '''
243
247
244 ret = numpy.array(self.__times)
248 ret = numpy.array(self.__times)
245 ret.sort()
249 ret.sort()
246 return ret
250 return ret
247
251
248 @property
252 @property
249 def heights(self):
253 def heights(self):
250 '''
254 '''
251 Return the list of heights of the current data
255 Return the list of heights of the current data
252 '''
256 '''
253
257
254 return numpy.array(self.__heights[-1])
258 return numpy.array(self.__heights[-1])
255
259
256 class PublishData(Operation):
260 class PublishData(Operation):
257 '''
261 '''
258 Operation to send data over zmq.
262 Operation to send data over zmq.
259 '''
263 '''
260
264
261 __attrs__ = ['host', 'port', 'delay', 'zeromq', 'mqtt', 'verbose']
265 __attrs__ = ['host', 'port', 'delay', 'zeromq', 'mqtt', 'verbose']
262
266
263 def __init__(self, **kwargs):
267 def __init__(self, **kwargs):
264 """Inicio."""
268 """Inicio."""
265 Operation.__init__(self, **kwargs)
269 Operation.__init__(self, **kwargs)
266 self.isConfig = False
270 self.isConfig = False
267 self.client = None
271 self.client = None
268 self.zeromq = None
272 self.zeromq = None
269 self.mqtt = None
273 self.mqtt = None
270
274
271 def on_disconnect(self, client, userdata, rc):
275 def on_disconnect(self, client, userdata, rc):
272 if rc != 0:
276 if rc != 0:
273 log.warning('Unexpected disconnection.')
277 log.warning('Unexpected disconnection.')
274 self.connect()
278 self.connect()
275
279
276 def connect(self):
280 def connect(self):
277 log.warning('trying to connect')
281 log.warning('trying to connect')
278 try:
282 try:
279 self.client.connect(
283 self.client.connect(
280 host=self.host,
284 host=self.host,
281 port=self.port,
285 port=self.port,
282 keepalive=60*10,
286 keepalive=60*10,
283 bind_address='')
287 bind_address='')
284 self.client.loop_start()
288 self.client.loop_start()
285 # self.client.publish(
289 # self.client.publish(
286 # self.topic + 'SETUP',
290 # self.topic + 'SETUP',
287 # json.dumps(setup),
291 # json.dumps(setup),
288 # retain=True
292 # retain=True
289 # )
293 # )
290 except:
294 except:
291 log.error('MQTT Conection error.')
295 log.error('MQTT Conection error.')
292 self.client = False
296 self.client = False
293
297
294 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
298 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
295 self.counter = 0
299 self.counter = 0
296 self.topic = kwargs.get('topic', 'schain')
300 self.topic = kwargs.get('topic', 'schain')
297 self.delay = kwargs.get('delay', 0)
301 self.delay = kwargs.get('delay', 0)
298 self.plottype = kwargs.get('plottype', 'spectra')
302 self.plottype = kwargs.get('plottype', 'spectra')
299 self.host = kwargs.get('host', "10.10.10.82")
303 self.host = kwargs.get('host', "10.10.10.82")
300 self.port = kwargs.get('port', 3000)
304 self.port = kwargs.get('port', 3000)
301 self.clientId = clientId
305 self.clientId = clientId
302 self.cnt = 0
306 self.cnt = 0
303 self.zeromq = zeromq
307 self.zeromq = zeromq
304 self.mqtt = kwargs.get('plottype', 0)
308 self.mqtt = kwargs.get('plottype', 0)
305 self.client = None
309 self.client = None
306 self.verbose = verbose
310 self.verbose = verbose
307 setup = []
311 setup = []
308 if mqtt is 1:
312 if mqtt is 1:
309 self.client = mqtt.Client(
313 self.client = mqtt.Client(
310 client_id=self.clientId + self.topic + 'SCHAIN',
314 client_id=self.clientId + self.topic + 'SCHAIN',
311 clean_session=True)
315 clean_session=True)
312 self.client.on_disconnect = self.on_disconnect
316 self.client.on_disconnect = self.on_disconnect
313 self.connect()
317 self.connect()
314 for plot in self.plottype:
318 for plot in self.plottype:
315 setup.append({
319 setup.append({
316 'plot': plot,
320 'plot': plot,
317 'topic': self.topic + plot,
321 'topic': self.topic + plot,
318 'title': getattr(self, plot + '_' + 'title', False),
322 'title': getattr(self, plot + '_' + 'title', False),
319 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
323 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
320 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
324 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
321 'xrange': getattr(self, plot + '_' + 'xrange', False),
325 'xrange': getattr(self, plot + '_' + 'xrange', False),
322 'yrange': getattr(self, plot + '_' + 'yrange', False),
326 'yrange': getattr(self, plot + '_' + 'yrange', False),
323 'zrange': getattr(self, plot + '_' + 'zrange', False),
327 'zrange': getattr(self, plot + '_' + 'zrange', False),
324 })
328 })
325 if zeromq is 1:
329 if zeromq is 1:
326 context = zmq.Context()
330 context = zmq.Context()
327 self.zmq_socket = context.socket(zmq.PUSH)
331 self.zmq_socket = context.socket(zmq.PUSH)
328 server = kwargs.get('server', 'zmq.pipe')
332 server = kwargs.get('server', 'zmq.pipe')
329
333
330 if 'tcp://' in server:
334 if 'tcp://' in server:
331 address = server
335 address = server
332 else:
336 else:
333 address = 'ipc:///tmp/%s' % server
337 address = 'ipc:///tmp/%s' % server
334
338
335 self.zmq_socket.connect(address)
339 self.zmq_socket.connect(address)
336 time.sleep(1)
340 time.sleep(1)
337
341
338
342
339 def publish_data(self):
343 def publish_data(self):
340 self.dataOut.finished = False
344 self.dataOut.finished = False
341 if self.mqtt is 1:
345 if self.mqtt is 1:
342 yData = self.dataOut.heightList[:2].tolist()
346 yData = self.dataOut.heightList[:2].tolist()
343 if self.plottype == 'spectra':
347 if self.plottype == 'spectra':
344 data = getattr(self.dataOut, 'data_spc')
348 data = getattr(self.dataOut, 'data_spc')
345 z = data/self.dataOut.normFactor
349 z = data/self.dataOut.normFactor
346 zdB = 10*numpy.log10(z)
350 zdB = 10*numpy.log10(z)
347 xlen, ylen = zdB[0].shape
351 xlen, ylen = zdB[0].shape
348 dx = int(xlen/MAXNUMX) + 1
352 dx = int(xlen/MAXNUMX) + 1
349 dy = int(ylen/MAXNUMY) + 1
353 dy = int(ylen/MAXNUMY) + 1
350 Z = [0 for i in self.dataOut.channelList]
354 Z = [0 for i in self.dataOut.channelList]
351 for i in self.dataOut.channelList:
355 for i in self.dataOut.channelList:
352 Z[i] = zdB[i][::dx, ::dy].tolist()
356 Z[i] = zdB[i][::dx, ::dy].tolist()
353 payload = {
357 payload = {
354 'timestamp': self.dataOut.utctime,
358 'timestamp': self.dataOut.utctime,
355 'data': roundFloats(Z),
359 'data': roundFloats(Z),
356 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
360 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
357 'interval': self.dataOut.getTimeInterval(),
361 'interval': self.dataOut.getTimeInterval(),
358 'type': self.plottype,
362 'type': self.plottype,
359 'yData': yData
363 'yData': yData
360 }
364 }
361
365
362 elif self.plottype in ('rti', 'power'):
366 elif self.plottype in ('rti', 'power'):
363 data = getattr(self.dataOut, 'data_spc')
367 data = getattr(self.dataOut, 'data_spc')
364 z = data/self.dataOut.normFactor
368 z = data/self.dataOut.normFactor
365 avg = numpy.average(z, axis=1)
369 avg = numpy.average(z, axis=1)
366 avgdB = 10*numpy.log10(avg)
370 avgdB = 10*numpy.log10(avg)
367 xlen, ylen = z[0].shape
371 xlen, ylen = z[0].shape
368 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
372 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
369 AVG = [0 for i in self.dataOut.channelList]
373 AVG = [0 for i in self.dataOut.channelList]
370 for i in self.dataOut.channelList:
374 for i in self.dataOut.channelList:
371 AVG[i] = avgdB[i][::dy].tolist()
375 AVG[i] = avgdB[i][::dy].tolist()
372 payload = {
376 payload = {
373 'timestamp': self.dataOut.utctime,
377 'timestamp': self.dataOut.utctime,
374 'data': roundFloats(AVG),
378 'data': roundFloats(AVG),
375 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
379 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
376 'interval': self.dataOut.getTimeInterval(),
380 'interval': self.dataOut.getTimeInterval(),
377 'type': self.plottype,
381 'type': self.plottype,
378 'yData': yData
382 'yData': yData
379 }
383 }
380 elif self.plottype == 'noise':
384 elif self.plottype == 'noise':
381 noise = self.dataOut.getNoise()/self.dataOut.normFactor
385 noise = self.dataOut.getNoise()/self.dataOut.normFactor
382 noisedB = 10*numpy.log10(noise)
386 noisedB = 10*numpy.log10(noise)
383 payload = {
387 payload = {
384 'timestamp': self.dataOut.utctime,
388 'timestamp': self.dataOut.utctime,
385 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
389 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
386 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
390 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
387 'interval': self.dataOut.getTimeInterval(),
391 'interval': self.dataOut.getTimeInterval(),
388 'type': self.plottype,
392 'type': self.plottype,
389 'yData': yData
393 'yData': yData
390 }
394 }
391 elif self.plottype == 'snr':
395 elif self.plottype == 'snr':
392 data = getattr(self.dataOut, 'data_SNR')
396 data = getattr(self.dataOut, 'data_SNR')
393 avgdB = 10*numpy.log10(data)
397 avgdB = 10*numpy.log10(data)
394
398
395 ylen = data[0].size
399 ylen = data[0].size
396 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
400 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
397 AVG = [0 for i in self.dataOut.channelList]
401 AVG = [0 for i in self.dataOut.channelList]
398 for i in self.dataOut.channelList:
402 for i in self.dataOut.channelList:
399 AVG[i] = avgdB[i][::dy].tolist()
403 AVG[i] = avgdB[i][::dy].tolist()
400 payload = {
404 payload = {
401 'timestamp': self.dataOut.utctime,
405 'timestamp': self.dataOut.utctime,
402 'data': roundFloats(AVG),
406 'data': roundFloats(AVG),
403 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
407 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
404 'type': self.plottype,
408 'type': self.plottype,
405 'yData': yData
409 'yData': yData
406 }
410 }
407 else:
411 else:
408 print "Tipo de grafico invalido"
412 print "Tipo de grafico invalido"
409 payload = {
413 payload = {
410 'data': 'None',
414 'data': 'None',
411 'timestamp': 'None',
415 'timestamp': 'None',
412 'type': None
416 'type': None
413 }
417 }
414
418
415 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
419 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
416
420
417 if self.zeromq is 1:
421 if self.zeromq is 1:
418 if self.verbose:
422 if self.verbose:
419 log.log(
423 log.log(
420 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
424 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
421 self.name
425 self.name
422 )
426 )
423 self.zmq_socket.send_pyobj(self.dataOut)
427 self.zmq_socket.send_pyobj(self.dataOut)
424
428
425 def run(self, dataOut, **kwargs):
429 def run(self, dataOut, **kwargs):
426 self.dataOut = dataOut
430 self.dataOut = dataOut
427 if not self.isConfig:
431 if not self.isConfig:
428 self.setup(**kwargs)
432 self.setup(**kwargs)
429 self.isConfig = True
433 self.isConfig = True
430
434
431 self.publish_data()
435 self.publish_data()
432 time.sleep(self.delay)
436 time.sleep(self.delay)
433
437
434 def close(self):
438 def close(self):
435 if self.zeromq is 1:
439 if self.zeromq is 1:
436 self.dataOut.finished = True
440 self.dataOut.finished = True
437 self.zmq_socket.send_pyobj(self.dataOut)
441 self.zmq_socket.send_pyobj(self.dataOut)
438 time.sleep(0.1)
442 time.sleep(0.1)
439 self.zmq_socket.close()
443 self.zmq_socket.close()
440 if self.client:
444 if self.client:
441 self.client.loop_stop()
445 self.client.loop_stop()
442 self.client.disconnect()
446 self.client.disconnect()
443
447
444
448
445 class ReceiverData(ProcessingUnit):
449 class ReceiverData(ProcessingUnit):
446
450
447 __attrs__ = ['server']
451 __attrs__ = ['server']
448
452
449 def __init__(self, **kwargs):
453 def __init__(self, **kwargs):
450
454
451 ProcessingUnit.__init__(self, **kwargs)
455 ProcessingUnit.__init__(self, **kwargs)
452
456
453 self.isConfig = False
457 self.isConfig = False
454 server = kwargs.get('server', 'zmq.pipe')
458 server = kwargs.get('server', 'zmq.pipe')
455 if 'tcp://' in server:
459 if 'tcp://' in server:
456 address = server
460 address = server
457 else:
461 else:
458 address = 'ipc:///tmp/%s' % server
462 address = 'ipc:///tmp/%s' % server
459
463
460 self.address = address
464 self.address = address
461 self.dataOut = JROData()
465 self.dataOut = JROData()
462
466
463 def setup(self):
467 def setup(self):
464
468
465 self.context = zmq.Context()
469 self.context = zmq.Context()
466 self.receiver = self.context.socket(zmq.PULL)
470 self.receiver = self.context.socket(zmq.PULL)
467 self.receiver.bind(self.address)
471 self.receiver.bind(self.address)
468 time.sleep(0.5)
472 time.sleep(0.5)
469 log.success('ReceiverData from {}'.format(self.address))
473 log.success('ReceiverData from {}'.format(self.address))
470
474
471
475
472 def run(self):
476 def run(self):
473
477
474 if not self.isConfig:
478 if not self.isConfig:
475 self.setup()
479 self.setup()
476 self.isConfig = True
480 self.isConfig = True
477
481
478 self.dataOut = self.receiver.recv_pyobj()
482 self.dataOut = self.receiver.recv_pyobj()
479 log.log('{} - {}'.format(self.dataOut.type,
483 log.log('{} - {}'.format(self.dataOut.type,
480 self.dataOut.datatime.ctime(),),
484 self.dataOut.datatime.ctime(),),
481 'Receiving')
485 'Receiving')
482
486
483
487
484 class PlotterReceiver(ProcessingUnit, Process):
488 class PlotterReceiver(ProcessingUnit, Process):
485
489
486 throttle_value = 5
490 throttle_value = 5
487 __attrs__ = ['server', 'plottypes', 'realtime', 'localtime', 'throttle',
491 __attrs__ = ['server', 'plottypes', 'realtime', 'localtime', 'throttle',
488 'exp_code', 'web_server']
492 'exp_code', 'web_server']
489
493
490 def __init__(self, **kwargs):
494 def __init__(self, **kwargs):
491
495
492 ProcessingUnit.__init__(self, **kwargs)
496 ProcessingUnit.__init__(self, **kwargs)
493 Process.__init__(self)
497 Process.__init__(self)
494 self.mp = False
498 self.mp = False
495 self.isConfig = False
499 self.isConfig = False
496 self.isWebConfig = False
500 self.isWebConfig = False
497 self.connections = 0
501 self.connections = 0
498 server = kwargs.get('server', 'zmq.pipe')
502 server = kwargs.get('server', 'zmq.pipe')
499 web_server = kwargs.get('web_server', None)
503 web_server = kwargs.get('web_server', None)
500 if 'tcp://' in server:
504 if 'tcp://' in server:
501 address = server
505 address = server
502 else:
506 else:
503 address = 'ipc:///tmp/%s' % server
507 address = 'ipc:///tmp/%s' % server
504 self.address = address
508 self.address = address
505 self.web_address = web_server
509 self.web_address = web_server
506 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
510 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
507 self.realtime = kwargs.get('realtime', False)
511 self.realtime = kwargs.get('realtime', False)
508 self.localtime = kwargs.get('localtime', True)
512 self.localtime = kwargs.get('localtime', True)
509 self.throttle_value = kwargs.get('throttle', 5)
513 self.throttle_value = kwargs.get('throttle', 5)
510 self.exp_code = kwargs.get('exp_code', None)
514 self.exp_code = kwargs.get('exp_code', None)
511 self.sendData = self.initThrottle(self.throttle_value)
515 self.sendData = self.initThrottle(self.throttle_value)
512 self.dates = []
516 self.dates = []
513 self.setup()
517 self.setup()
514
518
515 def setup(self):
519 def setup(self):
516
520
517 self.data = Data(self.plottypes, self.throttle_value, self.exp_code)
521 self.data = Data(self.plottypes, self.throttle_value, self.exp_code)
518 self.isConfig = True
522 self.isConfig = True
519
523
520 def event_monitor(self, monitor):
524 def event_monitor(self, monitor):
521
525
522 events = {}
526 events = {}
523
527
524 for name in dir(zmq):
528 for name in dir(zmq):
525 if name.startswith('EVENT_'):
529 if name.startswith('EVENT_'):
526 value = getattr(zmq, name)
530 value = getattr(zmq, name)
527 events[value] = name
531 events[value] = name
528
532
529 while monitor.poll():
533 while monitor.poll():
530 evt = recv_monitor_message(monitor)
534 evt = recv_monitor_message(monitor)
531 if evt['event'] == 32:
535 if evt['event'] == 32:
532 self.connections += 1
536 self.connections += 1
533 if evt['event'] == 512:
537 if evt['event'] == 512:
534 pass
538 pass
535
539
536 evt.update({'description': events[evt['event']]})
540 evt.update({'description': events[evt['event']]})
537
541
538 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
542 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
539 break
543 break
540 monitor.close()
544 monitor.close()
541 print('event monitor thread done!')
545 print('event monitor thread done!')
542
546
543 def initThrottle(self, throttle_value):
547 def initThrottle(self, throttle_value):
544
548
545 @throttle(seconds=throttle_value)
549 @throttle(seconds=throttle_value)
546 def sendDataThrottled(fn_sender, data):
550 def sendDataThrottled(fn_sender, data):
547 fn_sender(data)
551 fn_sender(data)
548
552
549 return sendDataThrottled
553 return sendDataThrottled
550
554
551 def send(self, data):
555 def send(self, data):
552 log.success('Sending {}'.format(data), self.name)
556 log.success('Sending {}'.format(data), self.name)
553 self.sender.send_pyobj(data)
557 self.sender.send_pyobj(data)
554
558
555 def run(self):
559 def run(self):
556
560
557 log.success(
561 log.success(
558 'Starting from {}'.format(self.address),
562 'Starting from {}'.format(self.address),
559 self.name
563 self.name
560 )
564 )
561
565
562 self.context = zmq.Context()
566 self.context = zmq.Context()
563 self.receiver = self.context.socket(zmq.PULL)
567 self.receiver = self.context.socket(zmq.PULL)
564 self.receiver.bind(self.address)
568 self.receiver.bind(self.address)
565 monitor = self.receiver.get_monitor_socket()
569 monitor = self.receiver.get_monitor_socket()
566 self.sender = self.context.socket(zmq.PUB)
570 self.sender = self.context.socket(zmq.PUB)
567 if self.web_address:
571 if self.web_address:
568 log.success(
572 log.success(
569 'Sending to web: {}'.format(self.web_address),
573 'Sending to web: {}'.format(self.web_address),
570 self.name
574 self.name
571 )
575 )
572 self.sender_web = self.context.socket(zmq.PUB)
576 self.sender_web = self.context.socket(zmq.PUB)
573 self.sender_web.connect(self.web_address)
577 self.sender_web.connect(self.web_address)
574 time.sleep(1)
578 time.sleep(1)
575
579
576 if 'server' in self.kwargs:
580 if 'server' in self.kwargs:
577 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
581 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
578 else:
582 else:
579 self.sender.bind("ipc:///tmp/zmq.plots")
583 self.sender.bind("ipc:///tmp/zmq.plots")
580
584
581 time.sleep(2)
585 time.sleep(2)
582
586
583 t = Thread(target=self.event_monitor, args=(monitor,))
587 t = Thread(target=self.event_monitor, args=(monitor,))
584 t.start()
588 t.start()
585
589
586 while True:
590 while True:
587 dataOut = self.receiver.recv_pyobj()
591 dataOut = self.receiver.recv_pyobj()
588 if not dataOut.flagNoData:
592 if not dataOut.flagNoData:
589 if dataOut.type == 'Parameters':
593 if dataOut.type == 'Parameters':
590 tm = dataOut.utctimeInit
594 tm = dataOut.utctimeInit
591 else:
595 else:
592 tm = dataOut.utctime
596 tm = dataOut.utctime
593 if dataOut.useLocalTime:
597 if dataOut.useLocalTime:
594 if not self.localtime:
598 if not self.localtime:
595 tm += time.timezone
599 tm += time.timezone
596 dt = datetime.datetime.fromtimestamp(tm).date()
600 dt = datetime.datetime.fromtimestamp(tm).date()
597 else:
601 else:
598 if self.localtime:
602 if self.localtime:
599 tm -= time.timezone
603 tm -= time.timezone
600 dt = datetime.datetime.utcfromtimestamp(tm).date()
604 dt = datetime.datetime.utcfromtimestamp(tm).date()
601 coerce = False
605 coerce = False
602 if dt not in self.dates:
606 if dt not in self.dates:
603 if self.data:
607 if self.data:
604 self.data.ended = True
608 self.data.ended = True
605 self.send(self.data)
609 self.send(self.data)
606 coerce = True
610 coerce = True
607 self.data.setup()
611 self.data.setup()
608 self.dates.append(dt)
612 self.dates.append(dt)
609
613
610 self.data.update(dataOut, tm)
614 self.data.update(dataOut, tm)
611
615
612 if dataOut.finished is True:
616 if dataOut.finished is True:
613 self.connections -= 1
617 self.connections -= 1
614 if self.connections == 0 and dt in self.dates:
618 if self.connections == 0 and dt in self.dates:
615 self.data.ended = True
619 self.data.ended = True
616 self.send(self.data)
620 self.send(self.data)
617 self.data.setup()
621 self.data.setup()
618 else:
622 else:
619 if self.realtime:
623 if self.realtime:
620 self.send(self.data)
624 self.send(self.data)
621 if self.web_address:
625 if self.web_address:
622 self.sender_web.send(self.data.jsonify())
626 self.sender_web.send(self.data.jsonify())
623 else:
627 else:
624 self.sendData(self.send, self.data, coerce=coerce)
628 self.sendData(self.send, self.data, coerce=coerce)
625 coerce = False
629 coerce = False
626
630
627 return
631 return
General Comments 0
You need to be logged in to leave comments. Login now