##// END OF EJS Templates
Fix PXReader for online data, add date to plot's title
jespinoza -
r1143:9ee641cc2d04
parent child
Show More
@@ -1,1085 +1,1085
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', 'spectral')]
25 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis', 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm', 'spectral')]
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', 'ftp']
54 'showprofile', 'decimation', 'ftp']
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.ftp = kwargs.get('ftp', False)
71 self.ftp = kwargs.get('ftp', False)
72 self.colormap = kwargs.get('colormap', self.colormap)
72 self.colormap = kwargs.get('colormap', self.colormap)
73 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
73 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
74 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
74 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
75 self.colormaps = kwargs.get('colormaps', None)
75 self.colormaps = kwargs.get('colormaps', None)
76 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
76 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
77 self.showprofile = kwargs.get('showprofile', False)
77 self.showprofile = kwargs.get('showprofile', False)
78 self.title = kwargs.get('wintitle', self.CODE.upper())
78 self.title = kwargs.get('wintitle', self.CODE.upper())
79 self.cb_label = kwargs.get('cb_label', None)
79 self.cb_label = kwargs.get('cb_label', None)
80 self.cb_labels = kwargs.get('cb_labels', None)
80 self.cb_labels = kwargs.get('cb_labels', None)
81 self.labels = kwargs.get('labels', None)
81 self.labels = kwargs.get('labels', None)
82 self.xaxis = kwargs.get('xaxis', 'frequency')
82 self.xaxis = kwargs.get('xaxis', 'frequency')
83 self.zmin = kwargs.get('zmin', None)
83 self.zmin = kwargs.get('zmin', None)
84 self.zmax = kwargs.get('zmax', None)
84 self.zmax = kwargs.get('zmax', None)
85 self.zlimits = kwargs.get('zlimits', None)
85 self.zlimits = kwargs.get('zlimits', None)
86 self.xmin = kwargs.get('xmin', None)
86 self.xmin = kwargs.get('xmin', None)
87 self.xmax = kwargs.get('xmax', None)
87 self.xmax = kwargs.get('xmax', None)
88 self.xrange = kwargs.get('xrange', 24)
88 self.xrange = kwargs.get('xrange', 24)
89 self.xscale = kwargs.get('xscale', None)
89 self.xscale = kwargs.get('xscale', None)
90 self.ymin = kwargs.get('ymin', None)
90 self.ymin = kwargs.get('ymin', None)
91 self.ymax = kwargs.get('ymax', None)
91 self.ymax = kwargs.get('ymax', None)
92 self.yscale = kwargs.get('yscale', None)
92 self.yscale = kwargs.get('yscale', None)
93 self.xlabel = kwargs.get('xlabel', None)
93 self.xlabel = kwargs.get('xlabel', None)
94 self.decimation = kwargs.get('decimation', None)
94 self.decimation = kwargs.get('decimation', None)
95 self.showSNR = kwargs.get('showSNR', False)
95 self.showSNR = kwargs.get('showSNR', False)
96 self.oneFigure = kwargs.get('oneFigure', True)
96 self.oneFigure = kwargs.get('oneFigure', True)
97 self.width = kwargs.get('width', None)
97 self.width = kwargs.get('width', None)
98 self.height = kwargs.get('height', None)
98 self.height = kwargs.get('height', None)
99 self.colorbar = kwargs.get('colorbar', True)
99 self.colorbar = kwargs.get('colorbar', True)
100 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
100 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
101 self.channels = kwargs.get('channels', None)
101 self.channels = kwargs.get('channels', None)
102 self.titles = kwargs.get('titles', [])
102 self.titles = kwargs.get('titles', [])
103 self.polar = False
103 self.polar = False
104
104
105 def __fmtTime(self, x, pos):
105 def __fmtTime(self, x, pos):
106 '''
106 '''
107 '''
107 '''
108
108
109 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
109 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
110
110
111 def __setup(self):
111 def __setup(self):
112 '''
112 '''
113 Common setup for all figures, here figures and axes are created
113 Common setup for all figures, here figures and axes are created
114 '''
114 '''
115
115
116 if self.CODE not in self.data:
116 if self.CODE not in self.data:
117 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
117 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
118 self.name))
118 self.name))
119
119
120 self.setup()
120 self.setup()
121
121
122 self.time_label = 'LT' if self.localtime else 'UTC'
122 self.time_label = 'LT' if self.localtime else 'UTC'
123 if self.data.localtime:
123 if self.data.localtime:
124 self.getDateTime = datetime.datetime.fromtimestamp
124 self.getDateTime = datetime.datetime.fromtimestamp
125 else:
125 else:
126 self.getDateTime = datetime.datetime.utcfromtimestamp
126 self.getDateTime = datetime.datetime.utcfromtimestamp
127
127
128 if self.width is None:
128 if self.width is None:
129 self.width = 8
129 self.width = 8
130
130
131 self.figures = []
131 self.figures = []
132 self.axes = []
132 self.axes = []
133 self.cb_axes = []
133 self.cb_axes = []
134 self.pf_axes = []
134 self.pf_axes = []
135 self.cmaps = []
135 self.cmaps = []
136
136
137 size = '15%' if self.ncols == 1 else '30%'
137 size = '15%' if self.ncols == 1 else '30%'
138 pad = '4%' if self.ncols == 1 else '8%'
138 pad = '4%' if self.ncols == 1 else '8%'
139
139
140 if self.oneFigure:
140 if self.oneFigure:
141 if self.height is None:
141 if self.height is None:
142 self.height = 1.4 * self.nrows + 1
142 self.height = 1.4 * self.nrows + 1
143 fig = plt.figure(figsize=(self.width, self.height),
143 fig = plt.figure(figsize=(self.width, self.height),
144 edgecolor='k',
144 edgecolor='k',
145 facecolor='w')
145 facecolor='w')
146 self.figures.append(fig)
146 self.figures.append(fig)
147 for n in range(self.nplots):
147 for n in range(self.nplots):
148 ax = fig.add_subplot(self.nrows, self.ncols,
148 ax = fig.add_subplot(self.nrows, self.ncols,
149 n + 1, polar=self.polar)
149 n + 1, polar=self.polar)
150 ax.tick_params(labelsize=8)
150 ax.tick_params(labelsize=8)
151 ax.firsttime = True
151 ax.firsttime = True
152 ax.index = 0
152 ax.index = 0
153 ax.press = None
153 ax.press = None
154 self.axes.append(ax)
154 self.axes.append(ax)
155 if self.showprofile:
155 if self.showprofile:
156 cax = self.__add_axes(ax, size=size, pad=pad)
156 cax = self.__add_axes(ax, size=size, pad=pad)
157 cax.tick_params(labelsize=8)
157 cax.tick_params(labelsize=8)
158 self.pf_axes.append(cax)
158 self.pf_axes.append(cax)
159 else:
159 else:
160 if self.height is None:
160 if self.height is None:
161 self.height = 3
161 self.height = 3
162 for n in range(self.nplots):
162 for n in range(self.nplots):
163 fig = plt.figure(figsize=(self.width, self.height),
163 fig = plt.figure(figsize=(self.width, self.height),
164 edgecolor='k',
164 edgecolor='k',
165 facecolor='w')
165 facecolor='w')
166 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
166 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
167 ax.tick_params(labelsize=8)
167 ax.tick_params(labelsize=8)
168 ax.firsttime = True
168 ax.firsttime = True
169 ax.index = 0
169 ax.index = 0
170 ax.press = None
170 ax.press = None
171 self.figures.append(fig)
171 self.figures.append(fig)
172 self.axes.append(ax)
172 self.axes.append(ax)
173 if self.showprofile:
173 if self.showprofile:
174 cax = self.__add_axes(ax, size=size, pad=pad)
174 cax = self.__add_axes(ax, size=size, pad=pad)
175 cax.tick_params(labelsize=8)
175 cax.tick_params(labelsize=8)
176 self.pf_axes.append(cax)
176 self.pf_axes.append(cax)
177
177
178 for n in range(self.nrows):
178 for n in range(self.nrows):
179 if self.colormaps is not None:
179 if self.colormaps is not None:
180 cmap = plt.get_cmap(self.colormaps[n])
180 cmap = plt.get_cmap(self.colormaps[n])
181 else:
181 else:
182 cmap = plt.get_cmap(self.colormap)
182 cmap = plt.get_cmap(self.colormap)
183 cmap.set_bad(self.bgcolor, 1.)
183 cmap.set_bad(self.bgcolor, 1.)
184 self.cmaps.append(cmap)
184 self.cmaps.append(cmap)
185
185
186 for fig in self.figures:
186 for fig in self.figures:
187 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
187 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
188 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
188 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
189 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
189 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
190 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
190 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
191 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
191 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
192 if self.show:
192 if self.show:
193 fig.show()
193 fig.show()
194
194
195 def OnKeyPress(self, event):
195 def OnKeyPress(self, event):
196 '''
196 '''
197 Event for pressing keys (up, down) change colormap
197 Event for pressing keys (up, down) change colormap
198 '''
198 '''
199 ax = event.inaxes
199 ax = event.inaxes
200 if ax in self.axes:
200 if ax in self.axes:
201 if event.key == 'down':
201 if event.key == 'down':
202 ax.index += 1
202 ax.index += 1
203 elif event.key == 'up':
203 elif event.key == 'up':
204 ax.index -= 1
204 ax.index -= 1
205 if ax.index < 0:
205 if ax.index < 0:
206 ax.index = len(CMAPS) - 1
206 ax.index = len(CMAPS) - 1
207 elif ax.index == len(CMAPS):
207 elif ax.index == len(CMAPS):
208 ax.index = 0
208 ax.index = 0
209 cmap = CMAPS[ax.index]
209 cmap = CMAPS[ax.index]
210 ax.cbar.set_cmap(cmap)
210 ax.cbar.set_cmap(cmap)
211 ax.cbar.draw_all()
211 ax.cbar.draw_all()
212 ax.plt.set_cmap(cmap)
212 ax.plt.set_cmap(cmap)
213 ax.cbar.patch.figure.canvas.draw()
213 ax.cbar.patch.figure.canvas.draw()
214 self.colormap = cmap.name
214 self.colormap = cmap.name
215
215
216 def OnBtnScroll(self, event):
216 def OnBtnScroll(self, event):
217 '''
217 '''
218 Event for scrolling, scale figure
218 Event for scrolling, scale figure
219 '''
219 '''
220 cb_ax = event.inaxes
220 cb_ax = event.inaxes
221 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
221 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
222 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
222 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
223 pt = ax.cbar.ax.bbox.get_points()[:, 1]
223 pt = ax.cbar.ax.bbox.get_points()[:, 1]
224 nrm = ax.cbar.norm
224 nrm = ax.cbar.norm
225 vmin, vmax, p0, p1, pS = (
225 vmin, vmax, p0, p1, pS = (
226 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
226 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
227 scale = 2 if event.step == 1 else 0.5
227 scale = 2 if event.step == 1 else 0.5
228 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
228 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
229 ax.cbar.norm.vmin = point - scale * (point - vmin)
229 ax.cbar.norm.vmin = point - scale * (point - vmin)
230 ax.cbar.norm.vmax = point - scale * (point - vmax)
230 ax.cbar.norm.vmax = point - scale * (point - vmax)
231 ax.plt.set_norm(ax.cbar.norm)
231 ax.plt.set_norm(ax.cbar.norm)
232 ax.cbar.draw_all()
232 ax.cbar.draw_all()
233 ax.cbar.patch.figure.canvas.draw()
233 ax.cbar.patch.figure.canvas.draw()
234
234
235 def onBtnPress(self, event):
235 def onBtnPress(self, event):
236 '''
236 '''
237 Event for mouse button press
237 Event for mouse button press
238 '''
238 '''
239 cb_ax = event.inaxes
239 cb_ax = event.inaxes
240 if cb_ax is None:
240 if cb_ax is None:
241 return
241 return
242
242
243 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
243 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
244 cb_ax.press = event.x, event.y
244 cb_ax.press = event.x, event.y
245 else:
245 else:
246 cb_ax.press = None
246 cb_ax.press = None
247
247
248 def onMotion(self, event):
248 def onMotion(self, event):
249 '''
249 '''
250 Event for move inside colorbar
250 Event for move inside colorbar
251 '''
251 '''
252 cb_ax = event.inaxes
252 cb_ax = event.inaxes
253 if cb_ax is None:
253 if cb_ax is None:
254 return
254 return
255 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
255 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
256 return
256 return
257 if cb_ax.press is None:
257 if cb_ax.press is None:
258 return
258 return
259
259
260 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
260 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
261 xprev, yprev = cb_ax.press
261 xprev, yprev = cb_ax.press
262 dx = event.x - xprev
262 dx = event.x - xprev
263 dy = event.y - yprev
263 dy = event.y - yprev
264 cb_ax.press = event.x, event.y
264 cb_ax.press = event.x, event.y
265 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
265 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
266 perc = 0.03
266 perc = 0.03
267
267
268 if event.button == 1:
268 if event.button == 1:
269 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
269 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
270 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
270 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
271 elif event.button == 3:
271 elif event.button == 3:
272 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
272 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
273 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
273 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
274
274
275 ax.cbar.draw_all()
275 ax.cbar.draw_all()
276 ax.plt.set_norm(ax.cbar.norm)
276 ax.plt.set_norm(ax.cbar.norm)
277 ax.cbar.patch.figure.canvas.draw()
277 ax.cbar.patch.figure.canvas.draw()
278
278
279 def onBtnRelease(self, event):
279 def onBtnRelease(self, event):
280 '''
280 '''
281 Event for mouse button release
281 Event for mouse button release
282 '''
282 '''
283 cb_ax = event.inaxes
283 cb_ax = event.inaxes
284 if cb_ax is not None:
284 if cb_ax is not None:
285 cb_ax.press = None
285 cb_ax.press = None
286
286
287 def __add_axes(self, ax, size='30%', pad='8%'):
287 def __add_axes(self, ax, size='30%', pad='8%'):
288 '''
288 '''
289 Add new axes to the given figure
289 Add new axes to the given figure
290 '''
290 '''
291 divider = make_axes_locatable(ax)
291 divider = make_axes_locatable(ax)
292 nax = divider.new_horizontal(size=size, pad=pad)
292 nax = divider.new_horizontal(size=size, pad=pad)
293 ax.figure.add_axes(nax)
293 ax.figure.add_axes(nax)
294 return nax
294 return nax
295
295
296 self.setup()
296 self.setup()
297
297
298 def setup(self):
298 def setup(self):
299 '''
299 '''
300 This method should be implemented in the child class, the following
300 This method should be implemented in the child class, the following
301 attributes should be set:
301 attributes should be set:
302
302
303 self.nrows: number of rows
303 self.nrows: number of rows
304 self.ncols: number of cols
304 self.ncols: number of cols
305 self.nplots: number of plots (channels or pairs)
305 self.nplots: number of plots (channels or pairs)
306 self.ylabel: label for Y axes
306 self.ylabel: label for Y axes
307 self.titles: list of axes title
307 self.titles: list of axes title
308
308
309 '''
309 '''
310 raise(NotImplementedError, 'Implement this method in child class')
310 raise(NotImplementedError, 'Implement this method in child class')
311
311
312 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
312 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
313 '''
313 '''
314 Create a masked array for missing data
314 Create a masked array for missing data
315 '''
315 '''
316 if x_buffer.shape[0] < 2:
316 if x_buffer.shape[0] < 2:
317 return x_buffer, y_buffer, z_buffer
317 return x_buffer, y_buffer, z_buffer
318
318
319 deltas = x_buffer[1:] - x_buffer[0:-1]
319 deltas = x_buffer[1:] - x_buffer[0:-1]
320 x_median = numpy.median(deltas)
320 x_median = numpy.median(deltas)
321
321
322 index = numpy.where(deltas > 5 * x_median)
322 index = numpy.where(deltas > 5 * x_median)
323
323
324 if len(index[0]) != 0:
324 if len(index[0]) != 0:
325 z_buffer[::, index[0], ::] = self.__missing
325 z_buffer[::, index[0], ::] = self.__missing
326 z_buffer = numpy.ma.masked_inside(z_buffer,
326 z_buffer = numpy.ma.masked_inside(z_buffer,
327 0.99 * self.__missing,
327 0.99 * self.__missing,
328 1.01 * self.__missing)
328 1.01 * self.__missing)
329
329
330 return x_buffer, y_buffer, z_buffer
330 return x_buffer, y_buffer, z_buffer
331
331
332 def decimate(self):
332 def decimate(self):
333
333
334 # dx = int(len(self.x)/self.__MAXNUMX) + 1
334 # dx = int(len(self.x)/self.__MAXNUMX) + 1
335 dy = int(len(self.y) / self.decimation) + 1
335 dy = int(len(self.y) / self.decimation) + 1
336
336
337 # x = self.x[::dx]
337 # x = self.x[::dx]
338 x = self.x
338 x = self.x
339 y = self.y[::dy]
339 y = self.y[::dy]
340 z = self.z[::, ::, ::dy]
340 z = self.z[::, ::, ::dy]
341
341
342 return x, y, z
342 return x, y, z
343
343
344 def format(self):
344 def format(self):
345 '''
345 '''
346 Set min and max values, labels, ticks and titles
346 Set min and max values, labels, ticks and titles
347 '''
347 '''
348
348
349 if self.xmin is None:
349 if self.xmin is None:
350 xmin = self.min_time
350 xmin = self.min_time
351 else:
351 else:
352 if self.xaxis is 'time':
352 if self.xaxis is 'time':
353 dt = self.getDateTime(self.min_time)
353 dt = self.getDateTime(self.min_time)
354 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
354 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
355 datetime.datetime(1970, 1, 1)).total_seconds()
355 datetime.datetime(1970, 1, 1)).total_seconds()
356 if self.data.localtime:
356 if self.data.localtime:
357 xmin += time.timezone
357 xmin += time.timezone
358 else:
358 else:
359 xmin = self.xmin
359 xmin = self.xmin
360
360
361 if self.xmax is None:
361 if self.xmax is None:
362 xmax = xmin + self.xrange * 60 * 60
362 xmax = xmin + self.xrange * 60 * 60
363 else:
363 else:
364 if self.xaxis is 'time':
364 if self.xaxis is 'time':
365 dt = self.getDateTime(self.max_time)
365 dt = self.getDateTime(self.max_time)
366 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
366 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
367 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
367 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
368 if self.data.localtime:
368 if self.data.localtime:
369 xmax += time.timezone
369 xmax += time.timezone
370 else:
370 else:
371 xmax = self.xmax
371 xmax = self.xmax
372
372
373 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
373 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
374 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
374 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
375
375
376 Y = numpy.array([5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000])
376 Y = numpy.array([5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000])
377 i = 1 if numpy.where(abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
377 i = 1 if numpy.where(abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
378 ystep = Y[i] / 5.
378 ystep = Y[i] / 5.
379
379
380 for n, ax in enumerate(self.axes):
380 for n, ax in enumerate(self.axes):
381 if ax.firsttime:
381 if ax.firsttime:
382 ax.set_facecolor(self.bgcolor)
382 ax.set_facecolor(self.bgcolor)
383 ax.yaxis.set_major_locator(MultipleLocator(ystep))
383 ax.yaxis.set_major_locator(MultipleLocator(ystep))
384 ax.xaxis.set_major_locator(MultipleLocator(ystep))
384 ax.xaxis.set_major_locator(MultipleLocator(ystep))
385 if self.xscale:
385 if self.xscale:
386 ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{0:g}'.format(x*self.xscale)))
386 ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{0:g}'.format(x*self.xscale)))
387 if self.xscale:
387 if self.xscale:
388 ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{0:g}'.format(x*self.yscale)))
388 ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{0:g}'.format(x*self.yscale)))
389 if self.xaxis is 'time':
389 if self.xaxis is 'time':
390 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
390 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
391 ax.xaxis.set_major_locator(LinearLocator(9))
391 ax.xaxis.set_major_locator(LinearLocator(9))
392 if self.xlabel is not None:
392 if self.xlabel is not None:
393 ax.set_xlabel(self.xlabel)
393 ax.set_xlabel(self.xlabel)
394 ax.set_ylabel(self.ylabel)
394 ax.set_ylabel(self.ylabel)
395 ax.firsttime = False
395 ax.firsttime = False
396 if self.showprofile:
396 if self.showprofile:
397 self.pf_axes[n].set_ylim(ymin, ymax)
397 self.pf_axes[n].set_ylim(ymin, ymax)
398 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
398 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
399 self.pf_axes[n].set_xlabel('dB')
399 self.pf_axes[n].set_xlabel('dB')
400 self.pf_axes[n].grid(b=True, axis='x')
400 self.pf_axes[n].grid(b=True, axis='x')
401 [tick.set_visible(False)
401 [tick.set_visible(False)
402 for tick in self.pf_axes[n].get_yticklabels()]
402 for tick in self.pf_axes[n].get_yticklabels()]
403 if self.colorbar:
403 if self.colorbar:
404 ax.cbar = plt.colorbar(
404 ax.cbar = plt.colorbar(
405 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
405 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
406 ax.cbar.ax.tick_params(labelsize=8)
406 ax.cbar.ax.tick_params(labelsize=8)
407 ax.cbar.ax.press = None
407 ax.cbar.ax.press = None
408 if self.cb_label:
408 if self.cb_label:
409 ax.cbar.set_label(self.cb_label, size=8)
409 ax.cbar.set_label(self.cb_label, size=8)
410 elif self.cb_labels:
410 elif self.cb_labels:
411 ax.cbar.set_label(self.cb_labels[n], size=8)
411 ax.cbar.set_label(self.cb_labels[n], size=8)
412 else:
412 else:
413 ax.cbar = None
413 ax.cbar = None
414
414
415 if not self.polar:
415 if not self.polar:
416 ax.set_xlim(xmin, xmax)
416 ax.set_xlim(xmin, xmax)
417 ax.set_ylim(ymin, ymax)
417 ax.set_ylim(ymin, ymax)
418 ax.set_title('{} - {} {}'.format(
418 ax.set_title('{} {} {}'.format(
419 self.titles[n],
419 self.titles[n],
420 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
420 self.getDateTime(self.max_time).strftime('%Y-%m-%dT%H:%M:%S'),
421 self.time_label),
421 self.time_label),
422 size=8)
422 size=8)
423 else:
423 else:
424 ax.set_title('{}'.format(self.titles[n]), size=8)
424 ax.set_title('{}'.format(self.titles[n]), size=8)
425 ax.set_ylim(0, 90)
425 ax.set_ylim(0, 90)
426 ax.set_yticks(numpy.arange(0, 90, 20))
426 ax.set_yticks(numpy.arange(0, 90, 20))
427 ax.yaxis.labelpad = 40
427 ax.yaxis.labelpad = 40
428
428
429 def __plot(self):
429 def __plot(self):
430 '''
430 '''
431 '''
431 '''
432 log.log('Plotting', self.name)
432 log.log('Plotting', self.name)
433
433
434 try:
434 try:
435 self.plot()
435 self.plot()
436 self.format()
436 self.format()
437 except Exception as e:
437 except Exception as e:
438 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
438 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
439 log.error(str(e), '')
439 log.error(str(e), '')
440 return
440 return
441
441
442 for n, fig in enumerate(self.figures):
442 for n, fig in enumerate(self.figures):
443 if self.nrows == 0 or self.nplots == 0:
443 if self.nrows == 0 or self.nplots == 0:
444 log.warning('No data', self.name)
444 log.warning('No data', self.name)
445 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
445 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
446 fig.canvas.manager.set_window_title(self.CODE)
446 fig.canvas.manager.set_window_title(self.CODE)
447 continue
447 continue
448
448
449 fig.tight_layout()
449 fig.tight_layout()
450 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
450 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
451 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
451 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
452 fig.canvas.draw()
452 fig.canvas.draw()
453
453
454 if self.save and (self.data.ended or not self.data.buffering):
454 if self.save and (self.data.ended or not self.data.buffering):
455
455
456 if self.save_labels:
456 if self.save_labels:
457 labels = self.save_labels
457 labels = self.save_labels
458 else:
458 else:
459 labels = range(self.nrows)
459 labels = range(self.nrows)
460
460
461 if self.oneFigure:
461 if self.oneFigure:
462 label = ''
462 label = ''
463 else:
463 else:
464 label = '-{}'.format(labels[n])
464 label = '-{}'.format(labels[n])
465 figname = os.path.join(
465 figname = os.path.join(
466 self.save,
466 self.save,
467 self.CODE,
467 self.CODE,
468 '{}{}_{}.png'.format(
468 '{}{}_{}.png'.format(
469 self.CODE,
469 self.CODE,
470 label,
470 label,
471 self.getDateTime(self.saveTime).strftime(
471 self.getDateTime(self.saveTime).strftime(
472 '%Y%m%d_%H%M%S'),
472 '%Y%m%d_%H%M%S'),
473 )
473 )
474 )
474 )
475 log.log('Saving figure: {}'.format(figname), self.name)
475 log.log('Saving figure: {}'.format(figname), self.name)
476 if not os.path.isdir(os.path.dirname(figname)):
476 if not os.path.isdir(os.path.dirname(figname)):
477 os.makedirs(os.path.dirname(figname))
477 os.makedirs(os.path.dirname(figname))
478 fig.savefig(figname)
478 fig.savefig(figname)
479
479
480 def plot(self):
480 def plot(self):
481 '''
481 '''
482 '''
482 '''
483 raise(NotImplementedError, 'Implement this method in child class')
483 raise(NotImplementedError, 'Implement this method in child class')
484
484
485 def run(self):
485 def run(self):
486
486
487 log.log('Starting', self.name)
487 log.log('Starting', self.name)
488
488
489 context = zmq.Context()
489 context = zmq.Context()
490 receiver = context.socket(zmq.SUB)
490 receiver = context.socket(zmq.SUB)
491 receiver.setsockopt(zmq.SUBSCRIBE, '')
491 receiver.setsockopt(zmq.SUBSCRIBE, '')
492 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
492 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
493
493
494 if 'server' in self.kwargs['parent']:
494 if 'server' in self.kwargs['parent']:
495 receiver.connect(
495 receiver.connect(
496 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
496 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
497 else:
497 else:
498 receiver.connect("ipc:///tmp/zmq.plots")
498 receiver.connect("ipc:///tmp/zmq.plots")
499
499
500 while True:
500 while True:
501 try:
501 try:
502 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
502 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
503 if self.data.localtime and self.localtime:
503 if self.data.localtime and self.localtime:
504 self.times = self.data.times
504 self.times = self.data.times
505 elif self.data.localtime and not self.localtime:
505 elif self.data.localtime and not self.localtime:
506 self.times = self.data.times + time.timezone
506 self.times = self.data.times + time.timezone
507 elif not self.data.localtime and self.localtime:
507 elif not self.data.localtime and self.localtime:
508 self.times = self.data.times - time.timezone
508 self.times = self.data.times - time.timezone
509 else:
509 else:
510 self.times = self.data.times
510 self.times = self.data.times
511
511
512 self.min_time = self.times[0]
512 self.min_time = self.times[0]
513 self.max_time = self.times[-1]
513 self.max_time = self.times[-1]
514
514
515 if self.isConfig is False:
515 if self.isConfig is False:
516 self.__setup()
516 self.__setup()
517 self.isConfig = True
517 self.isConfig = True
518
518
519 self.__plot()
519 self.__plot()
520
520
521 except zmq.Again as e:
521 except zmq.Again as e:
522 # log.log('.', tag='', nl=False)
522 # log.log('.', tag='', nl=False)
523 if self.data:
523 if self.data:
524 figpause(self.data.throttle)
524 figpause(self.data.throttle)
525 else:
525 else:
526 time.sleep(2)
526 time.sleep(2)
527
527
528 def close(self):
528 def close(self):
529 if self.data:
529 if self.data:
530 self.__plot()
530 self.__plot()
531
531
532
532
533 class PlotSpectraData(PlotData):
533 class PlotSpectraData(PlotData):
534 '''
534 '''
535 Plot for Spectra data
535 Plot for Spectra data
536 '''
536 '''
537
537
538 CODE = 'spc'
538 CODE = 'spc'
539 colormap = 'jro'
539 colormap = 'jro'
540
540
541 def setup(self):
541 def setup(self):
542 self.nplots = len(self.data.channels)
542 self.nplots = len(self.data.channels)
543 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
543 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
544 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
544 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
545 self.width = 3.4 * self.ncols
545 self.width = 3.4 * self.ncols
546 self.height = 3 * self.nrows
546 self.height = 3 * self.nrows
547 self.cb_label = 'dB'
547 self.cb_label = 'dB'
548 if self.showprofile:
548 if self.showprofile:
549 self.width += 0.8 * self.ncols
549 self.width += 0.8 * self.ncols
550
550
551 self.ylabel = 'Range [km]'
551 self.ylabel = 'Range [km]'
552
552
553 def plot(self):
553 def plot(self):
554 if self.xaxis == "frequency":
554 if self.xaxis == "frequency":
555 x = self.data.xrange[0]
555 x = self.data.xrange[0]
556 self.xlabel = "Frequency (kHz)"
556 self.xlabel = "Frequency (kHz)"
557 elif self.xaxis == "time":
557 elif self.xaxis == "time":
558 x = self.data.xrange[1]
558 x = self.data.xrange[1]
559 self.xlabel = "Time (ms)"
559 self.xlabel = "Time (ms)"
560 else:
560 else:
561 x = self.data.xrange[2]
561 x = self.data.xrange[2]
562 self.xlabel = "Velocity (m/s)"
562 self.xlabel = "Velocity (m/s)"
563
563
564 if self.CODE == 'spc_mean':
564 if self.CODE == 'spc_mean':
565 x = self.data.xrange[2]
565 x = self.data.xrange[2]
566 self.xlabel = "Velocity (m/s)"
566 self.xlabel = "Velocity (m/s)"
567
567
568 self.titles = []
568 self.titles = []
569
569
570 y = self.data.heights
570 y = self.data.heights
571 self.y = y
571 self.y = y
572 z = self.data['spc']
572 z = self.data['spc']
573
573
574 for n, ax in enumerate(self.axes):
574 for n, ax in enumerate(self.axes):
575 noise = self.data['noise'][n][-1]
575 noise = self.data['noise'][n][-1]
576 if self.CODE == 'spc_mean':
576 if self.CODE == 'spc_mean':
577 mean = self.data['mean'][n][-1]
577 mean = self.data['mean'][n][-1]
578 if ax.firsttime:
578 if ax.firsttime:
579 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
579 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
580 self.xmin = self.xmin if self.xmin else -self.xmax
580 self.xmin = self.xmin if self.xmin else -self.xmax
581 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
581 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
582 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
582 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
583 ax.plt = ax.pcolormesh(x, y, z[n].T,
583 ax.plt = ax.pcolormesh(x, y, z[n].T,
584 vmin=self.zmin,
584 vmin=self.zmin,
585 vmax=self.zmax,
585 vmax=self.zmax,
586 cmap=plt.get_cmap(self.colormap)
586 cmap=plt.get_cmap(self.colormap)
587 )
587 )
588
588
589 if self.showprofile:
589 if self.showprofile:
590 ax.plt_profile = self.pf_axes[n].plot(
590 ax.plt_profile = self.pf_axes[n].plot(
591 self.data['rti'][n][-1], y)[0]
591 self.data['rti'][n][-1], y)[0]
592 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
592 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
593 color="k", linestyle="dashed", lw=1)[0]
593 color="k", linestyle="dashed", lw=1)[0]
594 if self.CODE == 'spc_mean':
594 if self.CODE == 'spc_mean':
595 ax.plt_mean = ax.plot(mean, y, color='k')[0]
595 ax.plt_mean = ax.plot(mean, y, color='k')[0]
596 else:
596 else:
597 ax.plt.set_array(z[n].T.ravel())
597 ax.plt.set_array(z[n].T.ravel())
598 if self.showprofile:
598 if self.showprofile:
599 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
599 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
600 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
600 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
601 if self.CODE == 'spc_mean':
601 if self.CODE == 'spc_mean':
602 ax.plt_mean.set_data(mean, y)
602 ax.plt_mean.set_data(mean, y)
603
603
604 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
604 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
605 self.saveTime = self.max_time
605 self.saveTime = self.max_time
606
606
607
607
608 class PlotCrossSpectraData(PlotData):
608 class PlotCrossSpectraData(PlotData):
609
609
610 CODE = 'cspc'
610 CODE = 'cspc'
611 zmin_coh = None
611 zmin_coh = None
612 zmax_coh = None
612 zmax_coh = None
613 zmin_phase = None
613 zmin_phase = None
614 zmax_phase = None
614 zmax_phase = None
615
615
616 def setup(self):
616 def setup(self):
617
617
618 self.ncols = 4
618 self.ncols = 4
619 self.nrows = len(self.data.pairs)
619 self.nrows = len(self.data.pairs)
620 self.nplots = self.nrows * 4
620 self.nplots = self.nrows * 4
621 self.width = 3.4 * self.ncols
621 self.width = 3.4 * self.ncols
622 self.height = 3 * self.nrows
622 self.height = 3 * self.nrows
623 self.ylabel = 'Range [km]'
623 self.ylabel = 'Range [km]'
624 self.showprofile = False
624 self.showprofile = False
625
625
626 def plot(self):
626 def plot(self):
627
627
628 if self.xaxis == "frequency":
628 if self.xaxis == "frequency":
629 x = self.data.xrange[0]
629 x = self.data.xrange[0]
630 self.xlabel = "Frequency (kHz)"
630 self.xlabel = "Frequency (kHz)"
631 elif self.xaxis == "time":
631 elif self.xaxis == "time":
632 x = self.data.xrange[1]
632 x = self.data.xrange[1]
633 self.xlabel = "Time (ms)"
633 self.xlabel = "Time (ms)"
634 else:
634 else:
635 x = self.data.xrange[2]
635 x = self.data.xrange[2]
636 self.xlabel = "Velocity (m/s)"
636 self.xlabel = "Velocity (m/s)"
637
637
638 self.titles = []
638 self.titles = []
639
639
640 y = self.data.heights
640 y = self.data.heights
641 self.y = y
641 self.y = y
642 spc = self.data['spc']
642 spc = self.data['spc']
643 cspc = self.data['cspc']
643 cspc = self.data['cspc']
644
644
645 for n in range(self.nrows):
645 for n in range(self.nrows):
646 noise = self.data['noise'][n][-1]
646 noise = self.data['noise'][n][-1]
647 pair = self.data.pairs[n]
647 pair = self.data.pairs[n]
648 ax = self.axes[4 * n]
648 ax = self.axes[4 * n]
649 ax3 = self.axes[4 * n + 3]
649 ax3 = self.axes[4 * n + 3]
650 if ax.firsttime:
650 if ax.firsttime:
651 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
651 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
652 self.xmin = self.xmin if self.xmin else -self.xmax
652 self.xmin = self.xmin if self.xmin else -self.xmax
653 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
653 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
654 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
654 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
655 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
655 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
656 vmin=self.zmin,
656 vmin=self.zmin,
657 vmax=self.zmax,
657 vmax=self.zmax,
658 cmap=plt.get_cmap(self.colormap)
658 cmap=plt.get_cmap(self.colormap)
659 )
659 )
660 else:
660 else:
661 ax.plt.set_array(spc[pair[0]].T.ravel())
661 ax.plt.set_array(spc[pair[0]].T.ravel())
662 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
662 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
663
663
664 ax = self.axes[4 * n + 1]
664 ax = self.axes[4 * n + 1]
665 if ax.firsttime:
665 if ax.firsttime:
666 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
666 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
667 vmin=self.zmin,
667 vmin=self.zmin,
668 vmax=self.zmax,
668 vmax=self.zmax,
669 cmap=plt.get_cmap(self.colormap)
669 cmap=plt.get_cmap(self.colormap)
670 )
670 )
671 else:
671 else:
672 ax.plt.set_array(spc[pair[1]].T.ravel())
672 ax.plt.set_array(spc[pair[1]].T.ravel())
673 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
673 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
674
674
675 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
675 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
676 coh = numpy.abs(out)
676 coh = numpy.abs(out)
677 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
677 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
678
678
679 ax = self.axes[4 * n + 2]
679 ax = self.axes[4 * n + 2]
680 if ax.firsttime:
680 if ax.firsttime:
681 ax.plt = ax.pcolormesh(x, y, coh.T,
681 ax.plt = ax.pcolormesh(x, y, coh.T,
682 vmin=0,
682 vmin=0,
683 vmax=1,
683 vmax=1,
684 cmap=plt.get_cmap(self.colormap_coh)
684 cmap=plt.get_cmap(self.colormap_coh)
685 )
685 )
686 else:
686 else:
687 ax.plt.set_array(coh.T.ravel())
687 ax.plt.set_array(coh.T.ravel())
688 self.titles.append(
688 self.titles.append(
689 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
689 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
690
690
691 ax = self.axes[4 * n + 3]
691 ax = self.axes[4 * n + 3]
692 if ax.firsttime:
692 if ax.firsttime:
693 ax.plt = ax.pcolormesh(x, y, phase.T,
693 ax.plt = ax.pcolormesh(x, y, phase.T,
694 vmin=-180,
694 vmin=-180,
695 vmax=180,
695 vmax=180,
696 cmap=plt.get_cmap(self.colormap_phase)
696 cmap=plt.get_cmap(self.colormap_phase)
697 )
697 )
698 else:
698 else:
699 ax.plt.set_array(phase.T.ravel())
699 ax.plt.set_array(phase.T.ravel())
700 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
700 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
701
701
702 self.saveTime = self.max_time
702 self.saveTime = self.max_time
703
703
704
704
705 class PlotSpectraMeanData(PlotSpectraData):
705 class PlotSpectraMeanData(PlotSpectraData):
706 '''
706 '''
707 Plot for Spectra and Mean
707 Plot for Spectra and Mean
708 '''
708 '''
709 CODE = 'spc_mean'
709 CODE = 'spc_mean'
710 colormap = 'jro'
710 colormap = 'jro'
711
711
712
712
713 class PlotRTIData(PlotData):
713 class PlotRTIData(PlotData):
714 '''
714 '''
715 Plot for RTI data
715 Plot for RTI data
716 '''
716 '''
717
717
718 CODE = 'rti'
718 CODE = 'rti'
719 colormap = 'jro'
719 colormap = 'jro'
720
720
721 def setup(self):
721 def setup(self):
722 self.xaxis = 'time'
722 self.xaxis = 'time'
723 self.ncols = 1
723 self.ncols = 1
724 self.nrows = len(self.data.channels)
724 self.nrows = len(self.data.channels)
725 self.nplots = len(self.data.channels)
725 self.nplots = len(self.data.channels)
726 self.ylabel = 'Range [km]'
726 self.ylabel = 'Range [km]'
727 self.cb_label = 'dB'
727 self.cb_label = 'dB'
728 self.titles = ['{} Channel {}'.format(
728 self.titles = ['{} Channel {}'.format(
729 self.CODE.upper(), x) for x in range(self.nrows)]
729 self.CODE.upper(), x) for x in range(self.nrows)]
730
730
731 def plot(self):
731 def plot(self):
732 self.x = self.times
732 self.x = self.times
733 self.y = self.data.heights
733 self.y = self.data.heights
734 self.z = self.data[self.CODE]
734 self.z = self.data[self.CODE]
735 self.z = numpy.ma.masked_invalid(self.z)
735 self.z = numpy.ma.masked_invalid(self.z)
736
736
737 if self.decimation is None:
737 if self.decimation is None:
738 x, y, z = self.fill_gaps(self.x, self.y, self.z)
738 x, y, z = self.fill_gaps(self.x, self.y, self.z)
739 else:
739 else:
740 x, y, z = self.fill_gaps(*self.decimate())
740 x, y, z = self.fill_gaps(*self.decimate())
741
741
742 for n, ax in enumerate(self.axes):
742 for n, ax in enumerate(self.axes):
743 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
743 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
744 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
744 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
745 if ax.firsttime:
745 if ax.firsttime:
746 ax.plt = ax.pcolormesh(x, y, z[n].T,
746 ax.plt = ax.pcolormesh(x, y, z[n].T,
747 vmin=self.zmin,
747 vmin=self.zmin,
748 vmax=self.zmax,
748 vmax=self.zmax,
749 cmap=plt.get_cmap(self.colormap)
749 cmap=plt.get_cmap(self.colormap)
750 )
750 )
751 if self.showprofile:
751 if self.showprofile:
752 ax.plot_profile = self.pf_axes[n].plot(
752 ax.plot_profile = self.pf_axes[n].plot(
753 self.data['rti'][n][-1], self.y)[0]
753 self.data['rti'][n][-1], self.y)[0]
754 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
754 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
755 color="k", linestyle="dashed", lw=1)[0]
755 color="k", linestyle="dashed", lw=1)[0]
756 else:
756 else:
757 ax.collections.remove(ax.collections[0])
757 ax.collections.remove(ax.collections[0])
758 ax.plt = ax.pcolormesh(x, y, z[n].T,
758 ax.plt = ax.pcolormesh(x, y, z[n].T,
759 vmin=self.zmin,
759 vmin=self.zmin,
760 vmax=self.zmax,
760 vmax=self.zmax,
761 cmap=plt.get_cmap(self.colormap)
761 cmap=plt.get_cmap(self.colormap)
762 )
762 )
763 if self.showprofile:
763 if self.showprofile:
764 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
764 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
765 ax.plot_noise.set_data(numpy.repeat(
765 ax.plot_noise.set_data(numpy.repeat(
766 self.data['noise'][n][-1], len(self.y)), self.y)
766 self.data['noise'][n][-1], len(self.y)), self.y)
767
767
768 self.saveTime = self.min_time
768 self.saveTime = self.min_time
769
769
770
770
771 class PlotCOHData(PlotRTIData):
771 class PlotCOHData(PlotRTIData):
772 '''
772 '''
773 Plot for Coherence data
773 Plot for Coherence data
774 '''
774 '''
775
775
776 CODE = 'coh'
776 CODE = 'coh'
777
777
778 def setup(self):
778 def setup(self):
779 self.xaxis = 'time'
779 self.xaxis = 'time'
780 self.ncols = 1
780 self.ncols = 1
781 self.nrows = len(self.data.pairs)
781 self.nrows = len(self.data.pairs)
782 self.nplots = len(self.data.pairs)
782 self.nplots = len(self.data.pairs)
783 self.ylabel = 'Range [km]'
783 self.ylabel = 'Range [km]'
784 if self.CODE == 'coh':
784 if self.CODE == 'coh':
785 self.cb_label = ''
785 self.cb_label = ''
786 self.titles = [
786 self.titles = [
787 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
787 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
788 else:
788 else:
789 self.cb_label = 'Degrees'
789 self.cb_label = 'Degrees'
790 self.titles = [
790 self.titles = [
791 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
791 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
792
792
793
793
794 class PlotPHASEData(PlotCOHData):
794 class PlotPHASEData(PlotCOHData):
795 '''
795 '''
796 Plot for Phase map data
796 Plot for Phase map data
797 '''
797 '''
798
798
799 CODE = 'phase'
799 CODE = 'phase'
800 colormap = 'seismic'
800 colormap = 'seismic'
801
801
802
802
803 class PlotNoiseData(PlotData):
803 class PlotNoiseData(PlotData):
804 '''
804 '''
805 Plot for noise
805 Plot for noise
806 '''
806 '''
807
807
808 CODE = 'noise'
808 CODE = 'noise'
809
809
810 def setup(self):
810 def setup(self):
811 self.xaxis = 'time'
811 self.xaxis = 'time'
812 self.ncols = 1
812 self.ncols = 1
813 self.nrows = 1
813 self.nrows = 1
814 self.nplots = 1
814 self.nplots = 1
815 self.ylabel = 'Intensity [dB]'
815 self.ylabel = 'Intensity [dB]'
816 self.titles = ['Noise']
816 self.titles = ['Noise']
817 self.colorbar = False
817 self.colorbar = False
818
818
819 def plot(self):
819 def plot(self):
820
820
821 x = self.times
821 x = self.times
822 xmin = self.min_time
822 xmin = self.min_time
823 xmax = xmin + self.xrange * 60 * 60
823 xmax = xmin + self.xrange * 60 * 60
824 Y = self.data[self.CODE]
824 Y = self.data[self.CODE]
825
825
826 if self.axes[0].firsttime:
826 if self.axes[0].firsttime:
827 for ch in self.data.channels:
827 for ch in self.data.channels:
828 y = Y[ch]
828 y = Y[ch]
829 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
829 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
830 plt.legend()
830 plt.legend()
831 else:
831 else:
832 for ch in self.data.channels:
832 for ch in self.data.channels:
833 y = Y[ch]
833 y = Y[ch]
834 self.axes[0].lines[ch].set_data(x, y)
834 self.axes[0].lines[ch].set_data(x, y)
835
835
836 self.ymin = numpy.nanmin(Y) - 5
836 self.ymin = numpy.nanmin(Y) - 5
837 self.ymax = numpy.nanmax(Y) + 5
837 self.ymax = numpy.nanmax(Y) + 5
838 self.saveTime = self.min_time
838 self.saveTime = self.min_time
839
839
840
840
841 class PlotSNRData(PlotRTIData):
841 class PlotSNRData(PlotRTIData):
842 '''
842 '''
843 Plot for SNR Data
843 Plot for SNR Data
844 '''
844 '''
845
845
846 CODE = 'snr'
846 CODE = 'snr'
847 colormap = 'jet'
847 colormap = 'jet'
848
848
849
849
850 class PlotDOPData(PlotRTIData):
850 class PlotDOPData(PlotRTIData):
851 '''
851 '''
852 Plot for DOPPLER Data
852 Plot for DOPPLER Data
853 '''
853 '''
854
854
855 CODE = 'dop'
855 CODE = 'dop'
856 colormap = 'jet'
856 colormap = 'jet'
857
857
858
858
859 class PlotSkyMapData(PlotData):
859 class PlotSkyMapData(PlotData):
860 '''
860 '''
861 Plot for meteors detection data
861 Plot for meteors detection data
862 '''
862 '''
863
863
864 CODE = 'param'
864 CODE = 'param'
865
865
866 def setup(self):
866 def setup(self):
867
867
868 self.ncols = 1
868 self.ncols = 1
869 self.nrows = 1
869 self.nrows = 1
870 self.width = 7.2
870 self.width = 7.2
871 self.height = 7.2
871 self.height = 7.2
872 self.nplots = 1
872 self.nplots = 1
873 self.xlabel = 'Zonal Zenith Angle (deg)'
873 self.xlabel = 'Zonal Zenith Angle (deg)'
874 self.ylabel = 'Meridional Zenith Angle (deg)'
874 self.ylabel = 'Meridional Zenith Angle (deg)'
875 self.polar = True
875 self.polar = True
876 self.ymin = -180
876 self.ymin = -180
877 self.ymax = 180
877 self.ymax = 180
878 self.colorbar = False
878 self.colorbar = False
879
879
880 def plot(self):
880 def plot(self):
881
881
882 arrayParameters = numpy.concatenate(self.data['param'])
882 arrayParameters = numpy.concatenate(self.data['param'])
883 error = arrayParameters[:, -1]
883 error = arrayParameters[:, -1]
884 indValid = numpy.where(error == 0)[0]
884 indValid = numpy.where(error == 0)[0]
885 finalMeteor = arrayParameters[indValid, :]
885 finalMeteor = arrayParameters[indValid, :]
886 finalAzimuth = finalMeteor[:, 3]
886 finalAzimuth = finalMeteor[:, 3]
887 finalZenith = finalMeteor[:, 4]
887 finalZenith = finalMeteor[:, 4]
888
888
889 x = finalAzimuth * numpy.pi / 180
889 x = finalAzimuth * numpy.pi / 180
890 y = finalZenith
890 y = finalZenith
891
891
892 ax = self.axes[0]
892 ax = self.axes[0]
893
893
894 if ax.firsttime:
894 if ax.firsttime:
895 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
895 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
896 else:
896 else:
897 ax.plot.set_data(x, y)
897 ax.plot.set_data(x, y)
898
898
899 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
899 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
900 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
900 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
901 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
901 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
902 dt2,
902 dt2,
903 len(x))
903 len(x))
904 self.titles[0] = title
904 self.titles[0] = title
905 self.saveTime = self.max_time
905 self.saveTime = self.max_time
906
906
907
907
908 class PlotParamData(PlotRTIData):
908 class PlotParamData(PlotRTIData):
909 '''
909 '''
910 Plot for data_param object
910 Plot for data_param object
911 '''
911 '''
912
912
913 CODE = 'param'
913 CODE = 'param'
914 colormap = 'seismic'
914 colormap = 'seismic'
915
915
916 def setup(self):
916 def setup(self):
917 self.xaxis = 'time'
917 self.xaxis = 'time'
918 self.ncols = 1
918 self.ncols = 1
919 self.nrows = self.data.shape(self.CODE)[0]
919 self.nrows = self.data.shape(self.CODE)[0]
920 self.nplots = self.nrows
920 self.nplots = self.nrows
921 if self.showSNR:
921 if self.showSNR:
922 self.nrows += 1
922 self.nrows += 1
923 self.nplots += 1
923 self.nplots += 1
924
924
925 self.ylabel = 'Height [km]'
925 self.ylabel = 'Height [km]'
926 if not self.titles:
926 if not self.titles:
927 self.titles = self.data.parameters \
927 self.titles = self.data.parameters \
928 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
928 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
929 if self.showSNR:
929 if self.showSNR:
930 self.titles.append('SNR')
930 self.titles.append('SNR')
931
931
932 def plot(self):
932 def plot(self):
933 self.data.normalize_heights()
933 self.data.normalize_heights()
934 self.x = self.times
934 self.x = self.times
935 self.y = self.data.heights
935 self.y = self.data.heights
936 if self.showSNR:
936 if self.showSNR:
937 self.z = numpy.concatenate(
937 self.z = numpy.concatenate(
938 (self.data[self.CODE], self.data['snr'])
938 (self.data[self.CODE], self.data['snr'])
939 )
939 )
940 else:
940 else:
941 self.z = self.data[self.CODE]
941 self.z = self.data[self.CODE]
942
942
943 self.z = numpy.ma.masked_invalid(self.z)
943 self.z = numpy.ma.masked_invalid(self.z)
944
944
945 if self.decimation is None:
945 if self.decimation is None:
946 x, y, z = self.fill_gaps(self.x, self.y, self.z)
946 x, y, z = self.fill_gaps(self.x, self.y, self.z)
947 else:
947 else:
948 x, y, z = self.fill_gaps(*self.decimate())
948 x, y, z = self.fill_gaps(*self.decimate())
949
949
950 for n, ax in enumerate(self.axes):
950 for n, ax in enumerate(self.axes):
951
951
952 self.zmax = self.zmax if self.zmax is not None else numpy.max(
952 self.zmax = self.zmax if self.zmax is not None else numpy.max(
953 self.z[n])
953 self.z[n])
954 self.zmin = self.zmin if self.zmin is not None else numpy.min(
954 self.zmin = self.zmin if self.zmin is not None else numpy.min(
955 self.z[n])
955 self.z[n])
956
956
957 if ax.firsttime:
957 if ax.firsttime:
958 if self.zlimits is not None:
958 if self.zlimits is not None:
959 self.zmin, self.zmax = self.zlimits[n]
959 self.zmin, self.zmax = self.zlimits[n]
960
960
961 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
961 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
962 vmin=self.zmin,
962 vmin=self.zmin,
963 vmax=self.zmax,
963 vmax=self.zmax,
964 cmap=self.cmaps[n]
964 cmap=self.cmaps[n]
965 )
965 )
966 else:
966 else:
967 if self.zlimits is not None:
967 if self.zlimits is not None:
968 self.zmin, self.zmax = self.zlimits[n]
968 self.zmin, self.zmax = self.zlimits[n]
969 ax.collections.remove(ax.collections[0])
969 ax.collections.remove(ax.collections[0])
970 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
970 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
971 vmin=self.zmin,
971 vmin=self.zmin,
972 vmax=self.zmax,
972 vmax=self.zmax,
973 cmap=self.cmaps[n]
973 cmap=self.cmaps[n]
974 )
974 )
975
975
976 self.saveTime = self.min_time
976 self.saveTime = self.min_time
977
977
978
978
979 class PlotOutputData(PlotParamData):
979 class PlotOutputData(PlotParamData):
980 '''
980 '''
981 Plot data_output object
981 Plot data_output object
982 '''
982 '''
983
983
984 CODE = 'output'
984 CODE = 'output'
985 colormap = 'seismic'
985 colormap = 'seismic'
986
986
987
987
988 class PlotPolarMapData(PlotData):
988 class PlotPolarMapData(PlotData):
989 '''
989 '''
990 Plot for meteors detection data
990 Plot for meteors detection data
991 '''
991 '''
992
992
993 CODE = 'param'
993 CODE = 'param'
994 colormap = 'seismic'
994 colormap = 'seismic'
995
995
996 def setup(self):
996 def setup(self):
997 self.ncols = 1
997 self.ncols = 1
998 self.nrows = 1
998 self.nrows = 1
999 self.width = 9
999 self.width = 9
1000 self.height = 8
1000 self.height = 8
1001 if self.channels is not None:
1001 if self.channels is not None:
1002 self.nplots = len(self.channels)
1002 self.nplots = len(self.channels)
1003 self.nrows = len(self.channels)
1003 self.nrows = len(self.channels)
1004 else:
1004 else:
1005 self.nplots = self.data.shape(self.CODE)[0]
1005 self.nplots = self.data.shape(self.CODE)[0]
1006 self.nrows = self.nplots
1006 self.nrows = self.nplots
1007 self.channels = range(self.nplots)
1007 self.channels = range(self.nplots)
1008 if self.data.meta['mode'] == 'E':
1008 if self.data.meta['mode'] == 'E':
1009 self.xlabel = 'Zonal Distance (km)'
1009 self.xlabel = 'Zonal Distance (km)'
1010 self.ylabel = 'Meridional Distance (km)'
1010 self.ylabel = 'Meridional Distance (km)'
1011 else:
1011 else:
1012 self.xlabel = 'Range (km)'
1012 self.xlabel = 'Range (km)'
1013 self.ylabel = 'Height (km)'
1013 self.ylabel = 'Height (km)'
1014 self.bgcolor = 'white'
1014 self.bgcolor = 'white'
1015 self.cb_labels = self.data.meta['units']
1015 self.cb_labels = self.data.meta['units']
1016 # self.polar = True
1016 # self.polar = True
1017
1017
1018 def plot(self):
1018 def plot(self):
1019
1019
1020 for n, ax in enumerate(self.axes):
1020 for n, ax in enumerate(self.axes):
1021 data = self.data['param'][self.channels[n]]
1021 data = self.data['param'][self.channels[n]]
1022
1022
1023 zeniths = numpy.linspace(0, self.data.meta['max_range'], data.shape[1])
1023 zeniths = numpy.linspace(0, self.data.meta['max_range'], data.shape[1])
1024 if self.data.meta['mode'] == 'E':
1024 if self.data.meta['mode'] == 'E':
1025 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
1025 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
1026 r, theta = numpy.meshgrid(zeniths, azimuths)
1026 r, theta = numpy.meshgrid(zeniths, azimuths)
1027 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
1027 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
1028 else:
1028 else:
1029 azimuths = numpy.radians(self.data.heights)
1029 azimuths = numpy.radians(self.data.heights)
1030 r, theta = numpy.meshgrid(zeniths, azimuths)
1030 r, theta = numpy.meshgrid(zeniths, azimuths)
1031 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
1031 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
1032 self.y = zeniths
1032 self.y = zeniths
1033
1033
1034 if ax.firsttime:
1034 if ax.firsttime:
1035 if self.zlimits is not None:
1035 if self.zlimits is not None:
1036 self.zmin, self.zmax = self.zlimits[n]
1036 self.zmin, self.zmax = self.zlimits[n]
1037 ax.plt = ax.pcolormesh(#r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
1037 ax.plt = ax.pcolormesh(#r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
1038 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
1038 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
1039 vmin=self.zmin,
1039 vmin=self.zmin,
1040 vmax=self.zmax,
1040 vmax=self.zmax,
1041 cmap=self.cmaps[n])
1041 cmap=self.cmaps[n])
1042 else:
1042 else:
1043 if self.zlimits is not None:
1043 if self.zlimits is not None:
1044 self.zmin, self.zmax = self.zlimits[n]
1044 self.zmin, self.zmax = self.zlimits[n]
1045 ax.collections.remove(ax.collections[0])
1045 ax.collections.remove(ax.collections[0])
1046 ax.plt = ax.pcolormesh(# r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
1046 ax.plt = ax.pcolormesh(# r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
1047 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
1047 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
1048 vmin=self.zmin,
1048 vmin=self.zmin,
1049 vmax=self.zmax,
1049 vmax=self.zmax,
1050 cmap=self.cmaps[n])
1050 cmap=self.cmaps[n])
1051
1051
1052 if self.data.meta['mode'] == 'A':
1052 if self.data.meta['mode'] == 'A':
1053 continue
1053 continue
1054 '''
1054 '''
1055 f = open('/data/workspace/schain_scripts/map_lima.csv')
1055 f = open('/data/workspace/schain_scripts/map_lima.csv')
1056
1056
1057 lat1 = -11.96
1057 lat1 = -11.96
1058 lon1 = -76.54
1058 lon1 = -76.54
1059
1059
1060 for line in f:
1060 for line in f:
1061 label, x, y = [s.strip() for s in line.split(',') if s]
1061 label, x, y = [s.strip() for s in line.split(',') if s]
1062 lat2 = float(y)
1062 lat2 = float(y)
1063 lon2 = float(x)
1063 lon2 = float(x)
1064
1064
1065 dx = (lon2-lon1)*40000*numpy.cos((lat1+lat2)*numpy.pi/360)/360
1065 dx = (lon2-lon1)*40000*numpy.cos((lat1+lat2)*numpy.pi/360)/360
1066 dy = (lat1-lat2)*40000/360
1066 dy = (lat1-lat2)*40000/360
1067 print label, dx, dy
1067 print label, dx, dy
1068 if label == 'map':
1068 if label == 'map':
1069 print 'SDHSDHSDHSGHSDFHSDF'
1069 print 'SDHSDHSDHSGHSDFHSDF'
1070 ax.plot([dx], [dy],'--k')
1070 ax.plot([dx], [dy],'--k')
1071 else:
1071 else:
1072 ax.plot([dx], [dy],'.b', ms=2)
1072 ax.plot([dx], [dy],'.b', ms=2)
1073 '''
1073 '''
1074 if self.data.meta['mode'] == 'E':
1074 if self.data.meta['mode'] == 'E':
1075 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
1075 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
1076 label = 'E{:d}'.format(int(self.data.meta['elevation']))
1076 label = 'E{:d}'.format(int(self.data.meta['elevation']))
1077 else:
1077 else:
1078 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
1078 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
1079 label = 'A{:d}'.format(int(self.data.meta['azimuth']))
1079 label = 'A{:d}'.format(int(self.data.meta['azimuth']))
1080
1080
1081 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
1081 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
1082 self.titles = ['{} {}'.format(self.data.parameters[x], title) for x in self.channels]
1082 self.titles = ['{} {}'.format(self.data.parameters[x], title) for x in self.channels]
1083 self.saveTime = self.max_time
1083 self.saveTime = self.max_time
1084
1084
1085
1085
@@ -1,361 +1,345
1 '''
1 '''
2 Created on Dec 27, 2017
2 Created on Jan 15, 2018
3
3
4 @author: Juan C. Espinoza
4 @author: Juan C. Espinoza
5 '''
5 '''
6
6
7 import os
7 import os
8 import sys
8 import sys
9 import time
9 import time
10 import json
11 import glob
10 import glob
12 import datetime
11 import datetime
13 import tarfile
12 import tarfile
14
13
15 import numpy
14 import numpy
16 from netCDF4 import Dataset
15 from netCDF4 import Dataset
17
16
18 from utils import folder_in_range
17 from utils import folder_in_range
19
18
20 from schainpy.model.io.jroIO_base import JRODataReader
19 from schainpy.model.io.jroIO_base import JRODataReader
21 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
20 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
22 from schainpy.model.data.jrodata import Parameters
21 from schainpy.model.data.jrodata import Parameters
23 from schainpy.utils import log
22 from schainpy.utils import log
24
23
25 UT1970 = datetime.datetime(1970, 1, 1) - datetime.timedelta(seconds=time.timezone)
24 UT1970 = datetime.datetime(1970, 1, 1) - datetime.timedelta(seconds=time.timezone)
26
25
27 def load_json(obj):
28 '''
29 Parse json as string instead of unicode
30 '''
31
32 if isinstance(obj, str):
33 iterable = json.loads(obj)
34 else:
35 iterable = obj
36
37 if isinstance(iterable, dict):
38 return {str(k): load_json(v) if isinstance(v, dict) else str(v) if isinstance(v, unicode) else v
39 for k, v in iterable.items()}
40 elif isinstance(iterable, (list, tuple)):
41 return [str(v) if isinstance(v, unicode) else v for v in iterable]
42
43 return iterable
44
45
26
46 class PXReader(JRODataReader, ProcessingUnit):
27 class PXReader(JRODataReader, ProcessingUnit):
47
28
48 def __init__(self, **kwargs):
29 def __init__(self, **kwargs):
49
30
50 ProcessingUnit.__init__(self, **kwargs)
31 ProcessingUnit.__init__(self, **kwargs)
51
32
52 self.dataOut = Parameters()
33 self.dataOut = Parameters()
53 self.counter_records = 0
34 self.counter_records = 0
54 self.nrecords = None
35 self.nrecords = None
55 self.flagNoMoreFiles = 0
36 self.flagNoMoreFiles = 0
56 self.isConfig = False
37 self.isConfig = False
57 self.filename = None
38 self.filename = None
58 self.intervals = set()
39 self.intervals = set()
59 self.ext = ('.nc', '.tgz')
40 self.ext = ('.nc', '.tgz')
60 self.online_mode = False
41 self.online_mode = False
61
42
62 def setup(self,
43 def setup(self,
63 path=None,
44 path=None,
64 startDate=None,
45 startDate=None,
65 endDate=None,
46 endDate=None,
66 format=None,
47 format=None,
67 startTime=datetime.time(0, 0, 0),
48 startTime=datetime.time(0, 0, 0),
68 endTime=datetime.time(23, 59, 59),
49 endTime=datetime.time(23, 59, 59),
69 walk=False,
50 walk=False,
70 **kwargs):
51 **kwargs):
71
52
72 self.path = path
53 self.path = path
73 self.startDate = startDate
54 self.startDate = startDate
74 self.endDate = endDate
55 self.endDate = endDate
75 self.startTime = startTime
56 self.startTime = startTime
76 self.endTime = endTime
57 self.endTime = endTime
77 self.datatime = datetime.datetime(1900,1,1)
58 self.datatime = datetime.datetime(1900,1,1)
78 self.walk = walk
59 self.walk = walk
79 self.nTries = kwargs.get('nTries', 3)
60 self.nTries = kwargs.get('nTries', 10)
80 self.online = kwargs.get('online', False)
61 self.online = kwargs.get('online', False)
81 self.delay = kwargs.get('delay', 30)
62 self.delay = kwargs.get('delay', 60)
82 self.ele = kwargs.get('ext', '')
63 self.ele = kwargs.get('ext', '')
83
64
84 if self.path is None:
65 if self.path is None:
85 raise ValueError, 'The path is not valid'
66 raise ValueError, 'The path is not valid'
86
67
87 self.search_files(path, startDate, endDate, startTime, endTime, walk)
68 self.search_files(path, startDate, endDate, startTime, endTime, walk)
88 self.cursor = 0
69 self.cursor = 0
89 self.counter_records = 0
70 self.counter_records = 0
90
71
91 if not self.files:
72 if not self.files:
92 raise Warning, 'There is no files matching these date in the folder: {}. \n Check startDate and endDate'.format(path)
73 raise Warning, 'There is no files matching these date in the folder: {}. \n Check startDate and endDate'.format(path)
93
74
94 def search_files(self, path, startDate, endDate, startTime, endTime, walk):
75 def search_files(self, path, startDate, endDate, startTime, endTime, walk):
95 '''
76 '''
96 Searching for NCDF files in path
77 Searching for NCDF files in path
97 Creating a list of files to procces included in [startDate,endDate]
78 Creating a list of files to procces included in [startDate,endDate]
98
79
99 Input:
80 Input:
100 path - Path to find files
81 path - Path to find files
101 '''
82 '''
102
83
103 log.log('Searching files {} in {} '.format(self.ext, path), 'PXReader')
84 log.log('Searching files {} in {} '.format(self.ext, path), 'PXReader')
104 if walk:
85 if walk:
105 paths = [os.path.join(path, p) for p in os.listdir(path) if os.path.isdir(os.path.join(path, p))]
86 paths = [os.path.join(path, p) for p in os.listdir(path) if os.path.isdir(os.path.join(path, p))]
106 paths.sort()
87 paths.sort()
107 else:
88 else:
108 paths = [path]
89 paths = [path]
109
90
110 fileList0 = []
91 fileList0 = []
111
92
112 for subpath in paths:
93 for subpath in paths:
113 if not folder_in_range(subpath.split('/')[-1], startDate, endDate, '%Y%m%d'):
94 if not folder_in_range(subpath.split('/')[-1], startDate, endDate, '%Y%m%d'):
114 continue
95 continue
115 fileList0 += [os.path.join(subpath, s) for s in glob.glob1(subpath, '*') if os.path.splitext(s)[-1] in self.ext and '{}'.format(self.ele) in s]
96 fileList0 += [os.path.join(subpath, s) for s in glob.glob1(subpath, '*') if os.path.splitext(s)[-1] in self.ext and '{}'.format(self.ele) in s]
116
97
117 fileList0.sort()
98 fileList0.sort()
118 if self.online:
99 if self.online:
119 fileList0 = fileList0[-1:]
100 fileList0 = fileList0[-1:]
120
101
121 self.files = {}
102 self.files = {}
122
103
123 startDate = startDate - datetime.timedelta(1)
104 startDate = startDate - datetime.timedelta(1)
124 endDate = endDate + datetime.timedelta(1)
105 endDate = endDate + datetime.timedelta(1)
125
106
126 for fullname in fileList0:
107 for fullname in fileList0:
127 thisFile = fullname.split('/')[-1]
108 thisFile = fullname.split('/')[-1]
128 year = thisFile[3:7]
109 year = thisFile[3:7]
129 if not year.isdigit():
110 if not year.isdigit():
130 continue
111 continue
131
112
132 month = thisFile[7:9]
113 month = thisFile[7:9]
133 if not month.isdigit():
114 if not month.isdigit():
134 continue
115 continue
135
116
136 day = thisFile[9:11]
117 day = thisFile[9:11]
137 if not day.isdigit():
118 if not day.isdigit():
138 continue
119 continue
139
120
140 year, month, day = int(year), int(month), int(day)
121 year, month, day = int(year), int(month), int(day)
141 dateFile = datetime.date(year, month, day)
122 dateFile = datetime.date(year, month, day)
142 timeFile = datetime.time(int(thisFile[12:14]), int(thisFile[14:16]), int(thisFile[16:18]))
123 timeFile = datetime.time(int(thisFile[12:14]), int(thisFile[14:16]), int(thisFile[16:18]))
143
124
144 if (startDate > dateFile) or (endDate < dateFile):
125 if (startDate > dateFile) or (endDate < dateFile):
145 continue
126 continue
146
127
147 dt = datetime.datetime.combine(dateFile, timeFile)
128 dt = datetime.datetime.combine(dateFile, timeFile)
148 if dt not in self.files:
129 if dt not in self.files:
149 self.files[dt] = []
130 self.files[dt] = []
150 self.files[dt].append(fullname)
131 self.files[dt].append(fullname)
151
132
152 self.dates = self.files.keys()
133 self.dates = self.files.keys()
153 self.dates.sort()
134 self.dates.sort()
154
135
155 return
136 return
156
137
157 def search_files_online(self):
138 def search_files_online(self):
158 '''
139 '''
159 Searching for NCDF files in online mode path
140 Searching for NCDF files in online mode path
160 Creating a list of files to procces included in [startDate,endDate]
141 Creating a list of files to procces included in [startDate,endDate]
161
142
162 Input:
143 Input:
163 path - Path to find files
144 path - Path to find files
164 '''
145 '''
165
146
166 self.files = {}
147 self.files = {}
167
148
168 for n in range(self.nTries):
149 for n in range(self.nTries):
169
150
170 if self.walk:
151 if self.walk:
171 paths = [os.path.join(self.path, p) for p in os.listdir(self.path) if os.path.isdir(os.path.join(self.path, p))]
152 paths = [os.path.join(self.path, p) for p in os.listdir(self.path) if os.path.isdir(os.path.join(self.path, p))]
153 paths.sort()
172 path = paths[-1]
154 path = paths[-1]
173 else:
155 else:
174 paths = self.path
156 path = self.path
175
157
176 new_files = [os.path.join(path, s) for s in glob.glob1(path, '*') if os.path.splitext(s)[-1] in self.ext and '{}'.format(self.ele) in s]
158 new_files = [os.path.join(path, s) for s in glob.glob1(path, '*') if os.path.splitext(s)[-1] in self.ext and '{}'.format(self.ele) in s]
177
178 new_files.sort()
159 new_files.sort()
179
160
180 for fullname in new_files:
161 for fullname in new_files:
181 thisFile = fullname.split('/')[-1]
162 thisFile = fullname.split('/')[-1]
182 year = thisFile[3:7]
163 year = thisFile[3:7]
183 if not year.isdigit():
164 if not year.isdigit():
184 continue
165 continue
185
166
186 month = thisFile[7:9]
167 month = thisFile[7:9]
187 if not month.isdigit():
168 if not month.isdigit():
188 continue
169 continue
189
170
190 day = thisFile[9:11]
171 day = thisFile[9:11]
191 if not day.isdigit():
172 if not day.isdigit():
192 continue
173 continue
193
174
194 year, month, day = int(year), int(month), int(day)
175 year, month, day = int(year), int(month), int(day)
195 dateFile = datetime.date(year, month, day)
176 dateFile = datetime.date(year, month, day)
196 timeFile = datetime.time(int(thisFile[12:14]), int(thisFile[14:16]), int(thisFile[16:18]))
177 timeFile = datetime.time(int(thisFile[12:14]), int(thisFile[14:16]), int(thisFile[16:18]))
197
178
198 dt = datetime.datetime.combine(dateFile, timeFile)
179 dt = datetime.datetime.combine(dateFile, timeFile)
199
180
200 if self.dt >= dt:
181 if self.dt >= dt:
201 continue
182 continue
202
183
203 if dt not in self.files:
184 if dt not in self.files:
204 self.dt = dt
185 self.dt = dt
205 self.files[dt] = []
186 self.files[dt] = []
206
187
207 self.files[dt].append(fullname)
188 self.files[dt].append(fullname)
208 break
189 break
209
190
210 if self.files:
191 if self.files:
211 break
192 break
212 else:
193 else:
213 log.warning('Waiting {} seconds for the next file, try {} ...'.format(self.delay, n + 1), 'PXReader')
194 log.warning('Waiting {} seconds for the next file, try {} ...'.format(self.delay, n + 1), 'PXReader')
214 time.sleep(self.delay)
195 time.sleep(self.delay)
215
196
216 if not self.files:
197 if not self.files:
217 return 0
198 return 0
218
199
219 self.dates = self.files.keys()
200 self.dates = self.files.keys()
220 self.dates.sort()
201 self.dates.sort()
221 self.cursor = 0
202 self.cursor = 0
222
203
223 return 1
204 return 1
224
205
225 def parseFile(self):
206 def parseFile(self):
226 '''
207 '''
227 '''
208 '''
228
209
229 header = {}
210 header = {}
230
211
231 for attr in self.fp.ncattrs():
212 for attr in self.fp.ncattrs():
232 header[str(attr)] = getattr(self.fp, attr)
213 header[str(attr)] = getattr(self.fp, attr)
233
214
234 self.header.append(header)
215 self.header.append(header)
235
216
236 self.data[header['TypeName']] = numpy.array(self.fp.variables[header['TypeName']])
217 self.data[header['TypeName']] = numpy.array(self.fp.variables[header['TypeName']])
237
218
238 def setNextFile(self):
219 def setNextFile(self):
239 '''
220 '''
240 Open next files for the current datetime
221 Open next files for the current datetime
241 '''
222 '''
242
223
243 cursor = self.cursor
224 cursor = self.cursor
244 if not self.online_mode:
225 if not self.online_mode:
245 if cursor == len(self.dates):
226 if cursor == len(self.dates):
246 if self.online:
227 if self.online:
247 cursor = 0
228 cursor = 0
248 self.dt = self.dates[cursor]
229 self.dt = self.dates[cursor]
249 self.online_mode = True
230 self.online_mode = True
250 if not self.search_files_online():
231 if not self.search_files_online():
251 log.success('No more files', 'PXReader')
232 log.success('No more files', 'PXReader')
252 return 0
233 return 0
253 else:
234 else:
254 log.success('No more files', 'PXReader')
235 log.success('No more files', 'PXReader')
255 self.flagNoMoreFiles = 1
236 self.flagNoMoreFiles = 1
256 return 0
237 return 0
257 else:
238 else:
258 if not self.search_files_online():
239 if not self.search_files_online():
259 return 0
240 return 0
260 cursor = self.cursor
241 cursor = self.cursor
261
242
262 self.data = {}
243 self.data = {}
263 self.header = []
244 self.header = []
264
245
265 for fullname in self.files[self.dates[cursor]]:
246 for fullname in self.files[self.dates[cursor]]:
266
247
267 log.log('Opening: {}'.format(fullname), 'PXReader')
248 log.log('Opening: {}'.format(fullname), 'PXReader')
268
249
269 if os.path.splitext(fullname)[-1] == '.tgz':
250 if os.path.splitext(fullname)[-1] == '.tgz':
270 tar = tarfile.open(fullname, 'r:gz')
251 tar = tarfile.open(fullname, 'r:gz')
271 tar.extractall('/tmp')
252 tar.extractall('/tmp')
272 files = [os.path.join('/tmp', member.name) for member in tar.getmembers()]
253 files = [os.path.join('/tmp', member.name) for member in tar.getmembers()]
273 else:
254 else:
274 files = [fullname]
255 files = [fullname]
275
256
276 for filename in files:
257 for filename in files:
277 if self.filename is not None:
258 if self.filename is not None:
278 self.fp.close()
259 self.fp.close()
279
260
280 self.filename = filename
261 self.filename = filename
281 self.filedate = self.dates[cursor]
262 self.filedate = self.dates[cursor]
282 self.fp = Dataset(self.filename, 'r')
263 self.fp = Dataset(self.filename, 'r')
283 self.parseFile()
264 self.parseFile()
284
265
285 self.counter_records += 1
266 self.counter_records += 1
286 self.cursor += 1
267 self.cursor += 1
287 return 1
268 return 1
288
269
289 def readNextFile(self):
270 def readNextFile(self):
290
271
291 while True:
272 while True:
292 self.flagDiscontinuousBlock = 0
273 self.flagDiscontinuousBlock = 0
293 if not self.setNextFile():
274 if not self.setNextFile():
294 return 0
275 return 0
295
276
296 self.datatime = datetime.datetime.utcfromtimestamp(self.header[0]['Time'])
277 self.datatime = datetime.datetime.utcfromtimestamp(self.header[0]['Time'])
297
278
279 if self.online:
280 break
281
298 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
282 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
299 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
283 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
300 log.warning(
284 log.warning(
301 'Reading Record No. {}/{} -> {} [Skipping]'.format(
285 'Reading Record No. {}/{} -> {} [Skipping]'.format(
302 self.counter_records,
286 self.counter_records,
303 self.nrecords,
287 self.nrecords,
304 self.datatime.ctime()),
288 self.datatime.ctime()),
305 'PXReader')
289 'PXReader')
306 continue
290 continue
307 break
291 break
308
292
309 log.log(
293 log.log(
310 'Reading Record No. {}/{} -> {}'.format(
294 'Reading Record No. {}/{} -> {}'.format(
311 self.counter_records,
295 self.counter_records,
312 self.nrecords,
296 self.nrecords,
313 self.datatime.ctime()),
297 self.datatime.ctime()),
314 'PXReader')
298 'PXReader')
315
299
316 return 1
300 return 1
317
301
318
302
319 def set_output(self):
303 def set_output(self):
320 '''
304 '''
321 Storing data from buffer to dataOut object
305 Storing data from buffer to dataOut object
322 '''
306 '''
323
307
324 self.data['Elevation'] = numpy.array(self.fp.variables['Elevation'])
308 self.data['Elevation'] = numpy.array(self.fp.variables['Elevation'])
325 self.data['Azimuth'] = numpy.array(self.fp.variables['Azimuth'])
309 self.data['Azimuth'] = numpy.array(self.fp.variables['Azimuth'])
326 self.dataOut.range = numpy.array(self.fp.variables['GateWidth'])
310 self.dataOut.range = numpy.array(self.fp.variables['GateWidth'])
327 self.dataOut.data = self.data
311 self.dataOut.data = self.data
328 self.dataOut.units = [h['Unit-value'] for h in self.header]
312 self.dataOut.units = [h['Unit-value'] for h in self.header]
329 self.dataOut.parameters = [h['TypeName'] for h in self.header]
313 self.dataOut.parameters = [h['TypeName'] for h in self.header]
330 self.dataOut.missing = self.header[0]['MissingData']
314 self.dataOut.missing = self.header[0]['MissingData']
331 self.dataOut.max_range = self.header[0]['MaximumRange-value']
315 self.dataOut.max_range = self.header[0]['MaximumRange-value']
332 self.dataOut.elevation = self.header[0]['Elevation']
316 self.dataOut.elevation = self.header[0]['Elevation']
333 self.dataOut.azimuth = self.header[0]['Azimuth']
317 self.dataOut.azimuth = self.header[0]['Azimuth']
334 self.dataOut.latitude = self.header[0]['Latitude']
318 self.dataOut.latitude = self.header[0]['Latitude']
335 self.dataOut.longitude = self.header[0]['Longitude']
319 self.dataOut.longitude = self.header[0]['Longitude']
336 self.dataOut.utctime = self.header[0]['Time']
320 self.dataOut.utctime = self.header[0]['Time']
337 self.dataOut.utctimeInit = self.dataOut.utctime
321 self.dataOut.utctimeInit = self.dataOut.utctime
338 self.dataOut.useLocalTime = True
322 self.dataOut.useLocalTime = True
339 self.dataOut.flagNoData = False
323 self.dataOut.flagNoData = False
340 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
324 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
341
325
342 log.log('Parameters found: {}'.format(','.join(self.dataOut.parameters)),
326 log.log('Parameters found: {}'.format(','.join(self.dataOut.parameters)),
343 'PXReader')
327 'PXReader')
344
328
345 def getData(self):
329 def getData(self):
346 '''
330 '''
347 Storing data from databuffer to dataOut object
331 Storing data from databuffer to dataOut object
348 '''
332 '''
349 if self.flagNoMoreFiles:
333 if self.flagNoMoreFiles:
350 self.dataOut.flagNoData = True
334 self.dataOut.flagNoData = True
351 log.error('No file left to process', 'PXReader')
335 log.error('No file left to process', 'PXReader')
352 return 0
336 return 0
353
337
354 if not self.readNextFile():
338 if not self.readNextFile():
355 self.dataOut.flagNoData = True
339 self.dataOut.flagNoData = True
356 return 0
340 return 0
357
341
358 self.set_output()
342 self.set_output()
359
343
360 return 1
344 return 1
361
345
General Comments 0
You need to be logged in to leave comments. Login now