##// END OF EJS Templates
Fix publish and plots operations issue #929
Juan C. Espinoza -
r1062:8048843f4edf
parent child
Show More
1 NO CONTENT: modified file
This diff has been collapsed as it changes many lines, (1122 lines changed) Show them Hide them
@@ -1,32 +1,33
1 1
2 2 import os
3 import zmq
4 3 import time
5 import numpy
4 import glob
6 5 import datetime
7 import numpy as np
6 from multiprocessing import Process
7
8 import zmq
9 import numpy
8 10 import matplotlib
9 import glob
10 matplotlib.use('TkAgg')
11 11 import matplotlib.pyplot as plt
12 12 from mpl_toolkits.axes_grid1 import make_axes_locatable
13 from matplotlib.ticker import FuncFormatter, LinearLocator
14 from multiprocessing import Process
13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
15 14
16 15 from schainpy.model.proc.jroproc_base import Operation
17
18 plt.ion()
16 from schainpy.utils import log
19 17
20 18 func = lambda x, pos: ('%s') %(datetime.datetime.fromtimestamp(x).strftime('%H:%M'))
21 fromtimestamp = lambda x, mintime : (datetime.datetime.utcfromtimestamp(mintime).replace(hour=(x + 5), minute=0) - d1970).total_seconds()
22
23 19
24 20 d1970 = datetime.datetime(1970,1,1)
25 21
22
26 23 class PlotData(Operation, Process):
24 '''
25 Base class for Schain plotting operations
26 '''
27 27
28 28 CODE = 'Figure'
29 29 colormap = 'jro'
30 bgcolor = 'white'
30 31 CONFLATE = False
31 32 __MAXNUMX = 80
32 33 __missing = 1E30
@@ -37,54 +38,143 class PlotData(Operation, Process):
37 38 Process.__init__(self)
38 39 self.kwargs['code'] = self.CODE
39 40 self.mp = False
40 self.dataOut = None
41 self.data = None
41 42 self.isConfig = False
42 self.figure = None
43 self.figures = []
43 44 self.axes = []
45 self.cb_axes = []
44 46 self.localtime = kwargs.pop('localtime', True)
45 47 self.show = kwargs.get('show', True)
46 48 self.save = kwargs.get('save', False)
47 49 self.colormap = kwargs.get('colormap', self.colormap)
48 50 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
49 51 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
50 self.showprofile = kwargs.get('showprofile', True)
51 self.title = kwargs.get('wintitle', '')
52 self.colormaps = kwargs.get('colormaps', None)
53 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
54 self.showprofile = kwargs.get('showprofile', False)
55 self.title = kwargs.get('wintitle', self.CODE.upper())
56 self.cb_label = kwargs.get('cb_label', None)
57 self.cb_labels = kwargs.get('cb_labels', None)
52 58 self.xaxis = kwargs.get('xaxis', 'frequency')
53 59 self.zmin = kwargs.get('zmin', None)
54 60 self.zmax = kwargs.get('zmax', None)
61 self.zlimits = kwargs.get('zlimits', None)
55 62 self.xmin = kwargs.get('xmin', None)
63 if self.xmin is not None:
64 self.xmin += 5
56 65 self.xmax = kwargs.get('xmax', None)
57 66 self.xrange = kwargs.get('xrange', 24)
58 67 self.ymin = kwargs.get('ymin', None)
59 68 self.ymax = kwargs.get('ymax', None)
60 self.__MAXNUMY = kwargs.get('decimation', 5000)
61 self.throttle_value = 5
62 self.times = []
63 #self.interactive = self.kwargs['parent']
69 self.xlabel = kwargs.get('xlabel', None)
70 self.__MAXNUMY = kwargs.get('decimation', 100)
71 self.showSNR = kwargs.get('showSNR', False)
72 self.oneFigure = kwargs.get('oneFigure', True)
73 self.width = kwargs.get('width', None)
74 self.height = kwargs.get('height', None)
75 self.colorbar = kwargs.get('colorbar', True)
76 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
77 self.titles = ['' for __ in range(16)]
78
79 def __setup(self):
80 '''
81 Common setup for all figures, here figures and axes are created
82 '''
83
84 self.setup()
85
86 if self.width is None:
87 self.width = 8
88
89 self.figures = []
90 self.axes = []
91 self.cb_axes = []
92 self.pf_axes = []
93 self.cmaps = []
64 94
95 size = '15%' if self.ncols==1 else '30%'
96 pad = '4%' if self.ncols==1 else '8%'
97
98 if self.oneFigure:
99 if self.height is None:
100 self.height = 1.4*self.nrows + 1
101 fig = plt.figure(figsize=(self.width, self.height),
102 edgecolor='k',
103 facecolor='w')
104 self.figures.append(fig)
105 for n in range(self.nplots):
106 ax = fig.add_subplot(self.nrows, self.ncols, n+1)
107 ax.tick_params(labelsize=8)
108 ax.firsttime = True
109 self.axes.append(ax)
110 if self.showprofile:
111 cax = self.__add_axes(ax, size=size, pad=pad)
112 cax.tick_params(labelsize=8)
113 self.pf_axes.append(cax)
114 else:
115 if self.height is None:
116 self.height = 3
117 for n in range(self.nplots):
118 fig = plt.figure(figsize=(self.width, self.height),
119 edgecolor='k',
120 facecolor='w')
121 ax = fig.add_subplot(1, 1, 1)
122 ax.tick_params(labelsize=8)
123 ax.firsttime = True
124 self.figures.append(fig)
125 self.axes.append(ax)
126 if self.showprofile:
127 cax = self.__add_axes(ax, size=size, pad=pad)
128 cax.tick_params(labelsize=8)
129 self.pf_axes.append(cax)
130
131 for n in range(self.nrows):
132 if self.colormaps is not None:
133 cmap = plt.get_cmap(self.colormaps[n])
134 else:
135 cmap = plt.get_cmap(self.colormap)
136 cmap.set_bad(self.bgcolor, 1.)
137 self.cmaps.append(cmap)
138
139 def __add_axes(self, ax, size='30%', pad='8%'):
65 140 '''
66 this new parameter is created to plot data from varius channels at different figures
67 1. crear una lista de figuras donde se puedan plotear las figuras,
68 2. dar las opciones de configuracion a cada figura, estas opciones son iguales para ambas figuras
69 3. probar?
141 Add new axes to the given figure
70 142 '''
71 self.ind_plt_ch = kwargs.get('ind_plt_ch', False)
72 self.figurelist = None
143 divider = make_axes_locatable(ax)
144 nax = divider.new_horizontal(size=size, pad=pad)
145 ax.figure.add_axes(nax)
146 return nax
73 147
74 148
75 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
149 def setup(self):
150 '''
151 This method should be implemented in the child class, the following
152 attributes should be set:
76 153
154 self.nrows: number of rows
155 self.ncols: number of cols
156 self.nplots: number of plots (channels or pairs)
157 self.ylabel: label for Y axes
158 self.titles: list of axes title
159
160 '''
161 raise(NotImplementedError, 'Implement this method in child class')
162
163 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
164 '''
165 Create a masked array for missing data
166 '''
77 167 if x_buffer.shape[0] < 2:
78 168 return x_buffer, y_buffer, z_buffer
79 169
80 170 deltas = x_buffer[1:] - x_buffer[0:-1]
81 x_median = np.median(deltas)
171 x_median = numpy.median(deltas)
82 172
83 index = np.where(deltas > 5*x_median)
173 index = numpy.where(deltas > 5*x_median)
84 174
85 175 if len(index[0]) != 0:
86 176 z_buffer[::, index[0], ::] = self.__missing
87 z_buffer = np.ma.masked_inside(z_buffer,
177 z_buffer = numpy.ma.masked_inside(z_buffer,
88 178 0.99*self.__missing,
89 179 1.01*self.__missing)
90 180
@@ -102,107 +192,114 class PlotData(Operation, Process):
102 192
103 193 return x, y, z
104 194
195 def format(self):
105 196 '''
106 JM:
107 elimana las otras imagenes generadas debido a que lso workers no llegan en orden y le pueden
108 poner otro tiempo a la figura q no necesariamente es el ultimo.
109 Solo se realiza cuando termina la imagen.
110 Problemas:
111
112 File "/home/ci-81/workspace/schainv2.3/schainpy/model/graphics/jroplot_data.py", line 145, in __plot
113 for n, eachfigure in enumerate(self.figurelist):
114 TypeError: 'NoneType' object is not iterable
115
197 Set min and max values, labels, ticks and titles
116 198 '''
117 def deleteanotherfiles(self):
118 figurenames=[]
119 if self.figurelist != None:
120 for n, eachfigure in enumerate(self.figurelist):
121 #add specific name for each channel in channelList
122 ghostfigname = os.path.join(self.save, '{}_{}_{}'.format(self.titles[n].replace(' ',''),self.CODE,
123 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d')))
124 figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n].replace(' ',''),self.CODE,
125 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
126 199
127 for ghostfigure in glob.glob(ghostfigname+'*'): #ghostfigure will adopt all posible names of figures
128 if ghostfigure != figname:
129 os.remove(ghostfigure)
130 print 'Removing GhostFigures:' , figname
200 if self.xmin is None:
201 xmin = self.min_time
202 else:
203 if self.xaxis is 'time':
204 dt = datetime.datetime.fromtimestamp(self.min_time)
205 xmin = (datetime.datetime.combine(dt.date(),
206 datetime.time(int(self.xmin), 0, 0))-d1970).total_seconds()
131 207 else :
132 '''Erasing ghost images for just on******************'''
133 ghostfigname = os.path.join(self.save, '{}_{}'.format(self.CODE,datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d')))
134 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
135 for ghostfigure in glob.glob(ghostfigname+'*'): #ghostfigure will adopt all posible names of figures
136 if ghostfigure != figname:
137 os.remove(ghostfigure)
138 print 'Removing GhostFigures:' , figname
208 xmin = self.xmin
209
210 if self.xmax is None:
211 xmax = xmin+self.xrange*60*60
212 else:
213 if self.xaxis is 'time':
214 dt = datetime.datetime.fromtimestamp(self.min_time)
215 xmax = (datetime.datetime.combine(dt.date(),
216 datetime.time(int(self.xmax), 0, 0))-d1970).total_seconds()
217 else:
218 xmax = self.xmax
219
220 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
221 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
222
223 ystep = 200 if ymax>= 800 else 100 if ymax>=400 else 50 if ymax>=200 else 20
224
225 for n, ax in enumerate(self.axes):
226 if ax.firsttime:
227 ax.set_facecolor(self.bgcolor)
228 ax.yaxis.set_major_locator(MultipleLocator(ystep))
229 if self.xaxis is 'time':
230 ax.xaxis.set_major_formatter(FuncFormatter(func))
231 ax.xaxis.set_major_locator(LinearLocator(9))
232 if self.xlabel is not None:
233 ax.set_xlabel(self.xlabel)
234 ax.set_ylabel(self.ylabel)
235 ax.firsttime = False
236 if self.showprofile:
237 self.pf_axes[n].set_ylim(ymin, ymax)
238 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
239 self.pf_axes[n].set_xlabel('dB')
240 self.pf_axes[n].grid(b=True, axis='x')
241 [tick.set_visible(False) for tick in self.pf_axes[n].get_yticklabels()]
242 if self.colorbar:
243 cb = plt.colorbar(ax.plt, ax=ax, pad=0.02)
244 cb.ax.tick_params(labelsize=8)
245 if self.cb_label:
246 cb.set_label(self.cb_label, size=8)
247 elif self.cb_labels:
248 cb.set_label(self.cb_labels[n], size=8)
249
250 ax.set_title('{} - {} UTC'.format(
251 self.titles[n],
252 datetime.datetime.fromtimestamp(self.max_time).strftime('%H:%M:%S')),
253 size=8)
254 ax.set_xlim(xmin, xmax)
255 ax.set_ylim(ymin, ymax)
256
139 257
140 258 def __plot(self):
259 '''
260 '''
261 log.success('Plotting', self.name)
141 262
142 print 'plotting...{}'.format(self.CODE)
143 if self.ind_plt_ch is False : #standard
144 if self.show:
145 self.figure.show()
146 263 self.plot()
147 plt.tight_layout()
148 self.figure.canvas.manager.set_window_title('{} {} - {}'.format(self.title, self.CODE.upper(),
149 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
150 else :
151 print 'len(self.figurelist): ',len(self.figurelist)
152 for n, eachfigure in enumerate(self.figurelist):
264 self.format()
265
266 for n, fig in enumerate(self.figures):
267 if self.nrows == 0 or self.nplots == 0:
268 log.warning('No data', self.name)
269 continue
153 270 if self.show:
154 eachfigure.show()
271 fig.show()
155 272
156 self.plot()
157 eachfigure.tight_layout() # ajuste de cada subplot
158 eachfigure.canvas.manager.set_window_title('{} {} - {}'.format(self.title[n], self.CODE.upper(),
273 fig.tight_layout()
274 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
159 275 datetime.datetime.fromtimestamp(self.max_time).strftime('%Y/%m/%d')))
276 # fig.canvas.draw()
160 277
161 # if self.save:
162 # if self.ind_plt_ch is False : #standard
163 # figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
164 # datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
165 # print 'Saving figure: {}'.format(figname)
166 # self.figure.savefig(figname)
167 # else :
168 # for n, eachfigure in enumerate(self.figurelist):
169 # #add specific name for each channel in channelList
170 # figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n],self.CODE,
171 # datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
172 #
173 # print 'Saving figure: {}'.format(figname)
174 # eachfigure.savefig(figname)
175
176 if self.ind_plt_ch is False :
177 self.figure.canvas.draw()
178 else :
179 for eachfigure in self.figurelist:
180 eachfigure.canvas.draw()
181
182 if self.save:
183 if self.ind_plt_ch is False : #standard
184 figname = os.path.join(self.save, '{}_{}.png'.format(self.CODE,
185 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
186 print 'Saving figure: {}'.format(figname)
187 self.figure.savefig(figname)
278 if self.save and self.data.ended:
279 channels = range(self.nrows)
280 if self.oneFigure:
281 label = ''
188 282 else :
189 for n, eachfigure in enumerate(self.figurelist):
190 #add specific name for each channel in channelList
191 figname = os.path.join(self.save, '{}_{}_{}.png'.format(self.titles[n].replace(' ',''),self.CODE,
192 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')))
193
283 label = '_{}'.format(channels[n])
284 figname = os.path.join(
285 self.save,
286 '{}{}_{}.png'.format(
287 self.CODE,
288 label,
289 datetime.datetime.fromtimestamp(self.saveTime).strftime('%y%m%d_%H%M%S')
290 )
291 )
194 292 print 'Saving figure: {}'.format(figname)
195 eachfigure.savefig(figname)
196
293 fig.savefig(figname)
197 294
198 295 def plot(self):
199
200 print 'plotting...{}'.format(self.CODE.upper())
201 return
296 '''
297 '''
298 raise(NotImplementedError, 'Implement this method in child class')
202 299
203 300 def run(self):
204 301
205 print '[Starting] {}'.format(self.name)
302 log.success('Starting', self.name)
206 303
207 304 context = zmq.Context()
208 305 receiver = context.socket(zmq.SUB)
@@ -214,150 +311,102 class PlotData(Operation, Process):
214 311 else:
215 312 receiver.connect("ipc:///tmp/zmq.plots")
216 313
217 seconds_passed = 0
218
219 314 while True:
220 315 try:
221 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)#flags=zmq.NOBLOCK
222 self.started = self.data['STARTED']
223 self.dataOut = self.data['dataOut']
316 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
224 317
225 if (len(self.times) < len(self.data['times']) and not self.started and self.data['ENDED']):
226 continue
227
228 self.times = self.data['times']
229 self.times.sort()
230 self.throttle_value = self.data['throttle']
231 self.min_time = self.times[0]
232 self.max_time = self.times[-1]
318 self.min_time = self.data.times[0]
319 self.max_time = self.data.times[-1]
233 320
234 321 if self.isConfig is False:
235 print 'setting up'
236 self.setup()
322 self.__setup()
237 323 self.isConfig = True
238 self.__plot()
239 324
240 if self.data['ENDED'] is True:
241 print '********GRAPHIC ENDED********'
242 self.ended = True
243 self.isConfig = False
244 325 self.__plot()
245 self.deleteanotherfiles() #CLPDG
246 elif seconds_passed >= self.data['throttle']:
247 print 'passed', seconds_passed
248 self.__plot()
249 seconds_passed = 0
250 326
251 327 except zmq.Again as e:
252 print 'Waiting for data...'
253 plt.pause(2)
254 seconds_passed += 2
328 log.log('Waiting for data...')
329 if self.data:
330 plt.pause(self.data.throttle)
331 else:
332 time.sleep(2)
255 333
256 334 def close(self):
257 if self.dataOut:
335 if self.data:
258 336 self.__plot()
259 337
260 338
261 339 class PlotSpectraData(PlotData):
340 '''
341 Plot for Spectra data
342 '''
262 343
263 344 CODE = 'spc'
264 345 colormap = 'jro'
265 CONFLATE = False
266 346
267 347 def setup(self):
268
269 ncolspan = 1
270 colspan = 1
271 self.ncols = int(numpy.sqrt(self.dataOut.nChannels)+0.9)
272 self.nrows = int(self.dataOut.nChannels*1./self.ncols + 0.9)
273 self.width = 3.6*self.ncols
274 self.height = 3.2*self.nrows
348 self.nplots = len(self.data.channels)
349 self.ncols = int(numpy.sqrt(self.nplots)+ 0.9)
350 self.nrows = int((1.0*self.nplots/self.ncols) + 0.9)
351 self.width = 3.4*self.ncols
352 self.height = 3*self.nrows
353 self.cb_label = 'dB'
275 354 if self.showprofile:
276 ncolspan = 3
277 colspan = 2
278 self.width += 1.2*self.ncols
355 self.width += 0.8*self.ncols
279 356
280 357 self.ylabel = 'Range [Km]'
281 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
282
283 if self.figure is None:
284 self.figure = plt.figure(figsize=(self.width, self.height),
285 edgecolor='k',
286 facecolor='w')
287 else:
288 self.figure.clf()
289
290 n = 0
291 for y in range(self.nrows):
292 for x in range(self.ncols):
293 if n >= self.dataOut.nChannels:
294 break
295 ax = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan), 1, colspan)
296 if self.showprofile:
297 ax.ax_profile = plt.subplot2grid((self.nrows, self.ncols*ncolspan), (y, x*ncolspan+colspan), 1, 1)
298
299 ax.firsttime = True
300 self.axes.append(ax)
301 n += 1
302 358
303 359 def plot(self):
304
305 360 if self.xaxis == "frequency":
306 x = self.dataOut.getFreqRange(1)/1000.
307 xlabel = "Frequency (kHz)"
361 x = self.data.xrange[0]
362 self.xlabel = "Frequency (kHz)"
308 363 elif self.xaxis == "time":
309 x = self.dataOut.getAcfRange(1)
310 xlabel = "Time (ms)"
364 x = self.data.xrange[1]
365 self.xlabel = "Time (ms)"
311 366 else:
312 x = self.dataOut.getVelRange(1)
313 xlabel = "Velocity (m/s)"
367 x = self.data.xrange[2]
368 self.xlabel = "Velocity (m/s)"
369
370 if self.CODE == 'spc_mean':
371 x = self.data.xrange[2]
372 self.xlabel = "Velocity (m/s)"
314 373
315 y = self.dataOut.getHeiRange()
316 z = self.data[self.CODE]
374 self.titles = []
375
376 y = self.data.heights
377 self.y = y
378 z = self.data['spc']
317 379
318 380 for n, ax in enumerate(self.axes):
381 noise = self.data['noise'][n][-1]
382 if self.CODE == 'spc_mean':
383 mean = self.data['mean'][n][-1]
319 384 if ax.firsttime:
320 self.xmax = self.xmax if self.xmax else np.nanmax(x)
385 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
321 386 self.xmin = self.xmin if self.xmin else -self.xmax
322 self.ymin = self.ymin if self.ymin else np.nanmin(y)
323 self.ymax = self.ymax if self.ymax else np.nanmax(y)
324 self.zmin = self.zmin if self.zmin else np.nanmin(z)
325 self.zmax = self.zmax if self.zmax else np.nanmax(z)
326 ax.plot = ax.pcolormesh(x, y, z[n].T,
387 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
388 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
389 ax.plt = ax.pcolormesh(x, y, z[n].T,
327 390 vmin=self.zmin,
328 391 vmax=self.zmax,
329 392 cmap=plt.get_cmap(self.colormap)
330 393 )
331 divider = make_axes_locatable(ax)
332 cax = divider.new_horizontal(size='3%', pad=0.05)
333 self.figure.add_axes(cax)
334 plt.colorbar(ax.plot, cax)
335
336 ax.set_xlim(self.xmin, self.xmax)
337 ax.set_ylim(self.ymin, self.ymax)
338
339 ax.set_ylabel(self.ylabel)
340 ax.set_xlabel(xlabel)
341
342 ax.firsttime = False
343 394
344 395 if self.showprofile:
345 ax.plot_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
346 ax.ax_profile.set_xlim(self.zmin, self.zmax)
347 ax.ax_profile.set_ylim(self.ymin, self.ymax)
348 ax.ax_profile.set_xlabel('dB')
349 ax.ax_profile.grid(b=True, axis='x')
350 ax.plot_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
351 color="k", linestyle="dashed", lw=2)[0]
352 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
396 ax.plt_profile= self.pf_axes[n].plot(self.data['rti'][n][-1], y)[0]
397 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
398 color="k", linestyle="dashed", lw=1)[0]
399 if self.CODE == 'spc_mean':
400 ax.plt_mean = ax.plot(mean, y, color='k')[0]
353 401 else:
354 ax.plot.set_array(z[n].T.ravel())
402 ax.plt.set_array(z[n].T.ravel())
355 403 if self.showprofile:
356 ax.plot_profile.set_data(self.data['rti'][self.max_time][n], y)
357 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
404 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
405 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
406 if self.CODE == 'spc_mean':
407 ax.plt_mean.set_data(mean, y)
358 408
359 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
360 size=8)
409 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
361 410 self.saveTime = self.max_time
362 411
363 412
@@ -368,544 +417,244 class PlotCrossSpectraData(PlotData):
368 417 zmax_coh = None
369 418 zmin_phase = None
370 419 zmax_phase = None
371 CONFLATE = False
372 420
373 421 def setup(self):
374 422
375 ncolspan = 1
376 colspan = 1
377 self.ncols = 2
378 self.nrows = self.dataOut.nPairs
379 self.width = 3.6*self.ncols
380 self.height = 3.2*self.nrows
381
423 self.ncols = 4
424 self.nrows = len(self.data.pairs)
425 self.nplots = self.nrows*4
426 self.width = 3.4*self.ncols
427 self.height = 3*self.nrows
382 428 self.ylabel = 'Range [Km]'
383 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
384
385 if self.figure is None:
386 self.figure = plt.figure(figsize=(self.width, self.height),
387 edgecolor='k',
388 facecolor='w')
389 else:
390 self.figure.clf()
391
392 for y in range(self.nrows):
393 for x in range(self.ncols):
394 ax = plt.subplot2grid((self.nrows, self.ncols), (y, x), 1, 1)
395 ax.firsttime = True
396 self.axes.append(ax)
429 self.showprofile = False
397 430
398 431 def plot(self):
399 432
400 433 if self.xaxis == "frequency":
401 x = self.dataOut.getFreqRange(1)/1000.
402 xlabel = "Frequency (kHz)"
434 x = self.data.xrange[0]
435 self.xlabel = "Frequency (kHz)"
403 436 elif self.xaxis == "time":
404 x = self.dataOut.getAcfRange(1)
405 xlabel = "Time (ms)"
437 x = self.data.xrange[1]
438 self.xlabel = "Time (ms)"
406 439 else:
407 x = self.dataOut.getVelRange(1)
408 xlabel = "Velocity (m/s)"
440 x = self.data.xrange[2]
441 self.xlabel = "Velocity (m/s)"
442
443 self.titles = []
409 444
410 y = self.dataOut.getHeiRange()
411 z_coh = self.data['cspc_coh']
412 z_phase = self.data['cspc_phase']
445 y = self.data.heights
446 self.y = y
447 spc = self.data['spc']
448 cspc = self.data['cspc']
413 449
414 450 for n in range(self.nrows):
415 ax = self.axes[2*n]
416 ax1 = self.axes[2*n+1]
451 noise = self.data['noise'][n][-1]
452 pair = self.data.pairs[n]
453 ax = self.axes[4*n]
454 ax3 = self.axes[4*n+3]
417 455 if ax.firsttime:
418 self.xmax = self.xmax if self.xmax else np.nanmax(x)
456 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
419 457 self.xmin = self.xmin if self.xmin else -self.xmax
420 self.ymin = self.ymin if self.ymin else np.nanmin(y)
421 self.ymax = self.ymax if self.ymax else np.nanmax(y)
422 self.zmin_coh = self.zmin_coh if self.zmin_coh else 0.0
423 self.zmax_coh = self.zmax_coh if self.zmax_coh else 1.0
424 self.zmin_phase = self.zmin_phase if self.zmin_phase else -180
425 self.zmax_phase = self.zmax_phase if self.zmax_phase else 180
426
427 ax.plot = ax.pcolormesh(x, y, z_coh[n].T,
428 vmin=self.zmin_coh,
429 vmax=self.zmax_coh,
430 cmap=plt.get_cmap(self.colormap_coh)
431 )
432 divider = make_axes_locatable(ax)
433 cax = divider.new_horizontal(size='3%', pad=0.05)
434 self.figure.add_axes(cax)
435 plt.colorbar(ax.plot, cax)
436
437 ax.set_xlim(self.xmin, self.xmax)
438 ax.set_ylim(self.ymin, self.ymax)
439
440 ax.set_ylabel(self.ylabel)
441 ax.set_xlabel(xlabel)
442 ax.firsttime = False
443
444 ax1.plot = ax1.pcolormesh(x, y, z_phase[n].T,
445 vmin=self.zmin_phase,
446 vmax=self.zmax_phase,
447 cmap=plt.get_cmap(self.colormap_phase)
458 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
459 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
460 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
461 vmin=self.zmin,
462 vmax=self.zmax,
463 cmap=plt.get_cmap(self.colormap)
448 464 )
449 divider = make_axes_locatable(ax1)
450 cax = divider.new_horizontal(size='3%', pad=0.05)
451 self.figure.add_axes(cax)
452 plt.colorbar(ax1.plot, cax)
453
454 ax1.set_xlim(self.xmin, self.xmax)
455 ax1.set_ylim(self.ymin, self.ymax)
456
457 ax1.set_ylabel(self.ylabel)
458 ax1.set_xlabel(xlabel)
459 ax1.firsttime = False
460 465 else:
461 ax.plot.set_array(z_coh[n].T.ravel())
462 ax1.plot.set_array(z_phase[n].T.ravel())
463
464 ax.set_title('Coherence Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
465 ax1.set_title('Phase Ch{} * Ch{}'.format(self.dataOut.pairsList[n][0], self.dataOut.pairsList[n][1]), size=8)
466 self.saveTime = self.max_time
467
468
469 class PlotSpectraMeanData(PlotSpectraData):
470
471 CODE = 'spc_mean'
472 colormap = 'jet'
473
474 def plot(self):
475
476 if self.xaxis == "frequency":
477 x = self.dataOut.getFreqRange(1)/1000.
478 xlabel = "Frequency (kHz)"
479 elif self.xaxis == "time":
480 x = self.dataOut.getAcfRange(1)
481 xlabel = "Time (ms)"
482 else:
483 x = self.dataOut.getVelRange(1)
484 xlabel = "Velocity (m/s)"
485
486 y = self.dataOut.getHeiRange()
487 z = self.data['spc']
488 mean = self.data['mean'][self.max_time]
489
490 for n, ax in enumerate(self.axes):
466 ax.plt.set_array(spc[pair[0]].T.ravel())
467 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
491 468
469 ax = self.axes[4*n+1]
492 470 if ax.firsttime:
493 self.xmax = self.xmax if self.xmax else np.nanmax(x)
494 self.xmin = self.xmin if self.xmin else -self.xmax
495 self.ymin = self.ymin if self.ymin else np.nanmin(y)
496 self.ymax = self.ymax if self.ymax else np.nanmax(y)
497 self.zmin = self.zmin if self.zmin else np.nanmin(z)
498 self.zmax = self.zmax if self.zmax else np.nanmax(z)
499 ax.plt = ax.pcolormesh(x, y, z[n].T,
471 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
500 472 vmin=self.zmin,
501 473 vmax=self.zmax,
502 474 cmap=plt.get_cmap(self.colormap)
503 475 )
504 ax.plt_dop = ax.plot(mean[n], y,
505 color='k')[0]
506
507 divider = make_axes_locatable(ax)
508 cax = divider.new_horizontal(size='3%', pad=0.05)
509 self.figure.add_axes(cax)
510 plt.colorbar(ax.plt, cax)
511
512 ax.set_xlim(self.xmin, self.xmax)
513 ax.set_ylim(self.ymin, self.ymax)
476 else:
477 ax.plt.set_array(spc[pair[1]].T.ravel())
478 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
514 479
515 ax.set_ylabel(self.ylabel)
516 ax.set_xlabel(xlabel)
480 out = cspc[n]/numpy.sqrt(spc[pair[0]]*spc[pair[1]])
481 coh = numpy.abs(out)
482 phase = numpy.arctan2(out.imag, out.real)*180/numpy.pi
517 483
518 ax.firsttime = False
484 ax = self.axes[4*n+2]
485 if ax.firsttime:
486 ax.plt = ax.pcolormesh(x, y, coh.T,
487 vmin=0,
488 vmax=1,
489 cmap=plt.get_cmap(self.colormap_coh)
490 )
491 else:
492 ax.plt.set_array(coh.T.ravel())
493 self.titles.append('Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
519 494
520 if self.showprofile:
521 ax.plt_profile= ax.ax_profile.plot(self.data['rti'][self.max_time][n], y)[0]
522 ax.ax_profile.set_xlim(self.zmin, self.zmax)
523 ax.ax_profile.set_ylim(self.ymin, self.ymax)
524 ax.ax_profile.set_xlabel('dB')
525 ax.ax_profile.grid(b=True, axis='x')
526 ax.plt_noise = ax.ax_profile.plot(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y,
527 color="k", linestyle="dashed", lw=2)[0]
528 [tick.set_visible(False) for tick in ax.ax_profile.get_yticklabels()]
495 ax = self.axes[4*n+3]
496 if ax.firsttime:
497 ax.plt = ax.pcolormesh(x, y, phase.T,
498 vmin=-180,
499 vmax=180,
500 cmap=plt.get_cmap(self.colormap_phase)
501 )
529 502 else:
530 ax.plt.set_array(z[n].T.ravel())
531 ax.plt_dop.set_data(mean[n], y)
532 if self.showprofile:
533 ax.plt_profile.set_data(self.data['rti'][self.max_time][n], y)
534 ax.plt_noise.set_data(numpy.repeat(self.data['noise'][self.max_time][n], len(y)), y)
503 ax.plt.set_array(phase.T.ravel())
504 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
535 505
536 ax.set_title('{} - Noise: {:.2f} dB'.format(self.titles[n], self.data['noise'][self.max_time][n]),
537 size=8)
538 506 self.saveTime = self.max_time
539 507
540 508
509 class PlotSpectraMeanData(PlotSpectraData):
510 '''
511 Plot for Spectra and Mean
512 '''
513 CODE = 'spc_mean'
514 colormap = 'jro'
515
516
541 517 class PlotRTIData(PlotData):
518 '''
519 Plot for RTI data
520 '''
542 521
543 522 CODE = 'rti'
544 523 colormap = 'jro'
545 524
546 525 def setup(self):
526 self.xaxis = 'time'
547 527 self.ncols = 1
548 self.nrows = self.dataOut.nChannels
549 self.width = 10
550 #TODO : arreglar la altura de la figura, esta hardcodeada.
551 #Se arreglo, testear!
552 if self.ind_plt_ch:
553 self.height = 3.2#*self.nrows if self.nrows<6 else 12
554 else:
555 self.height = 2.2*self.nrows if self.nrows<6 else 12
556
557 '''
558 if self.nrows==1:
559 self.height += 1
560 '''
528 self.nrows = len(self.data.channels)
529 self.nplots = len(self.data.channels)
561 530 self.ylabel = 'Range [Km]'
562 self.titles = ['Channel {}'.format(x) for x in self.dataOut.channelList]
563
564 '''
565 Logica:
566 1) Si la variable ind_plt_ch es True, va a crear mas de 1 figura
567 2) guardamos "Figures" en una lista y "axes" en otra, quizas se deberia guardar el
568 axis dentro de "Figures" como un diccionario.
569 '''
570 if self.ind_plt_ch is False: #standard mode
571
572 if self.figure is None: #solo para la priemra vez
573 self.figure = plt.figure(figsize=(self.width, self.height),
574 edgecolor='k',
575 facecolor='w')
576 else:
577 self.figure.clf()
578 self.axes = []
579
580
581 for n in range(self.nrows):
582 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
583 #ax = self.figure(n+1)
584 ax.firsttime = True
585 self.axes.append(ax)
586
587 else : #append one figure foreach channel in channelList
588 if self.figurelist == None:
589 self.figurelist = []
590 for n in range(self.nrows):
591 self.figure = plt.figure(figsize=(self.width, self.height),
592 edgecolor='k',
593 facecolor='w')
594 #add always one subplot
595 self.figurelist.append(self.figure)
596
597 else : # cada dia nuevo limpia el axes, pero mantiene el figure
598 for eachfigure in self.figurelist:
599 eachfigure.clf() # eliminaria todas las figuras de la lista?
600 self.axes = []
601
602 for eachfigure in self.figurelist:
603 ax = eachfigure.add_subplot(1,1,1) #solo 1 axis por figura
604 #ax = self.figure(n+1)
605 ax.firsttime = True
606 #Cada figura tiene un distinto puntero
607 self.axes.append(ax)
608 #plt.close(eachfigure)
609
531 self.cb_label = 'dB'
532 self.titles = ['{} Channel {}'.format(self.CODE.upper(), x) for x in range(self.nrows)]
610 533
611 534 def plot(self):
535 self.x = self.data.times
536 self.y = self.data.heights
537 self.z = self.data[self.CODE]
538 self.z = numpy.ma.masked_invalid(self.z)
612 539
613 if self.ind_plt_ch is False: #standard mode
614 self.x = np.array(self.times)
615 self.y = self.dataOut.getHeiRange()
616 self.z = []
617
618 for ch in range(self.nrows):
619 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
620
621 self.z = np.array(self.z)
622 540 for n, ax in enumerate(self.axes):
623 541 x, y, z = self.fill_gaps(*self.decimate())
624 if self.xmin is None:
625 xmin = self.min_time
626 else:
627 xmin = fromtimestamp(int(self.xmin), self.min_time)
628 if self.xmax is None:
629 xmax = xmin + self.xrange*60*60
630 else:
631 xmax = xmin + (self.xmax - self.xmin) * 60 * 60
632 self.zmin = self.zmin if self.zmin else np.min(self.z)
633 self.zmax = self.zmax if self.zmax else np.max(self.z)
542 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
543 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
634 544 if ax.firsttime:
635 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
636 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
637 plot = ax.pcolormesh(x, y, z[n].T,
545 ax.plt = ax.pcolormesh(x, y, z[n].T,
638 546 vmin=self.zmin,
639 547 vmax=self.zmax,
640 548 cmap=plt.get_cmap(self.colormap)
641 549 )
642 divider = make_axes_locatable(ax)
643 cax = divider.new_horizontal(size='2%', pad=0.05)
644 self.figure.add_axes(cax)
645 plt.colorbar(plot, cax)
646 ax.set_ylim(self.ymin, self.ymax)
647 ax.xaxis.set_major_formatter(FuncFormatter(func))
648 ax.xaxis.set_major_locator(LinearLocator(6))
649 ax.set_ylabel(self.ylabel)
650 # if self.xmin is None:
651 # xmin = self.min_time
652 # else:
653 # xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
654 # datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
655
656 ax.set_xlim(xmin, xmax)
657 ax.firsttime = False
550 if self.showprofile:
551 ax.plot_profile= self.pf_axes[n].plot(self.data['rti'][n][-1], self.y)[0]
552 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
553 color="k", linestyle="dashed", lw=1)[0]
658 554 else:
659 555 ax.collections.remove(ax.collections[0])
660 ax.set_xlim(xmin, xmax)
661 plot = ax.pcolormesh(x, y, z[n].T,
662 vmin=self.zmin,
663 vmax=self.zmax,
664 cmap=plt.get_cmap(self.colormap)
665 )
666 ax.set_title('{} {}'.format(self.titles[n],
667 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
668 size=8)
669
670 self.saveTime = self.min_time
671 else :
672 self.x = np.array(self.times)
673 self.y = self.dataOut.getHeiRange()
674 self.z = []
675
676 for ch in range(self.nrows):
677 self.z.append([self.data[self.CODE][t][ch] for t in self.times])
678
679 self.z = np.array(self.z)
680 for n, eachfigure in enumerate(self.figurelist): #estaba ax in axes
681
682 x, y, z = self.fill_gaps(*self.decimate())
683 xmin = self.min_time
684 xmax = xmin+self.xrange*60*60
685 self.zmin = self.zmin if self.zmin else np.min(self.z)
686 self.zmax = self.zmax if self.zmax else np.max(self.z)
687 if self.axes[n].firsttime:
688 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
689 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
690 plot = self.axes[n].pcolormesh(x, y, z[n].T,
691 vmin=self.zmin,
692 vmax=self.zmax,
693 cmap=plt.get_cmap(self.colormap)
694 )
695 divider = make_axes_locatable(self.axes[n])
696 cax = divider.new_horizontal(size='2%', pad=0.05)
697 eachfigure.add_axes(cax)
698 #self.figure2.add_axes(cax)
699 plt.colorbar(plot, cax)
700 self.axes[n].set_ylim(self.ymin, self.ymax)
701
702 self.axes[n].xaxis.set_major_formatter(FuncFormatter(func))
703 self.axes[n].xaxis.set_major_locator(LinearLocator(6))
704
705 self.axes[n].set_ylabel(self.ylabel)
706
707 if self.xmin is None:
708 xmin = self.min_time
709 else:
710 xmin = (datetime.datetime.combine(self.dataOut.datatime.date(),
711 datetime.time(self.xmin, 0, 0))-d1970).total_seconds()
712
713 self.axes[n].set_xlim(xmin, xmax)
714 self.axes[n].firsttime = False
715 else:
716 self.axes[n].collections.remove(self.axes[n].collections[0])
717 self.axes[n].set_xlim(xmin, xmax)
718 plot = self.axes[n].pcolormesh(x, y, z[n].T,
556 ax.plt = ax.pcolormesh(x, y, z[n].T,
719 557 vmin=self.zmin,
720 558 vmax=self.zmax,
721 559 cmap=plt.get_cmap(self.colormap)
722 560 )
723 self.axes[n].set_title('{} {}'.format(self.titles[n],
724 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
725 size=8)
561 if self.showprofile:
562 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
563 ax.plot_noise.set_data(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y)
726 564
727 565 self.saveTime = self.min_time
728 566
729 567
730 568 class PlotCOHData(PlotRTIData):
569 '''
570 Plot for Coherence data
571 '''
731 572
732 573 CODE = 'coh'
733 574
734 575 def setup(self):
735
576 self.xaxis = 'time'
736 577 self.ncols = 1
737 self.nrows = self.dataOut.nPairs
738 self.width = 10
739 self.height = 2.2*self.nrows if self.nrows<6 else 12
740 self.ind_plt_ch = False #just for coherence and phase
741 if self.nrows==1:
742 self.height += 1
578 self.nrows = len(self.data.pairs)
579 self.nplots = len(self.data.pairs)
743 580 self.ylabel = 'Range [Km]'
744 self.titles = ['{} Ch{} * Ch{}'.format(self.CODE.upper(), x[0], x[1]) for x in self.dataOut.pairsList]
745
746 if self.figure is None:
747 self.figure = plt.figure(figsize=(self.width, self.height),
748 edgecolor='k',
749 facecolor='w')
581 if self.CODE == 'coh':
582 self.cb_label = ''
583 self.titles = ['Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
750 584 else:
751 self.figure.clf()
752 self.axes = []
585 self.cb_label = 'Degrees'
586 self.titles = ['Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
753 587
754 for n in range(self.nrows):
755 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
756 ax.firsttime = True
757 self.axes.append(ax)
588
589 class PlotPHASEData(PlotCOHData):
590 '''
591 Plot for Phase map data
592 '''
593
594 CODE = 'phase'
595 colormap = 'seismic'
758 596
759 597
760 598 class PlotNoiseData(PlotData):
599 '''
600 Plot for noise
601 '''
602
761 603 CODE = 'noise'
762 604
763 605 def setup(self):
764
606 self.xaxis = 'time'
765 607 self.ncols = 1
766 608 self.nrows = 1
767 self.width = 10
768 self.height = 3.2
609 self.nplots = 1
769 610 self.ylabel = 'Intensity [dB]'
770 611 self.titles = ['Noise']
771
772 if self.figure is None:
773 self.figure = plt.figure(figsize=(self.width, self.height),
774 edgecolor='k',
775 facecolor='w')
776 else:
777 self.figure.clf()
778 self.axes = []
779
780 self.ax = self.figure.add_subplot(self.nrows, self.ncols, 1)
781 self.ax.firsttime = True
782
783 def plot(self):
784
785 x = self.times
786 xmin = self.min_time
787 xmax = xmin+self.xrange*60*60
788 if self.ax.firsttime:
789 for ch in self.dataOut.channelList:
790 y = [self.data[self.CODE][t][ch] for t in self.times]
791 self.ax.plot(x, y, lw=1, label='Ch{}'.format(ch))
792 self.ax.firsttime = False
793 self.ax.xaxis.set_major_formatter(FuncFormatter(func))
794 self.ax.xaxis.set_major_locator(LinearLocator(6))
795 self.ax.set_ylabel(self.ylabel)
796 plt.legend()
797 else:
798 for ch in self.dataOut.channelList:
799 y = [self.data[self.CODE][t][ch] for t in self.times]
800 self.ax.lines[ch].set_data(x, y)
801
802 self.ax.set_xlim(xmin, xmax)
803 self.ax.set_ylim(min(y)-5, max(y)+5)
804 self.saveTime = self.min_time
805
806
807 class PlotWindProfilerData(PlotRTIData):
808
809 CODE = 'wind'
810 colormap = 'seismic'
811
812 def setup(self):
813 self.ncols = 1
814 self.nrows = self.dataOut.data_output.shape[0]
815 self.width = 10
816 self.height = 2.2*self.nrows
817 self.ylabel = 'Height [Km]'
818 self.titles = ['Zonal Wind' ,'Meridional Wind', 'Vertical Wind']
819 self.clabels = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)']
820 self.windFactor = [1, 1, 100]
821
822 if self.figure is None:
823 self.figure = plt.figure(figsize=(self.width, self.height),
824 edgecolor='k',
825 facecolor='w')
826 else:
827 self.figure.clf()
828 self.axes = []
829
830 for n in range(self.nrows):
831 ax = self.figure.add_subplot(self.nrows, self.ncols, n+1)
832 ax.firsttime = True
833 self.axes.append(ax)
612 self.colorbar = False
834 613
835 614 def plot(self):
836 615
837 self.x = np.array(self.times)
838 self.y = self.dataOut.heightList
839 self.z = []
840
841 for ch in range(self.nrows):
842 self.z.append([self.data['output'][t][ch] for t in self.times])
843
844 self.z = np.array(self.z)
845 self.z = numpy.ma.masked_invalid(self.z)
846
847 cmap=plt.get_cmap(self.colormap)
848 cmap.set_bad('black', 1.)
849
850 for n, ax in enumerate(self.axes):
851 x, y, z = self.fill_gaps(*self.decimate())
616 x = self.data.times
852 617 xmin = self.min_time
853 618 xmax = xmin+self.xrange*60*60
854 if ax.firsttime:
855 self.ymin = self.ymin if self.ymin else np.nanmin(self.y)
856 self.ymax = self.ymax if self.ymax else np.nanmax(self.y)
857 self.zmax = self.zmax if self.zmax else numpy.nanmax(abs(self.z[:-1, :]))
858 self.zmin = self.zmin if self.zmin else -self.zmax
859
860 plot = ax.pcolormesh(x, y, z[n].T*self.windFactor[n],
861 vmin=self.zmin,
862 vmax=self.zmax,
863 cmap=cmap
864 )
865 divider = make_axes_locatable(ax)
866 cax = divider.new_horizontal(size='2%', pad=0.05)
867 self.figure.add_axes(cax)
868 cb = plt.colorbar(plot, cax)
869 cb.set_label(self.clabels[n])
870 ax.set_ylim(self.ymin, self.ymax)
619 Y = self.data[self.CODE]
871 620
872 ax.xaxis.set_major_formatter(FuncFormatter(func))
873 ax.xaxis.set_major_locator(LinearLocator(6))
874
875 ax.set_ylabel(self.ylabel)
876
877 ax.set_xlim(xmin, xmax)
878 ax.firsttime = False
621 if self.axes[0].firsttime:
622 for ch in self.data.channels:
623 y = Y[ch]
624 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
625 plt.legend()
879 626 else:
880 ax.collections.remove(ax.collections[0])
881 ax.set_xlim(xmin, xmax)
882 plot = ax.pcolormesh(x, y, z[n].T*self.windFactor[n],
883 vmin=self.zmin,
884 vmax=self.zmax,
885 cmap=plt.get_cmap(self.colormap)
886 )
887 ax.set_title('{} {}'.format(self.titles[n],
888 datetime.datetime.fromtimestamp(self.max_time).strftime('%y/%m/%d %H:%M:%S')),
889 size=8)
627 for ch in self.data.channels:
628 y = Y[ch]
629 self.axes[0].lines[ch].set_data(x, y)
890 630
631 self.ymin = numpy.nanmin(Y) - 5
632 self.ymax = numpy.nanmax(Y) + 5
891 633 self.saveTime = self.min_time
892 634
893 635
894 636 class PlotSNRData(PlotRTIData):
637 '''
638 Plot for SNR Data
639 '''
640
895 641 CODE = 'snr'
896 642 colormap = 'jet'
897 643
644
898 645 class PlotDOPData(PlotRTIData):
646 '''
647 Plot for DOPPLER Data
648 '''
649
899 650 CODE = 'dop'
900 651 colormap = 'jet'
901 652
902 653
903 class PlotPHASEData(PlotCOHData):
904 CODE = 'phase'
905 colormap = 'seismic'
906
907
908 654 class PlotSkyMapData(PlotData):
655 '''
656 Plot for meteors detection data
657 '''
909 658
910 659 CODE = 'met'
911 660
@@ -932,7 +681,7 class PlotSkyMapData(PlotData):
932 681
933 682 def plot(self):
934 683
935 arrayParameters = np.concatenate([self.data['param'][t] for t in self.times])
684 arrayParameters = numpy.concatenate([self.data['param'][t] for t in self.data.times])
936 685 error = arrayParameters[:,-1]
937 686 indValid = numpy.where(error == 0)[0]
938 687 finalMeteor = arrayParameters[indValid,:]
@@ -962,3 +711,72 class PlotSkyMapData(PlotData):
962 711 self.ax.set_title(title, size=8)
963 712
964 713 self.saveTime = self.max_time
714
715 class PlotParamData(PlotRTIData):
716 '''
717 Plot for data_param object
718 '''
719
720 CODE = 'param'
721 colormap = 'seismic'
722
723 def setup(self):
724 self.xaxis = 'time'
725 self.ncols = 1
726 self.nrows = self.data.shape(self.CODE)[0]
727 self.nplots = self.nrows
728 if self.showSNR:
729 self.nrows += 1
730
731 self.ylabel = 'Height [Km]'
732 self.titles = self.data.parameters \
733 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
734 if self.showSNR:
735 self.titles.append('SNR')
736
737 def plot(self):
738 self.data.normalize_heights()
739 self.x = self.data.times
740 self.y = self.data.heights
741 if self.showSNR:
742 self.z = numpy.concatenate(
743 (self.data[self.CODE], self.data['snr'])
744 )
745 else:
746 self.z = self.data[self.CODE]
747
748 self.z = numpy.ma.masked_invalid(self.z)
749
750 for n, ax in enumerate(self.axes):
751
752 x, y, z = self.fill_gaps(*self.decimate())
753
754 if ax.firsttime:
755 if self.zlimits is not None:
756 self.zmin, self.zmax = self.zlimits[n]
757 self.zmax = self.zmax if self.zmax is not None else numpy.nanmax(abs(self.z[:-1, :]))
758 self.zmin = self.zmin if self.zmin is not None else -self.zmax
759 ax.plt = ax.pcolormesh(x, y, z[n, :, :].T*self.factors[n],
760 vmin=self.zmin,
761 vmax=self.zmax,
762 cmap=self.cmaps[n]
763 )
764 else:
765 if self.zlimits is not None:
766 self.zmin, self.zmax = self.zlimits[n]
767 ax.collections.remove(ax.collections[0])
768 ax.plt = ax.pcolormesh(x, y, z[n, :, :].T*self.factors[n],
769 vmin=self.zmin,
770 vmax=self.zmax,
771 cmap=self.cmaps[n]
772 )
773
774 self.saveTime = self.min_time
775
776 class PlotOuputData(PlotParamData):
777 '''
778 Plot data_output object
779 '''
780
781 CODE = 'output'
782 colormap = 'seismic' No newline at end of file
This diff has been collapsed as it changes many lines, (1338 lines changed) Show them Hide them
@@ -1,16 +1,56
1 1 import numpy
2 2 import math
3 3 from scipy import optimize, interpolate, signal, stats, ndimage
4 import scipy
4 5 import re
5 6 import datetime
6 7 import copy
7 8 import sys
8 9 import importlib
9 10 import itertools
10
11 from multiprocessing import Pool, TimeoutError
12 from multiprocessing.pool import ThreadPool
13 import copy_reg
14 import cPickle
15 import types
16 from functools import partial
17 import time
18 #from sklearn.cluster import KMeans
19
20 import matplotlib.pyplot as plt
21
22 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
11 23 from jroproc_base import ProcessingUnit, Operation
12 24 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
25 from scipy import asarray as ar,exp
26 from scipy.optimize import curve_fit
27
28 import warnings
29 from numpy import NaN
30 from scipy.optimize.optimize import OptimizeWarning
31 warnings.filterwarnings('ignore')
32
33
34 SPEED_OF_LIGHT = 299792458
35
36
37 '''solving pickling issue'''
13 38
39 def _pickle_method(method):
40 func_name = method.im_func.__name__
41 obj = method.im_self
42 cls = method.im_class
43 return _unpickle_method, (func_name, obj, cls)
44
45 def _unpickle_method(func_name, obj, cls):
46 for cls in cls.mro():
47 try:
48 func = cls.__dict__[func_name]
49 except KeyError:
50 pass
51 else:
52 break
53 return func.__get__(obj, cls)
14 54
15 55 class ParametersProc(ProcessingUnit):
16 56
@@ -83,12 +123,32 class ParametersProc(ProcessingUnit):
83 123 self.dataOut.nIncohInt = self.dataIn.nIncohInt
84 124 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
85 125 self.dataOut.ippFactor = self.dataIn.ippFactor
86 #self.dataOut.normFactor = self.dataIn.getNormFactor()
126 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
127 self.dataOut.spc_noise = self.dataIn.getNoise()
128 self.dataOut.spc_range = (self.dataIn.getFreqRange(1)/1000. , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
87 129 self.dataOut.pairsList = self.dataIn.pairsList
88 130 self.dataOut.groupList = self.dataIn.pairsList
89 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
90 131 self.dataOut.flagNoData = False
91 132
133 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
134 self.dataOut.ChanDist = self.dataIn.ChanDist
135 else: self.dataOut.ChanDist = None
136
137 if hasattr(self.dataIn, 'VelRange'): #Velocities range
138 self.dataOut.VelRange = self.dataIn.VelRange
139 else: self.dataOut.VelRange = None
140
141 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
142 self.dataOut.RadarConst = self.dataIn.RadarConst
143
144 if hasattr(self.dataIn, 'NPW'): #NPW
145 self.dataOut.NPW = self.dataIn.NPW
146
147 if hasattr(self.dataIn, 'COFA'): #COFA
148 self.dataOut.COFA = self.dataIn.COFA
149
150
151
92 152 #---------------------- Correlation Data ---------------------------
93 153
94 154 if self.dataIn.type == "Correlation":
@@ -108,7 +168,6 class ParametersProc(ProcessingUnit):
108 168
109 169 if self.dataIn.type == "Parameters":
110 170 self.dataOut.copy(self.dataIn)
111 self.dataOut.utctimeInit = self.dataIn.utctime
112 171 self.dataOut.flagNoData = False
113 172
114 173 return True
@@ -119,6 +178,1186 class ParametersProc(ProcessingUnit):
119 178
120 179 return
121 180
181
182 def target(tups):
183
184 obj, args = tups
185 #print 'TARGETTT', obj, args
186 return obj.FitGau(args)
187
188 class GaussianFit(Operation):
189
190 '''
191 Function that fit of one and two generalized gaussians (gg) based
192 on the PSD shape across an "power band" identified from a cumsum of
193 the measured spectrum - noise.
194
195 Input:
196 self.dataOut.data_pre : SelfSpectra
197
198 Output:
199 self.dataOut.GauSPC : SPC_ch1, SPC_ch2
200
201 '''
202 def __init__(self, **kwargs):
203 Operation.__init__(self, **kwargs)
204 self.i=0
205
206
207 def run(self, dataOut, num_intg=7, pnoise=1., vel_arr=None, SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
208 """This routine will find a couple of generalized Gaussians to a power spectrum
209 input: spc
210 output:
211 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
212 """
213
214 self.spc = dataOut.data_pre[0].copy()
215
216
217 print 'SelfSpectra Shape', numpy.asarray(self.spc).shape
218
219
220 #plt.figure(50)
221 #plt.subplot(121)
222 #plt.plot(self.spc,'k',label='spc(66)')
223 #plt.plot(xFrec,ySamples[1],'g',label='Ch1')
224 #plt.plot(xFrec,ySamples[2],'r',label='Ch2')
225 #plt.plot(xFrec,FitGauss,'yo:',label='fit')
226 #plt.legend()
227 #plt.title('DATOS A ALTURA DE 7500 METROS')
228 #plt.show()
229
230 self.Num_Hei = self.spc.shape[2]
231 #self.Num_Bin = len(self.spc)
232 self.Num_Bin = self.spc.shape[1]
233 self.Num_Chn = self.spc.shape[0]
234
235 Vrange = dataOut.abscissaList
236
237 #print 'self.spc2', numpy.asarray(self.spc).shape
238
239 GauSPC = numpy.empty([2,self.Num_Bin,self.Num_Hei])
240 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
241 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
242 SPC_ch1[:] = numpy.NaN
243 SPC_ch2[:] = numpy.NaN
244
245
246 start_time = time.time()
247
248 noise_ = dataOut.spc_noise[0].copy()
249
250
251
252 pool = Pool(processes=self.Num_Chn)
253 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
254 objs = [self for __ in range(self.Num_Chn)]
255 attrs = zip(objs, args)
256 gauSPC = pool.map(target, attrs)
257 dataOut.GauSPC = numpy.asarray(gauSPC)
258 # ret = []
259 # for n in range(self.Num_Chn):
260 # self.FitGau(args[n])
261 # dataOut.GauSPC = ret
262
263
264
265 # for ch in range(self.Num_Chn):
266 #
267 # for ht in range(self.Num_Hei):
268 # #print (numpy.asarray(self.spc).shape)
269 # spc = numpy.asarray(self.spc)[ch,:,ht]
270 #
271 # #############################################
272 # # normalizing spc and noise
273 # # This part differs from gg1
274 # spc_norm_max = max(spc)
275 # spc = spc / spc_norm_max
276 # pnoise = pnoise / spc_norm_max
277 # #############################################
278 #
279 # if abs(vel_arr[0])<15.0: # this switch is for spectra collected with different length IPP's
280 # fatspectra=1.0
281 # else:
282 # fatspectra=0.5
283 #
284 # wnoise = noise_ / spc_norm_max
285 # #print 'wnoise', noise_, dataOut.spc_noise[0], wnoise
286 # #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
287 # #if wnoise>1.1*pnoise: # to be tested later
288 # # wnoise=pnoise
289 # noisebl=wnoise*0.9; noisebh=wnoise*1.1
290 # spc=spc-wnoise
291 #
292 # minx=numpy.argmin(spc)
293 # spcs=numpy.roll(spc,-minx)
294 # cum=numpy.cumsum(spcs)
295 # tot_noise=wnoise * self.Num_Bin #64;
296 # #tot_signal=sum(cum[-5:])/5.; ''' How does this line work? '''
297 # #snr=tot_signal/tot_noise
298 # #snr=cum[-1]/tot_noise
299 #
300 # #print 'spc' , spcs[5:8] , 'tot_noise', tot_noise
301 #
302 # snr = sum(spcs)/tot_noise
303 # snrdB=10.*numpy.log10(snr)
304 #
305 # #if snrdB < -9 :
306 # # snrdB = numpy.NaN
307 # # continue
308 #
309 # #print 'snr',snrdB # , sum(spcs) , tot_noise
310 #
311 #
312 # #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
313 # # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
314 #
315 # cummax=max(cum); epsi=0.08*fatspectra # cumsum to narrow down the energy region
316 # cumlo=cummax*epsi;
317 # cumhi=cummax*(1-epsi)
318 # powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
319 #
320 # #if len(powerindex)==1:
321 # ##return [numpy.mod(powerindex[0]+minx,64),None,None,None,],[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
322 # #return [numpy.mod(powerindex[0]+minx, self.Num_Bin ),None,None,None,],[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
323 # #elif len(powerindex)<4*fatspectra:
324 # #return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
325 #
326 # if len(powerindex) < 1:# case for powerindex 0
327 # continue
328 # powerlo=powerindex[0]
329 # powerhi=powerindex[-1]
330 # powerwidth=powerhi-powerlo
331 #
332 # firstpeak=powerlo+powerwidth/10.# first gaussian energy location
333 # secondpeak=powerhi-powerwidth/10.#second gaussian energy location
334 # midpeak=(firstpeak+secondpeak)/2.
335 # firstamp=spcs[int(firstpeak)]
336 # secondamp=spcs[int(secondpeak)]
337 # midamp=spcs[int(midpeak)]
338 # #x=numpy.spc.shape[1]
339 #
340 # #x=numpy.arange(64)
341 # x=numpy.arange( self.Num_Bin )
342 # y_data=spc+wnoise
343 #
344 # # single gaussian
345 # #shift0=numpy.mod(midpeak+minx,64)
346 # shift0=numpy.mod(midpeak+minx, self.Num_Bin )
347 # width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
348 # power0=2.
349 # amplitude0=midamp
350 # state0=[shift0,width0,amplitude0,power0,wnoise]
351 # #bnds=((0,63),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
352 # bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
353 # #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(0.1,0.5))
354 # # bnds = range of fft, power width, amplitude, power, noise
355 # lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
356 #
357 # chiSq1=lsq1[1];
358 # jack1= self.y_jacobian1(x,lsq1[0])
359 #
360 #
361 # try:
362 # sigmas1=numpy.sqrt(chiSq1*numpy.diag(numpy.linalg.inv(numpy.dot(jack1.T,jack1))))
363 # except:
364 # std1=32.; sigmas1=numpy.ones(5)
365 # else:
366 # std1=sigmas1[0]
367 #
368 #
369 # if fatspectra<1.0 and powerwidth<4:
370 # choice=0
371 # Amplitude0=lsq1[0][2]
372 # shift0=lsq1[0][0]
373 # width0=lsq1[0][1]
374 # p0=lsq1[0][3]
375 # Amplitude1=0.
376 # shift1=0.
377 # width1=0.
378 # p1=0.
379 # noise=lsq1[0][4]
380 # #return (numpy.array([shift0,width0,Amplitude0,p0]),
381 # # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
382 #
383 # # two gaussians
384 # #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
385 # shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
386 # shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
387 # width0=powerwidth/6.;
388 # width1=width0
389 # power0=2.;
390 # power1=power0
391 # amplitude0=firstamp;
392 # amplitude1=secondamp
393 # state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
394 # #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
395 # bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
396 # #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
397 #
398 # lsq2=fmin_l_bfgs_b(self.misfit2,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
399 #
400 #
401 # chiSq2=lsq2[1]; jack2=self.y_jacobian2(x,lsq2[0])
402 #
403 #
404 # try:
405 # sigmas2=numpy.sqrt(chiSq2*numpy.diag(numpy.linalg.inv(numpy.dot(jack2.T,jack2))))
406 # except:
407 # std2a=32.; std2b=32.; sigmas2=numpy.ones(9)
408 # else:
409 # std2a=sigmas2[0]; std2b=sigmas2[4]
410 #
411 #
412 #
413 # oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
414 #
415 # if snrdB>-9: # when SNR is strong pick the peak with least shift (LOS velocity) error
416 # if oneG:
417 # choice=0
418 # else:
419 # w1=lsq2[0][1]; w2=lsq2[0][5]
420 # a1=lsq2[0][2]; a2=lsq2[0][6]
421 # p1=lsq2[0][3]; p2=lsq2[0][7]
422 # s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1; s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
423 # gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
424 #
425 # if gp1>gp2:
426 # if a1>0.7*a2:
427 # choice=1
428 # else:
429 # choice=2
430 # elif gp2>gp1:
431 # if a2>0.7*a1:
432 # choice=2
433 # else:
434 # choice=1
435 # else:
436 # choice=numpy.argmax([a1,a2])+1
437 # #else:
438 # #choice=argmin([std2a,std2b])+1
439 #
440 # else: # with low SNR go to the most energetic peak
441 # choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
442 #
443 # #print 'choice',choice
444 #
445 # if choice==0: # pick the single gaussian fit
446 # Amplitude0=lsq1[0][2]
447 # shift0=lsq1[0][0]
448 # width0=lsq1[0][1]
449 # p0=lsq1[0][3]
450 # Amplitude1=0.
451 # shift1=0.
452 # width1=0.
453 # p1=0.
454 # noise=lsq1[0][4]
455 # elif choice==1: # take the first one of the 2 gaussians fitted
456 # Amplitude0 = lsq2[0][2]
457 # shift0 = lsq2[0][0]
458 # width0 = lsq2[0][1]
459 # p0 = lsq2[0][3]
460 # Amplitude1 = lsq2[0][6] # This is 0 in gg1
461 # shift1 = lsq2[0][4] # This is 0 in gg1
462 # width1 = lsq2[0][5] # This is 0 in gg1
463 # p1 = lsq2[0][7] # This is 0 in gg1
464 # noise = lsq2[0][8]
465 # else: # the second one
466 # Amplitude0 = lsq2[0][6]
467 # shift0 = lsq2[0][4]
468 # width0 = lsq2[0][5]
469 # p0 = lsq2[0][7]
470 # Amplitude1 = lsq2[0][2] # This is 0 in gg1
471 # shift1 = lsq2[0][0] # This is 0 in gg1
472 # width1 = lsq2[0][1] # This is 0 in gg1
473 # p1 = lsq2[0][3] # This is 0 in gg1
474 # noise = lsq2[0][8]
475 #
476 # #print len(noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0)
477 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
478 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
479 # #print 'SPC_ch1.shape',SPC_ch1.shape
480 # #print 'SPC_ch2.shape',SPC_ch2.shape
481 # #dataOut.data_param = SPC_ch1
482 # GauSPC[0] = SPC_ch1
483 # GauSPC[1] = SPC_ch2
484
485 # #plt.gcf().clear()
486 # plt.figure(50+self.i)
487 # self.i=self.i+1
488 # #plt.subplot(121)
489 # plt.plot(self.spc,'k')#,label='spc(66)')
490 # plt.plot(SPC_ch1[ch,ht],'b')#,label='gg1')
491 # #plt.plot(SPC_ch2,'r')#,label='gg2')
492 # #plt.plot(xFrec,ySamples[1],'g',label='Ch1')
493 # #plt.plot(xFrec,ySamples[2],'r',label='Ch2')
494 # #plt.plot(xFrec,FitGauss,'yo:',label='fit')
495 # plt.legend()
496 # plt.title('DATOS A ALTURA DE 7500 METROS')
497 # plt.show()
498 # print 'shift0', shift0
499 # print 'Amplitude0', Amplitude0
500 # print 'width0', width0
501 # print 'p0', p0
502 # print '========================'
503 # print 'shift1', shift1
504 # print 'Amplitude1', Amplitude1
505 # print 'width1', width1
506 # print 'p1', p1
507 # print 'noise', noise
508 # print 's_noise', wnoise
509
510 print '========================================================'
511 print 'total_time: ', time.time()-start_time
512
513 # re-normalizing spc and noise
514 # This part differs from gg1
515
516
517
518 ''' Parameters:
519 1. Amplitude
520 2. Shift
521 3. Width
522 4. Power
523 '''
524
525
526 ###############################################################################
527 def FitGau(self, X):
528
529 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
530 #print 'VARSSSS', ch, pnoise, noise, num_intg
531
532 #print 'HEIGHTS', self.Num_Hei
533
534 GauSPC = []
535 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
536 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
537 SPC_ch1[:] = 0#numpy.NaN
538 SPC_ch2[:] = 0#numpy.NaN
539
540
541
542 for ht in range(self.Num_Hei):
543 #print (numpy.asarray(self.spc).shape)
544
545 #print 'TTTTT', ch , ht
546 #print self.spc.shape
547
548
549 spc = numpy.asarray(self.spc)[ch,:,ht]
550
551 #############################################
552 # normalizing spc and noise
553 # This part differs from gg1
554 spc_norm_max = max(spc)
555 spc = spc / spc_norm_max
556 pnoise = pnoise / spc_norm_max
557 #############################################
558
559 fatspectra=1.0
560
561 wnoise = noise_ / spc_norm_max
562 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
563 #if wnoise>1.1*pnoise: # to be tested later
564 # wnoise=pnoise
565 noisebl=wnoise*0.9; noisebh=wnoise*1.1
566 spc=spc-wnoise
567 # print 'wnoise', noise_[0], spc_norm_max, wnoise
568 minx=numpy.argmin(spc)
569 spcs=numpy.roll(spc,-minx)
570 cum=numpy.cumsum(spcs)
571 tot_noise=wnoise * self.Num_Bin #64;
572 #print 'spc' , spcs[5:8] , 'tot_noise', tot_noise
573 #tot_signal=sum(cum[-5:])/5.; ''' How does this line work? '''
574 #snr=tot_signal/tot_noise
575 #snr=cum[-1]/tot_noise
576 snr = sum(spcs)/tot_noise
577 snrdB=10.*numpy.log10(snr)
578
579 if snrdB < SNRlimit :
580 snr = numpy.NaN
581 SPC_ch1[:,ht] = 0#numpy.NaN
582 SPC_ch1[:,ht] = 0#numpy.NaN
583 GauSPC = (SPC_ch1,SPC_ch2)
584 continue
585 #print 'snr',snrdB #, sum(spcs) , tot_noise
586
587
588
589 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
590 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
591
592 cummax=max(cum); epsi=0.08*fatspectra # cumsum to narrow down the energy region
593 cumlo=cummax*epsi;
594 cumhi=cummax*(1-epsi)
595 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
596
597
598 if len(powerindex) < 1:# case for powerindex 0
599 continue
600 powerlo=powerindex[0]
601 powerhi=powerindex[-1]
602 powerwidth=powerhi-powerlo
603
604 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
605 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
606 midpeak=(firstpeak+secondpeak)/2.
607 firstamp=spcs[int(firstpeak)]
608 secondamp=spcs[int(secondpeak)]
609 midamp=spcs[int(midpeak)]
610
611 x=numpy.arange( self.Num_Bin )
612 y_data=spc+wnoise
613
614 # single gaussian
615 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
616 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
617 power0=2.
618 amplitude0=midamp
619 state0=[shift0,width0,amplitude0,power0,wnoise]
620 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
621 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
622
623 chiSq1=lsq1[1];
624 jack1= self.y_jacobian1(x,lsq1[0])
625
626
627 try:
628 sigmas1=numpy.sqrt(chiSq1*numpy.diag(numpy.linalg.inv(numpy.dot(jack1.T,jack1))))
629 except:
630 std1=32.; sigmas1=numpy.ones(5)
631 else:
632 std1=sigmas1[0]
633
634
635 if fatspectra<1.0 and powerwidth<4:
636 choice=0
637 Amplitude0=lsq1[0][2]
638 shift0=lsq1[0][0]
639 width0=lsq1[0][1]
640 p0=lsq1[0][3]
641 Amplitude1=0.
642 shift1=0.
643 width1=0.
644 p1=0.
645 noise=lsq1[0][4]
646 #return (numpy.array([shift0,width0,Amplitude0,p0]),
647 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
648
649 # two gaussians
650 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
651 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
652 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
653 width0=powerwidth/6.;
654 width1=width0
655 power0=2.;
656 power1=power0
657 amplitude0=firstamp;
658 amplitude1=secondamp
659 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
660 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
661 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
662 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
663
664 lsq2=fmin_l_bfgs_b(self.misfit2,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
665
666
667 chiSq2=lsq2[1]; jack2=self.y_jacobian2(x,lsq2[0])
668
669
670 try:
671 sigmas2=numpy.sqrt(chiSq2*numpy.diag(numpy.linalg.inv(numpy.dot(jack2.T,jack2))))
672 except:
673 std2a=32.; std2b=32.; sigmas2=numpy.ones(9)
674 else:
675 std2a=sigmas2[0]; std2b=sigmas2[4]
676
677
678
679 oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
680
681 if snrdB>-6: # when SNR is strong pick the peak with least shift (LOS velocity) error
682 if oneG:
683 choice=0
684 else:
685 w1=lsq2[0][1]; w2=lsq2[0][5]
686 a1=lsq2[0][2]; a2=lsq2[0][6]
687 p1=lsq2[0][3]; p2=lsq2[0][7]
688 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
689 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
690 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
691
692 if gp1>gp2:
693 if a1>0.7*a2:
694 choice=1
695 else:
696 choice=2
697 elif gp2>gp1:
698 if a2>0.7*a1:
699 choice=2
700 else:
701 choice=1
702 else:
703 choice=numpy.argmax([a1,a2])+1
704 #else:
705 #choice=argmin([std2a,std2b])+1
706
707 else: # with low SNR go to the most energetic peak
708 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
709
710
711 shift0=lsq2[0][0]; vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
712 shift1=lsq2[0][4]; vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
713
714 max_vel = 20
715
716 #first peak will be 0, second peak will be 1
717 if vel0 > 0 and vel0 < max_vel : #first peak is in the correct range
718 shift0=lsq2[0][0]
719 width0=lsq2[0][1]
720 Amplitude0=lsq2[0][2]
721 p0=lsq2[0][3]
722
723 shift1=lsq2[0][4]
724 width1=lsq2[0][5]
725 Amplitude1=lsq2[0][6]
726 p1=lsq2[0][7]
727 noise=lsq2[0][8]
728 else:
729 shift1=lsq2[0][0]
730 width1=lsq2[0][1]
731 Amplitude1=lsq2[0][2]
732 p1=lsq2[0][3]
733
734 shift0=lsq2[0][4]
735 width0=lsq2[0][5]
736 Amplitude0=lsq2[0][6]
737 p0=lsq2[0][7]
738 noise=lsq2[0][8]
739
740 if Amplitude0<0.1: # in case the peak is noise
741 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
742 if Amplitude1<0.1:
743 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
744
745
746 # if choice==0: # pick the single gaussian fit
747 # Amplitude0=lsq1[0][2]
748 # shift0=lsq1[0][0]
749 # width0=lsq1[0][1]
750 # p0=lsq1[0][3]
751 # Amplitude1=0.
752 # shift1=0.
753 # width1=0.
754 # p1=0.
755 # noise=lsq1[0][4]
756 # elif choice==1: # take the first one of the 2 gaussians fitted
757 # Amplitude0 = lsq2[0][2]
758 # shift0 = lsq2[0][0]
759 # width0 = lsq2[0][1]
760 # p0 = lsq2[0][3]
761 # Amplitude1 = lsq2[0][6] # This is 0 in gg1
762 # shift1 = lsq2[0][4] # This is 0 in gg1
763 # width1 = lsq2[0][5] # This is 0 in gg1
764 # p1 = lsq2[0][7] # This is 0 in gg1
765 # noise = lsq2[0][8]
766 # else: # the second one
767 # Amplitude0 = lsq2[0][6]
768 # shift0 = lsq2[0][4]
769 # width0 = lsq2[0][5]
770 # p0 = lsq2[0][7]
771 # Amplitude1 = lsq2[0][2] # This is 0 in gg1
772 # shift1 = lsq2[0][0] # This is 0 in gg1
773 # width1 = lsq2[0][1] # This is 0 in gg1
774 # p1 = lsq2[0][3] # This is 0 in gg1
775 # noise = lsq2[0][8]
776
777 #print len(noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0)
778 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
779 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
780 #print 'SPC_ch1.shape',SPC_ch1.shape
781 #print 'SPC_ch2.shape',SPC_ch2.shape
782 #dataOut.data_param = SPC_ch1
783 GauSPC = (SPC_ch1,SPC_ch2)
784 #GauSPC[1] = SPC_ch2
785
786 # print 'shift0', shift0
787 # print 'Amplitude0', Amplitude0
788 # print 'width0', width0
789 # print 'p0', p0
790 # print '========================'
791 # print 'shift1', shift1
792 # print 'Amplitude1', Amplitude1
793 # print 'width1', width1
794 # print 'p1', p1
795 # print 'noise', noise
796 # print 's_noise', wnoise
797
798 return GauSPC
799
800
801 def y_jacobian1(self,x,state): # This function is for further analysis of generalized Gaussians, it is not too importan for the signal discrimination.
802 y_model=self.y_model1(x,state)
803 s0,w0,a0,p0,n=state
804 e0=((x-s0)/w0)**2;
805
806 e0u=((x-s0-self.Num_Bin)/w0)**2;
807
808 e0d=((x-s0+self.Num_Bin)/w0)**2
809 m0=numpy.exp(-0.5*e0**(p0/2.));
810 m0u=numpy.exp(-0.5*e0u**(p0/2.));
811 m0d=numpy.exp(-0.5*e0d**(p0/2.))
812 JA=m0+m0u+m0d
813 JP=(-1/4.)*a0*m0*e0**(p0/2.)*numpy.log(e0)+(-1/4.)*a0*m0u*e0u**(p0/2.)*numpy.log(e0u)+(-1/4.)*a0*m0d*e0d**(p0/2.)*numpy.log(e0d)
814
815 JS=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)
816
817 JW=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)**2+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)**2+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)**2
818 jack1=numpy.sqrt(7)*numpy.array([JS/y_model,JW/y_model,JA/y_model,JP/y_model,1./y_model])
819 return jack1.T
820
821 def y_jacobian2(self,x,state):
822 y_model=self.y_model2(x,state)
823 s0,w0,a0,p0,s1,w1,a1,p1,n=state
824 e0=((x-s0)/w0)**2;
825
826 e0u=((x-s0- self.Num_Bin )/w0)**2;
827
828 e0d=((x-s0+ self.Num_Bin )/w0)**2
829 e1=((x-s1)/w1)**2;
830
831 e1u=((x-s1- self.Num_Bin )/w1)**2;
832
833 e1d=((x-s1+ self.Num_Bin )/w1)**2
834 m0=numpy.exp(-0.5*e0**(p0/2.));
835 m0u=numpy.exp(-0.5*e0u**(p0/2.));
836 m0d=numpy.exp(-0.5*e0d**(p0/2.))
837 m1=numpy.exp(-0.5*e1**(p1/2.));
838 m1u=numpy.exp(-0.5*e1u**(p1/2.));
839 m1d=numpy.exp(-0.5*e1d**(p1/2.))
840 JA=m0+m0u+m0d
841 JA1=m1+m1u+m1d
842 JP=(-1/4.)*a0*m0*e0**(p0/2.)*numpy.log(e0)+(-1/4.)*a0*m0u*e0u**(p0/2.)*numpy.log(e0u)+(-1/4.)*a0*m0d*e0d**(p0/2.)*numpy.log(e0d)
843 JP1=(-1/4.)*a1*m1*e1**(p1/2.)*numpy.log(e1)+(-1/4.)*a1*m1u*e1u**(p1/2.)*numpy.log(e1u)+(-1/4.)*a1*m1d*e1d**(p1/2.)*numpy.log(e1d)
844
845 JS=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)
846
847 JS1=(p1/w1/2.)*a1*m1*e1**(p1/2.-1)*((x-s1)/w1)+(p1/w1/2.)*a1*m1u*e1u**(p1/2.-1)*((x-s1- self.Num_Bin )/w1)+(p1/w1/2.)*a1*m1d*e1d**(p1/2.-1)*((x-s1+ self.Num_Bin )/w1)
848
849 JW=(p0/w0/2.)*a0*m0*e0**(p0/2.-1)*((x-s0)/w0)**2+(p0/w0/2.)*a0*m0u*e0u**(p0/2.-1)*((x-s0- self.Num_Bin )/w0)**2+(p0/w0/2.)*a0*m0d*e0d**(p0/2.-1)*((x-s0+ self.Num_Bin )/w0)**2
850
851 JW1=(p1/w1/2.)*a1*m1*e1**(p1/2.-1)*((x-s1)/w1)**2+(p1/w1/2.)*a1*m1u*e1u**(p1/2.-1)*((x-s1- self.Num_Bin )/w1)**2+(p1/w1/2.)*a1*m1d*e1d**(p1/2.-1)*((x-s1+ self.Num_Bin )/w1)**2
852 jack2=numpy.sqrt(7)*numpy.array([JS/y_model,JW/y_model,JA/y_model,JP/y_model,JS1/y_model,JW1/y_model,JA1/y_model,JP1/y_model,1./y_model])
853 return jack2.T
854
855 def y_model1(self,x,state):
856 shift0,width0,amplitude0,power0,noise=state
857 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
858
859 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
860
861 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
862 return model0+model0u+model0d+noise
863
864 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
865 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
866 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
867
868 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
869
870 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
871 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
872
873 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
874
875 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
876 return model0+model0u+model0d+model1+model1u+model1d+noise
877
878 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
879
880 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
881
882 def misfit2(self,state,y_data,x,num_intg):
883 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
884
885
886 class PrecipitationProc(Operation):
887
888 '''
889 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
890
891 Input:
892 self.dataOut.data_pre : SelfSpectra
893
894 Output:
895
896 self.dataOut.data_output : Reflectivity factor, rainfall Rate
897
898
899 Parameters affected:
900 '''
901
902
903 def run(self, dataOut, radar=None, Pt=None, Gt=None, Gr=None, Lambda=None, aL=None,
904 tauW=None, ThetaT=None, ThetaR=None, Km = 0.93, Altitude=None):
905
906 self.spc = dataOut.data_pre[0].copy()
907 self.Num_Hei = self.spc.shape[2]
908 self.Num_Bin = self.spc.shape[1]
909 self.Num_Chn = self.spc.shape[0]
910
911 Velrange = dataOut.abscissaList
912
913 if radar == "MIRA35C" :
914
915 Ze = self.dBZeMODE2(dataOut)
916
917 else:
918
919 self.Pt = Pt
920 self.Gt = Gt
921 self.Gr = Gr
922 self.Lambda = Lambda
923 self.aL = aL
924 self.tauW = tauW
925 self.ThetaT = ThetaT
926 self.ThetaR = ThetaR
927
928 RadarConstant = GetRadarConstant()
929 SPCmean = numpy.mean(self.spc,0)
930 ETA = numpy.zeros(self.Num_Hei)
931 Pr = numpy.sum(SPCmean,0)
932
933 #for R in range(self.Num_Hei):
934 # ETA[R] = RadarConstant * Pr[R] * R**2 #Reflectivity (ETA)
935
936 D_range = numpy.zeros(self.Num_Hei)
937 EqSec = numpy.zeros(self.Num_Hei)
938 del_V = numpy.zeros(self.Num_Hei)
939
940 for R in range(self.Num_Hei):
941 ETA[R] = RadarConstant * Pr[R] * R**2 #Reflectivity (ETA)
942
943 h = R + Altitude #Range from ground to radar pulse altitude
944 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
945
946 D_range[R] = numpy.log( (9.65 - (Velrange[R]/del_V[R])) / 10.3 ) / -0.6 #Range of Diameter of drops related to velocity
947 SIGMA[R] = numpy.pi**5 / Lambda**4 * Km * D_range[R]**6 #Equivalent Section of drops (sigma)
948
949 N_dist[R] = ETA[R] / SIGMA[R]
950
951 Ze = (ETA * Lambda**4) / (numpy.pi * Km)
952 Z = numpy.sum( N_dist * D_range**6 )
953 RR = 6*10**-4*numpy.pi * numpy.sum( D_range**3 * N_dist * Velrange ) #Rainfall rate
954
955
956 RR = (Ze/200)**(1/1.6)
957 dBRR = 10*numpy.log10(RR)
958
959 dBZe = 10*numpy.log10(Ze)
960 dataOut.data_output = Ze
961 dataOut.data_param = numpy.ones([2,self.Num_Hei])
962 dataOut.channelList = [0,1]
963 print 'channelList', dataOut.channelList
964 dataOut.data_param[0]=dBZe
965 dataOut.data_param[1]=dBRR
966 print 'RR SHAPE', dBRR.shape
967 print 'Ze SHAPE', dBZe.shape
968 print 'dataOut.data_param SHAPE', dataOut.data_param.shape
969
970
971 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
972
973 NPW = dataOut.NPW
974 COFA = dataOut.COFA
975
976 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
977 RadarConst = dataOut.RadarConst
978 #frequency = 34.85*10**9
979
980 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
981 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
982
983 ETA = numpy.sum(SNR,1)
984 print 'ETA' , ETA
985 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
986
987 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
988
989 for r in range(self.Num_Hei):
990
991 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
992 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
993
994 return Ze
995
996 def GetRadarConstant(self):
997
998 """
999 Constants:
1000
1001 Pt: Transmission Power dB
1002 Gt: Transmission Gain dB
1003 Gr: Reception Gain dB
1004 Lambda: Wavelenght m
1005 aL: Attenuation loses dB
1006 tauW: Width of transmission pulse s
1007 ThetaT: Transmission antenna bean angle rad
1008 ThetaR: Reception antenna beam angle rad
1009
1010 """
1011 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1012 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
1013 RadarConstant = Numerator / Denominator
1014
1015 return RadarConstant
1016
1017
1018
1019 class FullSpectralAnalysis(Operation):
1020
1021 """
1022 Function that implements Full Spectral Analisys technique.
1023
1024 Input:
1025 self.dataOut.data_pre : SelfSpectra and CrossSPectra data
1026 self.dataOut.groupList : Pairlist of channels
1027 self.dataOut.ChanDist : Physical distance between receivers
1028
1029
1030 Output:
1031
1032 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
1033
1034
1035 Parameters affected: Winds, height range, SNR
1036
1037 """
1038 def run(self, dataOut, E01=None, E02=None, E12=None, N01=None, N02=None, N12=None, SNRlimit=7):
1039
1040 spc = dataOut.data_pre[0].copy()
1041 cspc = dataOut.data_pre[1].copy()
1042
1043 nChannel = spc.shape[0]
1044 nProfiles = spc.shape[1]
1045 nHeights = spc.shape[2]
1046
1047 pairsList = dataOut.groupList
1048 if dataOut.ChanDist is not None :
1049 ChanDist = dataOut.ChanDist
1050 else:
1051 ChanDist = numpy.array([[E01, N01],[E02,N02],[E12,N12]])
1052
1053 #print 'ChanDist', ChanDist
1054
1055 if dataOut.VelRange is not None:
1056 VelRange= dataOut.VelRange
1057 else:
1058 VelRange= dataOut.abscissaList
1059
1060 ySamples=numpy.ones([nChannel,nProfiles])
1061 phase=numpy.ones([nChannel,nProfiles])
1062 CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_)
1063 coherence=numpy.ones([nChannel,nProfiles])
1064 PhaseSlope=numpy.ones(nChannel)
1065 PhaseInter=numpy.ones(nChannel)
1066 dataSNR = dataOut.data_SNR
1067
1068
1069
1070 data = dataOut.data_pre
1071 noise = dataOut.noise
1072 print 'noise',noise
1073 #SNRdB = 10*numpy.log10(dataOut.data_SNR)
1074
1075 FirstMoment = numpy.average(dataOut.data_param[:,1,:],0)
1076 #SNRdBMean = []
1077
1078
1079 #for j in range(nHeights):
1080 # FirstMoment = numpy.append(FirstMoment,numpy.mean([dataOut.data_param[0,1,j],dataOut.data_param[1,1,j],dataOut.data_param[2,1,j]]))
1081 # SNRdBMean = numpy.append(SNRdBMean,numpy.mean([SNRdB[0,j],SNRdB[1,j],SNRdB[2,j]]))
1082
1083 data_output=numpy.ones([3,spc.shape[2]])*numpy.NaN
1084
1085 velocityX=[]
1086 velocityY=[]
1087 velocityV=[]
1088
1089 dbSNR = 10*numpy.log10(dataSNR)
1090 dbSNR = numpy.average(dbSNR,0)
1091 for Height in range(nHeights):
1092
1093 [Vzon,Vmer,Vver, GaussCenter]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, VelRange, dbSNR[Height], SNRlimit)
1094
1095 if abs(Vzon)<100. and abs(Vzon)> 0.:
1096 velocityX=numpy.append(velocityX, Vzon)#Vmag
1097
1098 else:
1099 print 'Vzon',Vzon
1100 velocityX=numpy.append(velocityX, numpy.NaN)
1101
1102 if abs(Vmer)<100. and abs(Vmer) > 0.:
1103 velocityY=numpy.append(velocityY, Vmer)#Vang
1104
1105 else:
1106 print 'Vmer',Vmer
1107 velocityY=numpy.append(velocityY, numpy.NaN)
1108
1109 if dbSNR[Height] > SNRlimit:
1110 velocityV=numpy.append(velocityV, FirstMoment[Height])
1111 else:
1112 velocityV=numpy.append(velocityV, numpy.NaN)
1113 #FirstMoment[Height]= numpy.NaN
1114 # if SNRdBMean[Height] <12:
1115 # FirstMoment[Height] = numpy.NaN
1116 # velocityX[Height] = numpy.NaN
1117 # velocityY[Height] = numpy.NaN
1118
1119
1120 data_output[0]=numpy.array(velocityX)
1121 data_output[1]=numpy.array(velocityY)
1122 data_output[2]=-velocityV#FirstMoment
1123
1124 print ' '
1125 #print 'FirstMoment'
1126 #print FirstMoment
1127 print 'velocityX',data_output[0]
1128 print ' '
1129 print 'velocityY',data_output[1]
1130 #print numpy.array(velocityY)
1131 print ' '
1132 #print 'SNR'
1133 #print 10*numpy.log10(dataOut.data_SNR)
1134 #print numpy.shape(10*numpy.log10(dataOut.data_SNR))
1135 print ' '
1136
1137
1138 dataOut.data_output=data_output
1139 return
1140
1141
1142 def moving_average(self,x, N=2):
1143 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
1144
1145 def gaus(self,xSamples,a,x0,sigma):
1146 return a*numpy.exp(-(xSamples-x0)**2/(2*sigma**2))
1147
1148 def Find(self,x,value):
1149 for index in range(len(x)):
1150 if x[index]==value:
1151 return index
1152
1153 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, VelRange, dbSNR, SNRlimit):
1154
1155 ySamples=numpy.ones([spc.shape[0],spc.shape[1]])
1156 phase=numpy.ones([spc.shape[0],spc.shape[1]])
1157 CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_)
1158 coherence=numpy.ones([spc.shape[0],spc.shape[1]])
1159 PhaseSlope=numpy.ones(spc.shape[0])
1160 PhaseInter=numpy.ones(spc.shape[0])
1161 xFrec=VelRange
1162
1163 '''Getting Eij and Nij'''
1164
1165 E01=ChanDist[0][0]
1166 N01=ChanDist[0][1]
1167
1168 E02=ChanDist[1][0]
1169 N02=ChanDist[1][1]
1170
1171 E12=ChanDist[2][0]
1172 N12=ChanDist[2][1]
1173
1174 z = spc.copy()
1175 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1176
1177 for i in range(spc.shape[0]):
1178
1179 '''****** Line of Data SPC ******'''
1180 zline=z[i,:,Height]
1181
1182 '''****** SPC is normalized ******'''
1183 FactNorm= (zline.copy()-noise[i]) / numpy.sum(zline.copy())
1184 FactNorm= FactNorm/numpy.sum(FactNorm)
1185
1186 SmoothSPC=self.moving_average(FactNorm,N=3)
1187
1188 xSamples = ar(range(len(SmoothSPC)))
1189 ySamples[i] = SmoothSPC
1190
1191 #dbSNR=10*numpy.log10(dataSNR)
1192 print ' '
1193 print ' '
1194 print ' '
1195
1196 #print 'dataSNR', dbSNR.shape, dbSNR[0,40:120]
1197 print 'SmoothSPC', SmoothSPC.shape, SmoothSPC[0:20]
1198 print 'noise',noise
1199 print 'zline',zline.shape, zline[0:20]
1200 print 'FactNorm',FactNorm.shape, FactNorm[0:20]
1201 print 'FactNorm suma', numpy.sum(FactNorm)
1202
1203 for i in range(spc.shape[0]):
1204
1205 '''****** Line of Data CSPC ******'''
1206 cspcLine=cspc[i,:,Height].copy()
1207
1208 '''****** CSPC is normalized ******'''
1209 chan_index0 = pairsList[i][0]
1210 chan_index1 = pairsList[i][1]
1211 CSPCFactor= abs(numpy.sum(ySamples[chan_index0]) * numpy.sum(ySamples[chan_index1])) #
1212
1213 CSPCNorm = (cspcLine.copy() -noise[i]) / numpy.sqrt(CSPCFactor)
1214
1215 CSPCSamples[i] = CSPCNorm
1216 coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor)
1217
1218 coherence[i]= self.moving_average(coherence[i],N=2)
1219
1220 phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi
1221
1222 print 'cspcLine', cspcLine.shape, cspcLine[0:20]
1223 print 'CSPCFactor', CSPCFactor#, CSPCFactor[0:20]
1224 print numpy.sum(ySamples[chan_index0]), numpy.sum(ySamples[chan_index1]), -noise[i]
1225 print 'CSPCNorm', CSPCNorm.shape, CSPCNorm[0:20]
1226 print 'CSPCNorm suma', numpy.sum(CSPCNorm)
1227 print 'CSPCSamples', CSPCSamples.shape, CSPCSamples[0,0:20]
1228
1229 '''****** Getting fij width ******'''
1230
1231 yMean=[]
1232 yMean2=[]
1233
1234 for j in range(len(ySamples[1])):
1235 yMean=numpy.append(yMean,numpy.mean([ySamples[0,j],ySamples[1,j],ySamples[2,j]]))
1236
1237 '''******* Getting fitting Gaussian ******'''
1238 meanGauss=sum(xSamples*yMean) / len(xSamples)
1239 sigma=sum(yMean*(xSamples-meanGauss)**2) / len(xSamples)
1240
1241 print '****************************'
1242 print 'len(xSamples): ',len(xSamples)
1243 print 'yMean: ', yMean.shape, yMean[0:20]
1244 print 'ySamples', ySamples.shape, ySamples[0,0:20]
1245 print 'xSamples: ',xSamples.shape, xSamples[0:20]
1246
1247 print 'meanGauss',meanGauss
1248 print 'sigma',sigma
1249
1250 #if (abs(meanGauss/sigma**2) > 0.0001) : #0.000000001):
1251 if dbSNR > SNRlimit :
1252 try:
1253 popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=[1,meanGauss,sigma])
1254
1255 if numpy.amax(popt)>numpy.amax(yMean)*0.3:
1256 FitGauss=self.gaus(xSamples,*popt)
1257
1258 else:
1259 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1260 print 'Verificador: Dentro', Height
1261 except :#RuntimeError:
1262 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1263
1264
1265 else:
1266 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1267
1268 Maximun=numpy.amax(yMean)
1269 eMinus1=Maximun*numpy.exp(-1)#*0.8
1270
1271 HWpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-eMinus1)))
1272 HalfWidth= xFrec[HWpos]
1273 GCpos=self.Find(FitGauss, numpy.amax(FitGauss))
1274 Vpos=self.Find(FactNorm, numpy.amax(FactNorm))
1275
1276 #Vpos=FirstMoment[]
1277
1278 '''****** Getting Fij ******'''
1279
1280 GaussCenter=xFrec[GCpos]
1281 if (GaussCenter<0 and HalfWidth>0) or (GaussCenter>0 and HalfWidth<0):
1282 Fij=abs(GaussCenter)+abs(HalfWidth)+0.0000001
1283 else:
1284 Fij=abs(GaussCenter-HalfWidth)+0.0000001
1285
1286 '''****** Getting Frecuency range of significant data ******'''
1287
1288 Rangpos=self.Find(FitGauss,min(FitGauss, key=lambda value:abs(value-Maximun*0.10)))
1289
1290 if Rangpos<GCpos:
1291 Range=numpy.array([Rangpos,2*GCpos-Rangpos])
1292 elif Rangpos< ( len(xFrec)- len(xFrec)*0.1):
1293 Range=numpy.array([2*GCpos-Rangpos,Rangpos])
1294 else:
1295 Range = numpy.array([0,0])
1296
1297 print ' '
1298 print 'GCpos',GCpos, ( len(xFrec)- len(xFrec)*0.1)
1299 print 'Rangpos',Rangpos
1300 print 'RANGE: ', Range
1301 FrecRange=xFrec[Range[0]:Range[1]]
1302
1303 '''****** Getting SCPC Slope ******'''
1304
1305 for i in range(spc.shape[0]):
1306
1307 if len(FrecRange)>5 and len(FrecRange)<spc.shape[1]*0.5:
1308 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1309
1310 print 'FrecRange', len(FrecRange) , FrecRange
1311 print 'PhaseRange', len(PhaseRange), PhaseRange
1312 print ' '
1313 if len(FrecRange) == len(PhaseRange):
1314 slope, intercept, r_value, p_value, std_err = stats.linregress(FrecRange,PhaseRange)
1315 PhaseSlope[i]=slope
1316 PhaseInter[i]=intercept
1317 else:
1318 PhaseSlope[i]=0
1319 PhaseInter[i]=0
1320 else:
1321 PhaseSlope[i]=0
1322 PhaseInter[i]=0
1323
1324 '''Getting constant C'''
1325 cC=(Fij*numpy.pi)**2
1326
1327 '''****** Getting constants F and G ******'''
1328 MijEijNij=numpy.array([[E02,N02], [E12,N12]])
1329 MijResult0=(-PhaseSlope[1]*cC) / (2*numpy.pi)
1330 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1331 MijResults=numpy.array([MijResult0,MijResult1])
1332 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1333
1334 '''****** Getting constants A, B and H ******'''
1335 W01=numpy.amax(coherence[0])
1336 W02=numpy.amax(coherence[1])
1337 W12=numpy.amax(coherence[2])
1338
1339 WijResult0=((cF*E01+cG*N01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi/cC))
1340 WijResult1=((cF*E02+cG*N02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi/cC))
1341 WijResult2=((cF*E12+cG*N12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi/cC))
1342
1343 WijResults=numpy.array([WijResult0, WijResult1, WijResult2])
1344
1345 WijEijNij=numpy.array([ [E01**2, N01**2, 2*E01*N01] , [E02**2, N02**2, 2*E02*N02] , [E12**2, N12**2, 2*E12*N12] ])
1346 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1347
1348 VxVy=numpy.array([[cA,cH],[cH,cB]])
1349
1350 VxVyResults=numpy.array([-cF,-cG])
1351 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1352
1353 Vzon = Vy
1354 Vmer = Vx
1355 Vmag=numpy.sqrt(Vzon**2+Vmer**2)
1356 Vang=numpy.arctan2(Vmer,Vzon)
1357 Vver=xFrec[Vpos]
1358 print 'vzon y vmer', Vzon, Vmer
1359 return Vzon, Vmer, Vver, GaussCenter
1360
122 1361 class SpectralMoments(Operation):
123 1362
124 1363 '''
@@ -167,20 +1406,21 class SpectralMoments(Operation):
167 1406 dataOut.data_STD = data_param[:,3]
168 1407 return
169 1408
170 def __calculateMoments(self, oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1409 def __calculateMoments(self, oldspec, oldfreq, n0,
1410 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
171 1411
172 if (nicoh is None): nicoh = 1
173 if (graph is None): graph = 0
174 if (smooth is None): smooth = 0
1412 if (nicoh == None): nicoh = 1
1413 if (graph == None): graph = 0
1414 if (smooth == None): smooth = 0
175 1415 elif (self.smooth < 3): smooth = 0
176 1416
177 if (type1 is None): type1 = 0
178 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
179 if (snrth is None): snrth = -3
180 if (dc is None): dc = 0
181 if (aliasing is None): aliasing = 0
182 if (oldfd is None): oldfd = 0
183 if (wwauto is None): wwauto = 0
1417 if (type1 == None): type1 = 0
1418 if (fwindow == None): fwindow = numpy.zeros(oldfreq.size) + 1
1419 if (snrth == None): snrth = -3
1420 if (dc == None): dc = 0
1421 if (aliasing == None): aliasing = 0
1422 if (oldfd == None): oldfd = 0
1423 if (wwauto == None): wwauto = 0
184 1424
185 1425 if (n0 < 1.e-20): n0 = 1.e-20
186 1426
@@ -247,8 +1487,8 class SpectralMoments(Operation):
247 1487 num_pairs = len(pairslist)
248 1488
249 1489 vel = self.dataOut.abscissaList
250 spectra = self.dataOut.data_pre[0]
251 cspectra = self.dataOut.data_pre[1]
1490 spectra = self.dataOut.data_pre
1491 cspectra = self.dataIn.data_cspc
252 1492 delta_v = vel[1] - vel[0]
253 1493
254 1494 #Calculating the power spectrum
@@ -480,7 +1720,7 class SpectralFitting(Operation):
480 1720 error1 = p0*numpy.nan
481 1721
482 1722 #Save
483 if self.dataOut.data_param is None:
1723 if self.dataOut.data_param == None:
484 1724 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
485 1725 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
486 1726
@@ -526,6 +1766,9 class WindProfiler(Operation):
526 1766
527 1767 n = None
528 1768
1769 def __init__(self):
1770 Operation.__init__(self)
1771
529 1772 def __calculateCosDir(self, elev, azim):
530 1773 zen = (90 - elev)*numpy.pi/180
531 1774 azim = azim*numpy.pi/180
@@ -816,7 +2059,7 class WindProfiler(Operation):
816 2059 self.__dataReady = True
817 2060 return
818 2061
819 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax, binkm=2):
2062 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
820 2063 '''
821 2064 Function that implements winds estimation technique with detected meteors.
822 2065
@@ -828,7 +2071,7 class WindProfiler(Operation):
828 2071 '''
829 2072 # print arrayMeteor.shape
830 2073 #Settings
831 nInt = (heightMax - heightMin)/binkm
2074 nInt = (heightMax - heightMin)/2
832 2075 # print nInt
833 2076 nInt = int(nInt)
834 2077 # print nInt
@@ -1130,11 +2373,6 class WindProfiler(Operation):
1130 2373 hmax = kwargs['hmax']
1131 2374 else: hmax = 110
1132 2375
1133 if kwargs.has_key('BinKm'):
1134 binkm = kwargs['BinKm']
1135 else:
1136 binkm = 2
1137
1138 2376 dataOut.outputInterval = nHours*3600
1139 2377
1140 2378 if self.__isConfig == False:
@@ -1145,7 +2383,7 class WindProfiler(Operation):
1145 2383
1146 2384 self.__isConfig = True
1147 2385
1148 if self.__buffer is None:
2386 if self.__buffer == None:
1149 2387 self.__buffer = dataOut.data_param
1150 2388 self.__firstdata = copy.copy(dataOut)
1151 2389
@@ -1159,7 +2397,7 class WindProfiler(Operation):
1159 2397
1160 2398 self.__initime += dataOut.outputInterval #to erase time offset
1161 2399
1162 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax, binkm)
2400 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
1163 2401 dataOut.flagNoData = False
1164 2402 self.__buffer = None
1165 2403
@@ -1187,7 +2425,7 class WindProfiler(Operation):
1187 2425 else: mode = 'SA'
1188 2426
1189 2427 #Borrar luego esto
1190 if dataOut.groupList is None:
2428 if dataOut.groupList == None:
1191 2429 dataOut.groupList = [(0,1),(0,2),(1,2)]
1192 2430 groupList = dataOut.groupList
1193 2431 C = 3e8
@@ -1209,7 +2447,7 class WindProfiler(Operation):
1209 2447
1210 2448 self.__isConfig = True
1211 2449
1212 if self.__buffer is None:
2450 if self.__buffer == None:
1213 2451 self.__buffer = dataOut.data_param
1214 2452 self.__firstdata = copy.copy(dataOut)
1215 2453
@@ -1235,6 +2473,8 class WindProfiler(Operation):
1235 2473
1236 2474 class EWDriftsEstimation(Operation):
1237 2475
2476 def __init__(self):
2477 Operation.__init__(self)
1238 2478
1239 2479 def __correctValues(self, heiRang, phi, velRadial, SNR):
1240 2480 listPhi = phi.tolist()
@@ -1569,7 +2809,7 class SMDetection(Operation):
1569 2809
1570 2810
1571 2811 #Getting Pairslist
1572 if channelPositions is None:
2812 if channelPositions == None:
1573 2813 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
1574 2814 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
1575 2815 meteorOps = SMOperations()
@@ -1700,7 +2940,7 class SMDetection(Operation):
1700 2940 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
1701 2941 dataOut.data_param = arrayParameters
1702 2942
1703 if arrayParameters is None:
2943 if arrayParameters == None:
1704 2944 dataOut.flagNoData = True
1705 2945 else:
1706 2946 dataOut.flagNoData = True
@@ -1894,7 +3134,7 class SMDetection(Operation):
1894 3134
1895 3135 if (indDNthresh.size > 0):
1896 3136 indEnd = indDNthresh[0] - 1
1897 indInit = indUPthresh[j] if isinstance(indUPthresh[j], (int, float)) else indUPthresh[j][0] ##CHECK!!!!
3137 indInit = indUPthresh[j]
1898 3138
1899 3139 meteor = powerAux[indInit:indEnd + 1]
1900 3140 indPeak = meteor.argmax() + indInit
@@ -1949,19 +3189,19 class SMDetection(Operation):
1949 3189 indSides = pairsarray[:,1]
1950 3190
1951 3191 pairslist1 = list(pairslist)
1952 pairslist1.append((0,4))
1953 pairslist1.append((1,3))
3192 pairslist1.append((0,1))
3193 pairslist1.append((3,4))
1954 3194
1955 3195 listMeteors1 = []
1956 3196 listPowerSeries = []
1957 3197 listVoltageSeries = []
1958 3198 #volts has the war data
1959 3199
1960 if frequency == 30.175e6:
3200 if frequency == 30e6:
1961 3201 timeLag = 45*10**-3
1962 3202 else:
1963 3203 timeLag = 15*10**-3
1964 lag = int(numpy.ceil(timeLag/timeInterval))
3204 lag = numpy.ceil(timeLag/timeInterval)
1965 3205
1966 3206 for i in range(len(listMeteors)):
1967 3207
@@ -1969,10 +3209,10 class SMDetection(Operation):
1969 3209 meteorAux = numpy.zeros(16)
1970 3210
1971 3211 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
1972 mHeight = int(listMeteors[i][0])
1973 mStart = int(listMeteors[i][1])
1974 mPeak = int(listMeteors[i][2])
1975 mEnd = int(listMeteors[i][3])
3212 mHeight = listMeteors[i][0]
3213 mStart = listMeteors[i][1]
3214 mPeak = listMeteors[i][2]
3215 mEnd = listMeteors[i][3]
1976 3216
1977 3217 #get the volt data between the start and end times of the meteor
1978 3218 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
@@ -2061,11 +3301,11 class SMDetection(Operation):
2061 3301
2062 3302 threshError = 10
2063 3303 #Depending if it is 30 or 50 MHz
2064 if frequency == 30.175e6:
3304 if frequency == 30e6:
2065 3305 timeLag = 45*10**-3
2066 3306 else:
2067 3307 timeLag = 15*10**-3
2068 lag = int(numpy.ceil(timeLag/timeInterval))
3308 lag = numpy.ceil(timeLag/timeInterval)
2069 3309
2070 3310 listMeteors1 = []
2071 3311
@@ -2121,14 +3361,14 class SMDetection(Operation):
2121 3361 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
2122 3362
2123 3363 pairslist1 = list(pairslist)
2124 pairslist1.append((0,4))
2125 pairslist1.append((1,3))
3364 pairslist1.append((0,1))
3365 pairslist1.append((3,4))
2126 3366 numPairs = len(pairslist1)
2127 3367 #Time Lag
2128 3368 timeLag = 45*10**-3
2129 3369 c = 3e8
2130 3370 lag = numpy.ceil(timeLag/timeInterval)
2131 freq = 30.175e6
3371 freq = 30e6
2132 3372
2133 3373 listMeteors1 = []
2134 3374
@@ -2149,7 +3389,7 class SMDetection(Operation):
2149 3389 #Method 2
2150 3390 slopes = numpy.zeros(numPairs)
2151 3391 time = numpy.array([-2,-1,1,2])*timeInterval
2152 angAllCCF = numpy.angle(allCCFs[:,[0,4,2,3],0])
3392 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
2153 3393
2154 3394 #Correct phases
2155 3395 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
@@ -2236,7 +3476,7 class CorrectSMPhases(Operation):
2236 3476 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
2237 3477
2238 3478 meteorOps = SMOperations()
2239 if channelPositions is None:
3479 if channelPositions == None:
2240 3480 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2241 3481 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2242 3482
@@ -2413,7 +3653,7 class SMPhaseCalibration(Operation):
2413 3653
2414 3654 self.__isConfig = True
2415 3655
2416 if self.__buffer is None:
3656 if self.__buffer == None:
2417 3657 self.__buffer = dataOut.data_param.copy()
2418 3658
2419 3659 else:
@@ -2469,7 +3709,6 class SMPhaseCalibration(Operation):
2469 3709 phasesOff = phasesOff.reshape((1,phasesOff.size))
2470 3710 dataOut.data_output = -phasesOff
2471 3711 dataOut.flagNoData = False
2472 dataOut.channelList = pairslist0
2473 3712 self.__buffer = None
2474 3713
2475 3714
@@ -2803,3 +4042,4 class SMOperations():
2803 4042 # error[indInvalid1] = 13
2804 4043 #
2805 4044 # return heights, error
4045 No newline at end of file
@@ -1,3 +1,5
1 import itertools
2
1 3 import numpy
2 4
3 5 from jroproc_base import ProcessingUnit, Operation
@@ -109,7 +111,10 class SpectraProc(ProcessingUnit):
109 111
110 112 if self.dataIn.type == "Spectra":
111 113 self.dataOut.copy(self.dataIn)
112 # self.__selectPairs(pairsList)
114 if not pairsList:
115 pairsList = itertools.combinations(self.dataOut.channelList, 2)
116 if self.dataOut.data_cspc is not None:
117 self.__selectPairs(pairsList)
113 118 return True
114 119
115 120 if self.dataIn.type == "Voltage":
@@ -178,27 +183,21 class SpectraProc(ProcessingUnit):
178 183
179 184 def __selectPairs(self, pairsList):
180 185
181 if channelList == None:
186 if not pairsList:
182 187 return
183 188
184 pairsIndexListSelected = []
185
186 for thisPair in pairsList:
189 pairs = []
190 pairsIndex = []
187 191
188 if thisPair not in self.dataOut.pairsList:
192 for pair in pairsList:
193 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
189 194 continue
195 pairs.append(pair)
196 pairsIndex.append(pairs.index(pair))
190 197
191 pairIndex = self.dataOut.pairsList.index(thisPair)
192
193 pairsIndexListSelected.append(pairIndex)
194
195 if not pairsIndexListSelected:
196 self.dataOut.data_cspc = None
197 self.dataOut.pairsList = []
198 return
199
200 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
201 self.dataOut.pairsList = [self.dataOut.pairsList[i] for i in pairsIndexListSelected]
198 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
199 self.dataOut.pairsList = pairs
200 self.dataOut.pairsIndexList = pairsIndex
202 201
203 202 return
204 203
@@ -15,6 +15,7 from multiprocessing import Process
15 15
16 16 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
17 17 from schainpy.model.data.jrodata import JROData
18 from schainpy.utils import log
18 19
19 20 MAXNUMX = 100
20 21 MAXNUMY = 100
@@ -30,14 +31,13 def roundFloats(obj):
30 31 return round(obj, 2)
31 32
32 33 def decimate(z, MAXNUMY):
33 # dx = int(len(self.x)/self.__MAXNUMX) + 1
34
35 34 dy = int(len(z[0])/MAXNUMY) + 1
36 35
37 36 return z[::, ::dy]
38 37
39 38 class throttle(object):
40 """Decorator that prevents a function from being called more than once every
39 '''
40 Decorator that prevents a function from being called more than once every
41 41 time period.
42 42 To create a function that cannot be called more than once a minute, but
43 43 will sleep until it can be called:
@@ -48,7 +48,7 class throttle(object):
48 48 for i in range(10):
49 49 foo()
50 50 print "This function has run %s times." % i
51 """
51 '''
52 52
53 53 def __init__(self, seconds=0, minutes=0, hours=0):
54 54 self.throttle_period = datetime.timedelta(
@@ -72,9 +72,169 class throttle(object):
72 72
73 73 return wrapper
74 74
75 class Data(object):
76 '''
77 Object to hold data to be plotted
78 '''
79
80 def __init__(self, plottypes, throttle_value):
81 self.plottypes = plottypes
82 self.throttle = throttle_value
83 self.ended = False
84 self.__times = []
85
86 def __str__(self):
87 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
88 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
89
90 def __len__(self):
91 return len(self.__times)
92
93 def __getitem__(self, key):
94 if key not in self.data:
95 raise KeyError(log.error('Missing key: {}'.format(key)))
96
97 if 'spc' in key:
98 ret = self.data[key]
99 else:
100 ret = numpy.array([self.data[key][x] for x in self.times])
101 if ret.ndim > 1:
102 ret = numpy.swapaxes(ret, 0, 1)
103 return ret
104
105 def setup(self):
106 '''
107 Configure object
108 '''
109
110 self.ended = False
111 self.data = {}
112 self.__times = []
113 self.__heights = []
114 self.__all_heights = set()
115 for plot in self.plottypes:
116 self.data[plot] = {}
117
118 def shape(self, key):
119 '''
120 Get the shape of the one-element data for the given key
121 '''
122
123 if len(self.data[key]):
124 if 'spc' in key:
125 return self.data[key].shape
126 return self.data[key][self.__times[0]].shape
127 return (0,)
128
129 def update(self, dataOut):
130 '''
131 Update data object with new dataOut
132 '''
133
134 tm = dataOut.utctime
135 if tm in self.__times:
136 return
137
138 self.parameters = getattr(dataOut, 'parameters', [])
139 self.pairs = dataOut.pairsList
140 self.channels = dataOut.channelList
141 self.xrange = (dataOut.getFreqRange(1)/1000. , dataOut.getAcfRange(1) , dataOut.getVelRange(1))
142 self.interval = dataOut.getTimeInterval()
143 self.__heights.append(dataOut.heightList)
144 self.__all_heights.update(dataOut.heightList)
145 self.__times.append(tm)
146
147 for plot in self.plottypes:
148 if plot == 'spc':
149 z = dataOut.data_spc/dataOut.normFactor
150 self.data[plot] = 10*numpy.log10(z)
151 if plot == 'cspc':
152 self.data[plot] = dataOut.data_cspc
153 if plot == 'noise':
154 self.data[plot][tm] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
155 if plot == 'rti':
156 self.data[plot][tm] = dataOut.getPower()
157 if plot == 'snr_db':
158 self.data['snr'][tm] = dataOut.data_SNR
159 if plot == 'snr':
160 self.data[plot][tm] = 10*numpy.log10(dataOut.data_SNR)
161 if plot == 'dop':
162 self.data[plot][tm] = 10*numpy.log10(dataOut.data_DOP)
163 if plot == 'mean':
164 self.data[plot][tm] = dataOut.data_MEAN
165 if plot == 'std':
166 self.data[plot][tm] = dataOut.data_STD
167 if plot == 'coh':
168 self.data[plot][tm] = dataOut.getCoherence()
169 if plot == 'phase':
170 self.data[plot][tm] = dataOut.getCoherence(phase=True)
171 if plot == 'output':
172 self.data[plot][tm] = dataOut.data_output
173 if plot == 'param':
174 self.data[plot][tm] = dataOut.data_param
175
176 def normalize_heights(self):
177 '''
178 Ensure same-dimension of the data for different heighList
179 '''
180
181 H = numpy.array(list(self.__all_heights))
182 H.sort()
183 for key in self.data:
184 shape = self.shape(key)[:-1] + H.shape
185 for tm, obj in self.data[key].items():
186 h = self.__heights[self.__times.index(tm)]
187 if H.size == h.size:
188 continue
189 index = numpy.where(numpy.in1d(H, h))[0]
190 dummy = numpy.zeros(shape) + numpy.nan
191 if len(shape) == 2:
192 dummy[:, index] = obj
193 else:
194 dummy[index] = obj
195 self.data[key][tm] = dummy
196
197 self.__heights = [H for tm in self.__times]
198
199 def jsonify(self, decimate=False):
200 '''
201 Convert data to json
202 '''
203
204 ret = {}
205 tm = self.times[-1]
206
207 for key, value in self.data:
208 if key in ('spc', 'cspc'):
209 ret[key] = roundFloats(self.data[key].to_list())
210 else:
211 ret[key] = roundFloats(self.data[key][tm].to_list())
212
213 ret['timestamp'] = tm
214 ret['interval'] = self.interval
215
216 @property
217 def times(self):
218 '''
219 Return the list of times of the current data
220 '''
221
222 ret = numpy.array(self.__times)
223 ret.sort()
224 return ret
225
226 @property
227 def heights(self):
228 '''
229 Return the list of heights of the current data
230 '''
231
232 return numpy.array(self.__heights[-1])
75 233
76 234 class PublishData(Operation):
77 """Clase publish."""
235 '''
236 Operation to send data over zmq.
237 '''
78 238
79 239 def __init__(self, **kwargs):
80 240 """Inicio."""
@@ -86,11 +246,11 class PublishData(Operation):
86 246
87 247 def on_disconnect(self, client, userdata, rc):
88 248 if rc != 0:
89 print("Unexpected disconnection.")
249 log.warning('Unexpected disconnection.')
90 250 self.connect()
91 251
92 252 def connect(self):
93 print 'trying to connect'
253 log.warning('trying to connect')
94 254 try:
95 255 self.client.connect(
96 256 host=self.host,
@@ -104,7 +264,7 class PublishData(Operation):
104 264 # retain=True
105 265 # )
106 266 except:
107 print "MQTT Conection error."
267 log.error('MQTT Conection error.')
108 268 self.client = False
109 269
110 270 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
@@ -120,7 +280,6 class PublishData(Operation):
120 280 self.mqtt = kwargs.get('plottype', 0)
121 281 self.client = None
122 282 self.verbose = verbose
123 self.dataOut.firstdata = True
124 283 setup = []
125 284 if mqtt is 1:
126 285 self.client = mqtt.Client(
@@ -175,7 +334,6 class PublishData(Operation):
175 334 'type': self.plottype,
176 335 'yData': yData
177 336 }
178 # print payload
179 337
180 338 elif self.plottype in ('rti', 'power'):
181 339 data = getattr(self.dataOut, 'data_spc')
@@ -229,15 +387,16 class PublishData(Operation):
229 387 'timestamp': 'None',
230 388 'type': None
231 389 }
232 # print 'Publishing data to {}'.format(self.host)
390
233 391 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
234 392
235 393 if self.zeromq is 1:
236 394 if self.verbose:
237 print '[Sending] {} - {}'.format(self.dataOut.type, self.dataOut.datatime)
395 log.log(
396 '{} - {}'.format(self.dataOut.type, self.dataOut.datatime),
397 'Sending'
398 )
238 399 self.zmq_socket.send_pyobj(self.dataOut)
239 self.dataOut.firstdata = False
240
241 400
242 401 def run(self, dataOut, **kwargs):
243 402 self.dataOut = dataOut
@@ -252,6 +411,7 class PublishData(Operation):
252 411 if self.zeromq is 1:
253 412 self.dataOut.finished = True
254 413 self.zmq_socket.send_pyobj(self.dataOut)
414 time.sleep(0.1)
255 415 self.zmq_socket.close()
256 416 if self.client:
257 417 self.client.loop_stop()
@@ -280,7 +440,7 class ReceiverData(ProcessingUnit):
280 440 self.receiver = self.context.socket(zmq.PULL)
281 441 self.receiver.bind(self.address)
282 442 time.sleep(0.5)
283 print '[Starting] ReceiverData from {}'.format(self.address)
443 log.success('ReceiverData from {}'.format(self.address))
284 444
285 445
286 446 def run(self):
@@ -290,8 +450,9 class ReceiverData(ProcessingUnit):
290 450 self.isConfig = True
291 451
292 452 self.dataOut = self.receiver.recv_pyobj()
293 print '[Receiving] {} - {}'.format(self.dataOut.type,
294 self.dataOut.datatime.ctime())
453 log.log('{} - {}'.format(self.dataOut.type,
454 self.dataOut.datatime.ctime(),),
455 'Receiving')
295 456
296 457
297 458 class PlotterReceiver(ProcessingUnit, Process):
@@ -305,7 +466,6 class PlotterReceiver(ProcessingUnit, Process):
305 466 self.mp = False
306 467 self.isConfig = False
307 468 self.isWebConfig = False
308 self.plottypes = []
309 469 self.connections = 0
310 470 server = kwargs.get('server', 'zmq.pipe')
311 471 plot_server = kwargs.get('plot_server', 'zmq.web')
@@ -325,19 +485,13 class PlotterReceiver(ProcessingUnit, Process):
325 485 self.realtime = kwargs.get('realtime', False)
326 486 self.throttle_value = kwargs.get('throttle', 5)
327 487 self.sendData = self.initThrottle(self.throttle_value)
488 self.dates = []
328 489 self.setup()
329 490
330 491 def setup(self):
331 492
332 self.data = {}
333 self.data['times'] = []
334 for plottype in self.plottypes:
335 self.data[plottype] = {}
336 self.data['noise'] = {}
337 self.data['throttle'] = self.throttle_value
338 self.data['ENDED'] = False
493 self.data = Data(self.plottypes, self.throttle_value)
339 494 self.isConfig = True
340 self.data_web = {}
341 495
342 496 def event_monitor(self, monitor):
343 497
@@ -354,15 +508,13 class PlotterReceiver(ProcessingUnit, Process):
354 508 self.connections += 1
355 509 if evt['event'] == 512:
356 510 pass
357 if self.connections == 0 and self.started is True:
358 self.ended = True
359 511
360 512 evt.update({'description': events[evt['event']]})
361 513
362 514 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
363 515 break
364 516 monitor.close()
365 print("event monitor thread done!")
517 print('event monitor thread done!')
366 518
367 519 def initThrottle(self, throttle_value):
368 520
@@ -372,65 +524,16 class PlotterReceiver(ProcessingUnit, Process):
372 524
373 525 return sendDataThrottled
374 526
375
376 527 def send(self, data):
377 # print '[sending] data=%s size=%s' % (data.keys(), len(data['times']))
528 log.success('Sending {}'.format(data), self.name)
378 529 self.sender.send_pyobj(data)
379 530
380
381 def update(self):
382 t = self.dataOut.utctime
383
384 if t in self.data['times']:
385 return
386
387 self.data['times'].append(t)
388 self.data['dataOut'] = self.dataOut
389
390 for plottype in self.plottypes:
391 if plottype == 'spc':
392 z = self.dataOut.data_spc/self.dataOut.normFactor
393 self.data[plottype] = 10*numpy.log10(z)
394 self.data['noise'][t] = 10*numpy.log10(self.dataOut.getNoise()/self.dataOut.normFactor)
395 if plottype == 'cspc':
396 jcoherence = self.dataOut.data_cspc/numpy.sqrt(self.dataOut.data_spc*self.dataOut.data_spc)
397 self.data['cspc_coh'] = numpy.abs(jcoherence)
398 self.data['cspc_phase'] = numpy.arctan2(jcoherence.imag, jcoherence.real)*180/numpy.pi
399 if plottype == 'rti':
400 self.data[plottype][t] = self.dataOut.getPower()
401 if plottype == 'snr':
402 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_SNR)
403 if plottype == 'dop':
404 self.data[plottype][t] = 10*numpy.log10(self.dataOut.data_DOP)
405 if plottype == 'mean':
406 self.data[plottype][t] = self.dataOut.data_MEAN
407 if plottype == 'std':
408 self.data[plottype][t] = self.dataOut.data_STD
409 if plottype == 'coh':
410 self.data[plottype][t] = self.dataOut.getCoherence()
411 if plottype == 'phase':
412 self.data[plottype][t] = self.dataOut.getCoherence(phase=True)
413 if plottype == 'output':
414 self.data[plottype][t] = self.dataOut.data_output
415 if plottype == 'param':
416 self.data[plottype][t] = self.dataOut.data_param
417 if self.realtime:
418 self.data_web['timestamp'] = t
419 if plottype == 'spc':
420 self.data_web[plottype] = roundFloats(decimate(self.data[plottype]).tolist())
421 elif plottype == 'cspc':
422 self.data_web['cspc_coh'] = roundFloats(decimate(self.data['cspc_coh']).tolist())
423 self.data_web['cspc_phase'] = roundFloats(decimate(self.data['cspc_phase']).tolist())
424 elif plottype == 'noise':
425 self.data_web['noise'] = roundFloats(self.data['noise'][t].tolist())
426 else:
427 self.data_web[plottype] = roundFloats(decimate(self.data[plottype][t]).tolist())
428 self.data_web['interval'] = self.dataOut.getTimeInterval()
429 self.data_web['type'] = plottype
430
431 531 def run(self):
432 532
433 print '[Starting] {} from {}'.format(self.name, self.address)
533 log.success(
534 'Starting from {}'.format(self.address),
535 self.name
536 )
434 537
435 538 self.context = zmq.Context()
436 539 self.receiver = self.context.socket(zmq.PULL)
@@ -447,39 +550,39 class PlotterReceiver(ProcessingUnit, Process):
447 550 else:
448 551 self.sender.bind("ipc:///tmp/zmq.plots")
449 552
450 time.sleep(3)
553 time.sleep(2)
451 554
452 555 t = Thread(target=self.event_monitor, args=(monitor,))
453 556 t.start()
454 557
455 558 while True:
456 self.dataOut = self.receiver.recv_pyobj()
457 # print '[Receiving] {} - {}'.format(self.dataOut.type,
458 # self.dataOut.datatime.ctime())
459
460 self.update()
559 dataOut = self.receiver.recv_pyobj()
560 dt = datetime.datetime.fromtimestamp(dataOut.utctime).date()
561 sended = False
562 if dt not in self.dates:
563 if self.data:
564 self.data.ended = True
565 self.send(self.data)
566 sended = True
567 self.data.setup()
568 self.dates.append(dt)
461 569
462 if self.dataOut.firstdata is True:
463 self.data['STARTED'] = True
570 self.data.update(dataOut)
464 571
465 if self.dataOut.finished is True:
466 self.send(self.data)
572 if dataOut.finished is True:
467 573 self.connections -= 1
468 if self.connections == 0 and self.started:
469 self.ended = True
470 self.data['ENDED'] = True
574 if self.connections == 0 and dt in self.dates:
575 self.data.ended = True
471 576 self.send(self.data)
472 self.setup()
473 self.started = False
577 self.data.setup()
474 578 else:
475 579 if self.realtime:
476 580 self.send(self.data)
477 self.sender_web.send_string(json.dumps(self.data_web))
581 # self.sender_web.send_string(self.data.jsonify())
478 582 else:
583 if not sended:
479 584 self.sendData(self.send, self.data)
480 self.started = True
481 585
482 self.data['STARTED'] = False
483 586 return
484 587
485 588 def sendToWeb(self):
@@ -496,6 +599,6 class PlotterReceiver(ProcessingUnit, Process):
496 599 time.sleep(1)
497 600 for kwargs in self.operationKwargs.values():
498 601 if 'plot' in kwargs:
499 print '[Sending] Config data to web for {}'.format(kwargs['code'].upper())
602 log.success('[Sending] Config data to web for {}'.format(kwargs['code'].upper()))
500 603 sender_web_config.send_string(json.dumps(kwargs))
501 604 self.isWebConfig = True No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now