##// END OF EJS Templates
New plotting architecture with buffering/throttle capabilities
Juan C. Espinoza -
r1187:66a3db7e736d
parent child
Show More
This diff has been collapsed as it changes many lines, (803 lines changed) Show them Hide them
@@ -0,0 +1,803
1
2 import os
3 import sys
4 import zmq
5 import time
6 import datetime
7 from functools import wraps
8 import numpy
9 import matplotlib
10
11 if 'BACKEND' in os.environ:
12 matplotlib.use(os.environ['BACKEND'])
13 elif 'linux' in sys.platform:
14 matplotlib.use("TkAgg")
15 elif 'darwin' in sys.platform:
16 matplotlib.use('TkAgg')
17 else:
18 from schainpy.utils import log
19 log.warning('Using default Backend="Agg"', 'INFO')
20 matplotlib.use('Agg')
21
22 import matplotlib.pyplot as plt
23 from matplotlib.patches import Polygon
24 from mpl_toolkits.axes_grid1 import make_axes_locatable
25 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
26
27 from schainpy.model.data.jrodata import PlotterData
28 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
29 from schainpy.utils import log
30
31 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
32 blu_values = matplotlib.pyplot.get_cmap(
33 'seismic_r', 20)(numpy.arange(20))[10:15]
34 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
35 'jro', numpy.vstack((blu_values, jet_values)))
36 matplotlib.pyplot.register_cmap(cmap=ncmap)
37
38 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
39 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
40
41 EARTH_RADIUS = 6.3710e3
42
43
44 def ll2xy(lat1, lon1, lat2, lon2):
45
46 p = 0.017453292519943295
47 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
48 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
49 r = 12742 * numpy.arcsin(numpy.sqrt(a))
50 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
51 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
52 theta = -theta + numpy.pi/2
53 return r*numpy.cos(theta), r*numpy.sin(theta)
54
55
56 def km2deg(km):
57 '''
58 Convert distance in km to degrees
59 '''
60
61 return numpy.rad2deg(km/EARTH_RADIUS)
62
63
64 def figpause(interval):
65 backend = plt.rcParams['backend']
66 if backend in matplotlib.rcsetup.interactive_bk:
67 figManager = matplotlib._pylab_helpers.Gcf.get_active()
68 if figManager is not None:
69 canvas = figManager.canvas
70 if canvas.figure.stale:
71 canvas.draw()
72 try:
73 canvas.start_event_loop(interval)
74 except:
75 pass
76 return
77
78
79 def popup(message):
80 '''
81 '''
82
83 fig = plt.figure(figsize=(12, 8), facecolor='r')
84 text = '\n'.join([s.strip() for s in message.split(':')])
85 fig.text(0.01, 0.5, text, ha='left', va='center',
86 size='20', weight='heavy', color='w')
87 fig.show()
88 figpause(1000)
89
90
91 class Throttle(object):
92 '''
93 Decorator that prevents a function from being called more than once every
94 time period.
95 To create a function that cannot be called more than once a minute, but
96 will sleep until it can be called:
97 @Throttle(minutes=1)
98 def foo():
99 pass
100
101 for i in range(10):
102 foo()
103 print "This function has run %s times." % i
104 '''
105
106 def __init__(self, seconds=0, minutes=0, hours=0):
107 self.throttle_period = datetime.timedelta(
108 seconds=seconds, minutes=minutes, hours=hours
109 )
110
111 self.time_of_last_call = datetime.datetime.min
112
113 def __call__(self, fn):
114 @wraps(fn)
115 def wrapper(*args, **kwargs):
116 coerce = kwargs.pop('coerce', None)
117 if coerce:
118 self.time_of_last_call = datetime.datetime.now()
119 return fn(*args, **kwargs)
120 else:
121 now = datetime.datetime.now()
122 time_since_last_call = now - self.time_of_last_call
123 time_left = self.throttle_period - time_since_last_call
124
125 if time_left > datetime.timedelta(seconds=0):
126 return
127
128 self.time_of_last_call = datetime.datetime.now()
129 return fn(*args, **kwargs)
130
131 return wrapper
132
133 def apply_throttle(value):
134
135 @Throttle(seconds=value)
136 def fnThrottled(fn):
137 fn()
138
139 return fnThrottled
140
141 @MPDecorator
142 class Plotter(ProcessingUnit):
143 '''
144 Proccessing unit to handle plot operations
145 '''
146
147 def __init__(self):
148
149 ProcessingUnit.__init__(self)
150
151 def setup(self, **kwargs):
152
153 self.connections = 0
154 self.web_address = kwargs.get('web_server', False)
155 self.realtime = kwargs.get('realtime', False)
156 self.localtime = kwargs.get('localtime', True)
157 self.buffering = kwargs.get('buffering', True)
158 self.throttle = kwargs.get('throttle', 2)
159 self.exp_code = kwargs.get('exp_code', None)
160 self.set_ready = apply_throttle(self.throttle)
161 self.dates = []
162 self.data = PlotterData(
163 self.plots, self.throttle, self.exp_code, self.buffering)
164 self.isConfig = True
165
166 def ready(self):
167 '''
168 Set dataOut ready
169 '''
170
171 self.data.ready = True
172 self.dataOut.data_plt = self.data
173
174 def run(self, realtime=True, localtime=True, buffering=True,
175 throttle=2, exp_code=None, web_server=None):
176
177 if not self.isConfig:
178 self.setup(realtime=realtime, localtime=localtime,
179 buffering=buffering, throttle=throttle, exp_code=exp_code,
180 web_server=web_server)
181
182 if self.web_address:
183 log.success(
184 'Sending to web: {}'.format(self.web_address),
185 self.name
186 )
187 self.context = zmq.Context()
188 self.sender_web = self.context.socket(zmq.REQ)
189 self.sender_web.connect(self.web_address)
190 self.poll = zmq.Poller()
191 self.poll.register(self.sender_web, zmq.POLLIN)
192 time.sleep(1)
193
194 # t = Thread(target=self.event_monitor, args=(monitor,))
195 # t.start()
196
197 self.dataOut = self.dataIn
198 self.data.ready = False
199
200 if self.dataOut.flagNoData:
201 coerce = True
202 else:
203 coerce = False
204
205 if self.dataOut.type == 'Parameters':
206 tm = self.dataOut.utctimeInit
207 else:
208 tm = self.dataOut.utctime
209 if self.dataOut.useLocalTime:
210 if not self.localtime:
211 tm += time.timezone
212 dt = datetime.datetime.fromtimestamp(tm).date()
213 else:
214 if self.localtime:
215 tm -= time.timezone
216 dt = datetime.datetime.utcfromtimestamp(tm).date()
217 if dt not in self.dates:
218 if self.data:
219 self.ready()
220 self.data.setup()
221 self.dates.append(dt)
222
223 self.data.update(self.dataOut, tm)
224
225 if False: # TODO check when publishers ends
226 self.connections -= 1
227 if self.connections == 0 and dt in self.dates:
228 self.data.ended = True
229 self.ready()
230 time.sleep(1)
231 else:
232 if self.realtime:
233 self.ready()
234 if self.web_address:
235 retries = 5
236 while True:
237 self.sender_web.send(self.data.jsonify())
238 socks = dict(self.poll.poll(5000))
239 if socks.get(self.sender_web) == zmq.POLLIN:
240 reply = self.sender_web.recv_string()
241 if reply == 'ok':
242 log.log("Response from server ok", self.name)
243 break
244 else:
245 log.warning(
246 "Malformed reply from server: {}".format(reply), self.name)
247
248 else:
249 log.warning(
250 "No response from server, retrying...", self.name)
251 self.sender_web.setsockopt(zmq.LINGER, 0)
252 self.sender_web.close()
253 self.poll.unregister(self.sender_web)
254 retries -= 1
255 if retries == 0:
256 log.error(
257 "Server seems to be offline, abandoning", self.name)
258 self.sender_web = self.context.socket(zmq.REQ)
259 self.sender_web.connect(self.web_address)
260 self.poll.register(self.sender_web, zmq.POLLIN)
261 time.sleep(1)
262 break
263 self.sender_web = self.context.socket(zmq.REQ)
264 self.sender_web.connect(self.web_address)
265 self.poll.register(self.sender_web, zmq.POLLIN)
266 time.sleep(1)
267 else:
268 self.set_ready(self.ready, coerce=coerce)
269
270 return
271
272 def close(self):
273 pass
274
275
276 @MPDecorator
277 class Plot(Operation):
278 '''
279 Base class for Schain plotting operations
280 '''
281
282 CODE = 'Figure'
283 colormap = 'jro'
284 bgcolor = 'white'
285 __missing = 1E30
286
287 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
288 'zlimits', 'xlabel', 'ylabel', 'xaxis', 'cb_label', 'title',
289 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
290 'showprofile', 'decimation', 'pause']
291
292 def __init__(self):
293
294 Operation.__init__(self)
295 self.isConfig = False
296 self.isPlotConfig = False
297
298 def __fmtTime(self, x, pos):
299 '''
300 '''
301
302 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
303
304 def __setup(self, **kwargs):
305 '''
306 Initialize variables
307 '''
308
309 self.figures = []
310 self.axes = []
311 self.cb_axes = []
312 self.localtime = kwargs.pop('localtime', True)
313 self.show = kwargs.get('show', True)
314 self.save = kwargs.get('save', False)
315 self.ftp = kwargs.get('ftp', False)
316 self.colormap = kwargs.get('colormap', self.colormap)
317 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
318 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
319 self.colormaps = kwargs.get('colormaps', None)
320 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
321 self.showprofile = kwargs.get('showprofile', False)
322 self.title = kwargs.get('wintitle', self.CODE.upper())
323 self.cb_label = kwargs.get('cb_label', None)
324 self.cb_labels = kwargs.get('cb_labels', None)
325 self.labels = kwargs.get('labels', None)
326 self.xaxis = kwargs.get('xaxis', 'frequency')
327 self.zmin = kwargs.get('zmin', None)
328 self.zmax = kwargs.get('zmax', None)
329 self.zlimits = kwargs.get('zlimits', None)
330 self.xmin = kwargs.get('xmin', None)
331 self.xmax = kwargs.get('xmax', None)
332 self.xrange = kwargs.get('xrange', 12)
333 self.xscale = kwargs.get('xscale', None)
334 self.ymin = kwargs.get('ymin', None)
335 self.ymax = kwargs.get('ymax', None)
336 self.yscale = kwargs.get('yscale', None)
337 self.xlabel = kwargs.get('xlabel', None)
338 self.decimation = kwargs.get('decimation', None)
339 self.showSNR = kwargs.get('showSNR', False)
340 self.oneFigure = kwargs.get('oneFigure', True)
341 self.width = kwargs.get('width', None)
342 self.height = kwargs.get('height', None)
343 self.colorbar = kwargs.get('colorbar', True)
344 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
345 self.channels = kwargs.get('channels', None)
346 self.titles = kwargs.get('titles', [])
347 self.polar = False
348 self.grid = kwargs.get('grid', False)
349 self.pause = kwargs.get('pause', False)
350 self.save_labels = kwargs.get('save_labels', None)
351 self.realtime = kwargs.get('realtime', True)
352 self.buffering = kwargs.get('buffering', True)
353 self.throttle = kwargs.get('throttle', 2)
354 self.exp_code = kwargs.get('exp_code', None)
355 self.__throttle_plot = apply_throttle(self.throttle)
356 self.data = PlotterData(
357 self.CODE, self.throttle, self.exp_code, self.buffering)
358
359 def __setup_plot(self):
360 '''
361 Common setup for all figures, here figures and axes are created
362 '''
363
364 self.setup()
365
366 self.time_label = 'LT' if self.localtime else 'UTC'
367 if self.data.localtime:
368 self.getDateTime = datetime.datetime.fromtimestamp
369 else:
370 self.getDateTime = datetime.datetime.utcfromtimestamp
371
372 if self.width is None:
373 self.width = 8
374
375 self.figures = []
376 self.axes = []
377 self.cb_axes = []
378 self.pf_axes = []
379 self.cmaps = []
380
381 size = '15%' if self.ncols == 1 else '30%'
382 pad = '4%' if self.ncols == 1 else '8%'
383
384 if self.oneFigure:
385 if self.height is None:
386 self.height = 1.4 * self.nrows + 1
387 fig = plt.figure(figsize=(self.width, self.height),
388 edgecolor='k',
389 facecolor='w')
390 self.figures.append(fig)
391 for n in range(self.nplots):
392 ax = fig.add_subplot(self.nrows, self.ncols,
393 n + 1, polar=self.polar)
394 ax.tick_params(labelsize=8)
395 ax.firsttime = True
396 ax.index = 0
397 ax.press = None
398 self.axes.append(ax)
399 if self.showprofile:
400 cax = self.__add_axes(ax, size=size, pad=pad)
401 cax.tick_params(labelsize=8)
402 self.pf_axes.append(cax)
403 else:
404 if self.height is None:
405 self.height = 3
406 for n in range(self.nplots):
407 fig = plt.figure(figsize=(self.width, self.height),
408 edgecolor='k',
409 facecolor='w')
410 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
411 ax.tick_params(labelsize=8)
412 ax.firsttime = True
413 ax.index = 0
414 ax.press = None
415 self.figures.append(fig)
416 self.axes.append(ax)
417 if self.showprofile:
418 cax = self.__add_axes(ax, size=size, pad=pad)
419 cax.tick_params(labelsize=8)
420 self.pf_axes.append(cax)
421
422 for n in range(self.nrows):
423 if self.colormaps is not None:
424 cmap = plt.get_cmap(self.colormaps[n])
425 else:
426 cmap = plt.get_cmap(self.colormap)
427 cmap.set_bad(self.bgcolor, 1.)
428 self.cmaps.append(cmap)
429
430 for fig in self.figures:
431 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
432 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
433 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
434 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
435 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
436 if self.show:
437 fig.show()
438
439 def OnKeyPress(self, event):
440 '''
441 Event for pressing keys (up, down) change colormap
442 '''
443 ax = event.inaxes
444 if ax in self.axes:
445 if event.key == 'down':
446 ax.index += 1
447 elif event.key == 'up':
448 ax.index -= 1
449 if ax.index < 0:
450 ax.index = len(CMAPS) - 1
451 elif ax.index == len(CMAPS):
452 ax.index = 0
453 cmap = CMAPS[ax.index]
454 ax.cbar.set_cmap(cmap)
455 ax.cbar.draw_all()
456 ax.plt.set_cmap(cmap)
457 ax.cbar.patch.figure.canvas.draw()
458 self.colormap = cmap.name
459
460 def OnBtnScroll(self, event):
461 '''
462 Event for scrolling, scale figure
463 '''
464 cb_ax = event.inaxes
465 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
466 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
467 pt = ax.cbar.ax.bbox.get_points()[:, 1]
468 nrm = ax.cbar.norm
469 vmin, vmax, p0, p1, pS = (
470 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
471 scale = 2 if event.step == 1 else 0.5
472 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
473 ax.cbar.norm.vmin = point - scale * (point - vmin)
474 ax.cbar.norm.vmax = point - scale * (point - vmax)
475 ax.plt.set_norm(ax.cbar.norm)
476 ax.cbar.draw_all()
477 ax.cbar.patch.figure.canvas.draw()
478
479 def onBtnPress(self, event):
480 '''
481 Event for mouse button press
482 '''
483 cb_ax = event.inaxes
484 if cb_ax is None:
485 return
486
487 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
488 cb_ax.press = event.x, event.y
489 else:
490 cb_ax.press = None
491
492 def onMotion(self, event):
493 '''
494 Event for move inside colorbar
495 '''
496 cb_ax = event.inaxes
497 if cb_ax is None:
498 return
499 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
500 return
501 if cb_ax.press is None:
502 return
503
504 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
505 xprev, yprev = cb_ax.press
506 dx = event.x - xprev
507 dy = event.y - yprev
508 cb_ax.press = event.x, event.y
509 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
510 perc = 0.03
511
512 if event.button == 1:
513 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
514 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
515 elif event.button == 3:
516 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
517 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
518
519 ax.cbar.draw_all()
520 ax.plt.set_norm(ax.cbar.norm)
521 ax.cbar.patch.figure.canvas.draw()
522
523 def onBtnRelease(self, event):
524 '''
525 Event for mouse button release
526 '''
527 cb_ax = event.inaxes
528 if cb_ax is not None:
529 cb_ax.press = None
530
531 def __add_axes(self, ax, size='30%', pad='8%'):
532 '''
533 Add new axes to the given figure
534 '''
535 divider = make_axes_locatable(ax)
536 nax = divider.new_horizontal(size=size, pad=pad)
537 ax.figure.add_axes(nax)
538 return nax
539
540 def setup(self):
541 '''
542 This method should be implemented in the child class, the following
543 attributes should be set:
544
545 self.nrows: number of rows
546 self.ncols: number of cols
547 self.nplots: number of plots (channels or pairs)
548 self.ylabel: label for Y axes
549 self.titles: list of axes title
550
551 '''
552 raise NotImplementedError
553
554 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
555 '''
556 Create a masked array for missing data
557 '''
558 if x_buffer.shape[0] < 2:
559 return x_buffer, y_buffer, z_buffer
560
561 deltas = x_buffer[1:] - x_buffer[0:-1]
562 x_median = numpy.median(deltas)
563
564 index = numpy.where(deltas > 5 * x_median)
565
566 if len(index[0]) != 0:
567 z_buffer[::, index[0], ::] = self.__missing
568 z_buffer = numpy.ma.masked_inside(z_buffer,
569 0.99 * self.__missing,
570 1.01 * self.__missing)
571
572 return x_buffer, y_buffer, z_buffer
573
574 def decimate(self):
575
576 # dx = int(len(self.x)/self.__MAXNUMX) + 1
577 dy = int(len(self.y) / self.decimation) + 1
578
579 # x = self.x[::dx]
580 x = self.x
581 y = self.y[::dy]
582 z = self.z[::, ::, ::dy]
583
584 return x, y, z
585
586 def format(self):
587 '''
588 Set min and max values, labels, ticks and titles
589 '''
590
591 if self.xmin is None:
592 xmin = self.data.min_time
593 else:
594 if self.xaxis is 'time':
595 dt = self.getDateTime(self.data.min_time)
596 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
597 datetime.datetime(1970, 1, 1)).total_seconds()
598 if self.data.localtime:
599 xmin += time.timezone
600 else:
601 xmin = self.xmin
602
603 if self.xmax is None:
604 xmax = xmin + self.xrange * 60 * 60
605 else:
606 if self.xaxis is 'time':
607 dt = self.getDateTime(self.data.max_time)
608 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
609 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
610 if self.data.localtime:
611 xmax += time.timezone
612 else:
613 xmax = self.xmax
614
615 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
616 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
617
618 Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000])
619 i = 1 if numpy.where(
620 abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
621 ystep = Y[i] / 10.
622
623 if self.xaxis is not 'time':
624 X = numpy.array([1, 2, 5, 10, 20, 50, 100,
625 200, 500, 1000, 2000, 5000])/2.
626 i = 1 if numpy.where(
627 abs(xmax-xmin) <= X)[0][0] < 0 else numpy.where(abs(xmax-xmin) <= X)[0][0]
628 xstep = X[i] / 10.
629
630 for n, ax in enumerate(self.axes):
631 if ax.firsttime:
632 ax.set_facecolor(self.bgcolor)
633 ax.yaxis.set_major_locator(MultipleLocator(ystep))
634 if self.xscale:
635 ax.xaxis.set_major_formatter(FuncFormatter(
636 lambda x, pos: '{0:g}'.format(x*self.xscale)))
637 if self.xscale:
638 ax.yaxis.set_major_formatter(FuncFormatter(
639 lambda x, pos: '{0:g}'.format(x*self.yscale)))
640 if self.xaxis is 'time':
641 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
642 ax.xaxis.set_major_locator(LinearLocator(9))
643 else:
644 ax.xaxis.set_major_locator(MultipleLocator(xstep))
645 if self.xlabel is not None:
646 ax.set_xlabel(self.xlabel)
647 ax.set_ylabel(self.ylabel)
648 ax.firsttime = False
649 if self.showprofile:
650 self.pf_axes[n].set_ylim(ymin, ymax)
651 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
652 self.pf_axes[n].set_xlabel('dB')
653 self.pf_axes[n].grid(b=True, axis='x')
654 [tick.set_visible(False)
655 for tick in self.pf_axes[n].get_yticklabels()]
656 if self.colorbar:
657 ax.cbar = plt.colorbar(
658 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
659 ax.cbar.ax.tick_params(labelsize=8)
660 ax.cbar.ax.press = None
661 if self.cb_label:
662 ax.cbar.set_label(self.cb_label, size=8)
663 elif self.cb_labels:
664 ax.cbar.set_label(self.cb_labels[n], size=8)
665 else:
666 ax.cbar = None
667 if self.grid:
668 ax.grid(True)
669
670 if not self.polar:
671 ax.set_xlim(xmin, xmax)
672 ax.set_ylim(ymin, ymax)
673 ax.set_title('{} {} {}'.format(
674 self.titles[n],
675 self.getDateTime(self.data.max_time).strftime(
676 '%Y-%m-%dT%H:%M:%S'),
677 self.time_label),
678 size=8)
679 else:
680 ax.set_title('{}'.format(self.titles[n]), size=8)
681 ax.set_ylim(0, 90)
682 ax.set_yticks(numpy.arange(0, 90, 20))
683 ax.yaxis.labelpad = 40
684
685 def clear_figures(self):
686 '''
687 Reset axes for redraw plots
688 '''
689
690 for ax in self.axes:
691 ax.clear()
692 ax.firsttime = True
693 if ax.cbar:
694 ax.cbar.remove()
695
696 def __plot(self):
697 '''
698 Main function to plot, format and save figures
699 '''
700
701 #try:
702 self.plot()
703 self.format()
704 #except Exception as e:
705 # log.warning('{} Plot could not be updated... check data'.format(
706 # self.CODE), self.name)
707 # log.error(str(e), '')
708 # return
709
710 for n, fig in enumerate(self.figures):
711 if self.nrows == 0 or self.nplots == 0:
712 log.warning('No data', self.name)
713 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
714 fig.canvas.manager.set_window_title(self.CODE)
715 continue
716
717 fig.tight_layout()
718 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
719 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
720 fig.canvas.draw()
721
722 if self.save:
723
724 if self.save_labels:
725 labels = self.save_labels
726 else:
727 labels = list(range(self.nrows))
728
729 if self.oneFigure:
730 label = ''
731 else:
732 label = '-{}'.format(labels[n])
733 figname = os.path.join(
734 self.save,
735 self.CODE,
736 '{}{}_{}.png'.format(
737 self.CODE,
738 label,
739 self.getDateTime(self.data.max_time).strftime(
740 '%Y%m%d_%H%M%S'),
741 )
742 )
743 log.log('Saving figure: {}'.format(figname), self.name)
744 if not os.path.isdir(os.path.dirname(figname)):
745 os.makedirs(os.path.dirname(figname))
746 fig.savefig(figname)
747
748 def plot(self):
749 '''
750 Must be defined in the child class
751 '''
752 raise NotImplementedError
753
754 def run(self, dataOut, **kwargs):
755
756 if dataOut.flagNoData and not dataOut.error:
757 return dataOut
758
759 if dataOut.error:
760 coerce = True
761 else:
762 coerce = False
763
764 if self.isConfig is False:
765 self.__setup(**kwargs)
766 self.data.setup()
767 self.isConfig = True
768
769 if dataOut.type == 'Parameters':
770 tm = dataOut.utctimeInit
771 else:
772 tm = dataOut.utctime
773
774 if dataOut.useLocalTime:
775 if not self.localtime:
776 tm += time.timezone
777 else:
778 if self.localtime:
779 tm -= time.timezone
780
781 if self.data and (tm - self.data.min_time) >= self.xrange*60*60:
782 self.__plot()
783 self.data.setup()
784 self.clear_figures()
785
786 self.data.update(dataOut, tm)
787
788 if self.isPlotConfig is False:
789 self.__setup_plot()
790 self.isPlotConfig = True
791
792 if self.realtime:
793 self.__plot()
794 else:
795 self.__throttle_plot(self.__plot, coerce=coerce)
796
797 figpause(0.001)
798
799 def close(self):
800
801 if self.data and self.pause:
802 figpause(10)
803
@@ -1,112 +1,119
1 1 ## CHANGELOG:
2 2
3 ### 3.0
4 * Python 3.x compatible
5 * New architecture with multiprocessing and IPC communication
6 * Add @MPDecorator for multiprocessing Units and Operations
7 * Added new type of operation `external` for non-locking operations
8 * New plotting architecture with buffering/throttle capabilities to speed up plots
9
3 10 ### 2.3
4 11 * Added support for Madrigal formats (reading/writing).
5 12 * Added support for reading BLTR parameters (*.sswma).
6 13 * Added support for reading Julia format (*.dat).
7 14 * Added high order function `MPProject` for multiprocessing scripts.
8 15 * Added two new Processing Units `PublishData` and `ReceiverData` for receiving and sending dataOut through multiple ways (tcp, ipc, inproc).
9 16 * Added a new graphics Processing Unit `PlotterReceiver`. It is decoupled from normal processing sequence with support for data generated by multiprocessing scripts.
10 17 * Added support for sending realtime graphic to web server.
11 18 * GUI command `schain` is now `schainGUI`.
12 19 * Added a CLI tool named `schain`.
13 20 * Scripts templates can be now generated with `schain generate`.
14 21 * Now it is possible to search Processing Units and Operations with `schain search [module]` to get the right name and its allowed parameters.
15 22 * `schain xml` to run xml scripts.
16 23 * Added suggestions when parameters are poorly written.
17 24 * `Controller.start()` now runs in a different process than the process calling it.
18 25 * Added `schainpy.utils.log` for log standarization.
19 26 * Running script on online mode no longer ignores date and hour. Issue #1109.
20 27 * Added support for receving voltage data directly from JARS (tcp, ipc).
21 28 * Updated README for MAC OS GUI installation.
22 29 * Setup now installs numpy.
23 30
24 31 ### 2.2.6
25 32 * Graphics generated by the GUI are now the same as generated by scripts. Issue #1074.
26 33 * Added support for C extensions.
27 34 * Function `hildebrand_sehkon` optimized with a C wrapper.
28 35 * Numpy version updated.
29 36 * Migration to GIT.
30 37
31 38 ### 2.2.5:
32 39 * splitProfiles and combineProfiles modules were added to VoltageProc and Signal Chain GUI.
33 40 * nProfiles of USRP data (hdf5) is the number of profiles thera are in one second.
34 41 * jroPlotter works directly with data objects instead of dictionaries
35 42 * script "schain" was added to Signal Chain installer
36 43
37 44 ### 2.2.4.1:
38 45 * jroIO_usrp.py is update to read Sandra's data
39 46 * decimation in Spectra and RTI plots is always enabled.
40 47 * time* window option added to GUI
41 48
42 49 ### 2.2.4:
43 50 * jroproc_spectra_lags.py added to schainpy
44 51 * Bug fixed in schainGUI: ProcUnit was created with the same id in some cases.
45 52 * Bug fixed in jroHeaderIO: Header size validation.
46 53
47 54 ### 2.2.3.1:
48 55 * Filtering block by time has been added.
49 56 * Bug fixed plotting RTI, CoherenceMap and others using xmin and xmax parameters. The first day worked
50 57 properly but the next days did not.
51 58
52 59 ### 2.2.3:
53 60 * Bug fixed in GUI: Error getting(reading) Code value
54 61 * Bug fixed in GUI: Flip option always needs channelList field
55 62 * Bug fixed in jrodata: when one branch modified a value in "dataOut" (example: dataOut.code) this value
56 63 was modified for every branch (because this was a reference). It was modified in data.copy()
57 64 * Bug fixed in jroproc_voltage.profileSelector(): rangeList replaces to profileRangeList.
58 65
59 66 ### 2.2.2:
60 67 * VoltageProc: ProfileSelector, Reshape, Decoder with nTxs!=1 and getblock=True was tested
61 68 * Rawdata and testRawdata.py added to Signal Chain project
62 69
63 70 ### 2.2.1:
64 71 * Bugs fixed in GUI
65 72 * Views were improved in GUI
66 73 * Support to MST* ISR experiments
67 74 * Bug fixed getting noise using hyldebrant. (minimum number of points > 20%)
68 75 * handleError added to jroplotter.py
69 76
70 77 ### 2.2.0:
71 78 * GUI: use of external plotter
72 79 * Compatible with matplotlib 1.5.0
73 80
74 81 ### 2.1.5:
75 82 * serializer module added to Signal Chain
76 83 * jroplotter.py added to Signal Chain
77 84
78 85 ### 2.1.4.2:
79 86 * A new Plotter Class was added
80 87 * Project.start() does not accept filename as a parameter anymore
81 88
82 89 ### 2.1.4.1:
83 90 * Send notifications when an error different to ValueError is detected
84 91
85 92 ### 2.1.4:
86 93 * Sending error notifications to signal chain administrator
87 94 * Login to email server added
88 95
89 96 ### 2.1.3.3:
90 97 * Colored Button Icons were added to GUI
91 98
92 99 ### 2.1.3.2:
93 100 * GUI: user interaction enhanced
94 101 * controller_api.py: Safe access to ControllerThead
95 102
96 103 ### 2.1.3.1:
97 104 * GUI: every icon were resized
98 105 * jroproc_voltage.py: Print a message when "Read from code" option is selected and the code is not defined inside data file
99 106
100 107 ### 2.1.3:
101 108 * jroplot_heispectra.py: SpectraHeisScope was not showing the right channels
102 109 * jroproc_voltage.py: Bug fixed selecting profiles (self.nProfiles took a wrong value),
103 110 Bug fixed selecting heights by block (selecting profiles instead heights)
104 111 * jroproc_voltage.py: New feature added: decoding data by block using FFT.
105 112 * jroIO_heispectra.py: Bug fixed in FitsReader. Using local Fits instance instead schainpy.mode.data.jrodata.Fits.
106 113 * jroIO_heispectra.py: Channel index list does not exist.
107 114
108 115 ### 2.1.2:
109 116 * jroutils_ftp.py: Bug fixed, Any error sending file stopped the Server Thread
110 117 Server thread opens and closes remote server each time file list is sent
111 118 * jroplot_spectra.py: Noise path was not being created when noise data is saved.
112 119 * jroIO_base.py: startTime can be greater than endTime. Example: SpreadF [18:00 * 07:00] No newline at end of file
@@ -1,506 +1,506
1 1 """
2 2 The admin module contains all administrative classes relating to the schain python api.
3 3
4 4 The main role of this module is to send some reports. It contains a
5 5 notification class and a standard error handing class.
6 6
7 7 $Id: admin.py 3966 2015-12-01 14:32:29Z miguel.urco $
8 8 """
9 9 import os
10 10 import sys
11 11 import time
12 12 import traceback
13 13 import smtplib
14 14 if sys.version[0] == '3':
15 15 from configparser import ConfigParser
16 16 else:
17 17 from ConfigParser import ConfigParser
18 18 import io
19 19 from threading import Thread
20 20 from multiprocessing import Process
21 21 from email.mime.text import MIMEText
22 22 from email.mime.application import MIMEApplication
23 23 from email.mime.multipart import MIMEMultipart
24 24
25 25 import schainpy
26 26 from schainpy.utils import log
27 from schainpy.model.graphics.jroplot_data import popup
27 from schainpy.model.graphics.jroplot_base import popup
28 28
29 29 def get_path():
30 30 '''
31 31 Return schainpy path
32 32 '''
33 33
34 34 try:
35 35 root = __file__
36 36 if os.path.islink(root):
37 37 root = os.path.realpath(root)
38 38
39 39 return os.path.dirname(os.path.abspath(root))
40 40 except:
41 41 log.error('I am sorry, but something is wrong... __file__ not found')
42 42
43 43 class Alarm(Process):
44 44 '''
45 45 modes:
46 46 0 - All
47 47 1 - Send email
48 48 2 - Popup message
49 49 3 - Sound alarm
50 50 4 - Send to alarm system TODO
51 51 '''
52 52
53 53 def __init__(self, modes=[], **kwargs):
54 54 Process.__init__(self)
55 55 self.modes = modes
56 56 self.kwargs = kwargs
57 57
58 58 @staticmethod
59 59 def play_sound():
60 60 sound = os.path.join(get_path(), 'alarm1.oga')
61 61 if os.path.exists(sound):
62 62 for __ in range(2):
63 63 os.system('paplay {}'.format(sound))
64 64 time.sleep(0.5)
65 65 else:
66 66 log.warning('Unable to play alarm, sound file not found', 'ADMIN')
67 67
68 68 @staticmethod
69 69 def send_email(**kwargs):
70 70 notifier = SchainNotify()
71 71 print(kwargs)
72 72 notifier.notify(**kwargs)
73 73
74 74 @staticmethod
75 75 def show_popup(message):
76 76 if isinstance(message, list):
77 77 message = message[-1]
78 78 popup(message)
79 79
80 80 @staticmethod
81 81 def send_alarm():
82 82 pass
83 83
84 84 @staticmethod
85 85 def get_kwargs(kwargs, keys):
86 86 ret = {}
87 87 for key in keys:
88 88 ret[key] = kwargs[key]
89 89 return ret
90 90
91 91 def run(self):
92 92 tasks = {
93 93 1 : self.send_email,
94 94 2 : self.show_popup,
95 95 3 : self.play_sound,
96 96 4 : self.send_alarm,
97 97 }
98 98
99 99 tasks_args = {
100 100 1: ['email', 'message', 'subject', 'subtitle', 'filename'],
101 101 2: ['message'],
102 102 3: [],
103 103 4: [],
104 104 }
105 105 procs = []
106 106 for mode in self.modes:
107 107 if 0 in self.modes:
108 108 for x in tasks:
109 109 t = Thread(target=tasks[x], kwargs=self.get_kwargs(self.kwargs, tasks_args[x]))
110 110 t.start()
111 111 procs.append(t)
112 112 break
113 113 else:
114 114 t = Thread(target=tasks[mode], kwargs=self.get_kwargs(self.kwargs, tasks_args[mode]))
115 115 t.start()
116 116 procs.append(t)
117 117 for t in procs:
118 118 t.join()
119 119
120 120
121 121 class SchainConfigure():
122 122
123 123 __DEFAULT_ADMINISTRATOR_EMAIL = "juan.espinoza@jro.igp.gob.pe"
124 124 __DEFAULT_EMAIL_SERVER = "jro-zimbra.igp.gob.pe"
125 125 __DEFAULT_SENDER_EMAIL = "notifier-schain@jro.igp.gob.pe"
126 126 __DEFAULT_SENDER_PASS = ""
127 127
128 128 __SCHAIN_ADMINISTRATOR_EMAIL = "CONTACT"
129 129 __SCHAIN_EMAIL_SERVER = "MAILSERVER"
130 130 __SCHAIN_SENDER_EMAIL = "MAILSERVER_ACCOUNT"
131 131 __SCHAIN_SENDER_PASS = "MAILSERVER_PASSWORD"
132 132
133 133 def __init__(self, initFile = None):
134 134
135 135 # Set configuration file
136 136 if (initFile == None):
137 137 self.__confFilePath = "/etc/schain.conf"
138 138 else:
139 139 self.__confFilePath = initFile
140 140
141 141 # open configuration file
142 142 try:
143 143 self.__confFile = open(self.__confFilePath, "r")
144 144 except IOError:
145 145 # can't read from file - use all hard-coded values
146 146 self.__initFromHardCode()
147 147 return
148 148
149 149 # create Parser using standard module ConfigParser
150 150 self.__parser = ConfigParser()
151 151
152 152 # read conf file into a StringIO with "[madrigal]\n" section heading prepended
153 153 strConfFile = io.StringIO("[schain]\n" + self.__confFile.read())
154 154
155 155 # parse StringIO configuration file
156 156 self.__parser.readfp(strConfFile)
157 157
158 158 # read information from configuration file
159 159 self.__readConfFile()
160 160
161 161 # close conf file
162 162 self.__confFile.close()
163 163
164 164
165 165 def __initFromHardCode(self):
166 166
167 167 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
168 168 self.__sender_pass = self.__DEFAULT_SENDER_PASS
169 169 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
170 170 self.__email_server = self.__DEFAULT_EMAIL_SERVER
171 171
172 172 def __readConfFile(self):
173 173 """__readConfFile is a private helper function that reads information from the parsed config file.
174 174
175 175 Inputs: None
176 176
177 177 Returns: Void.
178 178
179 179 Affects: Initializes class member variables that are found in the config file.
180 180
181 181 Exceptions: MadrigalError thrown if any key not found.
182 182 """
183 183
184 184 # get the sender email
185 185 try:
186 186 self.__sender_email = self.__parser.get("schain", self.__SCHAIN_SENDER_EMAIL)
187 187 except:
188 188 self.__sender_email = self.__DEFAULT_SENDER_EMAIL
189 189
190 190 # get the sender password
191 191 try:
192 192 self.__sender_pass = self.__parser.get("schain", self.__SCHAIN_SENDER_PASS)
193 193 except:
194 194 self.__sender_pass = self.__DEFAULT_SENDER_PASS
195 195
196 196 # get the administrator email
197 197 try:
198 198 self.__admin_email = self.__parser.get("schain", self.__SCHAIN_ADMINISTRATOR_EMAIL)
199 199 except:
200 200 self.__admin_email = self.__DEFAULT_ADMINISTRATOR_EMAIL
201 201
202 202 # get the server email
203 203 try:
204 204 self.__email_server = self.__parser.get("schain", self.__SCHAIN_EMAIL_SERVER)
205 205 except:
206 206 self.__email_server = self.__DEFAULT_EMAIL_SERVER
207 207
208 208 def getEmailServer(self):
209 209
210 210 return self.__email_server
211 211
212 212 def getSenderEmail(self):
213 213
214 214 return self.__sender_email
215 215
216 216 def getSenderPass(self):
217 217
218 218 return self.__sender_pass
219 219
220 220 def getAdminEmail(self):
221 221
222 222 return self.__admin_email
223 223
224 224 class SchainNotify:
225 225 """SchainNotify is an object used to send messages to an administrator about a Schain software.
226 226
227 227 This object provides functions needed to send messages to an administrator about a Schain , for now
228 228 only sendAlert, which sends an email to the site administrator found is ADMIN_EMAIL
229 229
230 230 Usage example:
231 231
232 232 import schainpy.admin
233 233
234 234 try:
235 235
236 236 adminObj = schainpy.admin.SchainNotify()
237 237 adminObj.sendAlert('This is important!', 'Important Message')
238 238
239 239 except schainpy.admin.SchainError, e:
240 240
241 241 print e.getExceptionStr()
242 242
243 243
244 244 Non-standard Python modules used:
245 245 None
246 246
247 247 Exceptions thrown: None - Note that SchainNotify tries every trick it knows to avoid
248 248 throwing exceptions, since this is the class that will generally be called when there is a problem.
249 249
250 250 Change history:
251 251
252 252 Written by "Miguel Urco":mailto:miguel.urco@jro.igp.gob.pe Dec. 1, 2015
253 253 """
254 254
255 255 #constants
256 256
257 257 def __init__(self):
258 258 """__init__ initializes SchainNotify by getting some basic information from SchainDB and SchainSite.
259 259
260 260 Note that SchainNotify tries every trick it knows to avoid throwing exceptions, since
261 261 this is the class that will generally be called when there is a problem.
262 262
263 263 Inputs: Existing SchainDB object, by default = None.
264 264
265 265 Returns: void
266 266
267 267 Affects: Initializes self.__binDir.
268 268
269 269 Exceptions: None.
270 270 """
271 271
272 272 # note that the main configuration file is unavailable
273 273 # the best that can be done is send an email to root using localhost mailserver
274 274 confObj = SchainConfigure()
275 275
276 276 self.__emailFromAddress = confObj.getSenderEmail()
277 277 self.__emailPass = confObj.getSenderPass()
278 278 self.__emailToAddress = confObj.getAdminEmail()
279 279 self.__emailServer = confObj.getEmailServer()
280 280
281 281 def sendEmail(self, email_from, email_to, subject='Error running ...', message="", subtitle="", filename="", html_format=True):
282 282
283 283 if not email_to:
284 284 return 0
285 285
286 286 if not self.__emailServer:
287 287 return 0
288 288
289 289 log.success('Sending email to {}...'.format(email_to), 'System')
290 290
291 291 msg = MIMEMultipart()
292 292 msg['Subject'] = subject
293 293 msg['From'] = "(Python SChain API): " + email_from
294 294 msg['Reply-to'] = email_from
295 295 msg['To'] = email_to
296 296
297 297 # That is what u see if dont have an email reader:
298 298 msg.preamble = 'SChainPy'
299 299
300 300 if html_format:
301 301 message = "<h1> %s </h1>" %subject + "<h3>" + subtitle.replace("\n", "</h3><h3>\n") + "</h3>" + message.replace("\n", "<br>\n")
302 302 message = "<html>\n" + message + '</html>'
303 303
304 304 # This is the textual part:
305 305 part = MIMEText(message, "html")
306 306 else:
307 307 message = subject + "\n" + subtitle + "\n" + message
308 308 part = MIMEText(message)
309 309
310 310 msg.attach(part)
311 311
312 312 if filename and os.path.isfile(filename):
313 313 # This is the binary part(The Attachment):
314 314 part = MIMEApplication(open(filename,"rb").read())
315 315 part.add_header('Content-Disposition',
316 316 'attachment',
317 317 filename=os.path.basename(filename))
318 318 msg.attach(part)
319 319
320 320 # Create an instance in SMTP server
321 321 try:
322 322 smtp = smtplib.SMTP(self.__emailServer)
323 323 except:
324 324 log.error('Could not connect to server {}'.format(self.__emailServer), 'System')
325 325 return 0
326 326
327 327 # Start the server:
328 328 # smtp.ehlo()
329 329 if self.__emailPass:
330 330 smtp.login(self.__emailFromAddress, self.__emailPass)
331 331
332 332 # Send the email
333 333 try:
334 334 smtp.sendmail(msg['From'], msg['To'], msg.as_string())
335 335 except:
336 336 log.error('Could not send the email to {}'.format(msg['To']), 'System')
337 337 smtp.quit()
338 338 return 0
339 339
340 340 smtp.quit()
341 341
342 342 log.success('Email sent ', 'System')
343 343
344 344 return 1
345 345
346 346 def sendAlert(self, message, subject = "", subtitle="", filename=""):
347 347 """sendAlert sends an email with the given message and optional title.
348 348
349 349 Inputs: message (string), and optional title (string)
350 350
351 351 Returns: void
352 352
353 353 Affects: none
354 354
355 355 Exceptions: None.
356 356 """
357 357
358 358 if not self.__emailToAddress:
359 359 return 0
360 360
361 361 print("***** Sending alert to %s *****" %self.__emailToAddress)
362 362 # set up message
363 363
364 364 sent=self.sendEmail(email_from=self.__emailFromAddress,
365 365 email_to=self.__emailToAddress,
366 366 subject=subject,
367 367 message=message,
368 368 subtitle=subtitle,
369 369 filename=filename)
370 370
371 371 if not sent:
372 372 return 0
373 373
374 374 return 1
375 375
376 376 def notify(self, email, message, subject = "", subtitle="", filename=""):
377 377 """notify sends an email with the given message and title to email.
378 378
379 379 Inputs: email (string), message (string), and subject (string)
380 380
381 381 Returns: void
382 382
383 383 Affects: none
384 384
385 385 Exceptions: None.
386 386 """
387 387
388 388 if email is None:
389 389 email = self.__emailToAddress
390 390
391 391 self.sendEmail(
392 392 email_from=self.__emailFromAddress,
393 393 email_to=email,
394 394 subject=subject,
395 395 message=message,
396 396 subtitle=subtitle,
397 397 filename=filename
398 398 )
399 399
400 400
401 401 class SchainError(Exception):
402 402 """SchainError is an exception class that is thrown for all known errors using Schain Py lib.
403 403
404 404 Usage example:
405 405
406 406 import sys, traceback
407 407 import schainpy.admin
408 408
409 409 try:
410 410
411 411 test = open('ImportantFile.txt', 'r')
412 412
413 413 except:
414 414
415 415 raise schainpy.admin.SchainError('ImportantFile.txt not opened!',
416 416 traceback.format_exception(sys.exc_info()[0],
417 417 sys.exc_info()[1],
418 418 sys.exc_info()[2]))
419 419 """
420 420
421 421
422 422 def __init__(self, strInterpretation, exceptionList=None):
423 423 """ __init__ gathers the interpretation string along with all information from sys.exc_info().
424 424
425 425 Inputs:
426 426 strIntepretation - A string representing the programmer's interpretation of
427 427 why the exception occurred
428 428
429 429 exceptionList - a list of strings completely describing the exception.
430 430 Generated by traceback.format_exception(sys.exc_info()[0],
431 431 sys.exc_info()[1],
432 432 sys.exc_info()[2])
433 433
434 434 Returns: Void.
435 435
436 436 Affects: Initializes class member variables _strInterp, _strExcList.
437 437
438 438 Exceptions: None.
439 439 """
440 440
441 441 if not exceptionList:
442 442 exceptionList = traceback.format_exception(sys.exc_info()[0],
443 443 sys.exc_info()[1],
444 444 sys.exc_info()[2])
445 445
446 446 self._strInterp = strInterpretation
447 447 self._strExcList = exceptionList
448 448
449 449
450 450 def getExceptionStr(self):
451 451 """ getExceptionStr returns a formatted string ready for printing completely describing the exception.
452 452
453 453 Inputs: None
454 454
455 455 Returns: A formatted string ready for printing completely describing the exception.
456 456
457 457 Affects: None
458 458
459 459 Exceptions: None.
460 460 """
461 461 excStr = ''
462 462 excStr = excStr + self._strInterp + '\n\n'
463 463
464 464 if self._strExcList != None:
465 465 for item in self._strExcList:
466 466 excStr = excStr + str(item) + '\n'
467 467
468 468 return excStr
469 469
470 470 def __str__(self):
471 471
472 472 return(self.getExceptionStr())
473 473
474 474
475 475 def getExceptionHtml(self):
476 476 """ getExceptionHtml returns an Html formatted string completely describing the exception.
477 477
478 478 Inputs: None
479 479
480 480 Returns: A formatted string ready for printing completely describing the exception.
481 481
482 482 Affects: None
483 483
484 484 Exceptions: None.
485 485 """
486 486
487 487 excStr = '<BR>The following Schain Python exception has occurred:\n<BR>'
488 488 excStr = excStr + self._strInterp + '\n<BR>\n'
489 489
490 490 if self._strExcList != None:
491 491 for item in self._strExcList:
492 492 excStr = excStr + str(item) + '\n<BR>'
493 493
494 494 return excStr
495 495
496 496 class SchainWarning(Exception):
497 497 pass
498 498
499 499
500 500 if __name__ == '__main__':
501 501
502 502 test = SchainNotify()
503 503
504 504 test.sendAlert('This is a message from the python module SchainNotify', 'Test from SchainNotify')
505 505
506 506 print('Hopefully message sent - check.') No newline at end of file
@@ -1,1265 +1,1263
1 1 '''
2 2 Updated on January , 2018, for multiprocessing purposes
3 3 Author: Sergio Cortez
4 4 Created on September , 2012
5 5 '''
6 6 from platform import python_version
7 7 import sys
8 8 import ast
9 9 import datetime
10 10 import traceback
11 11 import math
12 12 import time
13 13 import zmq
14 14 from multiprocessing import Process, cpu_count
15 15 from threading import Thread
16 16 from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
17 17 from xml.dom import minidom
18 18
19 19
20 20 from schainpy.admin import Alarm, SchainWarning
21 21
22 22 ### Temporary imports!!!
23 23 # from schainpy.model import *
24 24 from schainpy.model.io import *
25 25 from schainpy.model.graphics import *
26 26 from schainpy.model.proc.jroproc_base import *
27 27 from schainpy.model.proc.bltrproc_parameters import *
28 28 from schainpy.model.proc.jroproc_spectra import *
29 29 from schainpy.model.proc.jroproc_voltage import *
30 30 from schainpy.model.proc.jroproc_parameters import *
31 31 from schainpy.model.utils.jroutils_publish import *
32 32 from schainpy.utils import log
33 33 ###
34 34
35 35 DTYPES = {
36 36 'Voltage': '.r',
37 37 'Spectra': '.pdata'
38 38 }
39 39
40 40
41 41 def MPProject(project, n=cpu_count()):
42 42 '''
43 43 Project wrapper to run schain in n processes
44 44 '''
45 45
46 46 rconf = project.getReadUnitObj()
47 47 op = rconf.getOperationObj('run')
48 48 dt1 = op.getParameterValue('startDate')
49 49 dt2 = op.getParameterValue('endDate')
50 50 tm1 = op.getParameterValue('startTime')
51 51 tm2 = op.getParameterValue('endTime')
52 52 days = (dt2 - dt1).days
53 53
54 54 for day in range(days + 1):
55 55 skip = 0
56 56 cursor = 0
57 57 processes = []
58 58 dt = dt1 + datetime.timedelta(day)
59 59 dt_str = dt.strftime('%Y/%m/%d')
60 60 reader = JRODataReader()
61 61 paths, files = reader.searchFilesOffLine(path=rconf.path,
62 62 startDate=dt,
63 63 endDate=dt,
64 64 startTime=tm1,
65 65 endTime=tm2,
66 66 ext=DTYPES[rconf.datatype])
67 67 nFiles = len(files)
68 68 if nFiles == 0:
69 69 continue
70 70 skip = int(math.ceil(nFiles / n))
71 71 while nFiles > cursor * skip:
72 72 rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor,
73 73 skip=skip)
74 74 p = project.clone()
75 75 p.start()
76 76 processes.append(p)
77 77 cursor += 1
78 78
79 79 def beforeExit(exctype, value, trace):
80 80 for process in processes:
81 81 process.terminate()
82 82 process.join()
83 83 print(traceback.print_tb(trace))
84 84
85 85 sys.excepthook = beforeExit
86 86
87 87 for process in processes:
88 88 process.join()
89 89 process.terminate()
90 90
91 91 time.sleep(3)
92 92
93 93 def wait(context):
94 94
95 95 time.sleep(1)
96 96 c = zmq.Context()
97 97 receiver = c.socket(zmq.SUB)
98 98 receiver.connect('ipc:///tmp/schain_{}_pub'.format(self.id))
99 99 receiver.setsockopt(zmq.SUBSCRIBE, self.id.encode())
100 log.error('startinggg')
101 100 msg = receiver.recv_multipart()[1]
102 #log.error(msg)
103 101 context.terminate()
104 102
105 103 class ParameterConf():
106 104
107 105 id = None
108 106 name = None
109 107 value = None
110 108 format = None
111 109
112 110 __formated_value = None
113 111
114 112 ELEMENTNAME = 'Parameter'
115 113
116 114 def __init__(self):
117 115
118 116 self.format = 'str'
119 117
120 118 def getElementName(self):
121 119
122 120 return self.ELEMENTNAME
123 121
124 122 def getValue(self):
125 123
126 124 value = self.value
127 125 format = self.format
128 126
129 127 if self.__formated_value != None:
130 128
131 129 return self.__formated_value
132 130
133 131 if format == 'obj':
134 132 return value
135 133
136 134 if format == 'str':
137 135 self.__formated_value = str(value)
138 136 return self.__formated_value
139 137
140 138 if value == '':
141 139 raise ValueError('%s: This parameter value is empty' % self.name)
142 140
143 141 if format == 'list':
144 142 strList = value.split(',')
145 143
146 144 self.__formated_value = strList
147 145
148 146 return self.__formated_value
149 147
150 148 if format == 'intlist':
151 149 '''
152 150 Example:
153 151 value = (0,1,2)
154 152 '''
155 153
156 154 new_value = ast.literal_eval(value)
157 155
158 156 if type(new_value) not in (tuple, list):
159 157 new_value = [int(new_value)]
160 158
161 159 self.__formated_value = new_value
162 160
163 161 return self.__formated_value
164 162
165 163 if format == 'floatlist':
166 164 '''
167 165 Example:
168 166 value = (0.5, 1.4, 2.7)
169 167 '''
170 168
171 169 new_value = ast.literal_eval(value)
172 170
173 171 if type(new_value) not in (tuple, list):
174 172 new_value = [float(new_value)]
175 173
176 174 self.__formated_value = new_value
177 175
178 176 return self.__formated_value
179 177
180 178 if format == 'date':
181 179 strList = value.split('/')
182 180 intList = [int(x) for x in strList]
183 181 date = datetime.date(intList[0], intList[1], intList[2])
184 182
185 183 self.__formated_value = date
186 184
187 185 return self.__formated_value
188 186
189 187 if format == 'time':
190 188 strList = value.split(':')
191 189 intList = [int(x) for x in strList]
192 190 time = datetime.time(intList[0], intList[1], intList[2])
193 191
194 192 self.__formated_value = time
195 193
196 194 return self.__formated_value
197 195
198 196 if format == 'pairslist':
199 197 '''
200 198 Example:
201 199 value = (0,1),(1,2)
202 200 '''
203 201
204 202 new_value = ast.literal_eval(value)
205 203
206 204 if type(new_value) not in (tuple, list):
207 205 raise ValueError('%s has to be a tuple or list of pairs' % value)
208 206
209 207 if type(new_value[0]) not in (tuple, list):
210 208 if len(new_value) != 2:
211 209 raise ValueError('%s has to be a tuple or list of pairs' % value)
212 210 new_value = [new_value]
213 211
214 212 for thisPair in new_value:
215 213 if len(thisPair) != 2:
216 214 raise ValueError('%s has to be a tuple or list of pairs' % value)
217 215
218 216 self.__formated_value = new_value
219 217
220 218 return self.__formated_value
221 219
222 220 if format == 'multilist':
223 221 '''
224 222 Example:
225 223 value = (0,1,2),(3,4,5)
226 224 '''
227 225 multiList = ast.literal_eval(value)
228 226
229 227 if type(multiList[0]) == int:
230 228 multiList = ast.literal_eval('(' + value + ')')
231 229
232 230 self.__formated_value = multiList
233 231
234 232 return self.__formated_value
235 233
236 234 if format == 'bool':
237 235 value = int(value)
238 236
239 237 if format == 'int':
240 238 value = float(value)
241 239
242 240 format_func = eval(format)
243 241
244 242 self.__formated_value = format_func(value)
245 243
246 244 return self.__formated_value
247 245
248 246 def updateId(self, new_id):
249 247
250 248 self.id = str(new_id)
251 249
252 250 def setup(self, id, name, value, format='str'):
253 251 self.id = str(id)
254 252 self.name = name
255 253 if format == 'obj':
256 254 self.value = value
257 255 else:
258 256 self.value = str(value)
259 257 self.format = str.lower(format)
260 258
261 259 self.getValue()
262 260
263 261 return 1
264 262
265 263 def update(self, name, value, format='str'):
266 264
267 265 self.name = name
268 266 self.value = str(value)
269 267 self.format = format
270 268
271 269 def makeXml(self, opElement):
272 270 if self.name not in ('queue',):
273 271 parmElement = SubElement(opElement, self.ELEMENTNAME)
274 272 parmElement.set('id', str(self.id))
275 273 parmElement.set('name', self.name)
276 274 parmElement.set('value', self.value)
277 275 parmElement.set('format', self.format)
278 276
279 277 def readXml(self, parmElement):
280 278
281 279 self.id = parmElement.get('id')
282 280 self.name = parmElement.get('name')
283 281 self.value = parmElement.get('value')
284 282 self.format = str.lower(parmElement.get('format'))
285 283
286 284 # Compatible with old signal chain version
287 285 if self.format == 'int' and self.name == 'idfigure':
288 286 self.name = 'id'
289 287
290 288 def printattr(self):
291 289
292 290 print('Parameter[%s]: name = %s, value = %s, format = %s, project_id = %s' % (self.id, self.name, self.value, self.format, self.project_id))
293 291
294 292 class OperationConf():
295 293
296 294 ELEMENTNAME = 'Operation'
297 295
298 296 def __init__(self):
299 297
300 298 self.id = '0'
301 299 self.name = None
302 300 self.priority = None
303 301 self.topic = None
304 302
305 303 def __getNewId(self):
306 304
307 305 return int(self.id) * 10 + len(self.parmConfObjList) + 1
308 306
309 307 def getId(self):
310 308 return self.id
311 309
312 310 def updateId(self, new_id):
313 311
314 312 self.id = str(new_id)
315 313
316 314 n = 1
317 315 for parmObj in self.parmConfObjList:
318 316
319 317 idParm = str(int(new_id) * 10 + n)
320 318 parmObj.updateId(idParm)
321 319
322 320 n += 1
323 321
324 322 def getElementName(self):
325 323
326 324 return self.ELEMENTNAME
327 325
328 326 def getParameterObjList(self):
329 327
330 328 return self.parmConfObjList
331 329
332 330 def getParameterObj(self, parameterName):
333 331
334 332 for parmConfObj in self.parmConfObjList:
335 333
336 334 if parmConfObj.name != parameterName:
337 335 continue
338 336
339 337 return parmConfObj
340 338
341 339 return None
342 340
343 341 def getParameterObjfromValue(self, parameterValue):
344 342
345 343 for parmConfObj in self.parmConfObjList:
346 344
347 345 if parmConfObj.getValue() != parameterValue:
348 346 continue
349 347
350 348 return parmConfObj.getValue()
351 349
352 350 return None
353 351
354 352 def getParameterValue(self, parameterName):
355 353
356 354 parameterObj = self.getParameterObj(parameterName)
357 355
358 356 # if not parameterObj:
359 357 # return None
360 358
361 359 value = parameterObj.getValue()
362 360
363 361 return value
364 362
365 363 def getKwargs(self):
366 364
367 365 kwargs = {}
368 366
369 367 for parmConfObj in self.parmConfObjList:
370 368 if self.name == 'run' and parmConfObj.name == 'datatype':
371 369 continue
372 370
373 371 kwargs[parmConfObj.name] = parmConfObj.getValue()
374 372
375 373 return kwargs
376 374
377 375 def setup(self, id, name, priority, type, project_id):
378 376
379 377 self.id = str(id)
380 378 self.project_id = project_id
381 379 self.name = name
382 380 self.type = type
383 381 self.priority = priority
384 382 self.parmConfObjList = []
385 383
386 384 def removeParameters(self):
387 385
388 386 for obj in self.parmConfObjList:
389 387 del obj
390 388
391 389 self.parmConfObjList = []
392 390
393 391 def addParameter(self, name, value, format='str'):
394 392
395 393 if value is None:
396 394 return None
397 395 id = self.__getNewId()
398 396
399 397 parmConfObj = ParameterConf()
400 398 if not parmConfObj.setup(id, name, value, format):
401 399 return None
402 400
403 401 self.parmConfObjList.append(parmConfObj)
404 402
405 403 return parmConfObj
406 404
407 405 def changeParameter(self, name, value, format='str'):
408 406
409 407 parmConfObj = self.getParameterObj(name)
410 408 parmConfObj.update(name, value, format)
411 409
412 410 return parmConfObj
413 411
414 412 def makeXml(self, procUnitElement):
415 413
416 414 opElement = SubElement(procUnitElement, self.ELEMENTNAME)
417 415 opElement.set('id', str(self.id))
418 416 opElement.set('name', self.name)
419 417 opElement.set('type', self.type)
420 418 opElement.set('priority', str(self.priority))
421 419
422 420 for parmConfObj in self.parmConfObjList:
423 421 parmConfObj.makeXml(opElement)
424 422
425 423 def readXml(self, opElement, project_id):
426 424
427 425 self.id = opElement.get('id')
428 426 self.name = opElement.get('name')
429 427 self.type = opElement.get('type')
430 428 self.priority = opElement.get('priority')
431 429 self.project_id = str(project_id) #yong
432 430
433 431 # Compatible with old signal chain version
434 432 # Use of 'run' method instead 'init'
435 433 if self.type == 'self' and self.name == 'init':
436 434 self.name = 'run'
437 435
438 436 self.parmConfObjList = []
439 437
440 438 parmElementList = opElement.iter(ParameterConf().getElementName())
441 439
442 440 for parmElement in parmElementList:
443 441 parmConfObj = ParameterConf()
444 442 parmConfObj.readXml(parmElement)
445 443
446 444 # Compatible with old signal chain version
447 445 # If an 'plot' OPERATION is found, changes name operation by the value of its type PARAMETER
448 446 if self.type != 'self' and self.name == 'Plot':
449 447 if parmConfObj.format == 'str' and parmConfObj.name == 'type':
450 448 self.name = parmConfObj.value
451 449 continue
452 450
453 451 self.parmConfObjList.append(parmConfObj)
454 452
455 453 def printattr(self):
456 454
457 455 print('%s[%s]: name = %s, type = %s, priority = %s, project_id = %s' % (self.ELEMENTNAME,
458 456 self.id,
459 457 self.name,
460 458 self.type,
461 459 self.priority,
462 460 self.project_id))
463 461
464 462 for parmConfObj in self.parmConfObjList:
465 463 parmConfObj.printattr()
466 464
467 465 def createObject(self):
468 466
469 467 className = eval(self.name)
470 468
471 469 if self.type == 'other':
472 470 opObj = className()
473 471 elif self.type == 'external':
474 472 kwargs = self.getKwargs()
475 473 opObj = className(self.id, self.project_id, **kwargs)
476 474 opObj.start()
477 475
478 476 return opObj
479 477
480 478 class ProcUnitConf():
481 479
482 480 ELEMENTNAME = 'ProcUnit'
483 481
484 482 def __init__(self):
485 483
486 484 self.id = None
487 485 self.datatype = None
488 486 self.name = None
489 487 self.inputId = None
490 488 self.opConfObjList = []
491 489 self.procUnitObj = None
492 490 self.opObjDict = {}
493 491
494 492 def __getPriority(self):
495 493
496 494 return len(self.opConfObjList) + 1
497 495
498 496 def __getNewId(self):
499 497
500 498 return int(self.id) * 10 + len(self.opConfObjList) + 1
501 499
502 500 def getElementName(self):
503 501
504 502 return self.ELEMENTNAME
505 503
506 504 def getId(self):
507 505
508 506 return self.id
509 507
510 508 def updateId(self, new_id):
511 509 '''
512 510 new_id = int(parentId) * 10 + (int(self.id) % 10)
513 511 new_inputId = int(parentId) * 10 + (int(self.inputId) % 10)
514 512
515 513 # If this proc unit has not inputs
516 514 #if self.inputId == '0':
517 515 #new_inputId = 0
518 516
519 517 n = 1
520 518 for opConfObj in self.opConfObjList:
521 519
522 520 idOp = str(int(new_id) * 10 + n)
523 521 opConfObj.updateId(idOp)
524 522
525 523 n += 1
526 524
527 525 self.parentId = str(parentId)
528 526 self.id = str(new_id)
529 527 #self.inputId = str(new_inputId)
530 528 '''
531 529 n = 1
532 530
533 531 def getInputId(self):
534 532
535 533 return self.inputId
536 534
537 535 def getOperationObjList(self):
538 536
539 537 return self.opConfObjList
540 538
541 539 def getOperationObj(self, name=None):
542 540
543 541 for opConfObj in self.opConfObjList:
544 542
545 543 if opConfObj.name != name:
546 544 continue
547 545
548 546 return opConfObj
549 547
550 548 return None
551 549
552 550 def getOpObjfromParamValue(self, value=None):
553 551
554 552 for opConfObj in self.opConfObjList:
555 553 if opConfObj.getParameterObjfromValue(parameterValue=value) != value:
556 554 continue
557 555 return opConfObj
558 556 return None
559 557
560 558 def getProcUnitObj(self):
561 559
562 560 return self.procUnitObj
563 561
564 562 def setup(self, project_id, id, name, datatype, inputId):
565 563 '''
566 564 id sera el topico a publicar
567 565 inputId sera el topico a subscribirse
568 566 '''
569 567
570 568 # Compatible with old signal chain version
571 569 if datatype == None and name == None:
572 570 raise ValueError('datatype or name should be defined')
573 571
574 572 #Definir una condicion para inputId cuando sea 0
575 573
576 574 if name == None:
577 575 if 'Proc' in datatype:
578 576 name = datatype
579 577 else:
580 578 name = '%sProc' % (datatype)
581 579
582 580 if datatype == None:
583 581 datatype = name.replace('Proc', '')
584 582
585 583 self.id = str(id)
586 584 self.project_id = project_id
587 585 self.name = name
588 586 self.datatype = datatype
589 587 self.inputId = inputId
590 588 self.opConfObjList = []
591 589
592 590 self.addOperation(name='run', optype='self')
593 591
594 592 def removeOperations(self):
595 593
596 594 for obj in self.opConfObjList:
597 595 del obj
598 596
599 597 self.opConfObjList = []
600 598 self.addOperation(name='run')
601 599
602 600 def addParameter(self, **kwargs):
603 601 '''
604 602 Add parameters to 'run' operation
605 603 '''
606 604 opObj = self.opConfObjList[0]
607 605
608 606 opObj.addParameter(**kwargs)
609 607
610 608 return opObj
611 609
612 610 def addOperation(self, name, optype='self'):
613 611 '''
614 612 Actualizacion - > proceso comunicacion
615 613 En el caso de optype='self', elminar. DEfinir comuncacion IPC -> Topic
616 614 definir el tipoc de socket o comunicacion ipc++
617 615
618 616 '''
619 617
620 618 id = self.__getNewId()
621 619 priority = self.__getPriority() # Sin mucho sentido, pero puede usarse
622 620 opConfObj = OperationConf()
623 621 opConfObj.setup(id, name=name, priority=priority, type=optype, project_id=self.project_id)
624 622 self.opConfObjList.append(opConfObj)
625 623
626 624 return opConfObj
627 625
628 626 def makeXml(self, projectElement):
629 627
630 628 procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
631 629 procUnitElement.set('id', str(self.id))
632 630 procUnitElement.set('name', self.name)
633 631 procUnitElement.set('datatype', self.datatype)
634 632 procUnitElement.set('inputId', str(self.inputId))
635 633
636 634 for opConfObj in self.opConfObjList:
637 635 opConfObj.makeXml(procUnitElement)
638 636
639 637 def readXml(self, upElement, project_id):
640 638
641 639 self.id = upElement.get('id')
642 640 self.name = upElement.get('name')
643 641 self.datatype = upElement.get('datatype')
644 642 self.inputId = upElement.get('inputId')
645 643 self.project_id = str(project_id)
646 644
647 645 if self.ELEMENTNAME == 'ReadUnit':
648 646 self.datatype = self.datatype.replace('Reader', '')
649 647
650 648 if self.ELEMENTNAME == 'ProcUnit':
651 649 self.datatype = self.datatype.replace('Proc', '')
652 650
653 651 if self.inputId == 'None':
654 652 self.inputId = '0'
655 653
656 654 self.opConfObjList = []
657 655
658 656 opElementList = upElement.iter(OperationConf().getElementName())
659 657
660 658 for opElement in opElementList:
661 659 opConfObj = OperationConf()
662 660 opConfObj.readXml(opElement, project_id)
663 661 self.opConfObjList.append(opConfObj)
664 662
665 663 def printattr(self):
666 664
667 665 print('%s[%s]: name = %s, datatype = %s, inputId = %s, project_id = %s' % (self.ELEMENTNAME,
668 666 self.id,
669 667 self.name,
670 668 self.datatype,
671 669 self.inputId,
672 670 self.project_id))
673 671
674 672 for opConfObj in self.opConfObjList:
675 673 opConfObj.printattr()
676 674
677 675 def getKwargs(self):
678 676
679 677 opObj = self.opConfObjList[0]
680 678 kwargs = opObj.getKwargs()
681 679
682 680 return kwargs
683 681
684 682 def createObjects(self):
685 683 '''
686 684 Instancia de unidades de procesamiento.
687 685 '''
688 686 className = eval(self.name)
689 687 kwargs = self.getKwargs()
690 688 procUnitObj = className(self.id, self.inputId, self.project_id, **kwargs) # necesitan saber su id y su entrada por fines de ipc
691 689 log.success('creating process...', self.name)
692 690
693 691 for opConfObj in self.opConfObjList:
694 692
695 693 if opConfObj.type == 'self' and opConfObj.name == 'run':
696 694 continue
697 695 elif opConfObj.type == 'self':
698 696 opObj = getattr(procUnitObj, opConfObj.name)
699 697 else:
700 698 opObj = opConfObj.createObject()
701 699
702 700 log.success('creating operation: {}, type:{}'.format(
703 701 opConfObj.name,
704 702 opConfObj.type), self.name)
705 703
706 704 procUnitObj.addOperation(opConfObj, opObj)
707 705
708 706 procUnitObj.start()
709 707 self.procUnitObj = procUnitObj
710 708
711 709 def close(self):
712 710
713 711 for opConfObj in self.opConfObjList:
714 712 if opConfObj.type == 'self':
715 713 continue
716 714
717 715 opObj = self.procUnitObj.getOperationObj(opConfObj.id)
718 716 opObj.close()
719 717
720 718 self.procUnitObj.close()
721 719
722 720 return
723 721
724 722
725 723 class ReadUnitConf(ProcUnitConf):
726 724
727 725 ELEMENTNAME = 'ReadUnit'
728 726
729 727 def __init__(self):
730 728
731 729 self.id = None
732 730 self.datatype = None
733 731 self.name = None
734 732 self.inputId = None
735 733 self.opConfObjList = []
736 734
737 735 def getElementName(self):
738 736
739 737 return self.ELEMENTNAME
740 738
741 739 def setup(self, project_id, id, name, datatype, path='', startDate='', endDate='',
742 740 startTime='', endTime='', server=None, **kwargs):
743 741
744 742
745 743 '''
746 744 *****el id del proceso sera el Topico
747 745
748 746 Adicion de {topic}, si no esta presente -> error
749 747 kwargs deben ser trasmitidos en la instanciacion
750 748
751 749 '''
752 750
753 751 # Compatible with old signal chain version
754 752 if datatype == None and name == None:
755 753 raise ValueError('datatype or name should be defined')
756 754 if name == None:
757 755 if 'Reader' in datatype:
758 756 name = datatype
759 757 datatype = name.replace('Reader','')
760 758 else:
761 759 name = '{}Reader'.format(datatype)
762 760 if datatype == None:
763 761 if 'Reader' in name:
764 762 datatype = name.replace('Reader','')
765 763 else:
766 764 datatype = name
767 765 name = '{}Reader'.format(name)
768 766
769 767 self.id = id
770 768 self.project_id = project_id
771 769 self.name = name
772 770 self.datatype = datatype
773 771 if path != '':
774 772 self.path = os.path.abspath(path)
775 773 self.startDate = startDate
776 774 self.endDate = endDate
777 775 self.startTime = startTime
778 776 self.endTime = endTime
779 777 self.server = server
780 778 self.addRunOperation(**kwargs)
781 779
782 780 def update(self, **kwargs):
783 781
784 782 if 'datatype' in kwargs:
785 783 datatype = kwargs.pop('datatype')
786 784 if 'Reader' in datatype:
787 785 self.name = datatype
788 786 else:
789 787 self.name = '%sReader' % (datatype)
790 788 self.datatype = self.name.replace('Reader', '')
791 789
792 790 attrs = ('path', 'startDate', 'endDate',
793 791 'startTime', 'endTime')
794 792
795 793 for attr in attrs:
796 794 if attr in kwargs:
797 795 setattr(self, attr, kwargs.pop(attr))
798 796
799 797 self.updateRunOperation(**kwargs)
800 798
801 799 def removeOperations(self):
802 800
803 801 for obj in self.opConfObjList:
804 802 del obj
805 803
806 804 self.opConfObjList = []
807 805
808 806 def addRunOperation(self, **kwargs):
809 807
810 808 opObj = self.addOperation(name='run', optype='self')
811 809
812 810 if self.server is None:
813 811 opObj.addParameter(
814 812 name='datatype', value=self.datatype, format='str')
815 813 opObj.addParameter(name='path', value=self.path, format='str')
816 814 opObj.addParameter(
817 815 name='startDate', value=self.startDate, format='date')
818 816 opObj.addParameter(
819 817 name='endDate', value=self.endDate, format='date')
820 818 opObj.addParameter(
821 819 name='startTime', value=self.startTime, format='time')
822 820 opObj.addParameter(
823 821 name='endTime', value=self.endTime, format='time')
824 822
825 823 for key, value in list(kwargs.items()):
826 824 opObj.addParameter(name=key, value=value,
827 825 format=type(value).__name__)
828 826 else:
829 827 opObj.addParameter(name='server', value=self.server, format='str')
830 828
831 829 return opObj
832 830
833 831 def updateRunOperation(self, **kwargs):
834 832
835 833 opObj = self.getOperationObj(name='run')
836 834 opObj.removeParameters()
837 835
838 836 opObj.addParameter(name='datatype', value=self.datatype, format='str')
839 837 opObj.addParameter(name='path', value=self.path, format='str')
840 838 opObj.addParameter(
841 839 name='startDate', value=self.startDate, format='date')
842 840 opObj.addParameter(name='endDate', value=self.endDate, format='date')
843 841 opObj.addParameter(
844 842 name='startTime', value=self.startTime, format='time')
845 843 opObj.addParameter(name='endTime', value=self.endTime, format='time')
846 844
847 845 for key, value in list(kwargs.items()):
848 846 opObj.addParameter(name=key, value=value,
849 847 format=type(value).__name__)
850 848
851 849 return opObj
852 850
853 851 def readXml(self, upElement, project_id):
854 852
855 853 self.id = upElement.get('id')
856 854 self.name = upElement.get('name')
857 855 self.datatype = upElement.get('datatype')
858 856 self.project_id = str(project_id) #yong
859 857
860 858 if self.ELEMENTNAME == 'ReadUnit':
861 859 self.datatype = self.datatype.replace('Reader', '')
862 860
863 861 self.opConfObjList = []
864 862
865 863 opElementList = upElement.iter(OperationConf().getElementName())
866 864
867 865 for opElement in opElementList:
868 866 opConfObj = OperationConf()
869 867 opConfObj.readXml(opElement, project_id)
870 868 self.opConfObjList.append(opConfObj)
871 869
872 870 if opConfObj.name == 'run':
873 871 self.path = opConfObj.getParameterValue('path')
874 872 self.startDate = opConfObj.getParameterValue('startDate')
875 873 self.endDate = opConfObj.getParameterValue('endDate')
876 874 self.startTime = opConfObj.getParameterValue('startTime')
877 875 self.endTime = opConfObj.getParameterValue('endTime')
878 876
879 877
880 878 class Project(Process):
881 879
882 880 ELEMENTNAME = 'Project'
883 881
884 882 def __init__(self):
885 883
886 884 Process.__init__(self)
887 885 self.id = None
888 886 self.filename = None
889 887 self.description = None
890 888 self.email = None
891 889 self.alarm = None
892 890 self.procUnitConfObjDict = {}
893 891
894 892 def __getNewId(self):
895 893
896 894 idList = list(self.procUnitConfObjDict.keys())
897 895 id = int(self.id) * 10
898 896
899 897 while True:
900 898 id += 1
901 899
902 900 if str(id) in idList:
903 901 continue
904 902
905 903 break
906 904
907 905 return str(id)
908 906
909 907 def getElementName(self):
910 908
911 909 return self.ELEMENTNAME
912 910
913 911 def getId(self):
914 912
915 913 return self.id
916 914
917 915 def updateId(self, new_id):
918 916
919 917 self.id = str(new_id)
920 918
921 919 keyList = list(self.procUnitConfObjDict.keys())
922 920 keyList.sort()
923 921
924 922 n = 1
925 923 newProcUnitConfObjDict = {}
926 924
927 925 for procKey in keyList:
928 926
929 927 procUnitConfObj = self.procUnitConfObjDict[procKey]
930 928 idProcUnit = str(int(self.id) * 10 + n)
931 929 procUnitConfObj.updateId(idProcUnit)
932 930 newProcUnitConfObjDict[idProcUnit] = procUnitConfObj
933 931 n += 1
934 932
935 933 self.procUnitConfObjDict = newProcUnitConfObjDict
936 934
937 935 def setup(self, id=1, name='', description='', email=None, alarm=[]):
938 936
939 937 print(' ')
940 938 print('*' * 60)
941 939 print('* Starting SIGNAL CHAIN PROCESSING (Multiprocessing) v%s *' % schainpy.__version__)
942 940 print('*' * 60)
943 941 print("* Python " + python_version() + " *")
944 942 print('*' * 19)
945 943 print(' ')
946 944 self.id = str(id)
947 945 self.description = description
948 946 self.email = email
949 947 self.alarm = alarm
950 948
951 949 def update(self, **kwargs):
952 950
953 951 for key, value in list(kwargs.items()):
954 952 setattr(self, key, value)
955 953
956 954 def clone(self):
957 955
958 956 p = Project()
959 957 p.procUnitConfObjDict = self.procUnitConfObjDict
960 958 return p
961 959
962 960 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
963 961
964 962 '''
965 963 Actualizacion:
966 964 Se agrego un nuevo argumento: topic -relativo a la forma de comunicar los procesos simultaneos
967 965
968 966 * El id del proceso sera el topico al que se deben subscribir los procUnits para recibir la informacion(data)
969 967
970 968 '''
971 969
972 970 if id is None:
973 971 idReadUnit = self.__getNewId()
974 972 else:
975 973 idReadUnit = str(id)
976 974
977 975 readUnitConfObj = ReadUnitConf()
978 976 readUnitConfObj.setup(self.id, idReadUnit, name, datatype, **kwargs)
979 977 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
980 978
981 979 return readUnitConfObj
982 980
983 981 def addProcUnit(self, inputId='0', datatype=None, name=None):
984 982
985 983 '''
986 984 Actualizacion:
987 985 Se agrego dos nuevos argumentos: topic_read (lee data de otro procUnit) y topic_write(escribe o envia data a otro procUnit)
988 986 Deberia reemplazar a "inputId"
989 987
990 988 ** A fin de mantener el inputID, este sera la representaacion del topicoal que deben subscribirse. El ID propio de la intancia
991 989 (proceso) sera el topico de la publicacion, todo sera asignado de manera dinamica.
992 990
993 991 '''
994 992
995 993 idProcUnit = self.__getNewId() #Topico para subscripcion
996 994 procUnitConfObj = ProcUnitConf()
997 995 procUnitConfObj.setup(self.id, idProcUnit, name, datatype, inputId) #topic_read, topic_write,
998 996 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
999 997
1000 998 return procUnitConfObj
1001 999
1002 1000 def removeProcUnit(self, id):
1003 1001
1004 1002 if id in list(self.procUnitConfObjDict.keys()):
1005 1003 self.procUnitConfObjDict.pop(id)
1006 1004
1007 1005 def getReadUnitId(self):
1008 1006
1009 1007 readUnitConfObj = self.getReadUnitObj()
1010 1008
1011 1009 return readUnitConfObj.id
1012 1010
1013 1011 def getReadUnitObj(self):
1014 1012
1015 1013 for obj in list(self.procUnitConfObjDict.values()):
1016 1014 if obj.getElementName() == 'ReadUnit':
1017 1015 return obj
1018 1016
1019 1017 return None
1020 1018
1021 1019 def getProcUnitObj(self, id=None, name=None):
1022 1020
1023 1021 if id != None:
1024 1022 return self.procUnitConfObjDict[id]
1025 1023
1026 1024 if name != None:
1027 1025 return self.getProcUnitObjByName(name)
1028 1026
1029 1027 return None
1030 1028
1031 1029 def getProcUnitObjByName(self, name):
1032 1030
1033 1031 for obj in list(self.procUnitConfObjDict.values()):
1034 1032 if obj.name == name:
1035 1033 return obj
1036 1034
1037 1035 return None
1038 1036
1039 1037 def procUnitItems(self):
1040 1038
1041 1039 return list(self.procUnitConfObjDict.items())
1042 1040
1043 1041 def makeXml(self):
1044 1042
1045 1043 projectElement = Element('Project')
1046 1044 projectElement.set('id', str(self.id))
1047 1045 projectElement.set('name', self.name)
1048 1046 projectElement.set('description', self.description)
1049 1047
1050 1048 for procUnitConfObj in list(self.procUnitConfObjDict.values()):
1051 1049 procUnitConfObj.makeXml(projectElement)
1052 1050
1053 1051 self.projectElement = projectElement
1054 1052
1055 1053 def writeXml(self, filename=None):
1056 1054
1057 1055 if filename == None:
1058 1056 if self.filename:
1059 1057 filename = self.filename
1060 1058 else:
1061 1059 filename = 'schain.xml'
1062 1060
1063 1061 if not filename:
1064 1062 print('filename has not been defined. Use setFilename(filename) for do it.')
1065 1063 return 0
1066 1064
1067 1065 abs_file = os.path.abspath(filename)
1068 1066
1069 1067 if not os.access(os.path.dirname(abs_file), os.W_OK):
1070 1068 print('No write permission on %s' % os.path.dirname(abs_file))
1071 1069 return 0
1072 1070
1073 1071 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
1074 1072 print('File %s already exists and it could not be overwriten' % abs_file)
1075 1073 return 0
1076 1074
1077 1075 self.makeXml()
1078 1076
1079 1077 ElementTree(self.projectElement).write(abs_file, method='xml')
1080 1078
1081 1079 self.filename = abs_file
1082 1080
1083 1081 return 1
1084 1082
1085 1083 def readXml(self, filename=None):
1086 1084
1087 1085 if not filename:
1088 1086 print('filename is not defined')
1089 1087 return 0
1090 1088
1091 1089 abs_file = os.path.abspath(filename)
1092 1090
1093 1091 if not os.path.isfile(abs_file):
1094 1092 print('%s file does not exist' % abs_file)
1095 1093 return 0
1096 1094
1097 1095 self.projectElement = None
1098 1096 self.procUnitConfObjDict = {}
1099 1097
1100 1098 try:
1101 1099 self.projectElement = ElementTree().parse(abs_file)
1102 1100 except:
1103 1101 print('Error reading %s, verify file format' % filename)
1104 1102 return 0
1105 1103
1106 1104 self.project = self.projectElement.tag
1107 1105
1108 1106 self.id = self.projectElement.get('id')
1109 1107 self.name = self.projectElement.get('name')
1110 1108 self.description = self.projectElement.get('description')
1111 1109
1112 1110 readUnitElementList = self.projectElement.iter(
1113 1111 ReadUnitConf().getElementName())
1114 1112
1115 1113 for readUnitElement in readUnitElementList:
1116 1114 readUnitConfObj = ReadUnitConf()
1117 1115 readUnitConfObj.readXml(readUnitElement, self.id)
1118 1116 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
1119 1117
1120 1118 procUnitElementList = self.projectElement.iter(
1121 1119 ProcUnitConf().getElementName())
1122 1120
1123 1121 for procUnitElement in procUnitElementList:
1124 1122 procUnitConfObj = ProcUnitConf()
1125 1123 procUnitConfObj.readXml(procUnitElement, self.id)
1126 1124 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1127 1125
1128 1126 self.filename = abs_file
1129 1127
1130 1128 return 1
1131 1129
1132 1130 def __str__(self):
1133 1131
1134 1132 print('Project[%s]: name = %s, description = %s, project_id = %s' % (self.id,
1135 1133 self.name,
1136 1134 self.description,
1137 1135 self.project_id))
1138 1136
1139 1137 for procUnitConfObj in self.procUnitConfObjDict.values():
1140 1138 print(procUnitConfObj)
1141 1139
1142 1140 def createObjects(self):
1143 1141
1144 1142 for procUnitConfObj in self.procUnitConfObjDict.values():
1145 1143 procUnitConfObj.createObjects()
1146 1144
1147 1145 def __handleError(self, procUnitConfObj, modes=None, stdout=True):
1148 1146
1149 1147 import socket
1150 1148
1151 1149 if modes is None:
1152 1150 modes = self.alarm
1153 1151
1154 1152 if not self.alarm:
1155 1153 modes = []
1156 1154
1157 1155 err = traceback.format_exception(sys.exc_info()[0],
1158 1156 sys.exc_info()[1],
1159 1157 sys.exc_info()[2])
1160 1158
1161 1159 log.error('{}'.format(err[-1]), procUnitConfObj.name)
1162 1160
1163 1161 message = ''.join(err)
1164 1162
1165 1163 if stdout:
1166 1164 sys.stderr.write(message)
1167 1165
1168 1166 subject = 'SChain v%s: Error running %s\n' % (
1169 1167 schainpy.__version__, procUnitConfObj.name)
1170 1168
1171 1169 subtitle = '%s: %s\n' % (
1172 1170 procUnitConfObj.getElementName(), procUnitConfObj.name)
1173 1171 subtitle += 'Hostname: %s\n' % socket.gethostbyname(
1174 1172 socket.gethostname())
1175 1173 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
1176 1174 subtitle += 'Configuration file: %s\n' % self.filename
1177 1175 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
1178 1176
1179 1177 readUnitConfObj = self.getReadUnitObj()
1180 1178 if readUnitConfObj:
1181 1179 subtitle += '\nInput parameters:\n'
1182 1180 subtitle += '[Data path = %s]\n' % readUnitConfObj.path
1183 1181 subtitle += '[Data type = %s]\n' % readUnitConfObj.datatype
1184 1182 subtitle += '[Start date = %s]\n' % readUnitConfObj.startDate
1185 1183 subtitle += '[End date = %s]\n' % readUnitConfObj.endDate
1186 1184 subtitle += '[Start time = %s]\n' % readUnitConfObj.startTime
1187 1185 subtitle += '[End time = %s]\n' % readUnitConfObj.endTime
1188 1186
1189 1187 a = Alarm(
1190 1188 modes=modes,
1191 1189 email=self.email,
1192 1190 message=message,
1193 1191 subject=subject,
1194 1192 subtitle=subtitle,
1195 1193 filename=self.filename
1196 1194 )
1197 1195
1198 1196 return a
1199 1197
1200 1198 def isPaused(self):
1201 1199 return 0
1202 1200
1203 1201 def isStopped(self):
1204 1202 return 0
1205 1203
1206 1204 def runController(self):
1207 1205 '''
1208 1206 returns 0 when this process has been stopped, 1 otherwise
1209 1207 '''
1210 1208
1211 1209 if self.isPaused():
1212 1210 print('Process suspended')
1213 1211
1214 1212 while True:
1215 1213 time.sleep(0.1)
1216 1214
1217 1215 if not self.isPaused():
1218 1216 break
1219 1217
1220 1218 if self.isStopped():
1221 1219 break
1222 1220
1223 1221 print('Process reinitialized')
1224 1222
1225 1223 if self.isStopped():
1226 1224 print('Process stopped')
1227 1225 return 0
1228 1226
1229 1227 return 1
1230 1228
1231 1229 def setFilename(self, filename):
1232 1230
1233 1231 self.filename = filename
1234 1232
1235 1233 def setProxyCom(self):
1236 1234
1237 1235 if not os.path.exists('/tmp/schain'):
1238 1236 os.mkdir('/tmp/schain')
1239 1237
1240 1238 self.ctx = zmq.Context()
1241 1239 xpub = self.ctx.socket(zmq.XPUB)
1242 1240 xpub.bind('ipc:///tmp/schain/{}_pub'.format(self.id))
1243 1241 xsub = self.ctx.socket(zmq.XSUB)
1244 1242 xsub.bind('ipc:///tmp/schain/{}_sub'.format(self.id))
1245 1243
1246 1244 try:
1247 1245 zmq.proxy(xpub, xsub)
1248 except zmq.ContextTerminated:
1246 except: # zmq.ContextTerminated:
1249 1247 xpub.close()
1250 1248 xsub.close()
1251 1249
1252 1250 def run(self):
1253 1251
1254 1252 log.success('Starting {}: {}'.format(self.name, self.id), tag='')
1255 1253 self.start_time = time.time()
1256 1254 self.createObjects()
1257 1255 # t = Thread(target=wait, args=(self.ctx, ))
1258 1256 # t.start()
1259 1257 self.setProxyCom()
1260 1258
1261 1259 # Iniciar todos los procesos .start(), monitoreo de procesos. ELiminar lo de abajo
1262 1260
1263 log.success('{} finished (time: {}s)'.format(
1261 log.success('{} Done (time: {}s)'.format(
1264 1262 self.name,
1265 1263 time.time()-self.start_time))
@@ -1,1251 +1,1342
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
5 5 '''
6 6
7 7 import copy
8 8 import numpy
9 9 import datetime
10 import json
10 11
12 from schainpy.utils import log
11 13 from .jroheaderIO import SystemHeader, RadarControllerHeader
12 14
13 15
14 16 def getNumpyDtype(dataTypeCode):
15 17
16 18 if dataTypeCode == 0:
17 19 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
18 20 elif dataTypeCode == 1:
19 21 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
20 22 elif dataTypeCode == 2:
21 23 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
22 24 elif dataTypeCode == 3:
23 25 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
24 26 elif dataTypeCode == 4:
25 27 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
26 28 elif dataTypeCode == 5:
27 29 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
28 30 else:
29 31 raise ValueError('dataTypeCode was not defined')
30 32
31 33 return numpyDtype
32 34
33 35
34 36 def getDataTypeCode(numpyDtype):
35 37
36 38 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
37 39 datatype = 0
38 40 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
39 41 datatype = 1
40 42 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
41 43 datatype = 2
42 44 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
43 45 datatype = 3
44 46 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
45 47 datatype = 4
46 48 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
47 49 datatype = 5
48 50 else:
49 51 datatype = None
50 52
51 53 return datatype
52 54
53 55
54 56 def hildebrand_sekhon(data, navg):
55 57 """
56 58 This method is for the objective determination of the noise level in Doppler spectra. This
57 59 implementation technique is based on the fact that the standard deviation of the spectral
58 60 densities is equal to the mean spectral density for white Gaussian noise
59 61
60 62 Inputs:
61 63 Data : heights
62 64 navg : numbers of averages
63 65
64 66 Return:
65 67 mean : noise's level
66 68 """
67 69
68 70 sortdata = numpy.sort(data, axis=None)
69 71 lenOfData = len(sortdata)
70 72 nums_min = lenOfData*0.2
71 73
72 74 if nums_min <= 5:
73 75
74 76 nums_min = 5
75 77
76 78 sump = 0.
77 79 sumq = 0.
78 80
79 81 j = 0
80 82 cont = 1
81 83
82 while((cont==1)and(j<lenOfData)):
84 while((cont == 1)and(j < lenOfData)):
83 85
84 86 sump += sortdata[j]
85 87 sumq += sortdata[j]**2
86 88
87 89 if j > nums_min:
88 90 rtest = float(j)/(j-1) + 1.0/navg
89 91 if ((sumq*j) > (rtest*sump**2)):
90 92 j = j - 1
91 sump = sump - sortdata[j]
92 sumq = sumq - sortdata[j]**2
93 sump = sump - sortdata[j]
94 sumq = sumq - sortdata[j]**2
93 95 cont = 0
94 96
95 97 j += 1
96 98
97 lnoise = sump /j
99 lnoise = sump / j
98 100
99 101 return lnoise
100 102
101 103
102 104 class Beam:
103 105
104 106 def __init__(self):
105 107 self.codeList = []
106 108 self.azimuthList = []
107 109 self.zenithList = []
108 110
109 111
110 112 class GenericData(object):
111 113
112 114 flagNoData = True
113 115
114 116 def copy(self, inputObj=None):
115 117
116 118 if inputObj == None:
117 119 return copy.deepcopy(self)
118 120
119 121 for key in list(inputObj.__dict__.keys()):
120 122
121 123 attribute = inputObj.__dict__[key]
122 124
123 125 # If this attribute is a tuple or list
124 126 if type(inputObj.__dict__[key]) in (tuple, list):
125 127 self.__dict__[key] = attribute[:]
126 128 continue
127 129
128 130 # If this attribute is another object or instance
129 131 if hasattr(attribute, '__dict__'):
130 132 self.__dict__[key] = attribute.copy()
131 133 continue
132 134
133 135 self.__dict__[key] = inputObj.__dict__[key]
134 136
135 137 def deepcopy(self):
136 138
137 139 return copy.deepcopy(self)
138 140
139 141 def isEmpty(self):
140 142
141 143 return self.flagNoData
142 144
143 145
144 146 class JROData(GenericData):
145 147
146 148 # m_BasicHeader = BasicHeader()
147 149 # m_ProcessingHeader = ProcessingHeader()
148 150
149 151 systemHeaderObj = SystemHeader()
150
151 152 radarControllerHeaderObj = RadarControllerHeader()
152
153 153 # data = None
154
155 154 type = None
156
157 155 datatype = None # dtype but in string
158
159 156 # dtype = None
160
161 157 # nChannels = None
162
163 158 # nHeights = None
164
165 159 nProfiles = None
166
167 160 heightList = None
168
169 161 channelList = None
170
171 162 flagDiscontinuousBlock = False
172
173 163 useLocalTime = False
174
175 164 utctime = None
176
177 165 timeZone = None
178
179 166 dstFlag = None
180
181 167 errorCount = None
182
183 168 blocksize = None
184
185 169 # nCode = None
186 #
187 170 # nBaud = None
188 #
189 171 # code = None
190
191 172 flagDecodeData = False # asumo q la data no esta decodificada
192
193 173 flagDeflipData = False # asumo q la data no esta sin flip
194
195 174 flagShiftFFT = False
196
197 175 # ippSeconds = None
198
199 176 # timeInterval = None
200
201 177 nCohInt = None
202
203 178 # noise = None
204
205 179 windowOfFilter = 1
206
207 180 # Speed of ligth
208 181 C = 3e8
209
210 182 frequency = 49.92e6
211
212 183 realtime = False
213
214 184 beacon_heiIndexList = None
215
216 185 last_block = None
217
218 186 blocknow = None
219
220 187 azimuth = None
221
222 188 zenith = None
223
224 189 beam = Beam()
225
226 190 profileIndex = None
191 error = None
192 data = None
193 data_plt = None
227 194
228 error = (0, '')
229 195
230 196 def __str__(self):
231 197
232 198 return '{} - {}'.format(self.type, self.getDatatime())
233 199
234 200 def getNoise(self):
235 201
236 202 raise NotImplementedError
237 203
238 204 def getNChannels(self):
239 205
240 206 return len(self.channelList)
241 207
242 208 def getChannelIndexList(self):
243 209
244 210 return list(range(self.nChannels))
245 211
246 212 def getNHeights(self):
247 213
248 214 return len(self.heightList)
249 215
250 216 def getHeiRange(self, extrapoints=0):
251 217
252 218 heis = self.heightList
253 219 # deltah = self.heightList[1] - self.heightList[0]
254 220 #
255 221 # heis.append(self.heightList[-1])
256 222
257 223 return heis
258 224
259 225 def getDeltaH(self):
260 226
261 227 delta = self.heightList[1] - self.heightList[0]
262 228
263 229 return delta
264 230
265 231 def getltctime(self):
266 232
267 233 if self.useLocalTime:
268 234 return self.utctime - self.timeZone * 60
269 235
270 236 return self.utctime
271 237
272 238 def getDatatime(self):
273 239
274 240 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
275 241 return datatimeValue
276 242
277 243 def getTimeRange(self):
278 244
279 245 datatime = []
280 246
281 247 datatime.append(self.ltctime)
282 248 datatime.append(self.ltctime + self.timeInterval + 1)
283 249
284 250 datatime = numpy.array(datatime)
285 251
286 252 return datatime
287 253
288 254 def getFmaxTimeResponse(self):
289 255
290 256 period = (10**-6) * self.getDeltaH() / (0.15)
291 257
292 258 PRF = 1. / (period * self.nCohInt)
293 259
294 260 fmax = PRF
295 261
296 262 return fmax
297 263
298 264 def getFmax(self):
299 265 PRF = 1. / (self.ippSeconds * self.nCohInt)
300 266
301 267 fmax = PRF
302 268 return fmax
303 269
304 270 def getVmax(self):
305 271
306 272 _lambda = self.C / self.frequency
307 273
308 274 vmax = self.getFmax() * _lambda / 2
309 275
310 276 return vmax
311 277
312 278 def get_ippSeconds(self):
313 279 '''
314 280 '''
315 281 return self.radarControllerHeaderObj.ippSeconds
316 282
317 283 def set_ippSeconds(self, ippSeconds):
318 284 '''
319 285 '''
320 286
321 287 self.radarControllerHeaderObj.ippSeconds = ippSeconds
322 288
323 289 return
324 290
325 291 def get_dtype(self):
326 292 '''
327 293 '''
328 294 return getNumpyDtype(self.datatype)
329 295
330 296 def set_dtype(self, numpyDtype):
331 297 '''
332 298 '''
333 299
334 300 self.datatype = getDataTypeCode(numpyDtype)
335 301
336 302 def get_code(self):
337 303 '''
338 304 '''
339 305 return self.radarControllerHeaderObj.code
340 306
341 307 def set_code(self, code):
342 308 '''
343 309 '''
344 310 self.radarControllerHeaderObj.code = code
345 311
346 312 return
347 313
348 314 def get_ncode(self):
349 315 '''
350 316 '''
351 317 return self.radarControllerHeaderObj.nCode
352 318
353 319 def set_ncode(self, nCode):
354 320 '''
355 321 '''
356 322 self.radarControllerHeaderObj.nCode = nCode
357 323
358 324 return
359 325
360 326 def get_nbaud(self):
361 327 '''
362 328 '''
363 329 return self.radarControllerHeaderObj.nBaud
364 330
365 331 def set_nbaud(self, nBaud):
366 332 '''
367 333 '''
368 334 self.radarControllerHeaderObj.nBaud = nBaud
369 335
370 336 return
371 337
372 338 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
373 339 channelIndexList = property(
374 340 getChannelIndexList, "I'm the 'channelIndexList' property.")
375 341 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
376 342 #noise = property(getNoise, "I'm the 'nHeights' property.")
377 343 datatime = property(getDatatime, "I'm the 'datatime' property")
378 344 ltctime = property(getltctime, "I'm the 'ltctime' property")
379 345 ippSeconds = property(get_ippSeconds, set_ippSeconds)
380 346 dtype = property(get_dtype, set_dtype)
381 347 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
382 348 code = property(get_code, set_code)
383 349 nCode = property(get_ncode, set_ncode)
384 350 nBaud = property(get_nbaud, set_nbaud)
385 351
386 352
387 353 class Voltage(JROData):
388 354
389 355 # data es un numpy array de 2 dmensiones (canales, alturas)
390 356 data = None
391 357
392 358 def __init__(self):
393 359 '''
394 360 Constructor
395 361 '''
396 362
397 363 self.useLocalTime = True
398
399 364 self.radarControllerHeaderObj = RadarControllerHeader()
400
401 365 self.systemHeaderObj = SystemHeader()
402
403 366 self.type = "Voltage"
404
405 367 self.data = None
406
407 368 # self.dtype = None
408
409 369 # self.nChannels = 0
410
411 370 # self.nHeights = 0
412
413 371 self.nProfiles = None
414
415 self.heightList = None
416
372 self.heightList = Non
417 373 self.channelList = None
418
419 374 # self.channelIndexList = None
420
421 375 self.flagNoData = True
422
423 376 self.flagDiscontinuousBlock = False
424
425 377 self.utctime = None
426
427 378 self.timeZone = None
428
429 379 self.dstFlag = None
430
431 380 self.errorCount = None
432
433 381 self.nCohInt = None
434
435 382 self.blocksize = None
436
437 383 self.flagDecodeData = False # asumo q la data no esta decodificada
438
439 384 self.flagDeflipData = False # asumo q la data no esta sin flip
440
441 385 self.flagShiftFFT = False
442
443 386 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
444
445 387 self.profileIndex = 0
446 388
447 389 def getNoisebyHildebrand(self, channel=None):
448 390 """
449 391 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
450 392
451 393 Return:
452 394 noiselevel
453 395 """
454 396
455 397 if channel != None:
456 398 data = self.data[channel]
457 399 nChannels = 1
458 400 else:
459 401 data = self.data
460 402 nChannels = self.nChannels
461 403
462 404 noise = numpy.zeros(nChannels)
463 405 power = data * numpy.conjugate(data)
464 406
465 407 for thisChannel in range(nChannels):
466 408 if nChannels == 1:
467 409 daux = power[:].real
468 410 else:
469 411 daux = power[thisChannel, :].real
470 412 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
471 413
472 414 return noise
473 415
474 416 def getNoise(self, type=1, channel=None):
475 417
476 418 if type == 1:
477 419 noise = self.getNoisebyHildebrand(channel)
478 420
479 421 return noise
480 422
481 423 def getPower(self, channel=None):
482 424
483 425 if channel != None:
484 426 data = self.data[channel]
485 427 else:
486 428 data = self.data
487 429
488 430 power = data * numpy.conjugate(data)
489 431 powerdB = 10 * numpy.log10(power.real)
490 432 powerdB = numpy.squeeze(powerdB)
491 433
492 434 return powerdB
493 435
494 436 def getTimeInterval(self):
495 437
496 438 timeInterval = self.ippSeconds * self.nCohInt
497 439
498 440 return timeInterval
499 441
500 442 noise = property(getNoise, "I'm the 'nHeights' property.")
501 443 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
502 444
503 445
504 446 class Spectra(JROData):
505 447
506 448 # data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
507 449 data_spc = None
508
509 450 # data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
510 451 data_cspc = None
511
512 452 # data dc es un numpy array de 2 dmensiones (canales, alturas)
513 453 data_dc = None
514
515 454 # data power
516 455 data_pwr = None
517
518 456 nFFTPoints = None
519
520 457 # nPairs = None
521
522 458 pairsList = None
523
524 459 nIncohInt = None
525
526 460 wavelength = None # Necesario para cacular el rango de velocidad desde la frecuencia
527
528 461 nCohInt = None # se requiere para determinar el valor de timeInterval
529
530 462 ippFactor = None
531
532 463 profileIndex = 0
533
534 464 plotting = "spectra"
535
536 465 def __init__(self):
537 466 '''
538 467 Constructor
539 468 '''
540 469
541 470 self.useLocalTime = True
542
543 471 self.radarControllerHeaderObj = RadarControllerHeader()
544
545 472 self.systemHeaderObj = SystemHeader()
546
547 473 self.type = "Spectra"
548
549 474 # self.data = None
550
551 475 # self.dtype = None
552
553 476 # self.nChannels = 0
554
555 477 # self.nHeights = 0
556
557 478 self.nProfiles = None
558
559 479 self.heightList = None
560
561 480 self.channelList = None
562
563 481 # self.channelIndexList = None
564
565 482 self.pairsList = None
566
567 483 self.flagNoData = True
568
569 484 self.flagDiscontinuousBlock = False
570
571 485 self.utctime = None
572
573 486 self.nCohInt = None
574
575 487 self.nIncohInt = None
576
577 488 self.blocksize = None
578
579 489 self.nFFTPoints = None
580
581 490 self.wavelength = None
582
583 491 self.flagDecodeData = False # asumo q la data no esta decodificada
584
585 492 self.flagDeflipData = False # asumo q la data no esta sin flip
586
587 493 self.flagShiftFFT = False
588
589 494 self.ippFactor = 1
590
591 495 #self.noise = None
592
593 496 self.beacon_heiIndexList = []
594
595 497 self.noise_estimation = None
596 498
597 499 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
598 500 """
599 501 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
600 502
601 503 Return:
602 504 noiselevel
603 505 """
604 506
605 507 noise = numpy.zeros(self.nChannels)
606 508
607 509 for channel in range(self.nChannels):
608 510 daux = self.data_spc[channel,
609 511 xmin_index:xmax_index, ymin_index:ymax_index]
610 512 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
611 513
612 514 return noise
613 515
614 516 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
615 517
616 518 if self.noise_estimation is not None:
617 519 # this was estimated by getNoise Operation defined in jroproc_spectra.py
618 520 return self.noise_estimation
619 521 else:
620 522 noise = self.getNoisebyHildebrand(
621 523 xmin_index, xmax_index, ymin_index, ymax_index)
622 524 return noise
623 525
624 526 def getFreqRangeTimeResponse(self, extrapoints=0):
625 527
626 528 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
627 529 freqrange = deltafreq * \
628 530 (numpy.arange(self.nFFTPoints + extrapoints) -
629 531 self.nFFTPoints / 2.) - deltafreq / 2
630 532
631 533 return freqrange
632 534
633 535 def getAcfRange(self, extrapoints=0):
634 536
635 537 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
636 538 freqrange = deltafreq * \
637 539 (numpy.arange(self.nFFTPoints + extrapoints) -
638 540 self.nFFTPoints / 2.) - deltafreq / 2
639 541
640 542 return freqrange
641 543
642 544 def getFreqRange(self, extrapoints=0):
643 545
644 546 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
645 547 freqrange = deltafreq * \
646 548 (numpy.arange(self.nFFTPoints + extrapoints) -
647 549 self.nFFTPoints / 2.) - deltafreq / 2
648 550
649 551 return freqrange
650 552
651 553 def getVelRange(self, extrapoints=0):
652 554
653 555 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
654 556 velrange = deltav * (numpy.arange(self.nFFTPoints +
655 557 extrapoints) - self.nFFTPoints / 2.) # - deltav/2
656 558
657 559 return velrange
658 560
659 561 def getNPairs(self):
660 562
661 563 return len(self.pairsList)
662 564
663 565 def getPairsIndexList(self):
664 566
665 567 return list(range(self.nPairs))
666 568
667 569 def getNormFactor(self):
668 570
669 571 pwcode = 1
670 572
671 573 if self.flagDecodeData:
672 574 pwcode = numpy.sum(self.code[0]**2)
673 575 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
674 576 normFactor = self.nProfiles * self.nIncohInt * \
675 577 self.nCohInt * pwcode * self.windowOfFilter
676 578
677 579 return normFactor
678 580
679 581 def getFlagCspc(self):
680 582
681 583 if self.data_cspc is None:
682 584 return True
683 585
684 586 return False
685 587
686 588 def getFlagDc(self):
687 589
688 590 if self.data_dc is None:
689 591 return True
690 592
691 593 return False
692 594
693 595 def getTimeInterval(self):
694 596
695 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
597 timeInterval = self.ippSeconds * self.nCohInt * \
598 self.nIncohInt * self.nProfiles * self.ippFactor
696 599
697 600 return timeInterval
698 601
699 602 def getPower(self):
700 603
701 604 factor = self.normFactor
702 605 z = self.data_spc / factor
703 606 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
704 607 avg = numpy.average(z, axis=1)
705 608
706 609 return 10 * numpy.log10(avg)
707 610
708 611 def getCoherence(self, pairsList=None, phase=False):
709 612
710 613 z = []
711 614 if pairsList is None:
712 615 pairsIndexList = self.pairsIndexList
713 616 else:
714 617 pairsIndexList = []
715 618 for pair in pairsList:
716 619 if pair not in self.pairsList:
717 620 raise ValueError("Pair %s is not in dataOut.pairsList" % (
718 621 pair))
719 622 pairsIndexList.append(self.pairsList.index(pair))
720 623 for i in range(len(pairsIndexList)):
721 624 pair = self.pairsList[pairsIndexList[i]]
722 625 ccf = numpy.average(
723 626 self.data_cspc[pairsIndexList[i], :, :], axis=0)
724 627 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
725 628 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
726 629 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
727 630 if phase:
728 631 data = numpy.arctan2(avgcoherenceComplex.imag,
729 632 avgcoherenceComplex.real) * 180 / numpy.pi
730 633 else:
731 634 data = numpy.abs(avgcoherenceComplex)
732 635
733 636 z.append(data)
734 637
735 638 return numpy.array(z)
736 639
737 640 def setValue(self, value):
738 641
739 642 print("This property should not be initialized")
740 643
741 644 return
742 645
743 646 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
744 647 pairsIndexList = property(
745 648 getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
746 649 normFactor = property(getNormFactor, setValue,
747 650 "I'm the 'getNormFactor' property.")
748 651 flag_cspc = property(getFlagCspc, setValue)
749 652 flag_dc = property(getFlagDc, setValue)
750 653 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
751 654 timeInterval = property(getTimeInterval, setValue,
752 655 "I'm the 'timeInterval' property")
753 656
754 657
755 658 class SpectraHeis(Spectra):
756 659
757 660 data_spc = None
758
759 661 data_cspc = None
760
761 662 data_dc = None
762
763 663 nFFTPoints = None
764
765 664 # nPairs = None
766
767 665 pairsList = None
768
769 666 nCohInt = None
770
771 667 nIncohInt = None
772 668
773 669 def __init__(self):
774 670
775 671 self.radarControllerHeaderObj = RadarControllerHeader()
776 672
777 673 self.systemHeaderObj = SystemHeader()
778 674
779 675 self.type = "SpectraHeis"
780 676
781 677 # self.dtype = None
782 678
783 679 # self.nChannels = 0
784 680
785 681 # self.nHeights = 0
786 682
787 683 self.nProfiles = None
788 684
789 685 self.heightList = None
790 686
791 687 self.channelList = None
792 688
793 689 # self.channelIndexList = None
794 690
795 691 self.flagNoData = True
796 692
797 693 self.flagDiscontinuousBlock = False
798 694
799 695 # self.nPairs = 0
800 696
801 697 self.utctime = None
802 698
803 699 self.blocksize = None
804 700
805 701 self.profileIndex = 0
806 702
807 703 self.nCohInt = 1
808 704
809 705 self.nIncohInt = 1
810 706
811 707 def getNormFactor(self):
812 708 pwcode = 1
813 709 if self.flagDecodeData:
814 710 pwcode = numpy.sum(self.code[0]**2)
815 711
816 712 normFactor = self.nIncohInt * self.nCohInt * pwcode
817 713
818 714 return normFactor
819 715
820 716 def getTimeInterval(self):
821 717
822 718 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
823 719
824 720 return timeInterval
825 721
826 722 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
827 723 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
828 724
829 725
830 726 class Fits(JROData):
831 727
832 728 heightList = None
833
834 729 channelList = None
835
836 730 flagNoData = True
837
838 731 flagDiscontinuousBlock = False
839
840 732 useLocalTime = False
841
842 733 utctime = None
843
844 734 timeZone = None
845
846 735 # ippSeconds = None
847
848 736 # timeInterval = None
849
850 737 nCohInt = None
851
852 738 nIncohInt = None
853
854 739 noise = None
855
856 740 windowOfFilter = 1
857
858 741 # Speed of ligth
859 742 C = 3e8
860
861 743 frequency = 49.92e6
862
863 744 realtime = False
864 745
865 746 def __init__(self):
866 747
867 748 self.type = "Fits"
868 749
869 750 self.nProfiles = None
870 751
871 752 self.heightList = None
872 753
873 754 self.channelList = None
874 755
875 756 # self.channelIndexList = None
876 757
877 758 self.flagNoData = True
878 759
879 760 self.utctime = None
880 761
881 762 self.nCohInt = 1
882 763
883 764 self.nIncohInt = 1
884 765
885 766 self.useLocalTime = True
886 767
887 768 self.profileIndex = 0
888 769
889 770 # self.utctime = None
890 771 # self.timeZone = None
891 772 # self.ltctime = None
892 773 # self.timeInterval = None
893 774 # self.header = None
894 775 # self.data_header = None
895 776 # self.data = None
896 777 # self.datatime = None
897 778 # self.flagNoData = False
898 779 # self.expName = ''
899 780 # self.nChannels = None
900 781 # self.nSamples = None
901 782 # self.dataBlocksPerFile = None
902 783 # self.comments = ''
903 784 #
904 785
905 786 def getltctime(self):
906 787
907 788 if self.useLocalTime:
908 789 return self.utctime - self.timeZone * 60
909 790
910 791 return self.utctime
911 792
912 793 def getDatatime(self):
913 794
914 795 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
915 796 return datatime
916 797
917 798 def getTimeRange(self):
918 799
919 800 datatime = []
920 801
921 802 datatime.append(self.ltctime)
922 803 datatime.append(self.ltctime + self.timeInterval)
923 804
924 805 datatime = numpy.array(datatime)
925 806
926 807 return datatime
927 808
928 809 def getHeiRange(self):
929 810
930 811 heis = self.heightList
931 812
932 813 return heis
933 814
934 815 def getNHeights(self):
935 816
936 817 return len(self.heightList)
937 818
938 819 def getNChannels(self):
939 820
940 821 return len(self.channelList)
941 822
942 823 def getChannelIndexList(self):
943 824
944 825 return list(range(self.nChannels))
945 826
946 827 def getNoise(self, type=1):
947 828
948 829 #noise = numpy.zeros(self.nChannels)
949 830
950 831 if type == 1:
951 832 noise = self.getNoisebyHildebrand()
952 833
953 834 if type == 2:
954 835 noise = self.getNoisebySort()
955 836
956 837 if type == 3:
957 838 noise = self.getNoisebyWindow()
958 839
959 840 return noise
960 841
961 842 def getTimeInterval(self):
962 843
963 844 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
964 845
965 846 return timeInterval
966 847
967 848 datatime = property(getDatatime, "I'm the 'datatime' property")
968 849 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
969 850 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
970 851 channelIndexList = property(
971 852 getChannelIndexList, "I'm the 'channelIndexList' property.")
972 853 noise = property(getNoise, "I'm the 'nHeights' property.")
973 854
974 855 ltctime = property(getltctime, "I'm the 'ltctime' property")
975 856 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
976 857
977 858
978 859 class Correlation(JROData):
979 860
980 861 noise = None
981
982 862 SNR = None
983
984 863 #--------------------------------------------------
985
986 864 mode = None
987
988 865 split = False
989
990 866 data_cf = None
991
992 867 lags = None
993
994 868 lagRange = None
995
996 869 pairsList = None
997
998 870 normFactor = None
999
1000 871 #--------------------------------------------------
1001
1002 872 # calculateVelocity = None
1003
1004 873 nLags = None
1005
1006 874 nPairs = None
1007
1008 875 nAvg = None
1009 876
1010 877 def __init__(self):
1011 878 '''
1012 879 Constructor
1013 880 '''
1014 881 self.radarControllerHeaderObj = RadarControllerHeader()
1015 882
1016 883 self.systemHeaderObj = SystemHeader()
1017 884
1018 885 self.type = "Correlation"
1019 886
1020 887 self.data = None
1021 888
1022 889 self.dtype = None
1023 890
1024 891 self.nProfiles = None
1025 892
1026 893 self.heightList = None
1027 894
1028 895 self.channelList = None
1029 896
1030 897 self.flagNoData = True
1031 898
1032 899 self.flagDiscontinuousBlock = False
1033 900
1034 901 self.utctime = None
1035 902
1036 903 self.timeZone = None
1037 904
1038 905 self.dstFlag = None
1039 906
1040 907 self.errorCount = None
1041 908
1042 909 self.blocksize = None
1043 910
1044 911 self.flagDecodeData = False # asumo q la data no esta decodificada
1045 912
1046 913 self.flagDeflipData = False # asumo q la data no esta sin flip
1047 914
1048 915 self.pairsList = None
1049 916
1050 917 self.nPoints = None
1051 918
1052 919 def getPairsList(self):
1053 920
1054 921 return self.pairsList
1055 922
1056 923 def getNoise(self, mode=2):
1057 924
1058 925 indR = numpy.where(self.lagR == 0)[0][0]
1059 926 indT = numpy.where(self.lagT == 0)[0][0]
1060 927
1061 928 jspectra0 = self.data_corr[:, :, indR, :]
1062 929 jspectra = copy.copy(jspectra0)
1063 930
1064 931 num_chan = jspectra.shape[0]
1065 932 num_hei = jspectra.shape[2]
1066 933
1067 934 freq_dc = jspectra.shape[1] / 2
1068 935 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
1069 936
1070 937 if ind_vel[0] < 0:
1071 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
938 ind_vel[list(range(0, 1))] = ind_vel[list(
939 range(0, 1))] + self.num_prof
1072 940
1073 941 if mode == 1:
1074 942 jspectra[:, freq_dc, :] = (
1075 943 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
1076 944
1077 945 if mode == 2:
1078 946
1079 947 vel = numpy.array([-2, -1, 1, 2])
1080 948 xx = numpy.zeros([4, 4])
1081 949
1082 950 for fil in range(4):
1083 951 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
1084 952
1085 953 xx_inv = numpy.linalg.inv(xx)
1086 954 xx_aux = xx_inv[0, :]
1087 955
1088 956 for ich in range(num_chan):
1089 957 yy = jspectra[ich, ind_vel, :]
1090 958 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
1091 959
1092 960 junkid = jspectra[ich, freq_dc, :] <= 0
1093 961 cjunkid = sum(junkid)
1094 962
1095 963 if cjunkid.any():
1096 964 jspectra[ich, freq_dc, junkid.nonzero()] = (
1097 965 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
1098 966
1099 967 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
1100 968
1101 969 return noise
1102 970
1103 971 def getTimeInterval(self):
1104 972
1105 973 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
1106 974
1107 975 return timeInterval
1108 976
1109 977 def splitFunctions(self):
1110 978
1111 979 pairsList = self.pairsList
1112 980 ccf_pairs = []
1113 981 acf_pairs = []
1114 982 ccf_ind = []
1115 983 acf_ind = []
1116 984 for l in range(len(pairsList)):
1117 985 chan0 = pairsList[l][0]
1118 986 chan1 = pairsList[l][1]
1119 987
1120 988 # Obteniendo pares de Autocorrelacion
1121 989 if chan0 == chan1:
1122 990 acf_pairs.append(chan0)
1123 991 acf_ind.append(l)
1124 992 else:
1125 993 ccf_pairs.append(pairsList[l])
1126 994 ccf_ind.append(l)
1127 995
1128 996 data_acf = self.data_cf[acf_ind]
1129 997 data_ccf = self.data_cf[ccf_ind]
1130 998
1131 999 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1132 1000
1133 1001 def getNormFactor(self):
1134 1002 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1135 1003 acf_pairs = numpy.array(acf_pairs)
1136 1004 normFactor = numpy.zeros((self.nPairs, self.nHeights))
1137 1005
1138 1006 for p in range(self.nPairs):
1139 1007 pair = self.pairsList[p]
1140 1008
1141 1009 ch0 = pair[0]
1142 1010 ch1 = pair[1]
1143 1011
1144 1012 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
1145 1013 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
1146 1014 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
1147 1015
1148 1016 return normFactor
1149 1017
1150 1018 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1151 1019 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1152 1020
1153 1021
1154 1022 class Parameters(Spectra):
1155 1023
1156 1024 experimentInfo = None # Information about the experiment
1157
1158 1025 # Information from previous data
1159
1160 1026 inputUnit = None # Type of data to be processed
1161
1162 1027 operation = None # Type of operation to parametrize
1163
1164 1028 # normFactor = None #Normalization Factor
1165
1166 1029 groupList = None # List of Pairs, Groups, etc
1167
1168 1030 # Parameters
1169
1170 1031 data_param = None # Parameters obtained
1171
1172 1032 data_pre = None # Data Pre Parametrization
1173
1174 1033 data_SNR = None # Signal to Noise Ratio
1175
1176 1034 # heightRange = None #Heights
1177
1178 1035 abscissaList = None # Abscissa, can be velocities, lags or time
1179
1180 1036 # noise = None #Noise Potency
1181
1182 1037 utctimeInit = None # Initial UTC time
1183
1184 1038 paramInterval = None # Time interval to calculate Parameters in seconds
1185
1186 1039 useLocalTime = True
1187
1188 1040 # Fitting
1189
1190 1041 data_error = None # Error of the estimation
1191
1192 1042 constants = None
1193
1194 1043 library = None
1195
1196 1044 # Output signal
1197
1198 1045 outputInterval = None # Time interval to calculate output signal in seconds
1199
1200 1046 data_output = None # Out signal
1201
1202 1047 nAvg = None
1203
1204 1048 noise_estimation = None
1205
1206 1049 GauSPC = None # Fit gaussian SPC
1207 1050
1208 1051 def __init__(self):
1209 1052 '''
1210 1053 Constructor
1211 1054 '''
1212 1055 self.radarControllerHeaderObj = RadarControllerHeader()
1213 1056
1214 1057 self.systemHeaderObj = SystemHeader()
1215 1058
1216 1059 self.type = "Parameters"
1217 1060
1218 1061 def getTimeRange1(self, interval):
1219 1062
1220 1063 datatime = []
1221 1064
1222 1065 if self.useLocalTime:
1223 1066 time1 = self.utctimeInit - self.timeZone * 60
1224 1067 else:
1225 1068 time1 = self.utctimeInit
1226 1069
1227 1070 datatime.append(time1)
1228 1071 datatime.append(time1 + interval)
1229 1072 datatime = numpy.array(datatime)
1230 1073
1231 1074 return datatime
1232 1075
1233 1076 def getTimeInterval(self):
1234 1077
1235 1078 if hasattr(self, 'timeInterval1'):
1236 1079 return self.timeInterval1
1237 1080 else:
1238 1081 return self.paramInterval
1239 1082
1240 1083 def setValue(self, value):
1241 1084
1242 1085 print("This property should not be initialized")
1243 1086
1244 1087 return
1245 1088
1246 1089 def getNoise(self):
1247 1090
1248 1091 return self.spc_noise
1249 1092
1250 1093 timeInterval = property(getTimeInterval)
1251 noise = property(getNoise, setValue, "I'm the 'Noise' property.") No newline at end of file
1094 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
1095
1096
1097 class PlotterData(object):
1098 '''
1099 Object to hold data to be plotted
1100 '''
1101
1102 MAXNUMX = 100
1103 MAXNUMY = 100
1104
1105 def __init__(self, code, throttle_value, exp_code, buffering=True):
1106
1107 self.throttle = throttle_value
1108 self.exp_code = exp_code
1109 self.buffering = buffering
1110 self.ready = False
1111 self.localtime = False
1112 self.data = {}
1113 self.meta = {}
1114 self.__times = []
1115 self.__heights = []
1116
1117 if 'snr' in code:
1118 self.plottypes = ['snr']
1119 elif code == 'spc':
1120 self.plottypes = ['spc', 'noise', 'rti']
1121 elif code == 'rti':
1122 self.plottypes = ['noise', 'rti']
1123 else:
1124 self.plottypes = [code]
1125
1126 for plot in self.plottypes:
1127 self.data[plot] = {}
1128
1129 def __str__(self):
1130 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1131 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
1132
1133 def __len__(self):
1134 return len(self.__times)
1135
1136 def __getitem__(self, key):
1137
1138 if key not in self.data:
1139 raise KeyError(log.error('Missing key: {}'.format(key)))
1140 if 'spc' in key or not self.buffering:
1141 ret = self.data[key]
1142 else:
1143 ret = numpy.array([self.data[key][x] for x in self.times])
1144 if ret.ndim > 1:
1145 ret = numpy.swapaxes(ret, 0, 1)
1146 return ret
1147
1148 def __contains__(self, key):
1149 return key in self.data
1150
1151 def setup(self):
1152 '''
1153 Configure object
1154 '''
1155
1156 self.type = ''
1157 self.ready = False
1158 self.data = {}
1159 self.__times = []
1160 self.__heights = []
1161 self.__all_heights = set()
1162 for plot in self.plottypes:
1163 if 'snr' in plot:
1164 plot = 'snr'
1165 self.data[plot] = {}
1166
1167 if 'spc' in self.data or 'rti' in self.data:
1168 self.data['noise'] = {}
1169 if 'noise' not in self.plottypes:
1170 self.plottypes.append('noise')
1171
1172 def shape(self, key):
1173 '''
1174 Get the shape of the one-element data for the given key
1175 '''
1176
1177 if len(self.data[key]):
1178 if 'spc' in key or not self.buffering:
1179 return self.data[key].shape
1180 return self.data[key][self.__times[0]].shape
1181 return (0,)
1182
1183 def update(self, dataOut, tm):
1184 '''
1185 Update data object with new dataOut
1186 '''
1187
1188 if tm in self.__times:
1189 return
1190
1191 self.type = dataOut.type
1192 self.parameters = getattr(dataOut, 'parameters', [])
1193 if hasattr(dataOut, 'pairsList'):
1194 self.pairs = dataOut.pairsList
1195 if hasattr(dataOut, 'meta'):
1196 self.meta = dataOut.meta
1197 self.channels = dataOut.channelList
1198 self.interval = dataOut.getTimeInterval()
1199 self.localtime = dataOut.useLocalTime
1200 if 'spc' in self.plottypes or 'cspc' in self.plottypes:
1201 self.xrange = (dataOut.getFreqRange(1)/1000.,
1202 dataOut.getAcfRange(1), dataOut.getVelRange(1))
1203 self.__heights.append(dataOut.heightList)
1204 self.__all_heights.update(dataOut.heightList)
1205 self.__times.append(tm)
1206
1207 for plot in self.plottypes:
1208 if plot == 'spc':
1209 z = dataOut.data_spc/dataOut.normFactor
1210 buffer = 10*numpy.log10(z)
1211 if plot == 'cspc':
1212 buffer = dataOut.data_cspc
1213 if plot == 'noise':
1214 buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
1215 if plot == 'rti':
1216 buffer = dataOut.getPower()
1217 if plot == 'snr_db':
1218 buffer = dataOut.data_SNR
1219 if plot == 'snr':
1220 buffer = 10*numpy.log10(dataOut.data_SNR)
1221 if plot == 'dop':
1222 buffer = 10*numpy.log10(dataOut.data_DOP)
1223 if plot == 'mean':
1224 buffer = dataOut.data_MEAN
1225 if plot == 'std':
1226 buffer = dataOut.data_STD
1227 if plot == 'coh':
1228 buffer = dataOut.getCoherence()
1229 if plot == 'phase':
1230 buffer = dataOut.getCoherence(phase=True)
1231 if plot == 'output':
1232 buffer = dataOut.data_output
1233 if plot == 'param':
1234 buffer = dataOut.data_param
1235
1236 if 'spc' in plot:
1237 self.data[plot] = buffer
1238 else:
1239 if self.buffering:
1240 self.data[plot][tm] = buffer
1241 else:
1242 self.data[plot] = buffer
1243
1244 def normalize_heights(self):
1245 '''
1246 Ensure same-dimension of the data for different heighList
1247 '''
1248
1249 H = numpy.array(list(self.__all_heights))
1250 H.sort()
1251 for key in self.data:
1252 shape = self.shape(key)[:-1] + H.shape
1253 for tm, obj in list(self.data[key].items()):
1254 h = self.__heights[self.__times.index(tm)]
1255 if H.size == h.size:
1256 continue
1257 index = numpy.where(numpy.in1d(H, h))[0]
1258 dummy = numpy.zeros(shape) + numpy.nan
1259 if len(shape) == 2:
1260 dummy[:, index] = obj
1261 else:
1262 dummy[index] = obj
1263 self.data[key][tm] = dummy
1264
1265 self.__heights = [H for tm in self.__times]
1266
1267 def jsonify(self, decimate=False):
1268 '''
1269 Convert data to json
1270 '''
1271
1272 data = {}
1273 tm = self.times[-1]
1274 dy = int(self.heights.size/self.MAXNUMY) + 1
1275 for key in self.data:
1276 if key in ('spc', 'cspc') or not self.buffering:
1277 dx = int(self.data[key].shape[1]/self.MAXNUMX) + 1
1278 data[key] = self.roundFloats(
1279 self.data[key][::, ::dx, ::dy].tolist())
1280 else:
1281 data[key] = self.roundFloats(self.data[key][tm].tolist())
1282
1283 ret = {'data': data}
1284 ret['exp_code'] = self.exp_code
1285 ret['time'] = float(tm)
1286 ret['interval'] = float(self.interval)
1287 ret['localtime'] = self.localtime
1288 ret['yrange'] = self.roundFloats(self.heights[::dy].tolist())
1289 if 'spc' in self.data or 'cspc' in self.data:
1290 ret['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1291 else:
1292 ret['xrange'] = []
1293 if hasattr(self, 'pairs'):
1294 ret['pairs'] = [(int(p[0]), int(p[1])) for p in self.pairs]
1295 else:
1296 ret['pairs'] = []
1297
1298 for key, value in list(self.meta.items()):
1299 ret[key] = value
1300
1301 return json.dumps(ret)
1302
1303 @property
1304 def times(self):
1305 '''
1306 Return the list of times of the current data
1307 '''
1308
1309 ret = numpy.array(self.__times)
1310 ret.sort()
1311 return ret
1312
1313 @property
1314 def min_time(self):
1315 '''
1316 Return the minimun time value
1317 '''
1318
1319 return self.times[0]
1320
1321 @property
1322 def max_time(self):
1323 '''
1324 Return the maximun time value
1325 '''
1326
1327 return self.times[-1]
1328
1329 @property
1330 def heights(self):
1331 '''
1332 Return the list of heights of the current data
1333 '''
1334
1335 return numpy.array(self.__heights[-1])
1336
1337 @staticmethod
1338 def roundFloats(obj):
1339 if isinstance(obj, list):
1340 return list(map(PlotterData.roundFloats, obj))
1341 elif isinstance(obj, float):
1342 return round(obj, 2)
@@ -1,7 +1,6
1 1 from .jroplot_voltage import *
2 2 from .jroplot_spectra import *
3 3 from .jroplot_heispectra import *
4 4 from .jroplot_correlation import *
5 5 from .jroplot_parameters import *
6 6 from .jroplot_data import *
7 from .jroplotter import *
@@ -1,187 +1,187
1 1 import os
2 2 import datetime
3 3 import numpy
4 4 import copy
5 5 from schainpy.model import *
6 6 from .figure import Figure, isRealtime
7 7
8 class CorrelationPlot(Figure):
8 class CorrelationPlot_(Figure):
9 9 isConfig = None
10 10 __nsubplots = None
11 11
12 12 WIDTHPROF = None
13 13 HEIGHTPROF = None
14 14 PREFIX = 'corr'
15 15
16 16 def __init__(self, **kwargs):
17 17 Figure.__init__(self, **kwargs)
18 18 self.isConfig = False
19 19 self.__nsubplots = 1
20 20
21 21 self.WIDTH = 280
22 22 self.HEIGHT = 250
23 23 self.WIDTHPROF = 120
24 24 self.HEIGHTPROF = 0
25 25 self.counter_imagwr = 0
26 26
27 27 self.PLOT_CODE = 1
28 28 self.FTP_WEI = None
29 29 self.EXP_CODE = None
30 30 self.SUB_EXP_CODE = None
31 31 self.PLOT_POS = None
32 32
33 33 def getSubplots(self):
34 34
35 35 ncol = int(numpy.sqrt(self.nplots)+0.9)
36 36 nrow = int(self.nplots*1./ncol + 0.9)
37 37
38 38 return nrow, ncol
39 39
40 40 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
41 41
42 42 showprofile = False
43 43 self.__showprofile = showprofile
44 44 self.nplots = nplots
45 45
46 46 ncolspan = 1
47 47 colspan = 1
48 48 if showprofile:
49 49 ncolspan = 3
50 50 colspan = 2
51 51 self.__nsubplots = 2
52 52
53 53 self.createFigure(id = id,
54 54 wintitle = wintitle,
55 55 widthplot = self.WIDTH + self.WIDTHPROF,
56 56 heightplot = self.HEIGHT + self.HEIGHTPROF,
57 57 show=show)
58 58
59 59 nrow, ncol = self.getSubplots()
60 60
61 61 counter = 0
62 62 for y in range(nrow):
63 63 for x in range(ncol):
64 64
65 65 if counter >= self.nplots:
66 66 break
67 67
68 68 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
69 69
70 70 if showprofile:
71 71 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
72 72
73 73 counter += 1
74 74
75 75 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
76 76 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
77 77 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
78 78 server=None, folder=None, username=None, password=None,
79 79 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
80 80
81 81 """
82 82
83 83 Input:
84 84 dataOut :
85 85 id :
86 86 wintitle :
87 87 channelList :
88 88 showProfile :
89 89 xmin : None,
90 90 xmax : None,
91 91 ymin : None,
92 92 ymax : None,
93 93 zmin : None,
94 94 zmax : None
95 95 """
96 96
97 97 if dataOut.flagNoData:
98 98 return None
99 99
100 100 if realtime:
101 101 if not(isRealtime(utcdatatime = dataOut.utctime)):
102 102 print('Skipping this plot function')
103 103 return
104 104
105 105 if channelList == None:
106 106 channelIndexList = dataOut.channelIndexList
107 107 else:
108 108 channelIndexList = []
109 109 for channel in channelList:
110 110 if channel not in dataOut.channelList:
111 111 raise ValueError("Channel %d is not in dataOut.channelList")
112 112 channelIndexList.append(dataOut.channelList.index(channel))
113 113
114 114 factor = dataOut.normFactor
115 115 lenfactor = factor.shape[1]
116 116 x = dataOut.getLagTRange(1)
117 117 y = dataOut.getHeiRange()
118 118
119 119 z = copy.copy(dataOut.data_corr[:,:,0,:])
120 120 for i in range(dataOut.data_corr.shape[0]):
121 121 z[i,:,:] = z[i,:,:]/factor[i,:]
122 122 zdB = numpy.abs(z)
123 123
124 124 avg = numpy.average(z, axis=1)
125 125 # avg = numpy.nanmean(z, axis=1)
126 126 # noise = dataOut.noise/factor
127 127
128 128 #thisDatetime = dataOut.datatime
129 129 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
130 130 title = wintitle + " Correlation"
131 131 xlabel = "Lag T (s)"
132 132 ylabel = "Range (Km)"
133 133
134 134 if not self.isConfig:
135 135
136 136 nplots = dataOut.data_corr.shape[0]
137 137
138 138 self.setup(id=id,
139 139 nplots=nplots,
140 140 wintitle=wintitle,
141 141 showprofile=showprofile,
142 142 show=show)
143 143
144 144 if xmin == None: xmin = numpy.nanmin(x)
145 145 if xmax == None: xmax = numpy.nanmax(x)
146 146 if ymin == None: ymin = numpy.nanmin(y)
147 147 if ymax == None: ymax = numpy.nanmax(y)
148 148 if zmin == None: zmin = 0
149 149 if zmax == None: zmax = 1
150 150
151 151 self.FTP_WEI = ftp_wei
152 152 self.EXP_CODE = exp_code
153 153 self.SUB_EXP_CODE = sub_exp_code
154 154 self.PLOT_POS = plot_pos
155 155
156 156 self.isConfig = True
157 157
158 158 self.setWinTitle(title)
159 159
160 160 for i in range(self.nplots):
161 161 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
162 162 title = "Channel %d and %d: : %s" %(dataOut.pairsList[i][0],dataOut.pairsList[i][1] , str_datetime)
163 163 axes = self.axesList[i*self.__nsubplots]
164 164 axes.pcolor(x, y, zdB[i,:,:],
165 165 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
166 166 xlabel=xlabel, ylabel=ylabel, title=title,
167 167 ticksize=9, cblabel='')
168 168
169 169 # if self.__showprofile:
170 170 # axes = self.axesList[i*self.__nsubplots +1]
171 171 # axes.pline(avgdB[i], y,
172 172 # xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
173 173 # xlabel='dB', ylabel='', title='',
174 174 # ytick_visible=False,
175 175 # grid='x')
176 176 #
177 177 # noiseline = numpy.repeat(noisedB[i], len(y))
178 178 # axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
179 179
180 180 self.draw()
181 181
182 182 self.save(figpath=figpath,
183 183 figfile=figfile,
184 184 save=save,
185 185 ftp=ftp,
186 186 wr_period=wr_period,
187 187 thisDatetime=thisDatetime) No newline at end of file
This diff has been collapsed as it changes many lines, (685 lines changed) Show them Hide them
@@ -1,1154 +1,613
1 '''
2 New Plots Operations
3
4 @author: juan.espinoza@jro.igp.gob.pe
5 '''
6
1 7
2 import os
3 8 import time
4 import glob
5 9 import datetime
6 from multiprocessing import Process
7
8 import zmq
9 10 import numpy
10 import matplotlib
11 import matplotlib.pyplot as plt
12 from matplotlib.patches import Polygon
13 from mpl_toolkits.axes_grid1 import make_axes_locatable
14 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
15 11
16 from schainpy.model.proc.jroproc_base import Operation
12 from schainpy.model.graphics.jroplot_base import Plot, plt
17 13 from schainpy.utils import log
18 14
19 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
20 blu_values = matplotlib.pyplot.get_cmap(
21 'seismic_r', 20)(numpy.arange(20))[10:15]
22 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
23 'jro', numpy.vstack((blu_values, jet_values)))
24 matplotlib.pyplot.register_cmap(cmap=ncmap)
25
26 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis', 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
27
28 15 EARTH_RADIUS = 6.3710e3
29 16
17
30 18 def ll2xy(lat1, lon1, lat2, lon2):
31 19
32 20 p = 0.017453292519943295
33 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
21 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
22 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
34 23 r = 12742 * numpy.arcsin(numpy.sqrt(a))
35 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)*numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
24 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
25 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
36 26 theta = -theta + numpy.pi/2
37 27 return r*numpy.cos(theta), r*numpy.sin(theta)
38 28
29
39 30 def km2deg(km):
40 31 '''
41 32 Convert distance in km to degrees
42 33 '''
43 34
44 35 return numpy.rad2deg(km/EARTH_RADIUS)
45 36
46 def figpause(interval):
47 backend = plt.rcParams['backend']
48 if backend in matplotlib.rcsetup.interactive_bk:
49 figManager = matplotlib._pylab_helpers.Gcf.get_active()
50 if figManager is not None:
51 canvas = figManager.canvas
52 if canvas.figure.stale:
53 canvas.draw()
54 try:
55 canvas.start_event_loop(interval)
56 except:
57 pass
58 return
59
60 def popup(message):
61 '''
62 '''
63
64 fig = plt.figure(figsize=(12, 8), facecolor='r')
65 text = '\n'.join([s.strip() for s in message.split(':')])
66 fig.text(0.01, 0.5, text, ha='left', va='center', size='20', weight='heavy', color='w')
67 fig.show()
68 figpause(1000)
69
70
71 class PlotData(Operation, Process):
72 '''
73 Base class for Schain plotting operations
74 '''
75
76 CODE = 'Figure'
77 colormap = 'jro'
78 bgcolor = 'white'
79 CONFLATE = False
80 __missing = 1E30
81
82 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
83 'zlimits', 'xlabel', 'ylabel', 'xaxis','cb_label', 'title',
84 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
85 'showprofile', 'decimation', 'ftp']
86
87 def __init__(self, **kwargs):
88
89 Operation.__init__(self, plot=True, **kwargs)
90 Process.__init__(self)
91
92 self.kwargs['code'] = self.CODE
93 self.mp = False
94 self.data = None
95 self.isConfig = False
96 self.figures = []
97 self.axes = []
98 self.cb_axes = []
99 self.localtime = kwargs.pop('localtime', True)
100 self.show = kwargs.get('show', True)
101 self.save = kwargs.get('save', False)
102 self.ftp = kwargs.get('ftp', False)
103 self.colormap = kwargs.get('colormap', self.colormap)
104 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
105 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
106 self.colormaps = kwargs.get('colormaps', None)
107 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
108 self.showprofile = kwargs.get('showprofile', False)
109 self.title = kwargs.get('wintitle', self.CODE.upper())
110 self.cb_label = kwargs.get('cb_label', None)
111 self.cb_labels = kwargs.get('cb_labels', None)
112 self.labels = kwargs.get('labels', None)
113 self.xaxis = kwargs.get('xaxis', 'frequency')
114 self.zmin = kwargs.get('zmin', None)
115 self.zmax = kwargs.get('zmax', None)
116 self.zlimits = kwargs.get('zlimits', None)
117 self.xmin = kwargs.get('xmin', None)
118 self.xmax = kwargs.get('xmax', None)
119 self.xrange = kwargs.get('xrange', 24)
120 self.xscale = kwargs.get('xscale', None)
121 self.ymin = kwargs.get('ymin', None)
122 self.ymax = kwargs.get('ymax', None)
123 self.yscale = kwargs.get('yscale', None)
124 self.xlabel = kwargs.get('xlabel', None)
125 self.decimation = kwargs.get('decimation', None)
126 self.showSNR = kwargs.get('showSNR', False)
127 self.oneFigure = kwargs.get('oneFigure', True)
128 self.width = kwargs.get('width', None)
129 self.height = kwargs.get('height', None)
130 self.colorbar = kwargs.get('colorbar', True)
131 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
132 self.channels = kwargs.get('channels', None)
133 self.titles = kwargs.get('titles', [])
134 self.polar = False
135 self.grid = kwargs.get('grid', False)
136
137 def __fmtTime(self, x, pos):
138 '''
139 '''
140
141 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
142
143 def __setup(self):
144 '''
145 Common setup for all figures, here figures and axes are created
146 '''
147
148 if self.CODE not in self.data:
149 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
150 self.name))
151
152 self.setup()
153
154 self.time_label = 'LT' if self.localtime else 'UTC'
155 if self.data.localtime:
156 self.getDateTime = datetime.datetime.fromtimestamp
157 else:
158 self.getDateTime = datetime.datetime.utcfromtimestamp
159
160 if self.width is None:
161 self.width = 8
162
163 self.figures = []
164 self.axes = []
165 self.cb_axes = []
166 self.pf_axes = []
167 self.cmaps = []
168
169 size = '15%' if self.ncols == 1 else '30%'
170 pad = '4%' if self.ncols == 1 else '8%'
171
172 if self.oneFigure:
173 if self.height is None:
174 self.height = 1.4 * self.nrows + 1
175 fig = plt.figure(figsize=(self.width, self.height),
176 edgecolor='k',
177 facecolor='w')
178 self.figures.append(fig)
179 for n in range(self.nplots):
180 ax = fig.add_subplot(self.nrows, self.ncols,
181 n + 1, polar=self.polar)
182 ax.tick_params(labelsize=8)
183 ax.firsttime = True
184 ax.index = 0
185 ax.press = None
186 self.axes.append(ax)
187 if self.showprofile:
188 cax = self.__add_axes(ax, size=size, pad=pad)
189 cax.tick_params(labelsize=8)
190 self.pf_axes.append(cax)
191 else:
192 if self.height is None:
193 self.height = 3
194 for n in range(self.nplots):
195 fig = plt.figure(figsize=(self.width, self.height),
196 edgecolor='k',
197 facecolor='w')
198 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
199 ax.tick_params(labelsize=8)
200 ax.firsttime = True
201 ax.index = 0
202 ax.press = None
203 self.figures.append(fig)
204 self.axes.append(ax)
205 if self.showprofile:
206 cax = self.__add_axes(ax, size=size, pad=pad)
207 cax.tick_params(labelsize=8)
208 self.pf_axes.append(cax)
209
210 for n in range(self.nrows):
211 if self.colormaps is not None:
212 cmap = plt.get_cmap(self.colormaps[n])
213 else:
214 cmap = plt.get_cmap(self.colormap)
215 cmap.set_bad(self.bgcolor, 1.)
216 self.cmaps.append(cmap)
217
218 for fig in self.figures:
219 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
220 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
221 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
222 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
223 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
224 if self.show:
225 fig.show()
226
227 def OnKeyPress(self, event):
228 '''
229 Event for pressing keys (up, down) change colormap
230 '''
231 ax = event.inaxes
232 if ax in self.axes:
233 if event.key == 'down':
234 ax.index += 1
235 elif event.key == 'up':
236 ax.index -= 1
237 if ax.index < 0:
238 ax.index = len(CMAPS) - 1
239 elif ax.index == len(CMAPS):
240 ax.index = 0
241 cmap = CMAPS[ax.index]
242 ax.cbar.set_cmap(cmap)
243 ax.cbar.draw_all()
244 ax.plt.set_cmap(cmap)
245 ax.cbar.patch.figure.canvas.draw()
246 self.colormap = cmap.name
247
248 def OnBtnScroll(self, event):
249 '''
250 Event for scrolling, scale figure
251 '''
252 cb_ax = event.inaxes
253 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
254 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
255 pt = ax.cbar.ax.bbox.get_points()[:, 1]
256 nrm = ax.cbar.norm
257 vmin, vmax, p0, p1, pS = (
258 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
259 scale = 2 if event.step == 1 else 0.5
260 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
261 ax.cbar.norm.vmin = point - scale * (point - vmin)
262 ax.cbar.norm.vmax = point - scale * (point - vmax)
263 ax.plt.set_norm(ax.cbar.norm)
264 ax.cbar.draw_all()
265 ax.cbar.patch.figure.canvas.draw()
266
267 def onBtnPress(self, event):
268 '''
269 Event for mouse button press
270 '''
271 cb_ax = event.inaxes
272 if cb_ax is None:
273 return
274
275 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
276 cb_ax.press = event.x, event.y
277 else:
278 cb_ax.press = None
279
280 def onMotion(self, event):
281 '''
282 Event for move inside colorbar
283 '''
284 cb_ax = event.inaxes
285 if cb_ax is None:
286 return
287 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
288 return
289 if cb_ax.press is None:
290 return
291
292 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
293 xprev, yprev = cb_ax.press
294 dx = event.x - xprev
295 dy = event.y - yprev
296 cb_ax.press = event.x, event.y
297 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
298 perc = 0.03
299
300 if event.button == 1:
301 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
302 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
303 elif event.button == 3:
304 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
305 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
306
307 ax.cbar.draw_all()
308 ax.plt.set_norm(ax.cbar.norm)
309 ax.cbar.patch.figure.canvas.draw()
310
311 def onBtnRelease(self, event):
312 '''
313 Event for mouse button release
314 '''
315 cb_ax = event.inaxes
316 if cb_ax is not None:
317 cb_ax.press = None
318
319 def __add_axes(self, ax, size='30%', pad='8%'):
320 '''
321 Add new axes to the given figure
322 '''
323 divider = make_axes_locatable(ax)
324 nax = divider.new_horizontal(size=size, pad=pad)
325 ax.figure.add_axes(nax)
326 return nax
327
328 self.setup()
329
330 def setup(self):
331 '''
332 This method should be implemented in the child class, the following
333 attributes should be set:
334
335 self.nrows: number of rows
336 self.ncols: number of cols
337 self.nplots: number of plots (channels or pairs)
338 self.ylabel: label for Y axes
339 self.titles: list of axes title
340
341 '''
342 raise NotImplementedError
343
344 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
345 '''
346 Create a masked array for missing data
347 '''
348 if x_buffer.shape[0] < 2:
349 return x_buffer, y_buffer, z_buffer
350
351 deltas = x_buffer[1:] - x_buffer[0:-1]
352 x_median = numpy.median(deltas)
353
354 index = numpy.where(deltas > 5 * x_median)
355
356 if len(index[0]) != 0:
357 z_buffer[::, index[0], ::] = self.__missing
358 z_buffer = numpy.ma.masked_inside(z_buffer,
359 0.99 * self.__missing,
360 1.01 * self.__missing)
361
362 return x_buffer, y_buffer, z_buffer
363
364 def decimate(self):
365
366 # dx = int(len(self.x)/self.__MAXNUMX) + 1
367 dy = int(len(self.y) / self.decimation) + 1
368
369 # x = self.x[::dx]
370 x = self.x
371 y = self.y[::dy]
372 z = self.z[::, ::, ::dy]
373
374 return x, y, z
375 37
376 def format(self):
377 '''
378 Set min and max values, labels, ticks and titles
379 '''
380
381 if self.xmin is None:
382 xmin = self.min_time
383 else:
384 if self.xaxis is 'time':
385 dt = self.getDateTime(self.min_time)
386 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
387 datetime.datetime(1970, 1, 1)).total_seconds()
388 if self.data.localtime:
389 xmin += time.timezone
390 else:
391 xmin = self.xmin
392
393 if self.xmax is None:
394 xmax = xmin + self.xrange * 60 * 60
395 else:
396 if self.xaxis is 'time':
397 dt = self.getDateTime(self.max_time)
398 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
399 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
400 if self.data.localtime:
401 xmax += time.timezone
402 else:
403 xmax = self.xmax
404
405 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
406 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
407
408 Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000])
409 i = 1 if numpy.where(abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
410 ystep = Y[i] / 10.
411
412 if self.xaxis is not 'time':
413 X = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000])/2.
414 i = 1 if numpy.where(abs(xmax-xmin) <= X)[0][0] < 0 else numpy.where(abs(xmax-xmin) <= X)[0][0]
415 xstep = X[i] / 10.
416
417 for n, ax in enumerate(self.axes):
418 if ax.firsttime:
419 ax.set_facecolor(self.bgcolor)
420 ax.yaxis.set_major_locator(MultipleLocator(ystep))
421 if self.xscale:
422 ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{0:g}'.format(x*self.xscale)))
423 if self.xscale:
424 ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{0:g}'.format(x*self.yscale)))
425 if self.xaxis is 'time':
426 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
427 ax.xaxis.set_major_locator(LinearLocator(9))
428 else:
429 ax.xaxis.set_major_locator(MultipleLocator(xstep))
430 if self.xlabel is not None:
431 ax.set_xlabel(self.xlabel)
432 ax.set_ylabel(self.ylabel)
433 ax.firsttime = False
434 if self.showprofile:
435 self.pf_axes[n].set_ylim(ymin, ymax)
436 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
437 self.pf_axes[n].set_xlabel('dB')
438 self.pf_axes[n].grid(b=True, axis='x')
439 [tick.set_visible(False)
440 for tick in self.pf_axes[n].get_yticklabels()]
441 if self.colorbar:
442 ax.cbar = plt.colorbar(
443 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
444 ax.cbar.ax.tick_params(labelsize=8)
445 ax.cbar.ax.press = None
446 if self.cb_label:
447 ax.cbar.set_label(self.cb_label, size=8)
448 elif self.cb_labels:
449 ax.cbar.set_label(self.cb_labels[n], size=8)
450 else:
451 ax.cbar = None
452 if self.grid:
453 ax.grid(True)
454
455 if not self.polar:
456 ax.set_xlim(xmin, xmax)
457 ax.set_ylim(ymin, ymax)
458 ax.set_title('{} {} {}'.format(
459 self.titles[n],
460 self.getDateTime(self.max_time).strftime('%Y-%m-%dT%H:%M:%S'),
461 self.time_label),
462 size=8)
463 else:
464 ax.set_title('{}'.format(self.titles[n]), size=8)
465 ax.set_ylim(0, 90)
466 ax.set_yticks(numpy.arange(0, 90, 20))
467 ax.yaxis.labelpad = 40
468
469 def __plot(self):
470 '''
471 '''
472 log.log('Plotting', self.name)
473
474 try:
475 self.plot()
476 self.format()
477 except Exception as e:
478 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
479 log.error(str(e), '')
480 return
481
482 for n, fig in enumerate(self.figures):
483 if self.nrows == 0 or self.nplots == 0:
484 log.warning('No data', self.name)
485 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
486 fig.canvas.manager.set_window_title(self.CODE)
487 continue
488
489 fig.tight_layout()
490 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
491 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
492 fig.canvas.draw()
493
494 if self.save and (self.data.ended or not self.data.buffering):
495
496 if self.save_labels:
497 labels = self.save_labels
498 else:
499 labels = list(range(self.nrows))
500
501 if self.oneFigure:
502 label = ''
503 else:
504 label = '-{}'.format(labels[n])
505 figname = os.path.join(
506 self.save,
507 self.CODE,
508 '{}{}_{}.png'.format(
509 self.CODE,
510 label,
511 self.getDateTime(self.saveTime).strftime(
512 '%Y%m%d_%H%M%S'),
513 )
514 )
515 log.log('Saving figure: {}'.format(figname), self.name)
516 if not os.path.isdir(os.path.dirname(figname)):
517 os.makedirs(os.path.dirname(figname))
518 fig.savefig(figname)
519
520 def plot(self):
521 '''
522 '''
523 raise NotImplementedError
524
525 def run(self):
526
527 log.log('Starting', self.name)
528
529 context = zmq.Context()
530 receiver = context.socket(zmq.SUB)
531 receiver.setsockopt(zmq.SUBSCRIBE, '')
532 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
533
534 if 'server' in self.kwargs['parent']:
535 receiver.connect(
536 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
537 else:
538 receiver.connect("ipc:///tmp/zmq.plots")
539
540 while True:
541 try:
542 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
543 if self.data.localtime and self.localtime:
544 self.times = self.data.times
545 elif self.data.localtime and not self.localtime:
546 self.times = self.data.times + time.timezone
547 elif not self.data.localtime and self.localtime:
548 self.times = self.data.times - time.timezone
549 else:
550 self.times = self.data.times
551
552 self.min_time = self.times[0]
553 self.max_time = self.times[-1]
554
555 if self.isConfig is False:
556 self.__setup()
557 self.isConfig = True
558
559 self.__plot()
560
561 except zmq.Again as e:
562 if self.data and self.data.ended:
563 break
564 log.log('Waiting for data...')
565 if self.data:
566 figpause(self.data.throttle)
567 else:
568 time.sleep(2)
569
570 def close(self):
571 if self.data:
572 self.__plot()
573
574
575 class PlotSpectraData(PlotData):
38 class SpectraPlot(Plot):
576 39 '''
577 40 Plot for Spectra data
578 41 '''
579 42
580 43 CODE = 'spc'
581 44 colormap = 'jro'
582 45
583 46 def setup(self):
584 47 self.nplots = len(self.data.channels)
585 48 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
586 49 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
587 50 self.width = 3.4 * self.ncols
588 51 self.height = 3 * self.nrows
589 52 self.cb_label = 'dB'
590 53 if self.showprofile:
591 54 self.width += 0.8 * self.ncols
592 55
593 56 self.ylabel = 'Range [km]'
594 57
595 58 def plot(self):
596 59 if self.xaxis == "frequency":
597 60 x = self.data.xrange[0]
598 61 self.xlabel = "Frequency (kHz)"
599 62 elif self.xaxis == "time":
600 63 x = self.data.xrange[1]
601 64 self.xlabel = "Time (ms)"
602 65 else:
603 66 x = self.data.xrange[2]
604 67 self.xlabel = "Velocity (m/s)"
605 68
606 69 if self.CODE == 'spc_mean':
607 70 x = self.data.xrange[2]
608 71 self.xlabel = "Velocity (m/s)"
609 72
610 73 self.titles = []
611 74
612 75 y = self.data.heights
613 76 self.y = y
614 77 z = self.data['spc']
615 78
616 79 for n, ax in enumerate(self.axes):
617 80 noise = self.data['noise'][n][-1]
618 81 if self.CODE == 'spc_mean':
619 82 mean = self.data['mean'][n][-1]
620 83 if ax.firsttime:
621 84 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
622 85 self.xmin = self.xmin if self.xmin else -self.xmax
623 86 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
624 87 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
625 88 ax.plt = ax.pcolormesh(x, y, z[n].T,
626 89 vmin=self.zmin,
627 90 vmax=self.zmax,
628 91 cmap=plt.get_cmap(self.colormap)
629 92 )
630 93
631 94 if self.showprofile:
632 95 ax.plt_profile = self.pf_axes[n].plot(
633 96 self.data['rti'][n][-1], y)[0]
634 97 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
635 98 color="k", linestyle="dashed", lw=1)[0]
636 99 if self.CODE == 'spc_mean':
637 100 ax.plt_mean = ax.plot(mean, y, color='k')[0]
638 101 else:
639 102 ax.plt.set_array(z[n].T.ravel())
640 103 if self.showprofile:
641 104 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
642 105 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
643 106 if self.CODE == 'spc_mean':
644 107 ax.plt_mean.set_data(mean, y)
645 108
646 109 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
647 self.saveTime = self.max_time
648 110
649 111
650 class PlotCrossSpectraData(PlotData):
112 class CrossSpectraPlot(Plot):
651 113
652 114 CODE = 'cspc'
653 115 zmin_coh = None
654 116 zmax_coh = None
655 117 zmin_phase = None
656 118 zmax_phase = None
657 119
658 120 def setup(self):
659 121
660 122 self.ncols = 4
661 123 self.nrows = len(self.data.pairs)
662 124 self.nplots = self.nrows * 4
663 125 self.width = 3.4 * self.ncols
664 126 self.height = 3 * self.nrows
665 127 self.ylabel = 'Range [km]'
666 128 self.showprofile = False
667 129
668 130 def plot(self):
669 131
670 132 if self.xaxis == "frequency":
671 133 x = self.data.xrange[0]
672 134 self.xlabel = "Frequency (kHz)"
673 135 elif self.xaxis == "time":
674 136 x = self.data.xrange[1]
675 137 self.xlabel = "Time (ms)"
676 138 else:
677 139 x = self.data.xrange[2]
678 140 self.xlabel = "Velocity (m/s)"
679 141
680 142 self.titles = []
681 143
682 144 y = self.data.heights
683 145 self.y = y
684 146 spc = self.data['spc']
685 147 cspc = self.data['cspc']
686 148
687 149 for n in range(self.nrows):
688 150 noise = self.data['noise'][n][-1]
689 151 pair = self.data.pairs[n]
690 152 ax = self.axes[4 * n]
691 153 ax3 = self.axes[4 * n + 3]
692 154 if ax.firsttime:
693 155 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
694 156 self.xmin = self.xmin if self.xmin else -self.xmax
695 157 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
696 158 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
697 159 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
698 160 vmin=self.zmin,
699 161 vmax=self.zmax,
700 162 cmap=plt.get_cmap(self.colormap)
701 163 )
702 164 else:
703 165 ax.plt.set_array(spc[pair[0]].T.ravel())
704 166 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
705 167
706 168 ax = self.axes[4 * n + 1]
707 169 if ax.firsttime:
708 170 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
709 171 vmin=self.zmin,
710 172 vmax=self.zmax,
711 173 cmap=plt.get_cmap(self.colormap)
712 174 )
713 175 else:
714 176 ax.plt.set_array(spc[pair[1]].T.ravel())
715 177 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
716 178
717 179 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
718 180 coh = numpy.abs(out)
719 181 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
720 182
721 183 ax = self.axes[4 * n + 2]
722 184 if ax.firsttime:
723 185 ax.plt = ax.pcolormesh(x, y, coh.T,
724 186 vmin=0,
725 187 vmax=1,
726 188 cmap=plt.get_cmap(self.colormap_coh)
727 189 )
728 190 else:
729 191 ax.plt.set_array(coh.T.ravel())
730 192 self.titles.append(
731 193 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
732 194
733 195 ax = self.axes[4 * n + 3]
734 196 if ax.firsttime:
735 197 ax.plt = ax.pcolormesh(x, y, phase.T,
736 198 vmin=-180,
737 199 vmax=180,
738 200 cmap=plt.get_cmap(self.colormap_phase)
739 201 )
740 202 else:
741 203 ax.plt.set_array(phase.T.ravel())
742 204 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
743 205
744 self.saveTime = self.max_time
745
746 206
747 class PlotSpectraMeanData(PlotSpectraData):
207 class SpectraMeanPlot(SpectraPlot):
748 208 '''
749 209 Plot for Spectra and Mean
750 210 '''
751 211 CODE = 'spc_mean'
752 212 colormap = 'jro'
753 213
754 214
755 class PlotRTIData(PlotData):
215 class RTIPlot(Plot):
756 216 '''
757 217 Plot for RTI data
758 218 '''
759 219
760 220 CODE = 'rti'
761 221 colormap = 'jro'
762 222
763 223 def setup(self):
764 224 self.xaxis = 'time'
765 225 self.ncols = 1
766 226 self.nrows = len(self.data.channels)
767 227 self.nplots = len(self.data.channels)
768 228 self.ylabel = 'Range [km]'
769 229 self.cb_label = 'dB'
770 230 self.titles = ['{} Channel {}'.format(
771 231 self.CODE.upper(), x) for x in range(self.nrows)]
772 232
773 233 def plot(self):
774 self.x = self.times
234 self.x = self.data.times
775 235 self.y = self.data.heights
776 236 self.z = self.data[self.CODE]
777 237 self.z = numpy.ma.masked_invalid(self.z)
778 238
779 239 if self.decimation is None:
780 240 x, y, z = self.fill_gaps(self.x, self.y, self.z)
781 241 else:
782 242 x, y, z = self.fill_gaps(*self.decimate())
783 243
784 for n, ax in enumerate(self.axes):
244 for n, ax in enumerate(self.axes):
785 245 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
786 246 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
787 247 if ax.firsttime:
788 248 ax.plt = ax.pcolormesh(x, y, z[n].T,
789 249 vmin=self.zmin,
790 250 vmax=self.zmax,
791 251 cmap=plt.get_cmap(self.colormap)
792 252 )
793 253 if self.showprofile:
794 254 ax.plot_profile = self.pf_axes[n].plot(
795 255 self.data['rti'][n][-1], self.y)[0]
796 256 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
797 257 color="k", linestyle="dashed", lw=1)[0]
798 258 else:
799 259 ax.collections.remove(ax.collections[0])
800 260 ax.plt = ax.pcolormesh(x, y, z[n].T,
801 261 vmin=self.zmin,
802 262 vmax=self.zmax,
803 263 cmap=plt.get_cmap(self.colormap)
804 264 )
805 265 if self.showprofile:
806 266 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
807 267 ax.plot_noise.set_data(numpy.repeat(
808 268 self.data['noise'][n][-1], len(self.y)), self.y)
809 269
810 self.saveTime = self.min_time
811
812 270
813 class PlotCOHData(PlotRTIData):
271 class CoherencePlot(RTIPlot):
814 272 '''
815 273 Plot for Coherence data
816 274 '''
817 275
818 276 CODE = 'coh'
819 277
820 278 def setup(self):
821 279 self.xaxis = 'time'
822 280 self.ncols = 1
823 281 self.nrows = len(self.data.pairs)
824 282 self.nplots = len(self.data.pairs)
825 283 self.ylabel = 'Range [km]'
826 284 if self.CODE == 'coh':
827 285 self.cb_label = ''
828 286 self.titles = [
829 287 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
830 288 else:
831 289 self.cb_label = 'Degrees'
832 290 self.titles = [
833 291 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
834 292
835 293
836 class PlotPHASEData(PlotCOHData):
294 class PhasePlot(CoherencePlot):
837 295 '''
838 296 Plot for Phase map data
839 297 '''
840 298
841 299 CODE = 'phase'
842 300 colormap = 'seismic'
843 301
844 302
845 class PlotNoiseData(PlotData):
303 class NoisePlot(Plot):
846 304 '''
847 305 Plot for noise
848 306 '''
849 307
850 308 CODE = 'noise'
851 309
852 310 def setup(self):
853 311 self.xaxis = 'time'
854 312 self.ncols = 1
855 313 self.nrows = 1
856 314 self.nplots = 1
857 315 self.ylabel = 'Intensity [dB]'
858 316 self.titles = ['Noise']
859 317 self.colorbar = False
860 318
861 319 def plot(self):
862 320
863 x = self.times
864 xmin = self.min_time
321 x = self.data.times
322 xmin = self.data.min_time
865 323 xmax = xmin + self.xrange * 60 * 60
866 324 Y = self.data[self.CODE]
867 325
868 326 if self.axes[0].firsttime:
869 327 for ch in self.data.channels:
870 328 y = Y[ch]
871 329 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
872 330 plt.legend()
873 331 else:
874 332 for ch in self.data.channels:
875 333 y = Y[ch]
876 334 self.axes[0].lines[ch].set_data(x, y)
877 335
878 336 self.ymin = numpy.nanmin(Y) - 5
879 337 self.ymax = numpy.nanmax(Y) + 5
880 self.saveTime = self.min_time
881 338
882 339
883 class PlotSNRData(PlotRTIData):
340 class SnrPlot(RTIPlot):
884 341 '''
885 342 Plot for SNR Data
886 343 '''
887 344
888 345 CODE = 'snr'
889 346 colormap = 'jet'
890 347
891 348
892 class PlotDOPData(PlotRTIData):
349 class DopplerPlot(RTIPlot):
893 350 '''
894 351 Plot for DOPPLER Data
895 352 '''
896 353
897 354 CODE = 'dop'
898 355 colormap = 'jet'
899 356
900 357
901 class PlotSkyMapData(PlotData):
358 class SkyMapPlot(Plot):
902 359 '''
903 360 Plot for meteors detection data
904 361 '''
905 362
906 363 CODE = 'param'
907 364
908 365 def setup(self):
909 366
910 367 self.ncols = 1
911 368 self.nrows = 1
912 369 self.width = 7.2
913 370 self.height = 7.2
914 371 self.nplots = 1
915 372 self.xlabel = 'Zonal Zenith Angle (deg)'
916 373 self.ylabel = 'Meridional Zenith Angle (deg)'
917 374 self.polar = True
918 375 self.ymin = -180
919 376 self.ymax = 180
920 377 self.colorbar = False
921 378
922 379 def plot(self):
923 380
924 381 arrayParameters = numpy.concatenate(self.data['param'])
925 382 error = arrayParameters[:, -1]
926 383 indValid = numpy.where(error == 0)[0]
927 384 finalMeteor = arrayParameters[indValid, :]
928 385 finalAzimuth = finalMeteor[:, 3]
929 386 finalZenith = finalMeteor[:, 4]
930 387
931 388 x = finalAzimuth * numpy.pi / 180
932 389 y = finalZenith
933 390
934 391 ax = self.axes[0]
935 392
936 393 if ax.firsttime:
937 394 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
938 395 else:
939 396 ax.plot.set_data(x, y)
940 397
941 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
942 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
398 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
399 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
943 400 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
944 401 dt2,
945 402 len(x))
946 403 self.titles[0] = title
947 self.saveTime = self.max_time
948 404
949 405
950 class PlotParamData(PlotRTIData):
406 class ParametersPlot(RTIPlot):
951 407 '''
952 408 Plot for data_param object
953 409 '''
954 410
955 411 CODE = 'param'
956 412 colormap = 'seismic'
957 413
958 414 def setup(self):
959 415 self.xaxis = 'time'
960 416 self.ncols = 1
961 417 self.nrows = self.data.shape(self.CODE)[0]
962 418 self.nplots = self.nrows
963 419 if self.showSNR:
964 420 self.nrows += 1
965 421 self.nplots += 1
966 422
967 423 self.ylabel = 'Height [km]'
968 424 if not self.titles:
969 425 self.titles = self.data.parameters \
970 426 if self.data.parameters else ['Param {}'.format(x) for x in range(self.nrows)]
971 427 if self.showSNR:
972 428 self.titles.append('SNR')
973 429
974 430 def plot(self):
975 431 self.data.normalize_heights()
976 self.x = self.times
432 self.x = self.data.times
977 433 self.y = self.data.heights
978 434 if self.showSNR:
979 435 self.z = numpy.concatenate(
980 436 (self.data[self.CODE], self.data['snr'])
981 437 )
982 438 else:
983 439 self.z = self.data[self.CODE]
984 440
985 441 self.z = numpy.ma.masked_invalid(self.z)
986 442
987 443 if self.decimation is None:
988 444 x, y, z = self.fill_gaps(self.x, self.y, self.z)
989 445 else:
990 446 x, y, z = self.fill_gaps(*self.decimate())
991 447
992 448 for n, ax in enumerate(self.axes):
993
449
994 450 self.zmax = self.zmax if self.zmax is not None else numpy.max(
995 451 self.z[n])
996 452 self.zmin = self.zmin if self.zmin is not None else numpy.min(
997 453 self.z[n])
998 454
999 455 if ax.firsttime:
1000 456 if self.zlimits is not None:
1001 457 self.zmin, self.zmax = self.zlimits[n]
1002 458
1003 459 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
1004 460 vmin=self.zmin,
1005 461 vmax=self.zmax,
1006 462 cmap=self.cmaps[n]
1007 463 )
1008 464 else:
1009 465 if self.zlimits is not None:
1010 466 self.zmin, self.zmax = self.zlimits[n]
1011 467 ax.collections.remove(ax.collections[0])
1012 468 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
1013 469 vmin=self.zmin,
1014 470 vmax=self.zmax,
1015 471 cmap=self.cmaps[n]
1016 472 )
1017 473
1018 self.saveTime = self.min_time
1019
1020 474
1021 class PlotOutputData(PlotParamData):
475 class OutputPlot(ParametersPlot):
1022 476 '''
1023 477 Plot data_output object
1024 478 '''
1025 479
1026 480 CODE = 'output'
1027 481 colormap = 'seismic'
1028 482
1029 483
1030 class PlotPolarMapData(PlotData):
484 class PolarMapPlot(Plot):
1031 485 '''
1032 Plot for meteors detection data
486 Plot for weather radar
1033 487 '''
1034 488
1035 489 CODE = 'param'
1036 490 colormap = 'seismic'
1037 491
1038 492 def setup(self):
1039 493 self.ncols = 1
1040 494 self.nrows = 1
1041 495 self.width = 9
1042 496 self.height = 8
1043 497 self.mode = self.data.meta['mode']
1044 498 if self.channels is not None:
1045 499 self.nplots = len(self.channels)
1046 500 self.nrows = len(self.channels)
1047 501 else:
1048 502 self.nplots = self.data.shape(self.CODE)[0]
1049 503 self.nrows = self.nplots
1050 504 self.channels = list(range(self.nplots))
1051 505 if self.mode == 'E':
1052 506 self.xlabel = 'Longitude'
1053 507 self.ylabel = 'Latitude'
1054 508 else:
1055 509 self.xlabel = 'Range (km)'
1056 510 self.ylabel = 'Height (km)'
1057 511 self.bgcolor = 'white'
1058 512 self.cb_labels = self.data.meta['units']
1059 513 self.lat = self.data.meta['latitude']
1060 514 self.lon = self.data.meta['longitude']
1061 self.xmin, self.xmax = float(km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
1062 self.ymin, self.ymax = float(km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
515 self.xmin, self.xmax = float(
516 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
517 self.ymin, self.ymax = float(
518 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
1063 519 # self.polar = True
1064 520
1065 def plot(self):
1066
521 def plot(self):
522
1067 523 for n, ax in enumerate(self.axes):
1068 524 data = self.data['param'][self.channels[n]]
1069
1070 zeniths = numpy.linspace(0, self.data.meta['max_range'], data.shape[1])
1071 if self.mode == 'E':
525
526 zeniths = numpy.linspace(
527 0, self.data.meta['max_range'], data.shape[1])
528 if self.mode == 'E':
1072 529 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
1073 530 r, theta = numpy.meshgrid(zeniths, azimuths)
1074 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
531 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
532 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
1075 533 x = km2deg(x) + self.lon
1076 534 y = km2deg(y) + self.lat
1077 535 else:
1078 536 azimuths = numpy.radians(self.data.heights)
1079 537 r, theta = numpy.meshgrid(zeniths, azimuths)
1080 538 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
1081 539 self.y = zeniths
1082 540
1083 541 if ax.firsttime:
1084 542 if self.zlimits is not None:
1085 543 self.zmin, self.zmax = self.zlimits[n]
1086 ax.plt = ax.pcolormesh(#r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
1087 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
1088 vmin=self.zmin,
1089 vmax=self.zmax,
1090 cmap=self.cmaps[n])
544 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
545 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
546 vmin=self.zmin,
547 vmax=self.zmax,
548 cmap=self.cmaps[n])
1091 549 else:
1092 550 if self.zlimits is not None:
1093 551 self.zmin, self.zmax = self.zlimits[n]
1094 552 ax.collections.remove(ax.collections[0])
1095 ax.plt = ax.pcolormesh(# r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
1096 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
1097 vmin=self.zmin,
1098 vmax=self.zmax,
1099 cmap=self.cmaps[n])
553 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
554 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
555 vmin=self.zmin,
556 vmax=self.zmax,
557 cmap=self.cmaps[n])
1100 558
1101 559 if self.mode == 'A':
1102 560 continue
1103
561
1104 562 # plot district names
1105 563 f = open('/data/workspace/schain_scripts/distrito.csv')
1106 564 for line in f:
1107 565 label, lon, lat = [s.strip() for s in line.split(',') if s]
1108 566 lat = float(lat)
1109 lon = float(lon)
567 lon = float(lon)
1110 568 # ax.plot(lon, lat, '.b', ms=2)
1111 ax.text(lon, lat, label.decode('utf8'), ha='center', va='bottom', size='8', color='black')
1112
569 ax.text(lon, lat, label.decode('utf8'), ha='center',
570 va='bottom', size='8', color='black')
571
1113 572 # plot limites
1114 limites =[]
573 limites = []
1115 574 tmp = []
1116 575 for line in open('/data/workspace/schain_scripts/lima.csv'):
1117 576 if '#' in line:
1118 577 if tmp:
1119 578 limites.append(tmp)
1120 579 tmp = []
1121 580 continue
1122 581 values = line.strip().split(',')
1123 582 tmp.append((float(values[0]), float(values[1])))
1124 583 for points in limites:
1125 ax.add_patch(Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
584 ax.add_patch(
585 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
1126 586
1127 587 # plot Cuencas
1128 588 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
1129 589 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
1130 590 values = [line.strip().split(',') for line in f]
1131 591 points = [(float(s[0]), float(s[1])) for s in values]
1132 592 ax.add_patch(Polygon(points, ec='b', fc='none'))
1133 593
1134 594 # plot grid
1135 595 for r in (15, 30, 45, 60):
1136 ax.add_artist(plt.Circle((self.lon, self.lat), km2deg(r), color='0.6', fill=False, lw=0.2))
596 ax.add_artist(plt.Circle((self.lon, self.lat),
597 km2deg(r), color='0.6', fill=False, lw=0.2))
1137 598 ax.text(
1138 599 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
1139 600 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
1140 '{}km'.format(r),
601 '{}km'.format(r),
1141 602 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
1142
603
1143 604 if self.mode == 'E':
1144 605 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
1145 606 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
1146 607 else:
1147 608 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
1148 609 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
1149
1150 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
1151 self.titles = ['{} {}'.format(self.data.parameters[x], title) for x in self.channels]
1152 self.saveTime = self.max_time
1153 610
1154 No newline at end of file
611 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
612 self.titles = ['{} {}'.format(
613 self.data.parameters[x], title) for x in self.channels]
@@ -1,329 +1,329
1 1 '''
2 2 Created on Jul 9, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import datetime
8 8 import numpy
9 9
10 10 from .figure import Figure, isRealtime
11 11 from .plotting_codes import *
12 12
13 class SpectraHeisScope(Figure):
13 class SpectraHeisScope_(Figure):
14 14
15 15
16 16 isConfig = None
17 17 __nsubplots = None
18 18
19 19 WIDTHPROF = None
20 20 HEIGHTPROF = None
21 21 PREFIX = 'spc'
22 22
23 23 def __init__(self, **kwargs):
24 24
25 25 Figure.__init__(self, **kwargs)
26 26 self.isConfig = False
27 27 self.__nsubplots = 1
28 28
29 29 self.WIDTH = 230
30 30 self.HEIGHT = 250
31 31 self.WIDTHPROF = 120
32 32 self.HEIGHTPROF = 0
33 33 self.counter_imagwr = 0
34 34
35 35 self.PLOT_CODE = SPEC_CODE
36 36
37 37 def getSubplots(self):
38 38
39 39 ncol = int(numpy.sqrt(self.nplots)+0.9)
40 40 nrow = int(self.nplots*1./ncol + 0.9)
41 41
42 42 return nrow, ncol
43 43
44 44 def setup(self, id, nplots, wintitle, show):
45 45
46 46 showprofile = False
47 47 self.__showprofile = showprofile
48 48 self.nplots = nplots
49 49
50 50 ncolspan = 1
51 51 colspan = 1
52 52 if showprofile:
53 53 ncolspan = 3
54 54 colspan = 2
55 55 self.__nsubplots = 2
56 56
57 57 self.createFigure(id = id,
58 58 wintitle = wintitle,
59 59 widthplot = self.WIDTH + self.WIDTHPROF,
60 60 heightplot = self.HEIGHT + self.HEIGHTPROF,
61 61 show = show)
62 62
63 63 nrow, ncol = self.getSubplots()
64 64
65 65 counter = 0
66 66 for y in range(nrow):
67 67 for x in range(ncol):
68 68
69 69 if counter >= self.nplots:
70 70 break
71 71
72 72 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
73 73
74 74 if showprofile:
75 75 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
76 76
77 77 counter += 1
78 78
79 79
80 80 def run(self, dataOut, id, wintitle="", channelList=None,
81 81 xmin=None, xmax=None, ymin=None, ymax=None, save=False,
82 82 figpath='./', figfile=None, ftp=False, wr_period=1, show=True,
83 83 server=None, folder=None, username=None, password=None,
84 84 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
85 85
86 86 """
87 87
88 88 Input:
89 89 dataOut :
90 90 id :
91 91 wintitle :
92 92 channelList :
93 93 xmin : None,
94 94 xmax : None,
95 95 ymin : None,
96 96 ymax : None,
97 97 """
98 98
99 99 if dataOut.realtime:
100 100 if not(isRealtime(utcdatatime = dataOut.utctime)):
101 101 print('Skipping this plot function')
102 102 return
103 103
104 104 if channelList == None:
105 105 channelIndexList = dataOut.channelIndexList
106 106 else:
107 107 channelIndexList = []
108 108 for channel in channelList:
109 109 if channel not in dataOut.channelList:
110 110 raise ValueError("Channel %d is not in dataOut.channelList")
111 111 channelIndexList.append(dataOut.channelList.index(channel))
112 112
113 113 # x = dataOut.heightList
114 114 c = 3E8
115 115 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
116 116 #deberia cambiar para el caso de 1Mhz y 100KHz
117 117 x = numpy.arange(-1*dataOut.nHeights/2.,dataOut.nHeights/2.)*(c/(2*deltaHeight*dataOut.nHeights*1000))
118 118 #para 1Mhz descomentar la siguiente linea
119 119 #x= x/(10000.0)
120 120 # y = dataOut.data[channelIndexList,:] * numpy.conjugate(dataOut.data[channelIndexList,:])
121 121 # y = y.real
122 122 factor = dataOut.normFactor
123 123 data = dataOut.data_spc / factor
124 124 datadB = 10.*numpy.log10(data)
125 125 y = datadB
126 126
127 127 #thisDatetime = dataOut.datatime
128 128 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
129 129 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
130 130 xlabel = ""
131 131 #para 1Mhz descomentar la siguiente linea
132 132 #xlabel = "Frequency x 10000"
133 133 ylabel = "Intensity (dB)"
134 134
135 135 if not self.isConfig:
136 136 nplots = len(channelIndexList)
137 137
138 138 self.setup(id=id,
139 139 nplots=nplots,
140 140 wintitle=wintitle,
141 141 show=show)
142 142
143 143 if xmin == None: xmin = numpy.nanmin(x)
144 144 if xmax == None: xmax = numpy.nanmax(x)
145 145 if ymin == None: ymin = numpy.nanmin(y)
146 146 if ymax == None: ymax = numpy.nanmax(y)
147 147
148 148 self.FTP_WEI = ftp_wei
149 149 self.EXP_CODE = exp_code
150 150 self.SUB_EXP_CODE = sub_exp_code
151 151 self.PLOT_POS = plot_pos
152 152
153 153 self.isConfig = True
154 154
155 155 self.setWinTitle(title)
156 156
157 157 for i in range(len(self.axesList)):
158 158 ychannel = y[i,:]
159 159 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
160 160 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[channelIndexList[i]], numpy.max(ychannel), str_datetime)
161 161 axes = self.axesList[i]
162 162 axes.pline(x, ychannel,
163 163 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
164 164 xlabel=xlabel, ylabel=ylabel, title=title, grid='both')
165 165
166 166
167 167 self.draw()
168 168
169 169 self.save(figpath=figpath,
170 170 figfile=figfile,
171 171 save=save,
172 172 ftp=ftp,
173 173 wr_period=wr_period,
174 174 thisDatetime=thisDatetime)
175 175
176 class RTIfromSpectraHeis(Figure):
176 class RTIfromSpectraHeis_(Figure):
177 177
178 178 isConfig = None
179 179 __nsubplots = None
180 180
181 181 PREFIX = 'rtinoise'
182 182
183 183 def __init__(self, **kwargs):
184 184 Figure.__init__(self, **kwargs)
185 185 self.timerange = 24*60*60
186 186 self.isConfig = False
187 187 self.__nsubplots = 1
188 188
189 189 self.WIDTH = 820
190 190 self.HEIGHT = 200
191 191 self.WIDTHPROF = 120
192 192 self.HEIGHTPROF = 0
193 193 self.counter_imagwr = 0
194 194 self.xdata = None
195 195 self.ydata = None
196 196 self.figfile = None
197 197
198 198 self.PLOT_CODE = RTI_CODE
199 199
200 200 def getSubplots(self):
201 201
202 202 ncol = 1
203 203 nrow = 1
204 204
205 205 return nrow, ncol
206 206
207 207 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
208 208
209 209 self.__showprofile = showprofile
210 210 self.nplots = nplots
211 211
212 212 ncolspan = 7
213 213 colspan = 6
214 214 self.__nsubplots = 2
215 215
216 216 self.createFigure(id = id,
217 217 wintitle = wintitle,
218 218 widthplot = self.WIDTH+self.WIDTHPROF,
219 219 heightplot = self.HEIGHT+self.HEIGHTPROF,
220 220 show = show)
221 221
222 222 nrow, ncol = self.getSubplots()
223 223
224 224 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
225 225
226 226
227 227 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True',
228 228 xmin=None, xmax=None, ymin=None, ymax=None,
229 229 timerange=None,
230 230 save=False, figpath='./', figfile=None, ftp=False, wr_period=1, show=True,
231 231 server=None, folder=None, username=None, password=None,
232 232 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
233 233
234 234 if channelList == None:
235 235 channelIndexList = dataOut.channelIndexList
236 236 channelList = dataOut.channelList
237 237 else:
238 238 channelIndexList = []
239 239 for channel in channelList:
240 240 if channel not in dataOut.channelList:
241 241 raise ValueError("Channel %d is not in dataOut.channelList")
242 242 channelIndexList.append(dataOut.channelList.index(channel))
243 243
244 244 if timerange != None:
245 245 self.timerange = timerange
246 246
247 247 x = dataOut.getTimeRange()
248 248 y = dataOut.getHeiRange()
249 249
250 250 factor = dataOut.normFactor
251 251 data = dataOut.data_spc / factor
252 252 data = numpy.average(data,axis=1)
253 253 datadB = 10*numpy.log10(data)
254 254
255 255 # factor = dataOut.normFactor
256 256 # noise = dataOut.getNoise()/factor
257 257 # noisedB = 10*numpy.log10(noise)
258 258
259 259 #thisDatetime = dataOut.datatime
260 260 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
261 261 title = wintitle + " RTI: %s" %(thisDatetime.strftime("%d-%b-%Y"))
262 262 xlabel = "Local Time"
263 263 ylabel = "Intensity (dB)"
264 264
265 265 if not self.isConfig:
266 266
267 267 nplots = 1
268 268
269 269 self.setup(id=id,
270 270 nplots=nplots,
271 271 wintitle=wintitle,
272 272 showprofile=showprofile,
273 273 show=show)
274 274
275 275 self.tmin, self.tmax = self.getTimeLim(x, xmin, xmax)
276 276
277 277 if ymin == None: ymin = numpy.nanmin(datadB)
278 278 if ymax == None: ymax = numpy.nanmax(datadB)
279 279
280 280 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
281 281 self.isConfig = True
282 282 self.figfile = figfile
283 283 self.xdata = numpy.array([])
284 284 self.ydata = numpy.array([])
285 285
286 286 self.FTP_WEI = ftp_wei
287 287 self.EXP_CODE = exp_code
288 288 self.SUB_EXP_CODE = sub_exp_code
289 289 self.PLOT_POS = plot_pos
290 290
291 291 self.setWinTitle(title)
292 292
293 293
294 294 # title = "RTI %s" %(thisDatetime.strftime("%d-%b-%Y"))
295 295 title = "RTI - %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
296 296
297 297 legendlabels = ["channel %d"%idchannel for idchannel in channelList]
298 298 axes = self.axesList[0]
299 299
300 300 self.xdata = numpy.hstack((self.xdata, x[0:1]))
301 301
302 302 if len(self.ydata)==0:
303 303 self.ydata = datadB[channelIndexList].reshape(-1,1)
304 304 else:
305 305 self.ydata = numpy.hstack((self.ydata, datadB[channelIndexList].reshape(-1,1)))
306 306
307 307
308 308 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
309 309 xmin=self.tmin, xmax=self.tmax, ymin=ymin, ymax=ymax,
310 310 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='.', markersize=8, linestyle="solid", grid='both',
311 311 XAxisAsTime=True
312 312 )
313 313
314 314 self.draw()
315 315
316 316 update_figfile = False
317 317
318 318 if dataOut.ltctime >= self.tmax:
319 319 self.counter_imagwr = wr_period
320 320 self.isConfig = False
321 321 update_figfile = True
322 322
323 323 self.save(figpath=figpath,
324 324 figfile=figfile,
325 325 save=save,
326 326 ftp=ftp,
327 327 wr_period=wr_period,
328 328 thisDatetime=thisDatetime,
329 329 update_figfile=update_figfile) No newline at end of file
@@ -1,2158 +1,2158
1 1 import os
2 2 import datetime
3 3 import numpy
4 4 import inspect
5 5 from .figure import Figure, isRealtime, isTimeInHourRange
6 6 from .plotting_codes import *
7 7 from schainpy.model.proc.jroproc_base import MPDecorator
8 8 from schainpy.utils import log
9 9
10 class FitGauPlot(Figure):
10 class FitGauPlot_(Figure):
11 11
12 12 isConfig = None
13 13 __nsubplots = None
14 14
15 15 WIDTHPROF = None
16 16 HEIGHTPROF = None
17 17 PREFIX = 'fitgau'
18 18
19 19 def __init__(self, **kwargs):
20 20 Figure.__init__(self, **kwargs)
21 21 self.isConfig = False
22 22 self.__nsubplots = 1
23 23
24 24 self.WIDTH = 250
25 25 self.HEIGHT = 250
26 26 self.WIDTHPROF = 120
27 27 self.HEIGHTPROF = 0
28 28 self.counter_imagwr = 0
29 29
30 30 self.PLOT_CODE = SPEC_CODE
31 31
32 32 self.FTP_WEI = None
33 33 self.EXP_CODE = None
34 34 self.SUB_EXP_CODE = None
35 35 self.PLOT_POS = None
36 36
37 37 self.__xfilter_ena = False
38 38 self.__yfilter_ena = False
39 39
40 40 def getSubplots(self):
41 41
42 42 ncol = int(numpy.sqrt(self.nplots)+0.9)
43 43 nrow = int(self.nplots*1./ncol + 0.9)
44 44
45 45 return nrow, ncol
46 46
47 47 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
48 48
49 49 self.__showprofile = showprofile
50 50 self.nplots = nplots
51 51
52 52 ncolspan = 1
53 53 colspan = 1
54 54 if showprofile:
55 55 ncolspan = 3
56 56 colspan = 2
57 57 self.__nsubplots = 2
58 58
59 59 self.createFigure(id = id,
60 60 wintitle = wintitle,
61 61 widthplot = self.WIDTH + self.WIDTHPROF,
62 62 heightplot = self.HEIGHT + self.HEIGHTPROF,
63 63 show=show)
64 64
65 65 nrow, ncol = self.getSubplots()
66 66
67 67 counter = 0
68 68 for y in range(nrow):
69 69 for x in range(ncol):
70 70
71 71 if counter >= self.nplots:
72 72 break
73 73
74 74 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
75 75
76 76 if showprofile:
77 77 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
78 78
79 79 counter += 1
80 80
81 81 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
82 82 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
83 83 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
84 84 server=None, folder=None, username=None, password=None,
85 85 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
86 86 xaxis="frequency", colormap='jet', normFactor=None , GauSelector = 1):
87 87
88 88 """
89 89
90 90 Input:
91 91 dataOut :
92 92 id :
93 93 wintitle :
94 94 channelList :
95 95 showProfile :
96 96 xmin : None,
97 97 xmax : None,
98 98 ymin : None,
99 99 ymax : None,
100 100 zmin : None,
101 101 zmax : None
102 102 """
103 103 if realtime:
104 104 if not(isRealtime(utcdatatime = dataOut.utctime)):
105 105 print('Skipping this plot function')
106 106 return
107 107
108 108 if channelList == None:
109 109 channelIndexList = dataOut.channelIndexList
110 110 else:
111 111 channelIndexList = []
112 112 for channel in channelList:
113 113 if channel not in dataOut.channelList:
114 114 raise ValueError("Channel %d is not in dataOut.channelList" %channel)
115 115 channelIndexList.append(dataOut.channelList.index(channel))
116 116
117 117 # if normFactor is None:
118 118 # factor = dataOut.normFactor
119 119 # else:
120 120 # factor = normFactor
121 121 if xaxis == "frequency":
122 122 x = dataOut.spc_range[0]
123 123 xlabel = "Frequency (kHz)"
124 124
125 125 elif xaxis == "time":
126 126 x = dataOut.spc_range[1]
127 127 xlabel = "Time (ms)"
128 128
129 129 else:
130 130 x = dataOut.spc_range[2]
131 131 xlabel = "Velocity (m/s)"
132 132
133 133 ylabel = "Range (Km)"
134 134
135 135 y = dataOut.getHeiRange()
136 136
137 137 z = dataOut.GauSPC[:,GauSelector,:,:] #GauSelector] #dataOut.data_spc/factor
138 138 print('GausSPC', z[0,32,10:40])
139 139 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
140 140 zdB = 10*numpy.log10(z)
141 141
142 142 avg = numpy.average(z, axis=1)
143 143 avgdB = 10*numpy.log10(avg)
144 144
145 145 noise = dataOut.spc_noise
146 146 noisedB = 10*numpy.log10(noise)
147 147
148 148 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
149 149 title = wintitle + " Spectra"
150 150 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
151 151 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
152 152
153 153 if not self.isConfig:
154 154
155 155 nplots = len(channelIndexList)
156 156
157 157 self.setup(id=id,
158 158 nplots=nplots,
159 159 wintitle=wintitle,
160 160 showprofile=showprofile,
161 161 show=show)
162 162
163 163 if xmin == None: xmin = numpy.nanmin(x)
164 164 if xmax == None: xmax = numpy.nanmax(x)
165 165 if ymin == None: ymin = numpy.nanmin(y)
166 166 if ymax == None: ymax = numpy.nanmax(y)
167 167 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
168 168 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
169 169
170 170 self.FTP_WEI = ftp_wei
171 171 self.EXP_CODE = exp_code
172 172 self.SUB_EXP_CODE = sub_exp_code
173 173 self.PLOT_POS = plot_pos
174 174
175 175 self.isConfig = True
176 176
177 177 self.setWinTitle(title)
178 178
179 179 for i in range(self.nplots):
180 180 index = channelIndexList[i]
181 181 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
182 182 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[index], noisedB[index], str_datetime)
183 183 if len(dataOut.beam.codeList) != 0:
184 184 title = "Ch%d:%4.2fdB,%2.2f,%2.2f:%s" %(dataOut.channelList[index], noisedB[index], dataOut.beam.azimuthList[index], dataOut.beam.zenithList[index], str_datetime)
185 185
186 186 axes = self.axesList[i*self.__nsubplots]
187 187 axes.pcolor(x, y, zdB[index,:,:],
188 188 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
189 189 xlabel=xlabel, ylabel=ylabel, title=title, colormap=colormap,
190 190 ticksize=9, cblabel='')
191 191
192 192 if self.__showprofile:
193 193 axes = self.axesList[i*self.__nsubplots +1]
194 194 axes.pline(avgdB[index,:], y,
195 195 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
196 196 xlabel='dB', ylabel='', title='',
197 197 ytick_visible=False,
198 198 grid='x')
199 199
200 200 noiseline = numpy.repeat(noisedB[index], len(y))
201 201 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
202 202
203 203 self.draw()
204 204
205 205 if figfile == None:
206 206 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
207 207 name = str_datetime
208 208 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
209 209 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
210 210 figfile = self.getFilename(name)
211 211
212 212 self.save(figpath=figpath,
213 213 figfile=figfile,
214 214 save=save,
215 215 ftp=ftp,
216 216 wr_period=wr_period,
217 217 thisDatetime=thisDatetime)
218 218
219 219
220 220
221 class MomentsPlot(Figure):
221 class MomentsPlot_(Figure):
222 222
223 223 isConfig = None
224 224 __nsubplots = None
225 225
226 226 WIDTHPROF = None
227 227 HEIGHTPROF = None
228 228 PREFIX = 'prm'
229 229 def __init__(self):
230 230 Figure.__init__(self)
231 231 self.isConfig = False
232 232 self.__nsubplots = 1
233 233
234 234 self.WIDTH = 280
235 235 self.HEIGHT = 250
236 236 self.WIDTHPROF = 120
237 237 self.HEIGHTPROF = 0
238 238 self.counter_imagwr = 0
239 239
240 240 self.PLOT_CODE = MOMENTS_CODE
241 241
242 242 self.FTP_WEI = None
243 243 self.EXP_CODE = None
244 244 self.SUB_EXP_CODE = None
245 245 self.PLOT_POS = None
246 246
247 247 def getSubplots(self):
248 248
249 249 ncol = int(numpy.sqrt(self.nplots)+0.9)
250 250 nrow = int(self.nplots*1./ncol + 0.9)
251 251
252 252 return nrow, ncol
253 253
254 254 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
255 255
256 256 self.__showprofile = showprofile
257 257 self.nplots = nplots
258 258
259 259 ncolspan = 1
260 260 colspan = 1
261 261 if showprofile:
262 262 ncolspan = 3
263 263 colspan = 2
264 264 self.__nsubplots = 2
265 265
266 266 self.createFigure(id = id,
267 267 wintitle = wintitle,
268 268 widthplot = self.WIDTH + self.WIDTHPROF,
269 269 heightplot = self.HEIGHT + self.HEIGHTPROF,
270 270 show=show)
271 271
272 272 nrow, ncol = self.getSubplots()
273 273
274 274 counter = 0
275 275 for y in range(nrow):
276 276 for x in range(ncol):
277 277
278 278 if counter >= self.nplots:
279 279 break
280 280
281 281 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
282 282
283 283 if showprofile:
284 284 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
285 285
286 286 counter += 1
287 287
288 288 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
289 289 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
290 290 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
291 291 server=None, folder=None, username=None, password=None,
292 292 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
293 293
294 294 """
295 295
296 296 Input:
297 297 dataOut :
298 298 id :
299 299 wintitle :
300 300 channelList :
301 301 showProfile :
302 302 xmin : None,
303 303 xmax : None,
304 304 ymin : None,
305 305 ymax : None,
306 306 zmin : None,
307 307 zmax : None
308 308 """
309 309
310 310 if dataOut.flagNoData:
311 311 return None
312 312
313 313 if realtime:
314 314 if not(isRealtime(utcdatatime = dataOut.utctime)):
315 315 print('Skipping this plot function')
316 316 return
317 317
318 318 if channelList == None:
319 319 channelIndexList = dataOut.channelIndexList
320 320 else:
321 321 channelIndexList = []
322 322 for channel in channelList:
323 323 if channel not in dataOut.channelList:
324 324 raise ValueError("Channel %d is not in dataOut.channelList")
325 325 channelIndexList.append(dataOut.channelList.index(channel))
326 326
327 327 factor = dataOut.normFactor
328 328 x = dataOut.abscissaList
329 329 y = dataOut.heightList
330 330
331 331 z = dataOut.data_pre[channelIndexList,:,:]/factor
332 332 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
333 333 avg = numpy.average(z, axis=1)
334 334 noise = dataOut.noise/factor
335 335
336 336 zdB = 10*numpy.log10(z)
337 337 avgdB = 10*numpy.log10(avg)
338 338 noisedB = 10*numpy.log10(noise)
339 339
340 340 #thisDatetime = dataOut.datatime
341 341 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
342 342 title = wintitle + " Parameters"
343 343 xlabel = "Velocity (m/s)"
344 344 ylabel = "Range (Km)"
345 345
346 346 update_figfile = False
347 347
348 348 if not self.isConfig:
349 349
350 350 nplots = len(channelIndexList)
351 351
352 352 self.setup(id=id,
353 353 nplots=nplots,
354 354 wintitle=wintitle,
355 355 showprofile=showprofile,
356 356 show=show)
357 357
358 358 if xmin == None: xmin = numpy.nanmin(x)
359 359 if xmax == None: xmax = numpy.nanmax(x)
360 360 if ymin == None: ymin = numpy.nanmin(y)
361 361 if ymax == None: ymax = numpy.nanmax(y)
362 362 if zmin == None: zmin = numpy.nanmin(avgdB)*0.9
363 363 if zmax == None: zmax = numpy.nanmax(avgdB)*0.9
364 364
365 365 self.FTP_WEI = ftp_wei
366 366 self.EXP_CODE = exp_code
367 367 self.SUB_EXP_CODE = sub_exp_code
368 368 self.PLOT_POS = plot_pos
369 369
370 370 self.isConfig = True
371 371 update_figfile = True
372 372
373 373 self.setWinTitle(title)
374 374
375 375 for i in range(self.nplots):
376 376 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
377 377 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[i], noisedB[i], str_datetime)
378 378 axes = self.axesList[i*self.__nsubplots]
379 379 axes.pcolor(x, y, zdB[i,:,:],
380 380 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
381 381 xlabel=xlabel, ylabel=ylabel, title=title,
382 382 ticksize=9, cblabel='')
383 383 #Mean Line
384 384 mean = dataOut.data_param[i, 1, :]
385 385 axes.addpline(mean, y, idline=0, color="black", linestyle="solid", lw=1)
386 386
387 387 if self.__showprofile:
388 388 axes = self.axesList[i*self.__nsubplots +1]
389 389 axes.pline(avgdB[i], y,
390 390 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
391 391 xlabel='dB', ylabel='', title='',
392 392 ytick_visible=False,
393 393 grid='x')
394 394
395 395 noiseline = numpy.repeat(noisedB[i], len(y))
396 396 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
397 397
398 398 self.draw()
399 399
400 400 self.save(figpath=figpath,
401 401 figfile=figfile,
402 402 save=save,
403 403 ftp=ftp,
404 404 wr_period=wr_period,
405 405 thisDatetime=thisDatetime)
406 406
407 407
408 class SkyMapPlot(Figure):
408 class SkyMapPlot_(Figure):
409 409
410 410 __isConfig = None
411 411 __nsubplots = None
412 412
413 413 WIDTHPROF = None
414 414 HEIGHTPROF = None
415 415 PREFIX = 'mmap'
416 416
417 417 def __init__(self, **kwargs):
418 418 Figure.__init__(self, **kwargs)
419 419 self.isConfig = False
420 420 self.__nsubplots = 1
421 421
422 422 # self.WIDTH = 280
423 423 # self.HEIGHT = 250
424 424 self.WIDTH = 600
425 425 self.HEIGHT = 600
426 426 self.WIDTHPROF = 120
427 427 self.HEIGHTPROF = 0
428 428 self.counter_imagwr = 0
429 429
430 430 self.PLOT_CODE = MSKYMAP_CODE
431 431
432 432 self.FTP_WEI = None
433 433 self.EXP_CODE = None
434 434 self.SUB_EXP_CODE = None
435 435 self.PLOT_POS = None
436 436
437 437 def getSubplots(self):
438 438
439 439 ncol = int(numpy.sqrt(self.nplots)+0.9)
440 440 nrow = int(self.nplots*1./ncol + 0.9)
441 441
442 442 return nrow, ncol
443 443
444 444 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
445 445
446 446 self.__showprofile = showprofile
447 447 self.nplots = nplots
448 448
449 449 ncolspan = 1
450 450 colspan = 1
451 451
452 452 self.createFigure(id = id,
453 453 wintitle = wintitle,
454 454 widthplot = self.WIDTH, #+ self.WIDTHPROF,
455 455 heightplot = self.HEIGHT,# + self.HEIGHTPROF,
456 456 show=show)
457 457
458 458 nrow, ncol = 1,1
459 459 counter = 0
460 460 x = 0
461 461 y = 0
462 462 self.addAxes(1, 1, 0, 0, 1, 1, True)
463 463
464 464 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
465 465 tmin=0, tmax=24, timerange=None,
466 466 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
467 467 server=None, folder=None, username=None, password=None,
468 468 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
469 469
470 470 """
471 471
472 472 Input:
473 473 dataOut :
474 474 id :
475 475 wintitle :
476 476 channelList :
477 477 showProfile :
478 478 xmin : None,
479 479 xmax : None,
480 480 ymin : None,
481 481 ymax : None,
482 482 zmin : None,
483 483 zmax : None
484 484 """
485 485
486 486 arrayParameters = dataOut.data_param
487 487 error = arrayParameters[:,-1]
488 488 indValid = numpy.where(error == 0)[0]
489 489 finalMeteor = arrayParameters[indValid,:]
490 490 finalAzimuth = finalMeteor[:,3]
491 491 finalZenith = finalMeteor[:,4]
492 492
493 493 x = finalAzimuth*numpy.pi/180
494 494 y = finalZenith
495 495 x1 = [dataOut.ltctime, dataOut.ltctime]
496 496
497 497 #thisDatetime = dataOut.datatime
498 498 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
499 499 title = wintitle + " Parameters"
500 500 xlabel = "Zonal Zenith Angle (deg) "
501 501 ylabel = "Meridional Zenith Angle (deg)"
502 502 update_figfile = False
503 503
504 504 if not self.isConfig:
505 505
506 506 nplots = 1
507 507
508 508 self.setup(id=id,
509 509 nplots=nplots,
510 510 wintitle=wintitle,
511 511 showprofile=showprofile,
512 512 show=show)
513 513
514 514 if self.xmin is None and self.xmax is None:
515 515 self.xmin, self.xmax = self.getTimeLim(x1, tmin, tmax, timerange)
516 516
517 517 if timerange != None:
518 518 self.timerange = timerange
519 519 else:
520 520 self.timerange = self.xmax - self.xmin
521 521
522 522 self.FTP_WEI = ftp_wei
523 523 self.EXP_CODE = exp_code
524 524 self.SUB_EXP_CODE = sub_exp_code
525 525 self.PLOT_POS = plot_pos
526 526 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
527 527 self.firstdate = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
528 528 self.isConfig = True
529 529 update_figfile = True
530 530
531 531 self.setWinTitle(title)
532 532
533 533 i = 0
534 534 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
535 535
536 536 axes = self.axesList[i*self.__nsubplots]
537 537 nevents = axes.x_buffer.shape[0] + x.shape[0]
538 538 title = "Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n" %(self.firstdate,str_datetime,nevents)
539 539 axes.polar(x, y,
540 540 title=title, xlabel=xlabel, ylabel=ylabel,
541 541 ticksize=9, cblabel='')
542 542
543 543 self.draw()
544 544
545 545 self.save(figpath=figpath,
546 546 figfile=figfile,
547 547 save=save,
548 548 ftp=ftp,
549 549 wr_period=wr_period,
550 550 thisDatetime=thisDatetime,
551 551 update_figfile=update_figfile)
552 552
553 553 if dataOut.ltctime >= self.xmax:
554 554 self.isConfigmagwr = wr_period
555 555 self.isConfig = False
556 556 update_figfile = True
557 557 axes.__firsttime = True
558 558 self.xmin += self.timerange
559 559 self.xmax += self.timerange
560 560
561 561
562 562
563 563
564 class WindProfilerPlot(Figure):
564 class WindProfilerPlot_(Figure):
565 565
566 566 __isConfig = None
567 567 __nsubplots = None
568 568
569 569 WIDTHPROF = None
570 570 HEIGHTPROF = None
571 571 PREFIX = 'wind'
572 572
573 573 def __init__(self, **kwargs):
574 574 Figure.__init__(self, **kwargs)
575 575 self.timerange = None
576 576 self.isConfig = False
577 577 self.__nsubplots = 1
578 578
579 579 self.WIDTH = 800
580 580 self.HEIGHT = 300
581 581 self.WIDTHPROF = 120
582 582 self.HEIGHTPROF = 0
583 583 self.counter_imagwr = 0
584 584
585 585 self.PLOT_CODE = WIND_CODE
586 586
587 587 self.FTP_WEI = None
588 588 self.EXP_CODE = None
589 589 self.SUB_EXP_CODE = None
590 590 self.PLOT_POS = None
591 591 self.tmin = None
592 592 self.tmax = None
593 593
594 594 self.xmin = None
595 595 self.xmax = None
596 596
597 597 self.figfile = None
598 598
599 599 def getSubplots(self):
600 600
601 601 ncol = 1
602 602 nrow = self.nplots
603 603
604 604 return nrow, ncol
605 605
606 606 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
607 607
608 608 self.__showprofile = showprofile
609 609 self.nplots = nplots
610 610
611 611 ncolspan = 1
612 612 colspan = 1
613 613
614 614 self.createFigure(id = id,
615 615 wintitle = wintitle,
616 616 widthplot = self.WIDTH + self.WIDTHPROF,
617 617 heightplot = self.HEIGHT + self.HEIGHTPROF,
618 618 show=show)
619 619
620 620 nrow, ncol = self.getSubplots()
621 621
622 622 counter = 0
623 623 for y in range(nrow):
624 624 if counter >= self.nplots:
625 625 break
626 626
627 627 self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1)
628 628 counter += 1
629 629
630 630 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='False',
631 631 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
632 632 zmax_ver = None, zmin_ver = None, SNRmin = None, SNRmax = None,
633 633 timerange=None, SNRthresh = None,
634 634 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
635 635 server=None, folder=None, username=None, password=None,
636 636 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
637 637 """
638 638
639 639 Input:
640 640 dataOut :
641 641 id :
642 642 wintitle :
643 643 channelList :
644 644 showProfile :
645 645 xmin : None,
646 646 xmax : None,
647 647 ymin : None,
648 648 ymax : None,
649 649 zmin : None,
650 650 zmax : None
651 651 """
652 652
653 653 # if timerange is not None:
654 654 # self.timerange = timerange
655 655 #
656 656 # tmin = None
657 657 # tmax = None
658 658
659 659 x = dataOut.getTimeRange1(dataOut.paramInterval)
660 660 y = dataOut.heightList
661 661 z = dataOut.data_output.copy()
662 662 nplots = z.shape[0] #Number of wind dimensions estimated
663 663 nplotsw = nplots
664 664
665 665
666 666 #If there is a SNR function defined
667 667 if dataOut.data_SNR is not None:
668 668 nplots += 1
669 669 SNR = dataOut.data_SNR
670 670 SNRavg = numpy.average(SNR, axis=0)
671 671
672 672 SNRdB = 10*numpy.log10(SNR)
673 673 SNRavgdB = 10*numpy.log10(SNRavg)
674 674
675 675 if SNRthresh == None: SNRthresh = -5.0
676 676 ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0]
677 677
678 678 for i in range(nplotsw):
679 679 z[i,ind] = numpy.nan
680 680
681 681 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
682 682 #thisDatetime = datetime.datetime.now()
683 683 title = wintitle + "Wind"
684 684 xlabel = ""
685 685 ylabel = "Height (km)"
686 686 update_figfile = False
687 687
688 688 if not self.isConfig:
689 689
690 690 self.setup(id=id,
691 691 nplots=nplots,
692 692 wintitle=wintitle,
693 693 showprofile=showprofile,
694 694 show=show)
695 695
696 696 if timerange is not None:
697 697 self.timerange = timerange
698 698
699 699 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
700 700
701 701 if ymin == None: ymin = numpy.nanmin(y)
702 702 if ymax == None: ymax = numpy.nanmax(y)
703 703
704 704 if zmax == None: zmax = numpy.nanmax(abs(z[list(range(2)),:]))
705 705 #if numpy.isnan(zmax): zmax = 50
706 706 if zmin == None: zmin = -zmax
707 707
708 708 if nplotsw == 3:
709 709 if zmax_ver == None: zmax_ver = numpy.nanmax(abs(z[2,:]))
710 710 if zmin_ver == None: zmin_ver = -zmax_ver
711 711
712 712 if dataOut.data_SNR is not None:
713 713 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
714 714 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
715 715
716 716
717 717 self.FTP_WEI = ftp_wei
718 718 self.EXP_CODE = exp_code
719 719 self.SUB_EXP_CODE = sub_exp_code
720 720 self.PLOT_POS = plot_pos
721 721
722 722 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
723 723 self.isConfig = True
724 724 self.figfile = figfile
725 725 update_figfile = True
726 726
727 727 self.setWinTitle(title)
728 728
729 729 if ((self.xmax - x[1]) < (x[1]-x[0])):
730 730 x[1] = self.xmax
731 731
732 732 strWind = ['Zonal', 'Meridional', 'Vertical']
733 733 strCb = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)']
734 734 zmaxVector = [zmax, zmax, zmax_ver]
735 735 zminVector = [zmin, zmin, zmin_ver]
736 736 windFactor = [1,1,100]
737 737
738 738 for i in range(nplotsw):
739 739
740 740 title = "%s Wind: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
741 741 axes = self.axesList[i*self.__nsubplots]
742 742
743 743 z1 = z[i,:].reshape((1,-1))*windFactor[i]
744 744 #z1=numpy.ma.masked_where(z1==0.,z1)
745 745
746 746 axes.pcolorbuffer(x, y, z1,
747 747 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i],
748 748 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
749 749 ticksize=9, cblabel=strCb[i], cbsize="1%", colormap="seismic" )
750 750
751 751 if dataOut.data_SNR is not None:
752 752 i += 1
753 753 title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
754 754 axes = self.axesList[i*self.__nsubplots]
755 755 SNRavgdB = SNRavgdB.reshape((1,-1))
756 756 axes.pcolorbuffer(x, y, SNRavgdB,
757 757 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
758 758 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
759 759 ticksize=9, cblabel='', cbsize="1%", colormap="jet")
760 760
761 761 self.draw()
762 762
763 763 self.save(figpath=figpath,
764 764 figfile=figfile,
765 765 save=save,
766 766 ftp=ftp,
767 767 wr_period=wr_period,
768 768 thisDatetime=thisDatetime,
769 769 update_figfile=update_figfile)
770 770
771 771 if dataOut.ltctime + dataOut.paramInterval >= self.xmax:
772 772 self.counter_imagwr = wr_period
773 773 self.isConfig = False
774 774 update_figfile = True
775 775
776 776 @MPDecorator
777 class ParametersPlot(Figure):
777 class ParametersPlot_(Figure):
778 778
779 779 __isConfig = None
780 780 __nsubplots = None
781 781
782 782 WIDTHPROF = None
783 783 HEIGHTPROF = None
784 784 PREFIX = 'param'
785 785
786 786 nplots = None
787 787 nchan = None
788 788
789 789 def __init__(self):#, **kwargs):
790 790 Figure.__init__(self)#, **kwargs)
791 791 self.timerange = None
792 792 self.isConfig = False
793 793 self.__nsubplots = 1
794 794
795 795 self.WIDTH = 800
796 796 self.HEIGHT = 180
797 797 self.WIDTHPROF = 120
798 798 self.HEIGHTPROF = 0
799 799 self.counter_imagwr = 0
800 800
801 801 self.PLOT_CODE = RTI_CODE
802 802
803 803 self.FTP_WEI = None
804 804 self.EXP_CODE = None
805 805 self.SUB_EXP_CODE = None
806 806 self.PLOT_POS = None
807 807 self.tmin = None
808 808 self.tmax = None
809 809
810 810 self.xmin = None
811 811 self.xmax = None
812 812
813 813 self.figfile = None
814 814
815 815 def getSubplots(self):
816 816
817 817 ncol = 1
818 818 nrow = self.nplots
819 819
820 820 return nrow, ncol
821 821
822 822 def setup(self, id, nplots, wintitle, show=True):
823 823
824 824 self.nplots = nplots
825 825
826 826 ncolspan = 1
827 827 colspan = 1
828 828
829 829 self.createFigure(id = id,
830 830 wintitle = wintitle,
831 831 widthplot = self.WIDTH + self.WIDTHPROF,
832 832 heightplot = self.HEIGHT + self.HEIGHTPROF,
833 833 show=show)
834 834
835 835 nrow, ncol = self.getSubplots()
836 836
837 837 counter = 0
838 838 for y in range(nrow):
839 839 for x in range(ncol):
840 840
841 841 if counter >= self.nplots:
842 842 break
843 843
844 844 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
845 845
846 846 counter += 1
847 847
848 848 def run(self, dataOut, id, wintitle="", channelList=None, paramIndex = 0, colormap="jet",
849 849 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None, timerange=None,
850 850 showSNR=False, SNRthresh = -numpy.inf, SNRmin=None, SNRmax=None,
851 851 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
852 852 server=None, folder=None, username=None, password=None,
853 853 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, HEIGHT=None):
854 854 """
855 855
856 856 Input:
857 857 dataOut :
858 858 id :
859 859 wintitle :
860 860 channelList :
861 861 showProfile :
862 862 xmin : None,
863 863 xmax : None,
864 864 ymin : None,
865 865 ymax : None,
866 866 zmin : None,
867 867 zmax : None
868 868 """
869 869 if dataOut.flagNoData:
870 870 return dataOut
871 871
872 872
873 873 if HEIGHT is not None:
874 874 self.HEIGHT = HEIGHT
875 875
876 876
877 877 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
878 878 return
879 879
880 880 if channelList == None:
881 881 channelIndexList = list(range(dataOut.data_param.shape[0]))
882 882 else:
883 883 channelIndexList = []
884 884 for channel in channelList:
885 885 if channel not in dataOut.channelList:
886 886 raise ValueError("Channel %d is not in dataOut.channelList")
887 887 channelIndexList.append(dataOut.channelList.index(channel))
888 888
889 889 x = dataOut.getTimeRange1(dataOut.paramInterval)
890 890 y = dataOut.getHeiRange()
891 891
892 892 if dataOut.data_param.ndim == 3:
893 893 z = dataOut.data_param[channelIndexList,paramIndex,:]
894 894 else:
895 895 z = dataOut.data_param[channelIndexList,:]
896 896
897 897 if showSNR:
898 898 #SNR data
899 899 SNRarray = dataOut.data_SNR[channelIndexList,:]
900 900 SNRdB = 10*numpy.log10(SNRarray)
901 901 ind = numpy.where(SNRdB < SNRthresh)
902 902 z[ind] = numpy.nan
903 903
904 904 thisDatetime = dataOut.datatime
905 905 # thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
906 906 title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
907 907 xlabel = ""
908 908 ylabel = "Range (Km)"
909 909
910 910 update_figfile = False
911 911
912 912 if not self.isConfig:
913 913
914 914 nchan = len(channelIndexList)
915 915 self.nchan = nchan
916 916 self.plotFact = 1
917 917 nplots = nchan
918 918
919 919 if showSNR:
920 920 nplots = nchan*2
921 921 self.plotFact = 2
922 922 if SNRmin == None: SNRmin = numpy.nanmin(SNRdB)
923 923 if SNRmax == None: SNRmax = numpy.nanmax(SNRdB)
924 924
925 925 self.setup(id=id,
926 926 nplots=nplots,
927 927 wintitle=wintitle,
928 928 show=show)
929 929
930 930 if timerange != None:
931 931 self.timerange = timerange
932 932
933 933 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
934 934
935 935 if ymin == None: ymin = numpy.nanmin(y)
936 936 if ymax == None: ymax = numpy.nanmax(y)
937 937 if zmin == None: zmin = numpy.nanmin(z)
938 938 if zmax == None: zmax = numpy.nanmax(z)
939 939
940 940 self.FTP_WEI = ftp_wei
941 941 self.EXP_CODE = exp_code
942 942 self.SUB_EXP_CODE = sub_exp_code
943 943 self.PLOT_POS = plot_pos
944 944
945 945 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
946 946 self.isConfig = True
947 947 self.figfile = figfile
948 948 update_figfile = True
949 949
950 950 self.setWinTitle(title)
951 951
952 952 for i in range(self.nchan):
953 953 index = channelIndexList[i]
954 954 title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
955 955 axes = self.axesList[i*self.plotFact]
956 956 z1 = z[i,:].reshape((1,-1))
957 957 axes.pcolorbuffer(x, y, z1,
958 958 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
959 959 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
960 960 ticksize=9, cblabel='', cbsize="1%",colormap=colormap)
961 961
962 962 if showSNR:
963 963 title = "Channel %d SNR: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
964 964 axes = self.axesList[i*self.plotFact + 1]
965 965 SNRdB1 = SNRdB[i,:].reshape((1,-1))
966 966 axes.pcolorbuffer(x, y, SNRdB1,
967 967 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
968 968 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
969 969 ticksize=9, cblabel='', cbsize="1%",colormap='jet')
970 970
971 971
972 972 self.draw()
973 973
974 974 if dataOut.ltctime >= self.xmax:
975 975 self.counter_imagwr = wr_period
976 976 self.isConfig = False
977 977 update_figfile = True
978 978
979 979 self.save(figpath=figpath,
980 980 figfile=figfile,
981 981 save=save,
982 982 ftp=ftp,
983 983 wr_period=wr_period,
984 984 thisDatetime=thisDatetime,
985 985 update_figfile=update_figfile)
986 986
987 987 return dataOut
988 988 @MPDecorator
989 class Parameters1Plot(Figure):
989 class Parameters1Plot_(Figure):
990 990
991 991 __isConfig = None
992 992 __nsubplots = None
993 993
994 994 WIDTHPROF = None
995 995 HEIGHTPROF = None
996 996 PREFIX = 'prm'
997 997
998 998 def __init__(self):
999 999 Figure.__init__(self)
1000 1000 self.timerange = 2*60*60
1001 1001 self.isConfig = False
1002 1002 self.__nsubplots = 1
1003 1003
1004 1004 self.WIDTH = 800
1005 1005 self.HEIGHT = 180
1006 1006 self.WIDTHPROF = 120
1007 1007 self.HEIGHTPROF = 0
1008 1008 self.counter_imagwr = 0
1009 1009
1010 1010 self.PLOT_CODE = PARMS_CODE
1011 1011
1012 1012 self.FTP_WEI = None
1013 1013 self.EXP_CODE = None
1014 1014 self.SUB_EXP_CODE = None
1015 1015 self.PLOT_POS = None
1016 1016 self.tmin = None
1017 1017 self.tmax = None
1018 1018
1019 1019 self.xmin = None
1020 1020 self.xmax = None
1021 1021
1022 1022 self.figfile = None
1023 1023
1024 1024 def getSubplots(self):
1025 1025
1026 1026 ncol = 1
1027 1027 nrow = self.nplots
1028 1028
1029 1029 return nrow, ncol
1030 1030
1031 1031 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1032 1032
1033 1033 self.__showprofile = showprofile
1034 1034 self.nplots = nplots
1035 1035
1036 1036 ncolspan = 1
1037 1037 colspan = 1
1038 1038
1039 1039 self.createFigure(id = id,
1040 1040 wintitle = wintitle,
1041 1041 widthplot = self.WIDTH + self.WIDTHPROF,
1042 1042 heightplot = self.HEIGHT + self.HEIGHTPROF,
1043 1043 show=show)
1044 1044
1045 1045 nrow, ncol = self.getSubplots()
1046 1046
1047 1047 counter = 0
1048 1048 for y in range(nrow):
1049 1049 for x in range(ncol):
1050 1050
1051 1051 if counter >= self.nplots:
1052 1052 break
1053 1053
1054 1054 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1055 1055
1056 1056 if showprofile:
1057 1057 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
1058 1058
1059 1059 counter += 1
1060 1060
1061 1061 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
1062 1062 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,timerange=None,
1063 1063 parameterIndex = None, onlyPositive = False,
1064 1064 SNRthresh = -numpy.inf, SNR = True, SNRmin = None, SNRmax = None, onlySNR = False,
1065 1065 DOP = True,
1066 1066 zlabel = "", parameterName = "", parameterObject = "data_param",
1067 1067 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
1068 1068 server=None, folder=None, username=None, password=None,
1069 1069 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1070 1070 #print inspect.getargspec(self.run).args
1071 1071 """
1072 1072
1073 1073 Input:
1074 1074 dataOut :
1075 1075 id :
1076 1076 wintitle :
1077 1077 channelList :
1078 1078 showProfile :
1079 1079 xmin : None,
1080 1080 xmax : None,
1081 1081 ymin : None,
1082 1082 ymax : None,
1083 1083 zmin : None,
1084 1084 zmax : None
1085 1085 """
1086 1086 if dataOut.flagNoData:
1087 1087 return dataOut
1088 1088
1089 1089 data_param = getattr(dataOut, parameterObject)
1090 1090
1091 1091 if channelList == None:
1092 1092 channelIndexList = numpy.arange(data_param.shape[0])
1093 1093 else:
1094 1094 channelIndexList = numpy.array(channelList)
1095 1095
1096 1096 nchan = len(channelIndexList) #Number of channels being plotted
1097 1097
1098 1098 if nchan < 1:
1099 1099 return
1100 1100
1101 1101 nGraphsByChannel = 0
1102 1102
1103 1103 if SNR:
1104 1104 nGraphsByChannel += 1
1105 1105 if DOP:
1106 1106 nGraphsByChannel += 1
1107 1107
1108 1108 if nGraphsByChannel < 1:
1109 1109 return
1110 1110
1111 1111 nplots = nGraphsByChannel*nchan
1112 1112
1113 1113 if timerange is not None:
1114 1114 self.timerange = timerange
1115 1115
1116 1116 #tmin = None
1117 1117 #tmax = None
1118 1118 if parameterIndex == None:
1119 1119 parameterIndex = 1
1120 1120
1121 1121 x = dataOut.getTimeRange1(dataOut.paramInterval)
1122 1122 y = dataOut.heightList
1123 1123
1124 1124 if dataOut.data_param.ndim == 3:
1125 1125 z = dataOut.data_param[channelIndexList,parameterIndex,:]
1126 1126 else:
1127 1127 z = dataOut.data_param[channelIndexList,:]
1128 1128
1129 1129 if dataOut.data_SNR is not None:
1130 1130 if dataOut.data_SNR.ndim == 2:
1131 1131 SNRavg = numpy.average(dataOut.data_SNR, axis=0)
1132 1132 else:
1133 1133 SNRavg = dataOut.data_SNR
1134 1134 SNRdB = 10*numpy.log10(SNRavg)
1135 1135
1136 1136 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1137 1137 title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
1138 1138 xlabel = ""
1139 1139 ylabel = "Range (Km)"
1140 1140
1141 1141 if onlyPositive:
1142 1142 colormap = "jet"
1143 1143 zmin = 0
1144 1144 else: colormap = "RdBu_r"
1145 1145
1146 1146 if not self.isConfig:
1147 1147
1148 1148 self.setup(id=id,
1149 1149 nplots=nplots,
1150 1150 wintitle=wintitle,
1151 1151 showprofile=showprofile,
1152 1152 show=show)
1153 1153
1154 1154 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1155 1155
1156 1156 if ymin == None: ymin = numpy.nanmin(y)
1157 1157 if ymax == None: ymax = numpy.nanmax(y)
1158 1158 if zmin == None: zmin = numpy.nanmin(z)
1159 1159 if zmax == None: zmax = numpy.nanmax(z)
1160 1160
1161 1161 if SNR:
1162 1162 if SNRmin == None: SNRmin = numpy.nanmin(SNRdB)
1163 1163 if SNRmax == None: SNRmax = numpy.nanmax(SNRdB)
1164 1164
1165 1165 self.FTP_WEI = ftp_wei
1166 1166 self.EXP_CODE = exp_code
1167 1167 self.SUB_EXP_CODE = sub_exp_code
1168 1168 self.PLOT_POS = plot_pos
1169 1169
1170 1170 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1171 1171 self.isConfig = True
1172 1172 self.figfile = figfile
1173 1173
1174 1174 self.setWinTitle(title)
1175 1175
1176 1176 if ((self.xmax - x[1]) < (x[1]-x[0])):
1177 1177 x[1] = self.xmax
1178 1178
1179 1179 for i in range(nchan):
1180 1180
1181 1181 if (SNR and not onlySNR): j = 2*i
1182 1182 else: j = i
1183 1183
1184 1184 j = nGraphsByChannel*i
1185 1185
1186 1186 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
1187 1187 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
1188 1188
1189 1189 if not onlySNR:
1190 1190 axes = self.axesList[j*self.__nsubplots]
1191 1191 z1 = z[i,:].reshape((1,-1))
1192 1192 axes.pcolorbuffer(x, y, z1,
1193 1193 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1194 1194 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap,
1195 1195 ticksize=9, cblabel=zlabel, cbsize="1%")
1196 1196
1197 1197 if DOP:
1198 1198 title = "%s Channel %d: %s" %(parameterName, channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1199 1199
1200 1200 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
1201 1201 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
1202 1202 axes = self.axesList[j]
1203 1203 z1 = z[i,:].reshape((1,-1))
1204 1204 axes.pcolorbuffer(x, y, z1,
1205 1205 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
1206 1206 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap,
1207 1207 ticksize=9, cblabel=zlabel, cbsize="1%")
1208 1208
1209 1209 if SNR:
1210 1210 title = "Channel %d Signal Noise Ratio (SNR): %s" %(channelIndexList[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1211 1211 axes = self.axesList[(j)*self.__nsubplots]
1212 1212 if not onlySNR:
1213 1213 axes = self.axesList[(j + 1)*self.__nsubplots]
1214 1214
1215 1215 axes = self.axesList[(j + nGraphsByChannel-1)]
1216 1216 z1 = SNRdB.reshape((1,-1))
1217 1217 axes.pcolorbuffer(x, y, z1,
1218 1218 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1219 1219 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap="jet",
1220 1220 ticksize=9, cblabel=zlabel, cbsize="1%")
1221 1221
1222 1222
1223 1223
1224 1224 self.draw()
1225 1225
1226 1226 if x[1] >= self.axesList[0].xmax:
1227 1227 self.counter_imagwr = wr_period
1228 1228 self.isConfig = False
1229 1229 self.figfile = None
1230 1230
1231 1231 self.save(figpath=figpath,
1232 1232 figfile=figfile,
1233 1233 save=save,
1234 1234 ftp=ftp,
1235 1235 wr_period=wr_period,
1236 1236 thisDatetime=thisDatetime,
1237 1237 update_figfile=False)
1238 1238 return dataOut
1239 1239
1240 class SpectralFittingPlot(Figure):
1240 class SpectralFittingPlot_(Figure):
1241 1241
1242 1242 __isConfig = None
1243 1243 __nsubplots = None
1244 1244
1245 1245 WIDTHPROF = None
1246 1246 HEIGHTPROF = None
1247 1247 PREFIX = 'prm'
1248 1248
1249 1249
1250 1250 N = None
1251 1251 ippSeconds = None
1252 1252
1253 1253 def __init__(self, **kwargs):
1254 1254 Figure.__init__(self, **kwargs)
1255 1255 self.isConfig = False
1256 1256 self.__nsubplots = 1
1257 1257
1258 1258 self.PLOT_CODE = SPECFIT_CODE
1259 1259
1260 1260 self.WIDTH = 450
1261 1261 self.HEIGHT = 250
1262 1262 self.WIDTHPROF = 0
1263 1263 self.HEIGHTPROF = 0
1264 1264
1265 1265 def getSubplots(self):
1266 1266
1267 1267 ncol = int(numpy.sqrt(self.nplots)+0.9)
1268 1268 nrow = int(self.nplots*1./ncol + 0.9)
1269 1269
1270 1270 return nrow, ncol
1271 1271
1272 1272 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
1273 1273
1274 1274 showprofile = False
1275 1275 self.__showprofile = showprofile
1276 1276 self.nplots = nplots
1277 1277
1278 1278 ncolspan = 5
1279 1279 colspan = 4
1280 1280 if showprofile:
1281 1281 ncolspan = 5
1282 1282 colspan = 4
1283 1283 self.__nsubplots = 2
1284 1284
1285 1285 self.createFigure(id = id,
1286 1286 wintitle = wintitle,
1287 1287 widthplot = self.WIDTH + self.WIDTHPROF,
1288 1288 heightplot = self.HEIGHT + self.HEIGHTPROF,
1289 1289 show=show)
1290 1290
1291 1291 nrow, ncol = self.getSubplots()
1292 1292
1293 1293 counter = 0
1294 1294 for y in range(nrow):
1295 1295 for x in range(ncol):
1296 1296
1297 1297 if counter >= self.nplots:
1298 1298 break
1299 1299
1300 1300 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1301 1301
1302 1302 if showprofile:
1303 1303 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
1304 1304
1305 1305 counter += 1
1306 1306
1307 1307 def run(self, dataOut, id, cutHeight=None, fit=False, wintitle="", channelList=None, showprofile=True,
1308 1308 xmin=None, xmax=None, ymin=None, ymax=None,
1309 1309 save=False, figpath='./', figfile=None, show=True):
1310 1310
1311 1311 """
1312 1312
1313 1313 Input:
1314 1314 dataOut :
1315 1315 id :
1316 1316 wintitle :
1317 1317 channelList :
1318 1318 showProfile :
1319 1319 xmin : None,
1320 1320 xmax : None,
1321 1321 zmin : None,
1322 1322 zmax : None
1323 1323 """
1324 1324
1325 1325 if cutHeight==None:
1326 1326 h=270
1327 1327 heightindex = numpy.abs(cutHeight - dataOut.heightList).argmin()
1328 1328 cutHeight = dataOut.heightList[heightindex]
1329 1329
1330 1330 factor = dataOut.normFactor
1331 1331 x = dataOut.abscissaList[:-1]
1332 1332 #y = dataOut.getHeiRange()
1333 1333
1334 1334 z = dataOut.data_pre[:,:,heightindex]/factor
1335 1335 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1336 1336 avg = numpy.average(z, axis=1)
1337 1337 listChannels = z.shape[0]
1338 1338
1339 1339 #Reconstruct Function
1340 1340 if fit==True:
1341 1341 groupArray = dataOut.groupList
1342 1342 listChannels = groupArray.reshape((groupArray.size))
1343 1343 listChannels.sort()
1344 1344 spcFitLine = numpy.zeros(z.shape)
1345 1345 constants = dataOut.constants
1346 1346
1347 1347 nGroups = groupArray.shape[0]
1348 1348 nChannels = groupArray.shape[1]
1349 1349 nProfiles = z.shape[1]
1350 1350
1351 1351 for f in range(nGroups):
1352 1352 groupChann = groupArray[f,:]
1353 1353 p = dataOut.data_param[f,:,heightindex]
1354 1354 # p = numpy.array([ 89.343967,0.14036615,0.17086219,18.89835291,1.58388365,1.55099167])
1355 1355 fitLineAux = dataOut.library.modelFunction(p, constants)*nProfiles
1356 1356 fitLineAux = fitLineAux.reshape((nChannels,nProfiles))
1357 1357 spcFitLine[groupChann,:] = fitLineAux
1358 1358 # spcFitLine = spcFitLine/factor
1359 1359
1360 1360 z = z[listChannels,:]
1361 1361 spcFitLine = spcFitLine[listChannels,:]
1362 1362 spcFitLinedB = 10*numpy.log10(spcFitLine)
1363 1363
1364 1364 zdB = 10*numpy.log10(z)
1365 1365 #thisDatetime = dataOut.datatime
1366 1366 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1367 1367 title = wintitle + " Doppler Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
1368 1368 xlabel = "Velocity (m/s)"
1369 1369 ylabel = "Spectrum"
1370 1370
1371 1371 if not self.isConfig:
1372 1372
1373 1373 nplots = listChannels.size
1374 1374
1375 1375 self.setup(id=id,
1376 1376 nplots=nplots,
1377 1377 wintitle=wintitle,
1378 1378 showprofile=showprofile,
1379 1379 show=show)
1380 1380
1381 1381 if xmin == None: xmin = numpy.nanmin(x)
1382 1382 if xmax == None: xmax = numpy.nanmax(x)
1383 1383 if ymin == None: ymin = numpy.nanmin(zdB)
1384 1384 if ymax == None: ymax = numpy.nanmax(zdB)+2
1385 1385
1386 1386 self.isConfig = True
1387 1387
1388 1388 self.setWinTitle(title)
1389 1389 for i in range(self.nplots):
1390 1390 # title = "Channel %d: %4.2fdB" %(dataOut.channelList[i]+1, noisedB[i])
1391 1391 title = "Height %4.1f km\nChannel %d:" %(cutHeight, listChannels[i])
1392 1392 axes = self.axesList[i*self.__nsubplots]
1393 1393 if fit == False:
1394 1394 axes.pline(x, zdB[i,:],
1395 1395 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1396 1396 xlabel=xlabel, ylabel=ylabel, title=title
1397 1397 )
1398 1398 if fit == True:
1399 1399 fitline=spcFitLinedB[i,:]
1400 1400 y=numpy.vstack([zdB[i,:],fitline] )
1401 1401 legendlabels=['Data','Fitting']
1402 1402 axes.pmultilineyaxis(x, y,
1403 1403 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1404 1404 xlabel=xlabel, ylabel=ylabel, title=title,
1405 1405 legendlabels=legendlabels, marker=None,
1406 1406 linestyle='solid', grid='both')
1407 1407
1408 1408 self.draw()
1409 1409
1410 1410 self.save(figpath=figpath,
1411 1411 figfile=figfile,
1412 1412 save=save,
1413 1413 ftp=ftp,
1414 1414 wr_period=wr_period,
1415 1415 thisDatetime=thisDatetime)
1416 1416
1417 1417
1418 class EWDriftsPlot(Figure):
1418 class EWDriftsPlot_(Figure):
1419 1419
1420 1420 __isConfig = None
1421 1421 __nsubplots = None
1422 1422
1423 1423 WIDTHPROF = None
1424 1424 HEIGHTPROF = None
1425 1425 PREFIX = 'drift'
1426 1426
1427 1427 def __init__(self, **kwargs):
1428 1428 Figure.__init__(self, **kwargs)
1429 1429 self.timerange = 2*60*60
1430 1430 self.isConfig = False
1431 1431 self.__nsubplots = 1
1432 1432
1433 1433 self.WIDTH = 800
1434 1434 self.HEIGHT = 150
1435 1435 self.WIDTHPROF = 120
1436 1436 self.HEIGHTPROF = 0
1437 1437 self.counter_imagwr = 0
1438 1438
1439 1439 self.PLOT_CODE = EWDRIFT_CODE
1440 1440
1441 1441 self.FTP_WEI = None
1442 1442 self.EXP_CODE = None
1443 1443 self.SUB_EXP_CODE = None
1444 1444 self.PLOT_POS = None
1445 1445 self.tmin = None
1446 1446 self.tmax = None
1447 1447
1448 1448 self.xmin = None
1449 1449 self.xmax = None
1450 1450
1451 1451 self.figfile = None
1452 1452
1453 1453 def getSubplots(self):
1454 1454
1455 1455 ncol = 1
1456 1456 nrow = self.nplots
1457 1457
1458 1458 return nrow, ncol
1459 1459
1460 1460 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1461 1461
1462 1462 self.__showprofile = showprofile
1463 1463 self.nplots = nplots
1464 1464
1465 1465 ncolspan = 1
1466 1466 colspan = 1
1467 1467
1468 1468 self.createFigure(id = id,
1469 1469 wintitle = wintitle,
1470 1470 widthplot = self.WIDTH + self.WIDTHPROF,
1471 1471 heightplot = self.HEIGHT + self.HEIGHTPROF,
1472 1472 show=show)
1473 1473
1474 1474 nrow, ncol = self.getSubplots()
1475 1475
1476 1476 counter = 0
1477 1477 for y in range(nrow):
1478 1478 if counter >= self.nplots:
1479 1479 break
1480 1480
1481 1481 self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1)
1482 1482 counter += 1
1483 1483
1484 1484 def run(self, dataOut, id, wintitle="", channelList=None,
1485 1485 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
1486 1486 zmaxVertical = None, zminVertical = None, zmaxZonal = None, zminZonal = None,
1487 1487 timerange=None, SNRthresh = -numpy.inf, SNRmin = None, SNRmax = None, SNR_1 = False,
1488 1488 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
1489 1489 server=None, folder=None, username=None, password=None,
1490 1490 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1491 1491 """
1492 1492
1493 1493 Input:
1494 1494 dataOut :
1495 1495 id :
1496 1496 wintitle :
1497 1497 channelList :
1498 1498 showProfile :
1499 1499 xmin : None,
1500 1500 xmax : None,
1501 1501 ymin : None,
1502 1502 ymax : None,
1503 1503 zmin : None,
1504 1504 zmax : None
1505 1505 """
1506 1506
1507 1507 if timerange is not None:
1508 1508 self.timerange = timerange
1509 1509
1510 1510 tmin = None
1511 1511 tmax = None
1512 1512
1513 1513 x = dataOut.getTimeRange1(dataOut.outputInterval)
1514 1514 # y = dataOut.heightList
1515 1515 y = dataOut.heightList
1516 1516
1517 1517 z = dataOut.data_output
1518 1518 nplots = z.shape[0] #Number of wind dimensions estimated
1519 1519 nplotsw = nplots
1520 1520
1521 1521 #If there is a SNR function defined
1522 1522 if dataOut.data_SNR is not None:
1523 1523 nplots += 1
1524 1524 SNR = dataOut.data_SNR
1525 1525
1526 1526 if SNR_1:
1527 1527 SNR += 1
1528 1528
1529 1529 SNRavg = numpy.average(SNR, axis=0)
1530 1530
1531 1531 SNRdB = 10*numpy.log10(SNR)
1532 1532 SNRavgdB = 10*numpy.log10(SNRavg)
1533 1533
1534 1534 ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0]
1535 1535
1536 1536 for i in range(nplotsw):
1537 1537 z[i,ind] = numpy.nan
1538 1538
1539 1539
1540 1540 showprofile = False
1541 1541 # thisDatetime = dataOut.datatime
1542 1542 thisDatetime = datetime.datetime.utcfromtimestamp(x[1])
1543 1543 title = wintitle + " EW Drifts"
1544 1544 xlabel = ""
1545 1545 ylabel = "Height (Km)"
1546 1546
1547 1547 if not self.isConfig:
1548 1548
1549 1549 self.setup(id=id,
1550 1550 nplots=nplots,
1551 1551 wintitle=wintitle,
1552 1552 showprofile=showprofile,
1553 1553 show=show)
1554 1554
1555 1555 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1556 1556
1557 1557 if ymin == None: ymin = numpy.nanmin(y)
1558 1558 if ymax == None: ymax = numpy.nanmax(y)
1559 1559
1560 1560 if zmaxZonal == None: zmaxZonal = numpy.nanmax(abs(z[0,:]))
1561 1561 if zminZonal == None: zminZonal = -zmaxZonal
1562 1562 if zmaxVertical == None: zmaxVertical = numpy.nanmax(abs(z[1,:]))
1563 1563 if zminVertical == None: zminVertical = -zmaxVertical
1564 1564
1565 1565 if dataOut.data_SNR is not None:
1566 1566 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
1567 1567 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
1568 1568
1569 1569 self.FTP_WEI = ftp_wei
1570 1570 self.EXP_CODE = exp_code
1571 1571 self.SUB_EXP_CODE = sub_exp_code
1572 1572 self.PLOT_POS = plot_pos
1573 1573
1574 1574 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1575 1575 self.isConfig = True
1576 1576
1577 1577
1578 1578 self.setWinTitle(title)
1579 1579
1580 1580 if ((self.xmax - x[1]) < (x[1]-x[0])):
1581 1581 x[1] = self.xmax
1582 1582
1583 1583 strWind = ['Zonal','Vertical']
1584 1584 strCb = 'Velocity (m/s)'
1585 1585 zmaxVector = [zmaxZonal, zmaxVertical]
1586 1586 zminVector = [zminZonal, zminVertical]
1587 1587
1588 1588 for i in range(nplotsw):
1589 1589
1590 1590 title = "%s Drifts: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1591 1591 axes = self.axesList[i*self.__nsubplots]
1592 1592
1593 1593 z1 = z[i,:].reshape((1,-1))
1594 1594
1595 1595 axes.pcolorbuffer(x, y, z1,
1596 1596 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i],
1597 1597 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1598 1598 ticksize=9, cblabel=strCb, cbsize="1%", colormap="RdBu_r")
1599 1599
1600 1600 if dataOut.data_SNR is not None:
1601 1601 i += 1
1602 1602 if SNR_1:
1603 1603 title = "Signal Noise Ratio + 1 (SNR+1): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1604 1604 else:
1605 1605 title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1606 1606 axes = self.axesList[i*self.__nsubplots]
1607 1607 SNRavgdB = SNRavgdB.reshape((1,-1))
1608 1608
1609 1609 axes.pcolorbuffer(x, y, SNRavgdB,
1610 1610 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1611 1611 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1612 1612 ticksize=9, cblabel='', cbsize="1%", colormap="jet")
1613 1613
1614 1614 self.draw()
1615 1615
1616 1616 if x[1] >= self.axesList[0].xmax:
1617 1617 self.counter_imagwr = wr_period
1618 1618 self.isConfig = False
1619 1619 self.figfile = None
1620 1620
1621 1621
1622 1622
1623 1623
1624 class PhasePlot(Figure):
1624 class PhasePlot_(Figure):
1625 1625
1626 1626 __isConfig = None
1627 1627 __nsubplots = None
1628 1628
1629 1629 PREFIX = 'mphase'
1630 1630
1631 1631
1632 1632 def __init__(self, **kwargs):
1633 1633 Figure.__init__(self, **kwargs)
1634 1634 self.timerange = 24*60*60
1635 1635 self.isConfig = False
1636 1636 self.__nsubplots = 1
1637 1637 self.counter_imagwr = 0
1638 1638 self.WIDTH = 600
1639 1639 self.HEIGHT = 300
1640 1640 self.WIDTHPROF = 120
1641 1641 self.HEIGHTPROF = 0
1642 1642 self.xdata = None
1643 1643 self.ydata = None
1644 1644
1645 1645 self.PLOT_CODE = MPHASE_CODE
1646 1646
1647 1647 self.FTP_WEI = None
1648 1648 self.EXP_CODE = None
1649 1649 self.SUB_EXP_CODE = None
1650 1650 self.PLOT_POS = None
1651 1651
1652 1652
1653 1653 self.filename_phase = None
1654 1654
1655 1655 self.figfile = None
1656 1656
1657 1657 def getSubplots(self):
1658 1658
1659 1659 ncol = 1
1660 1660 nrow = 1
1661 1661
1662 1662 return nrow, ncol
1663 1663
1664 1664 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1665 1665
1666 1666 self.__showprofile = showprofile
1667 1667 self.nplots = nplots
1668 1668
1669 1669 ncolspan = 7
1670 1670 colspan = 6
1671 1671 self.__nsubplots = 2
1672 1672
1673 1673 self.createFigure(id = id,
1674 1674 wintitle = wintitle,
1675 1675 widthplot = self.WIDTH+self.WIDTHPROF,
1676 1676 heightplot = self.HEIGHT+self.HEIGHTPROF,
1677 1677 show=show)
1678 1678
1679 1679 nrow, ncol = self.getSubplots()
1680 1680
1681 1681 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1682 1682
1683 1683
1684 1684 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1685 1685 xmin=None, xmax=None, ymin=None, ymax=None,
1686 1686 timerange=None,
1687 1687 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1688 1688 server=None, folder=None, username=None, password=None,
1689 1689 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1690 1690
1691 1691
1692 1692 tmin = None
1693 1693 tmax = None
1694 1694 x = dataOut.getTimeRange1(dataOut.outputInterval)
1695 1695 y = dataOut.getHeiRange()
1696 1696
1697 1697
1698 1698 #thisDatetime = dataOut.datatime
1699 1699 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
1700 1700 title = wintitle + " Phase of Beacon Signal" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1701 1701 xlabel = "Local Time"
1702 1702 ylabel = "Phase"
1703 1703
1704 1704
1705 1705 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1706 1706 phase_beacon = dataOut.data_output
1707 1707 update_figfile = False
1708 1708
1709 1709 if not self.isConfig:
1710 1710
1711 1711 self.nplots = phase_beacon.size
1712 1712
1713 1713 self.setup(id=id,
1714 1714 nplots=self.nplots,
1715 1715 wintitle=wintitle,
1716 1716 showprofile=showprofile,
1717 1717 show=show)
1718 1718
1719 1719 if timerange is not None:
1720 1720 self.timerange = timerange
1721 1721
1722 1722 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1723 1723
1724 1724 if ymin == None: ymin = numpy.nanmin(phase_beacon) - 10.0
1725 1725 if ymax == None: ymax = numpy.nanmax(phase_beacon) + 10.0
1726 1726
1727 1727 self.FTP_WEI = ftp_wei
1728 1728 self.EXP_CODE = exp_code
1729 1729 self.SUB_EXP_CODE = sub_exp_code
1730 1730 self.PLOT_POS = plot_pos
1731 1731
1732 1732 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1733 1733 self.isConfig = True
1734 1734 self.figfile = figfile
1735 1735 self.xdata = numpy.array([])
1736 1736 self.ydata = numpy.array([])
1737 1737
1738 1738 #open file beacon phase
1739 1739 path = '%s%03d' %(self.PREFIX, self.id)
1740 1740 beacon_file = os.path.join(path,'%s.txt'%self.name)
1741 1741 self.filename_phase = os.path.join(figpath,beacon_file)
1742 1742 update_figfile = True
1743 1743
1744 1744
1745 1745 #store data beacon phase
1746 1746 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1747 1747
1748 1748 self.setWinTitle(title)
1749 1749
1750 1750
1751 1751 title = "Phase Offset %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1752 1752
1753 1753 legendlabels = ["phase %d"%(chan) for chan in numpy.arange(self.nplots)]
1754 1754
1755 1755 axes = self.axesList[0]
1756 1756
1757 1757 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1758 1758
1759 1759 if len(self.ydata)==0:
1760 1760 self.ydata = phase_beacon.reshape(-1,1)
1761 1761 else:
1762 1762 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1763 1763
1764 1764
1765 1765 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1766 1766 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1767 1767 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1768 1768 XAxisAsTime=True, grid='both'
1769 1769 )
1770 1770
1771 1771 self.draw()
1772 1772
1773 1773 self.save(figpath=figpath,
1774 1774 figfile=figfile,
1775 1775 save=save,
1776 1776 ftp=ftp,
1777 1777 wr_period=wr_period,
1778 1778 thisDatetime=thisDatetime,
1779 1779 update_figfile=update_figfile)
1780 1780
1781 1781 if dataOut.ltctime + dataOut.outputInterval >= self.xmax:
1782 1782 self.counter_imagwr = wr_period
1783 1783 self.isConfig = False
1784 1784 update_figfile = True
1785 1785
1786 1786
1787 1787
1788 class NSMeteorDetection1Plot(Figure):
1788 class NSMeteorDetection1Plot_(Figure):
1789 1789
1790 1790 isConfig = None
1791 1791 __nsubplots = None
1792 1792
1793 1793 WIDTHPROF = None
1794 1794 HEIGHTPROF = None
1795 1795 PREFIX = 'nsm'
1796 1796
1797 1797 zminList = None
1798 1798 zmaxList = None
1799 1799 cmapList = None
1800 1800 titleList = None
1801 1801 nPairs = None
1802 1802 nChannels = None
1803 1803 nParam = None
1804 1804
1805 1805 def __init__(self, **kwargs):
1806 1806 Figure.__init__(self, **kwargs)
1807 1807 self.isConfig = False
1808 1808 self.__nsubplots = 1
1809 1809
1810 1810 self.WIDTH = 750
1811 1811 self.HEIGHT = 250
1812 1812 self.WIDTHPROF = 120
1813 1813 self.HEIGHTPROF = 0
1814 1814 self.counter_imagwr = 0
1815 1815
1816 1816 self.PLOT_CODE = SPEC_CODE
1817 1817
1818 1818 self.FTP_WEI = None
1819 1819 self.EXP_CODE = None
1820 1820 self.SUB_EXP_CODE = None
1821 1821 self.PLOT_POS = None
1822 1822
1823 1823 self.__xfilter_ena = False
1824 1824 self.__yfilter_ena = False
1825 1825
1826 1826 def getSubplots(self):
1827 1827
1828 1828 ncol = 3
1829 1829 nrow = int(numpy.ceil(self.nplots/3.0))
1830 1830
1831 1831 return nrow, ncol
1832 1832
1833 1833 def setup(self, id, nplots, wintitle, show=True):
1834 1834
1835 1835 self.nplots = nplots
1836 1836
1837 1837 ncolspan = 1
1838 1838 colspan = 1
1839 1839
1840 1840 self.createFigure(id = id,
1841 1841 wintitle = wintitle,
1842 1842 widthplot = self.WIDTH + self.WIDTHPROF,
1843 1843 heightplot = self.HEIGHT + self.HEIGHTPROF,
1844 1844 show=show)
1845 1845
1846 1846 nrow, ncol = self.getSubplots()
1847 1847
1848 1848 counter = 0
1849 1849 for y in range(nrow):
1850 1850 for x in range(ncol):
1851 1851
1852 1852 if counter >= self.nplots:
1853 1853 break
1854 1854
1855 1855 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1856 1856
1857 1857 counter += 1
1858 1858
1859 1859 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
1860 1860 xmin=None, xmax=None, ymin=None, ymax=None, SNRmin=None, SNRmax=None,
1861 1861 vmin=None, vmax=None, wmin=None, wmax=None, mode = 'SA',
1862 1862 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1863 1863 server=None, folder=None, username=None, password=None,
1864 1864 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
1865 1865 xaxis="frequency"):
1866 1866
1867 1867 """
1868 1868
1869 1869 Input:
1870 1870 dataOut :
1871 1871 id :
1872 1872 wintitle :
1873 1873 channelList :
1874 1874 showProfile :
1875 1875 xmin : None,
1876 1876 xmax : None,
1877 1877 ymin : None,
1878 1878 ymax : None,
1879 1879 zmin : None,
1880 1880 zmax : None
1881 1881 """
1882 1882 #SEPARAR EN DOS PLOTS
1883 1883 nParam = dataOut.data_param.shape[1] - 3
1884 1884
1885 1885 utctime = dataOut.data_param[0,0]
1886 1886 tmet = dataOut.data_param[:,1].astype(int)
1887 1887 hmet = dataOut.data_param[:,2].astype(int)
1888 1888
1889 1889 x = dataOut.abscissaList
1890 1890 y = dataOut.heightList
1891 1891
1892 1892 z = numpy.zeros((nParam, y.size, x.size - 1))
1893 1893 z[:,:] = numpy.nan
1894 1894 z[:,hmet,tmet] = dataOut.data_param[:,3:].T
1895 1895 z[0,:,:] = 10*numpy.log10(z[0,:,:])
1896 1896
1897 1897 xlabel = "Time (s)"
1898 1898 ylabel = "Range (km)"
1899 1899
1900 1900 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
1901 1901
1902 1902 if not self.isConfig:
1903 1903
1904 1904 nplots = nParam
1905 1905
1906 1906 self.setup(id=id,
1907 1907 nplots=nplots,
1908 1908 wintitle=wintitle,
1909 1909 show=show)
1910 1910
1911 1911 if xmin is None: xmin = numpy.nanmin(x)
1912 1912 if xmax is None: xmax = numpy.nanmax(x)
1913 1913 if ymin is None: ymin = numpy.nanmin(y)
1914 1914 if ymax is None: ymax = numpy.nanmax(y)
1915 1915 if SNRmin is None: SNRmin = numpy.nanmin(z[0,:])
1916 1916 if SNRmax is None: SNRmax = numpy.nanmax(z[0,:])
1917 1917 if vmax is None: vmax = numpy.nanmax(numpy.abs(z[1,:]))
1918 1918 if vmin is None: vmin = -vmax
1919 1919 if wmin is None: wmin = 0
1920 1920 if wmax is None: wmax = 50
1921 1921
1922 1922 pairsList = dataOut.groupList
1923 1923 self.nPairs = len(dataOut.groupList)
1924 1924
1925 1925 zminList = [SNRmin, vmin, cmin] + [pmin]*self.nPairs
1926 1926 zmaxList = [SNRmax, vmax, cmax] + [pmax]*self.nPairs
1927 1927 titleList = ["SNR","Radial Velocity","Coherence"]
1928 1928 cmapList = ["jet","RdBu_r","jet"]
1929 1929
1930 1930 for i in range(self.nPairs):
1931 1931 strAux1 = "Phase Difference "+ str(pairsList[i][0]) + str(pairsList[i][1])
1932 1932 titleList = titleList + [strAux1]
1933 1933 cmapList = cmapList + ["RdBu_r"]
1934 1934
1935 1935 self.zminList = zminList
1936 1936 self.zmaxList = zmaxList
1937 1937 self.cmapList = cmapList
1938 1938 self.titleList = titleList
1939 1939
1940 1940 self.FTP_WEI = ftp_wei
1941 1941 self.EXP_CODE = exp_code
1942 1942 self.SUB_EXP_CODE = sub_exp_code
1943 1943 self.PLOT_POS = plot_pos
1944 1944
1945 1945 self.isConfig = True
1946 1946
1947 1947 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
1948 1948
1949 1949 for i in range(nParam):
1950 1950 title = self.titleList[i] + ": " +str_datetime
1951 1951 axes = self.axesList[i]
1952 1952 axes.pcolor(x, y, z[i,:].T,
1953 1953 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=self.zminList[i], zmax=self.zmaxList[i],
1954 1954 xlabel=xlabel, ylabel=ylabel, title=title, colormap=self.cmapList[i],ticksize=9, cblabel='')
1955 1955 self.draw()
1956 1956
1957 1957 if figfile == None:
1958 1958 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
1959 1959 name = str_datetime
1960 1960 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
1961 1961 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
1962 1962 figfile = self.getFilename(name)
1963 1963
1964 1964 self.save(figpath=figpath,
1965 1965 figfile=figfile,
1966 1966 save=save,
1967 1967 ftp=ftp,
1968 1968 wr_period=wr_period,
1969 1969 thisDatetime=thisDatetime)
1970 1970
1971 1971
1972 class NSMeteorDetection2Plot(Figure):
1972 class NSMeteorDetection2Plot_(Figure):
1973 1973
1974 1974 isConfig = None
1975 1975 __nsubplots = None
1976 1976
1977 1977 WIDTHPROF = None
1978 1978 HEIGHTPROF = None
1979 1979 PREFIX = 'nsm'
1980 1980
1981 1981 zminList = None
1982 1982 zmaxList = None
1983 1983 cmapList = None
1984 1984 titleList = None
1985 1985 nPairs = None
1986 1986 nChannels = None
1987 1987 nParam = None
1988 1988
1989 1989 def __init__(self, **kwargs):
1990 1990 Figure.__init__(self, **kwargs)
1991 1991 self.isConfig = False
1992 1992 self.__nsubplots = 1
1993 1993
1994 1994 self.WIDTH = 750
1995 1995 self.HEIGHT = 250
1996 1996 self.WIDTHPROF = 120
1997 1997 self.HEIGHTPROF = 0
1998 1998 self.counter_imagwr = 0
1999 1999
2000 2000 self.PLOT_CODE = SPEC_CODE
2001 2001
2002 2002 self.FTP_WEI = None
2003 2003 self.EXP_CODE = None
2004 2004 self.SUB_EXP_CODE = None
2005 2005 self.PLOT_POS = None
2006 2006
2007 2007 self.__xfilter_ena = False
2008 2008 self.__yfilter_ena = False
2009 2009
2010 2010 def getSubplots(self):
2011 2011
2012 2012 ncol = 3
2013 2013 nrow = int(numpy.ceil(self.nplots/3.0))
2014 2014
2015 2015 return nrow, ncol
2016 2016
2017 2017 def setup(self, id, nplots, wintitle, show=True):
2018 2018
2019 2019 self.nplots = nplots
2020 2020
2021 2021 ncolspan = 1
2022 2022 colspan = 1
2023 2023
2024 2024 self.createFigure(id = id,
2025 2025 wintitle = wintitle,
2026 2026 widthplot = self.WIDTH + self.WIDTHPROF,
2027 2027 heightplot = self.HEIGHT + self.HEIGHTPROF,
2028 2028 show=show)
2029 2029
2030 2030 nrow, ncol = self.getSubplots()
2031 2031
2032 2032 counter = 0
2033 2033 for y in range(nrow):
2034 2034 for x in range(ncol):
2035 2035
2036 2036 if counter >= self.nplots:
2037 2037 break
2038 2038
2039 2039 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
2040 2040
2041 2041 counter += 1
2042 2042
2043 2043 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
2044 2044 xmin=None, xmax=None, ymin=None, ymax=None, SNRmin=None, SNRmax=None,
2045 2045 vmin=None, vmax=None, wmin=None, wmax=None, mode = 'SA',
2046 2046 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
2047 2047 server=None, folder=None, username=None, password=None,
2048 2048 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
2049 2049 xaxis="frequency"):
2050 2050
2051 2051 """
2052 2052
2053 2053 Input:
2054 2054 dataOut :
2055 2055 id :
2056 2056 wintitle :
2057 2057 channelList :
2058 2058 showProfile :
2059 2059 xmin : None,
2060 2060 xmax : None,
2061 2061 ymin : None,
2062 2062 ymax : None,
2063 2063 zmin : None,
2064 2064 zmax : None
2065 2065 """
2066 2066 #Rebuild matrix
2067 2067 utctime = dataOut.data_param[0,0]
2068 2068 cmet = dataOut.data_param[:,1].astype(int)
2069 2069 tmet = dataOut.data_param[:,2].astype(int)
2070 2070 hmet = dataOut.data_param[:,3].astype(int)
2071 2071
2072 2072 nParam = 3
2073 2073 nChan = len(dataOut.groupList)
2074 2074 x = dataOut.abscissaList
2075 2075 y = dataOut.heightList
2076 2076
2077 2077 z = numpy.full((nChan, nParam, y.size, x.size - 1),numpy.nan)
2078 2078 z[cmet,:,hmet,tmet] = dataOut.data_param[:,4:]
2079 2079 z[:,0,:,:] = 10*numpy.log10(z[:,0,:,:]) #logarithmic scale
2080 2080 z = numpy.reshape(z, (nChan*nParam, y.size, x.size-1))
2081 2081
2082 2082 xlabel = "Time (s)"
2083 2083 ylabel = "Range (km)"
2084 2084
2085 2085 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.ltctime)
2086 2086
2087 2087 if not self.isConfig:
2088 2088
2089 2089 nplots = nParam*nChan
2090 2090
2091 2091 self.setup(id=id,
2092 2092 nplots=nplots,
2093 2093 wintitle=wintitle,
2094 2094 show=show)
2095 2095
2096 2096 if xmin is None: xmin = numpy.nanmin(x)
2097 2097 if xmax is None: xmax = numpy.nanmax(x)
2098 2098 if ymin is None: ymin = numpy.nanmin(y)
2099 2099 if ymax is None: ymax = numpy.nanmax(y)
2100 2100 if SNRmin is None: SNRmin = numpy.nanmin(z[0,:])
2101 2101 if SNRmax is None: SNRmax = numpy.nanmax(z[0,:])
2102 2102 if vmax is None: vmax = numpy.nanmax(numpy.abs(z[1,:]))
2103 2103 if vmin is None: vmin = -vmax
2104 2104 if wmin is None: wmin = 0
2105 2105 if wmax is None: wmax = 50
2106 2106
2107 2107 self.nChannels = nChan
2108 2108
2109 2109 zminList = []
2110 2110 zmaxList = []
2111 2111 titleList = []
2112 2112 cmapList = []
2113 2113 for i in range(self.nChannels):
2114 2114 strAux1 = "SNR Channel "+ str(i)
2115 2115 strAux2 = "Radial Velocity Channel "+ str(i)
2116 2116 strAux3 = "Spectral Width Channel "+ str(i)
2117 2117
2118 2118 titleList = titleList + [strAux1,strAux2,strAux3]
2119 2119 cmapList = cmapList + ["jet","RdBu_r","jet"]
2120 2120 zminList = zminList + [SNRmin,vmin,wmin]
2121 2121 zmaxList = zmaxList + [SNRmax,vmax,wmax]
2122 2122
2123 2123 self.zminList = zminList
2124 2124 self.zmaxList = zmaxList
2125 2125 self.cmapList = cmapList
2126 2126 self.titleList = titleList
2127 2127
2128 2128 self.FTP_WEI = ftp_wei
2129 2129 self.EXP_CODE = exp_code
2130 2130 self.SUB_EXP_CODE = sub_exp_code
2131 2131 self.PLOT_POS = plot_pos
2132 2132
2133 2133 self.isConfig = True
2134 2134
2135 2135 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
2136 2136
2137 2137 for i in range(self.nplots):
2138 2138 title = self.titleList[i] + ": " +str_datetime
2139 2139 axes = self.axesList[i]
2140 2140 axes.pcolor(x, y, z[i,:].T,
2141 2141 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=self.zminList[i], zmax=self.zmaxList[i],
2142 2142 xlabel=xlabel, ylabel=ylabel, title=title, colormap=self.cmapList[i],ticksize=9, cblabel='')
2143 2143 self.draw()
2144 2144
2145 2145 if figfile == None:
2146 2146 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
2147 2147 name = str_datetime
2148 2148 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
2149 2149 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
2150 2150 figfile = self.getFilename(name)
2151 2151
2152 2152 self.save(figpath=figpath,
2153 2153 figfile=figfile,
2154 2154 save=save,
2155 2155 ftp=ftp,
2156 2156 wr_period=wr_period,
2157 2157 thisDatetime=thisDatetime)
2158 2158 No newline at end of file
@@ -1,1587 +1,1587
1 1 '''
2 2 Created on Jul 9, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import datetime
8 8 import numpy
9 9
10 10 from .figure import Figure, isRealtime, isTimeInHourRange
11 11 from .plotting_codes import *
12 12 from schainpy.model.proc.jroproc_base import MPDecorator
13 13
14 14 from schainpy.utils import log
15 15
16 16 @MPDecorator
17 class SpectraPlot(Figure):
17 class SpectraPlot_(Figure):
18 18
19 19 isConfig = None
20 20 __nsubplots = None
21 21
22 22 WIDTHPROF = None
23 23 HEIGHTPROF = None
24 24 PREFIX = 'spc'
25 25
26 26 def __init__(self):
27 27 Figure.__init__(self)
28 28 self.isConfig = False
29 29 self.__nsubplots = 1
30 30 self.WIDTH = 250
31 31 self.HEIGHT = 250
32 32 self.WIDTHPROF = 120
33 33 self.HEIGHTPROF = 0
34 34 self.counter_imagwr = 0
35 35
36 36 self.PLOT_CODE = SPEC_CODE
37 37
38 38 self.FTP_WEI = None
39 39 self.EXP_CODE = None
40 40 self.SUB_EXP_CODE = None
41 41 self.PLOT_POS = None
42 42
43 43 self.__xfilter_ena = False
44 44 self.__yfilter_ena = False
45 45
46 46 def getSubplots(self):
47 47
48 48 ncol = int(numpy.sqrt(self.nplots)+0.9)
49 49 nrow = int(self.nplots*1./ncol + 0.9)
50 50
51 51 return nrow, ncol
52 52
53 53 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
54 54
55 55 self.__showprofile = showprofile
56 56 self.nplots = nplots
57 57
58 58 ncolspan = 1
59 59 colspan = 1
60 60 if showprofile:
61 61 ncolspan = 3
62 62 colspan = 2
63 63 self.__nsubplots = 2
64 64
65 65 self.createFigure(id = id,
66 66 wintitle = wintitle,
67 67 widthplot = self.WIDTH + self.WIDTHPROF,
68 68 heightplot = self.HEIGHT + self.HEIGHTPROF,
69 69 show=show)
70 70
71 71 nrow, ncol = self.getSubplots()
72 72
73 73 counter = 0
74 74 for y in range(nrow):
75 75 for x in range(ncol):
76 76
77 77 if counter >= self.nplots:
78 78 break
79 79
80 80 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
81 81
82 82 if showprofile:
83 83 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
84 84
85 85 counter += 1
86 86
87 87 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
88 88 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
89 89 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
90 90 server=None, folder=None, username=None, password=None,
91 91 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False,
92 92 xaxis="frequency", colormap='jet', normFactor=None):
93 93
94 94 """
95 95
96 96 Input:
97 97 dataOut :
98 98 id :
99 99 wintitle :
100 100 channelList :
101 101 showProfile :
102 102 xmin : None,
103 103 xmax : None,
104 104 ymin : None,
105 105 ymax : None,
106 106 zmin : None,
107 107 zmax : None
108 108 """
109 109 if dataOut.flagNoData:
110 110 return dataOut
111 111
112 112 if realtime:
113 113 if not(isRealtime(utcdatatime = dataOut.utctime)):
114 114 print('Skipping this plot function')
115 115 return
116 116
117 117 if channelList == None:
118 118 channelIndexList = dataOut.channelIndexList
119 119 else:
120 120 channelIndexList = []
121 121 for channel in channelList:
122 122 if channel not in dataOut.channelList:
123 123 raise ValueError("Channel %d is not in dataOut.channelList" %channel)
124 124 channelIndexList.append(dataOut.channelList.index(channel))
125 125
126 126 if normFactor is None:
127 127 factor = dataOut.normFactor
128 128 else:
129 129 factor = normFactor
130 130 if xaxis == "frequency":
131 131 x = dataOut.getFreqRange(1)/1000.
132 132 xlabel = "Frequency (kHz)"
133 133
134 134 elif xaxis == "time":
135 135 x = dataOut.getAcfRange(1)
136 136 xlabel = "Time (ms)"
137 137
138 138 else:
139 139 x = dataOut.getVelRange(1)
140 140 xlabel = "Velocity (m/s)"
141 141
142 142 ylabel = "Range (Km)"
143 143
144 144 y = dataOut.getHeiRange()
145 145
146 146 z = dataOut.data_spc/factor
147 147 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
148 148 zdB = 10*numpy.log10(z)
149 149
150 150 avg = numpy.average(z, axis=1)
151 151 avgdB = 10*numpy.log10(avg)
152 152
153 153 noise = dataOut.getNoise()/factor
154 154 noisedB = 10*numpy.log10(noise)
155 155
156 156 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
157 157 title = wintitle + " Spectra"
158 158 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
159 159 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
160 160
161 161 if not self.isConfig:
162 162
163 163 nplots = len(channelIndexList)
164 164
165 165 self.setup(id=id,
166 166 nplots=nplots,
167 167 wintitle=wintitle,
168 168 showprofile=showprofile,
169 169 show=show)
170 170
171 171 if xmin == None: xmin = numpy.nanmin(x)
172 172 if xmax == None: xmax = numpy.nanmax(x)
173 173 if ymin == None: ymin = numpy.nanmin(y)
174 174 if ymax == None: ymax = numpy.nanmax(y)
175 175 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
176 176 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
177 177
178 178 self.FTP_WEI = ftp_wei
179 179 self.EXP_CODE = exp_code
180 180 self.SUB_EXP_CODE = sub_exp_code
181 181 self.PLOT_POS = plot_pos
182 182
183 183 self.isConfig = True
184 184
185 185 self.setWinTitle(title)
186 186
187 187 for i in range(self.nplots):
188 188 index = channelIndexList[i]
189 189 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
190 190 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[index], noisedB[index], str_datetime)
191 191 if len(dataOut.beam.codeList) != 0:
192 192 title = "Ch%d:%4.2fdB,%2.2f,%2.2f:%s" %(dataOut.channelList[index], noisedB[index], dataOut.beam.azimuthList[index], dataOut.beam.zenithList[index], str_datetime)
193 193
194 194 axes = self.axesList[i*self.__nsubplots]
195 195 axes.pcolor(x, y, zdB[index,:,:],
196 196 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
197 197 xlabel=xlabel, ylabel=ylabel, title=title, colormap=colormap,
198 198 ticksize=9, cblabel='')
199 199
200 200 if self.__showprofile:
201 201 axes = self.axesList[i*self.__nsubplots +1]
202 202 axes.pline(avgdB[index,:], y,
203 203 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
204 204 xlabel='dB', ylabel='', title='',
205 205 ytick_visible=False,
206 206 grid='x')
207 207
208 208 noiseline = numpy.repeat(noisedB[index], len(y))
209 209 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
210 210
211 211 self.draw()
212 212
213 213 if figfile == None:
214 214 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
215 215 name = str_datetime
216 216 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
217 217 name = name + '_az' + '_%2.2f'%(dataOut.azimuth) + '_zn' + '_%2.2f'%(dataOut.zenith)
218 218 figfile = self.getFilename(name)
219 219
220 220 self.save(figpath=figpath,
221 221 figfile=figfile,
222 222 save=save,
223 223 ftp=ftp,
224 224 wr_period=wr_period,
225 225 thisDatetime=thisDatetime)
226 226
227 227 return dataOut
228 228 @MPDecorator
229 class CrossSpectraPlot(Figure):
229 class CrossSpectraPlot_(Figure):
230 230
231 231 isConfig = None
232 232 __nsubplots = None
233 233
234 234 WIDTH = None
235 235 HEIGHT = None
236 236 WIDTHPROF = None
237 237 HEIGHTPROF = None
238 238 PREFIX = 'cspc'
239 239
240 240 def __init__(self):
241 241 Figure.__init__(self)
242 242 self.isConfig = False
243 243 self.__nsubplots = 4
244 244 self.counter_imagwr = 0
245 245 self.WIDTH = 250
246 246 self.HEIGHT = 250
247 247 self.WIDTHPROF = 0
248 248 self.HEIGHTPROF = 0
249 249
250 250 self.PLOT_CODE = CROSS_CODE
251 251 self.FTP_WEI = None
252 252 self.EXP_CODE = None
253 253 self.SUB_EXP_CODE = None
254 254 self.PLOT_POS = None
255 255
256 256 def getSubplots(self):
257 257
258 258 ncol = 4
259 259 nrow = self.nplots
260 260
261 261 return nrow, ncol
262 262
263 263 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
264 264
265 265 self.__showprofile = showprofile
266 266 self.nplots = nplots
267 267
268 268 ncolspan = 1
269 269 colspan = 1
270 270
271 271 self.createFigure(id = id,
272 272 wintitle = wintitle,
273 273 widthplot = self.WIDTH + self.WIDTHPROF,
274 274 heightplot = self.HEIGHT + self.HEIGHTPROF,
275 275 show=True)
276 276
277 277 nrow, ncol = self.getSubplots()
278 278
279 279 counter = 0
280 280 for y in range(nrow):
281 281 for x in range(ncol):
282 282 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
283 283
284 284 counter += 1
285 285
286 286 def run(self, dataOut, id, wintitle="", pairsList=None,
287 287 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
288 288 coh_min=None, coh_max=None, phase_min=None, phase_max=None,
289 289 save=False, figpath='./', figfile=None, ftp=False, wr_period=1,
290 290 power_cmap='jet', coherence_cmap='jet', phase_cmap='RdBu_r', show=True,
291 291 server=None, folder=None, username=None, password=None,
292 292 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, normFactor=None,
293 293 xaxis='frequency'):
294 294
295 295 """
296 296
297 297 Input:
298 298 dataOut :
299 299 id :
300 300 wintitle :
301 301 channelList :
302 302 showProfile :
303 303 xmin : None,
304 304 xmax : None,
305 305 ymin : None,
306 306 ymax : None,
307 307 zmin : None,
308 308 zmax : None
309 309 """
310 310
311 311 if dataOut.flagNoData:
312 312 return dataOut
313 313
314 314 if pairsList == None:
315 315 pairsIndexList = dataOut.pairsIndexList
316 316 else:
317 317 pairsIndexList = []
318 318 for pair in pairsList:
319 319 if pair not in dataOut.pairsList:
320 320 raise ValueError("Pair %s is not in dataOut.pairsList" %str(pair))
321 321 pairsIndexList.append(dataOut.pairsList.index(pair))
322 322
323 323 if not pairsIndexList:
324 324 return
325 325
326 326 if len(pairsIndexList) > 4:
327 327 pairsIndexList = pairsIndexList[0:4]
328 328
329 329 if normFactor is None:
330 330 factor = dataOut.normFactor
331 331 else:
332 332 factor = normFactor
333 333 x = dataOut.getVelRange(1)
334 334 y = dataOut.getHeiRange()
335 335 z = dataOut.data_spc[:,:,:]/factor
336 336 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
337 337
338 338 noise = dataOut.noise/factor
339 339
340 340 zdB = 10*numpy.log10(z)
341 341 noisedB = 10*numpy.log10(noise)
342 342
343 343 if coh_min == None:
344 344 coh_min = 0.0
345 345 if coh_max == None:
346 346 coh_max = 1.0
347 347
348 348 if phase_min == None:
349 349 phase_min = -180
350 350 if phase_max == None:
351 351 phase_max = 180
352 352
353 353 #thisDatetime = dataOut.datatime
354 354 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
355 355 title = wintitle + " Cross-Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
356 356 # xlabel = "Velocity (m/s)"
357 357 ylabel = "Range (Km)"
358 358
359 359 if xaxis == "frequency":
360 360 x = dataOut.getFreqRange(1)/1000.
361 361 xlabel = "Frequency (kHz)"
362 362
363 363 elif xaxis == "time":
364 364 x = dataOut.getAcfRange(1)
365 365 xlabel = "Time (ms)"
366 366
367 367 else:
368 368 x = dataOut.getVelRange(1)
369 369 xlabel = "Velocity (m/s)"
370 370
371 371 if not self.isConfig:
372 372
373 373 nplots = len(pairsIndexList)
374 374
375 375 self.setup(id=id,
376 376 nplots=nplots,
377 377 wintitle=wintitle,
378 378 showprofile=False,
379 379 show=show)
380 380
381 381 avg = numpy.abs(numpy.average(z, axis=1))
382 382 avgdB = 10*numpy.log10(avg)
383 383
384 384 if xmin == None: xmin = numpy.nanmin(x)
385 385 if xmax == None: xmax = numpy.nanmax(x)
386 386 if ymin == None: ymin = numpy.nanmin(y)
387 387 if ymax == None: ymax = numpy.nanmax(y)
388 388 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
389 389 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
390 390
391 391 self.FTP_WEI = ftp_wei
392 392 self.EXP_CODE = exp_code
393 393 self.SUB_EXP_CODE = sub_exp_code
394 394 self.PLOT_POS = plot_pos
395 395
396 396 self.isConfig = True
397 397
398 398 self.setWinTitle(title)
399 399
400 400 for i in range(self.nplots):
401 401 pair = dataOut.pairsList[pairsIndexList[i]]
402 402
403 403 chan_index0 = dataOut.channelList.index(pair[0])
404 404 chan_index1 = dataOut.channelList.index(pair[1])
405 405
406 406 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
407 407 title = "Ch%d: %4.2fdB: %s" %(pair[0], noisedB[chan_index0], str_datetime)
408 408 zdB = 10.*numpy.log10(dataOut.data_spc[chan_index0,:,:]/factor)
409 409 axes0 = self.axesList[i*self.__nsubplots]
410 410 axes0.pcolor(x, y, zdB,
411 411 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
412 412 xlabel=xlabel, ylabel=ylabel, title=title,
413 413 ticksize=9, colormap=power_cmap, cblabel='')
414 414
415 415 title = "Ch%d: %4.2fdB: %s" %(pair[1], noisedB[chan_index1], str_datetime)
416 416 zdB = 10.*numpy.log10(dataOut.data_spc[chan_index1,:,:]/factor)
417 417 axes0 = self.axesList[i*self.__nsubplots+1]
418 418 axes0.pcolor(x, y, zdB,
419 419 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
420 420 xlabel=xlabel, ylabel=ylabel, title=title,
421 421 ticksize=9, colormap=power_cmap, cblabel='')
422 422
423 423 coherenceComplex = dataOut.data_cspc[pairsIndexList[i],:,:]/numpy.sqrt(dataOut.data_spc[chan_index0,:,:]*dataOut.data_spc[chan_index1,:,:])
424 424 coherence = numpy.abs(coherenceComplex)
425 425 # phase = numpy.arctan(-1*coherenceComplex.imag/coherenceComplex.real)*180/numpy.pi
426 426 phase = numpy.arctan2(coherenceComplex.imag, coherenceComplex.real)*180/numpy.pi
427 427
428 428 title = "Coherence Ch%d * Ch%d" %(pair[0], pair[1])
429 429 axes0 = self.axesList[i*self.__nsubplots+2]
430 430 axes0.pcolor(x, y, coherence,
431 431 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=coh_min, zmax=coh_max,
432 432 xlabel=xlabel, ylabel=ylabel, title=title,
433 433 ticksize=9, colormap=coherence_cmap, cblabel='')
434 434
435 435 title = "Phase Ch%d * Ch%d" %(pair[0], pair[1])
436 436 axes0 = self.axesList[i*self.__nsubplots+3]
437 437 axes0.pcolor(x, y, phase,
438 438 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=phase_min, zmax=phase_max,
439 439 xlabel=xlabel, ylabel=ylabel, title=title,
440 440 ticksize=9, colormap=phase_cmap, cblabel='')
441 441
442 442
443 443
444 444 self.draw()
445 445
446 446 self.save(figpath=figpath,
447 447 figfile=figfile,
448 448 save=save,
449 449 ftp=ftp,
450 450 wr_period=wr_period,
451 451 thisDatetime=thisDatetime)
452 452
453 453 return dataOut
454 454
455 455 @MPDecorator
456 class RTIPlot(Figure):
456 class RTIPlot_(Figure):
457 457
458 458 __isConfig = None
459 459 __nsubplots = None
460 460
461 461 WIDTHPROF = None
462 462 HEIGHTPROF = None
463 463 PREFIX = 'rti'
464 464
465 465 def __init__(self):
466 466
467 467 Figure.__init__(self)
468 468 self.timerange = None
469 469 self.isConfig = False
470 470 self.__nsubplots = 1
471 471
472 472 self.WIDTH = 800
473 473 self.HEIGHT = 180
474 474 self.WIDTHPROF = 120
475 475 self.HEIGHTPROF = 0
476 476 self.counter_imagwr = 0
477 477
478 478 self.PLOT_CODE = RTI_CODE
479 479
480 480 self.FTP_WEI = None
481 481 self.EXP_CODE = None
482 482 self.SUB_EXP_CODE = None
483 483 self.PLOT_POS = None
484 484 self.tmin = None
485 485 self.tmax = None
486 486
487 487 self.xmin = None
488 488 self.xmax = None
489 489
490 490 self.figfile = None
491 491
492 492 def getSubplots(self):
493 493
494 494 ncol = 1
495 495 nrow = self.nplots
496 496
497 497 return nrow, ncol
498 498
499 499 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
500 500
501 501 self.__showprofile = showprofile
502 502 self.nplots = nplots
503 503
504 504 ncolspan = 1
505 505 colspan = 1
506 506 if showprofile:
507 507 ncolspan = 7
508 508 colspan = 6
509 509 self.__nsubplots = 2
510 510
511 511 self.createFigure(id = id,
512 512 wintitle = wintitle,
513 513 widthplot = self.WIDTH + self.WIDTHPROF,
514 514 heightplot = self.HEIGHT + self.HEIGHTPROF,
515 515 show=show)
516 516
517 517 nrow, ncol = self.getSubplots()
518 518
519 519 counter = 0
520 520 for y in range(nrow):
521 521 for x in range(ncol):
522 522
523 523 if counter >= self.nplots:
524 524 break
525 525
526 526 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
527 527
528 528 if showprofile:
529 529 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
530 530
531 531 counter += 1
532 532
533 533 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True',
534 534 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
535 535 timerange=None, colormap='jet',
536 536 save=False, figpath='./', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
537 537 server=None, folder=None, username=None, password=None,
538 538 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, normFactor=None, HEIGHT=None):
539 539
540 540 """
541 541
542 542 Input:
543 543 dataOut :
544 544 id :
545 545 wintitle :
546 546 channelList :
547 547 showProfile :
548 548 xmin : None,
549 549 xmax : None,
550 550 ymin : None,
551 551 ymax : None,
552 552 zmin : None,
553 553 zmax : None
554 554 """
555 555 if dataOut.flagNoData:
556 556 return dataOut
557 557
558 558 #colormap = kwargs.get('colormap', 'jet')
559 559 if HEIGHT is not None:
560 560 self.HEIGHT = HEIGHT
561 561
562 562 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
563 563 return
564 564
565 565 if channelList == None:
566 566 channelIndexList = dataOut.channelIndexList
567 567 else:
568 568 channelIndexList = []
569 569 for channel in channelList:
570 570 if channel not in dataOut.channelList:
571 571 raise ValueError("Channel %d is not in dataOut.channelList")
572 572 channelIndexList.append(dataOut.channelList.index(channel))
573 573
574 574 if normFactor is None:
575 575 factor = dataOut.normFactor
576 576 else:
577 577 factor = normFactor
578 578
579 579 #factor = dataOut.normFactor
580 580 x = dataOut.getTimeRange()
581 581 y = dataOut.getHeiRange()
582 582
583 583 z = dataOut.data_spc/factor
584 584 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
585 585 avg = numpy.average(z, axis=1)
586 586 avgdB = 10.*numpy.log10(avg)
587 587 # avgdB = dataOut.getPower()
588 588
589 589
590 590 thisDatetime = dataOut.datatime
591 591 #thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
592 592 title = wintitle + " RTI" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
593 593 xlabel = ""
594 594 ylabel = "Range (Km)"
595 595
596 596 update_figfile = False
597 597
598 598 if self.xmax is not None and dataOut.ltctime >= self.xmax: #yong
599 599 self.counter_imagwr = wr_period
600 600 self.isConfig = False
601 601 update_figfile = True
602 602
603 603 if not self.isConfig:
604 604
605 605 nplots = len(channelIndexList)
606 606
607 607 self.setup(id=id,
608 608 nplots=nplots,
609 609 wintitle=wintitle,
610 610 showprofile=showprofile,
611 611 show=show)
612 612
613 613 if timerange != None:
614 614 self.timerange = timerange
615 615
616 616 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
617 617
618 618 noise = dataOut.noise/factor
619 619 noisedB = 10*numpy.log10(noise)
620 620
621 621 if ymin == None: ymin = numpy.nanmin(y)
622 622 if ymax == None: ymax = numpy.nanmax(y)
623 623 if zmin == None: zmin = numpy.floor(numpy.nanmin(noisedB)) - 3
624 624 if zmax == None: zmax = numpy.ceil(numpy.nanmax(avgdB)) + 3
625 625
626 626 self.FTP_WEI = ftp_wei
627 627 self.EXP_CODE = exp_code
628 628 self.SUB_EXP_CODE = sub_exp_code
629 629 self.PLOT_POS = plot_pos
630 630
631 631 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
632 632 self.isConfig = True
633 633 self.figfile = figfile
634 634 update_figfile = True
635 635
636 636 self.setWinTitle(title)
637 637
638 638 for i in range(self.nplots):
639 639 index = channelIndexList[i]
640 640 title = "Channel %d: %s" %(dataOut.channelList[index], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
641 641 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
642 642 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
643 643 axes = self.axesList[i*self.__nsubplots]
644 644 zdB = avgdB[index].reshape((1,-1))
645 645 axes.pcolorbuffer(x, y, zdB,
646 646 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
647 647 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
648 648 ticksize=9, cblabel='', cbsize="1%", colormap=colormap)
649 649
650 650 if self.__showprofile:
651 651 axes = self.axesList[i*self.__nsubplots +1]
652 652 axes.pline(avgdB[index], y,
653 653 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
654 654 xlabel='dB', ylabel='', title='',
655 655 ytick_visible=False,
656 656 grid='x')
657 657
658 658 self.draw()
659 659
660 660 self.save(figpath=figpath,
661 661 figfile=figfile,
662 662 save=save,
663 663 ftp=ftp,
664 664 wr_period=wr_period,
665 665 thisDatetime=thisDatetime,
666 666 update_figfile=update_figfile)
667 667 return dataOut
668 668
669 669 @MPDecorator
670 class CoherenceMap(Figure):
670 class CoherenceMap_(Figure):
671 671 isConfig = None
672 672 __nsubplots = None
673 673
674 674 WIDTHPROF = None
675 675 HEIGHTPROF = None
676 676 PREFIX = 'cmap'
677 677
678 678 def __init__(self):
679 679 Figure.__init__(self)
680 680 self.timerange = 2*60*60
681 681 self.isConfig = False
682 682 self.__nsubplots = 1
683 683
684 684 self.WIDTH = 800
685 685 self.HEIGHT = 180
686 686 self.WIDTHPROF = 120
687 687 self.HEIGHTPROF = 0
688 688 self.counter_imagwr = 0
689 689
690 690 self.PLOT_CODE = COH_CODE
691 691
692 692 self.FTP_WEI = None
693 693 self.EXP_CODE = None
694 694 self.SUB_EXP_CODE = None
695 695 self.PLOT_POS = None
696 696 self.counter_imagwr = 0
697 697
698 698 self.xmin = None
699 699 self.xmax = None
700 700
701 701 def getSubplots(self):
702 702 ncol = 1
703 703 nrow = self.nplots*2
704 704
705 705 return nrow, ncol
706 706
707 707 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
708 708 self.__showprofile = showprofile
709 709 self.nplots = nplots
710 710
711 711 ncolspan = 1
712 712 colspan = 1
713 713 if showprofile:
714 714 ncolspan = 7
715 715 colspan = 6
716 716 self.__nsubplots = 2
717 717
718 718 self.createFigure(id = id,
719 719 wintitle = wintitle,
720 720 widthplot = self.WIDTH + self.WIDTHPROF,
721 721 heightplot = self.HEIGHT + self.HEIGHTPROF,
722 722 show=True)
723 723
724 724 nrow, ncol = self.getSubplots()
725 725
726 726 for y in range(nrow):
727 727 for x in range(ncol):
728 728
729 729 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
730 730
731 731 if showprofile:
732 732 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
733 733
734 734 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
735 735 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
736 736 timerange=None, phase_min=None, phase_max=None,
737 737 save=False, figpath='./', figfile=None, ftp=False, wr_period=1,
738 738 coherence_cmap='jet', phase_cmap='RdBu_r', show=True,
739 739 server=None, folder=None, username=None, password=None,
740 740 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
741 741
742 742
743 743 if dataOut.flagNoData:
744 744 return dataOut
745 745
746 746 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
747 747 return
748 748
749 749 if pairsList == None:
750 750 pairsIndexList = dataOut.pairsIndexList
751 751 else:
752 752 pairsIndexList = []
753 753 for pair in pairsList:
754 754 if pair not in dataOut.pairsList:
755 755 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
756 756 pairsIndexList.append(dataOut.pairsList.index(pair))
757 757
758 758 if pairsIndexList == []:
759 759 return
760 760
761 761 if len(pairsIndexList) > 4:
762 762 pairsIndexList = pairsIndexList[0:4]
763 763
764 764 if phase_min == None:
765 765 phase_min = -180
766 766 if phase_max == None:
767 767 phase_max = 180
768 768
769 769 x = dataOut.getTimeRange()
770 770 y = dataOut.getHeiRange()
771 771
772 772 thisDatetime = dataOut.datatime
773 773
774 774 title = wintitle + " CoherenceMap" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
775 775 xlabel = ""
776 776 ylabel = "Range (Km)"
777 777 update_figfile = False
778 778
779 779 if not self.isConfig:
780 780 nplots = len(pairsIndexList)
781 781 self.setup(id=id,
782 782 nplots=nplots,
783 783 wintitle=wintitle,
784 784 showprofile=showprofile,
785 785 show=show)
786 786
787 787 if timerange != None:
788 788 self.timerange = timerange
789 789
790 790 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
791 791
792 792 if ymin == None: ymin = numpy.nanmin(y)
793 793 if ymax == None: ymax = numpy.nanmax(y)
794 794 if zmin == None: zmin = 0.
795 795 if zmax == None: zmax = 1.
796 796
797 797 self.FTP_WEI = ftp_wei
798 798 self.EXP_CODE = exp_code
799 799 self.SUB_EXP_CODE = sub_exp_code
800 800 self.PLOT_POS = plot_pos
801 801
802 802 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
803 803
804 804 self.isConfig = True
805 805 update_figfile = True
806 806
807 807 self.setWinTitle(title)
808 808
809 809 for i in range(self.nplots):
810 810
811 811 pair = dataOut.pairsList[pairsIndexList[i]]
812 812
813 813 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i],:,:],axis=0)
814 814 powa = numpy.average(dataOut.data_spc[pair[0],:,:],axis=0)
815 815 powb = numpy.average(dataOut.data_spc[pair[1],:,:],axis=0)
816 816
817 817
818 818 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
819 819 coherence = numpy.abs(avgcoherenceComplex)
820 820
821 821 z = coherence.reshape((1,-1))
822 822
823 823 counter = 0
824 824
825 825 title = "Coherence Ch%d * Ch%d: %s" %(pair[0], pair[1], thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
826 826 axes = self.axesList[i*self.__nsubplots*2]
827 827 axes.pcolorbuffer(x, y, z,
828 828 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
829 829 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
830 830 ticksize=9, cblabel='', colormap=coherence_cmap, cbsize="1%")
831 831
832 832 if self.__showprofile:
833 833 counter += 1
834 834 axes = self.axesList[i*self.__nsubplots*2 + counter]
835 835 axes.pline(coherence, y,
836 836 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
837 837 xlabel='', ylabel='', title='', ticksize=7,
838 838 ytick_visible=False, nxticks=5,
839 839 grid='x')
840 840
841 841 counter += 1
842 842
843 843 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
844 844
845 845 z = phase.reshape((1,-1))
846 846
847 847 title = "Phase Ch%d * Ch%d: %s" %(pair[0], pair[1], thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
848 848 axes = self.axesList[i*self.__nsubplots*2 + counter]
849 849 axes.pcolorbuffer(x, y, z,
850 850 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=phase_min, zmax=phase_max,
851 851 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
852 852 ticksize=9, cblabel='', colormap=phase_cmap, cbsize="1%")
853 853
854 854 if self.__showprofile:
855 855 counter += 1
856 856 axes = self.axesList[i*self.__nsubplots*2 + counter]
857 857 axes.pline(phase, y,
858 858 xmin=phase_min, xmax=phase_max, ymin=ymin, ymax=ymax,
859 859 xlabel='', ylabel='', title='', ticksize=7,
860 860 ytick_visible=False, nxticks=4,
861 861 grid='x')
862 862
863 863 self.draw()
864 864
865 865 if dataOut.ltctime >= self.xmax:
866 866 self.counter_imagwr = wr_period
867 867 self.isConfig = False
868 868 update_figfile = True
869 869
870 870 self.save(figpath=figpath,
871 871 figfile=figfile,
872 872 save=save,
873 873 ftp=ftp,
874 874 wr_period=wr_period,
875 875 thisDatetime=thisDatetime,
876 876 update_figfile=update_figfile)
877 877
878 878 return dataOut
879 879
880 880 @MPDecorator
881 class PowerProfilePlot(Figure):
881 class PowerProfilePlot_(Figure):
882 882
883 883 isConfig = None
884 884 __nsubplots = None
885 885
886 886 WIDTHPROF = None
887 887 HEIGHTPROF = None
888 888 PREFIX = 'spcprofile'
889 889
890 890 def __init__(self):
891 891 Figure.__init__(self)
892 892 self.isConfig = False
893 893 self.__nsubplots = 1
894 894
895 895 self.PLOT_CODE = POWER_CODE
896 896
897 897 self.WIDTH = 300
898 898 self.HEIGHT = 500
899 899 self.counter_imagwr = 0
900 900
901 901 def getSubplots(self):
902 902 ncol = 1
903 903 nrow = 1
904 904
905 905 return nrow, ncol
906 906
907 907 def setup(self, id, nplots, wintitle, show):
908 908
909 909 self.nplots = nplots
910 910
911 911 ncolspan = 1
912 912 colspan = 1
913 913
914 914 self.createFigure(id = id,
915 915 wintitle = wintitle,
916 916 widthplot = self.WIDTH,
917 917 heightplot = self.HEIGHT,
918 918 show=show)
919 919
920 920 nrow, ncol = self.getSubplots()
921 921
922 922 counter = 0
923 923 for y in range(nrow):
924 924 for x in range(ncol):
925 925 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
926 926
927 927 def run(self, dataOut, id, wintitle="", channelList=None,
928 928 xmin=None, xmax=None, ymin=None, ymax=None,
929 929 save=False, figpath='./', figfile=None, show=True,
930 930 ftp=False, wr_period=1, server=None,
931 931 folder=None, username=None, password=None):
932 932
933 933 if dataOut.flagNoData:
934 934 return dataOut
935 935
936 936
937 937 if channelList == None:
938 938 channelIndexList = dataOut.channelIndexList
939 939 channelList = dataOut.channelList
940 940 else:
941 941 channelIndexList = []
942 942 for channel in channelList:
943 943 if channel not in dataOut.channelList:
944 944 raise ValueError("Channel %d is not in dataOut.channelList")
945 945 channelIndexList.append(dataOut.channelList.index(channel))
946 946
947 947 factor = dataOut.normFactor
948 948
949 949 y = dataOut.getHeiRange()
950 950
951 951 #for voltage
952 952 if dataOut.type == 'Voltage':
953 953 x = dataOut.data[channelIndexList,:] * numpy.conjugate(dataOut.data[channelIndexList,:])
954 954 x = x.real
955 955 x = numpy.where(numpy.isfinite(x), x, numpy.NAN)
956 956
957 957 #for spectra
958 958 if dataOut.type == 'Spectra':
959 959 x = dataOut.data_spc[channelIndexList,:,:]/factor
960 960 x = numpy.where(numpy.isfinite(x), x, numpy.NAN)
961 961 x = numpy.average(x, axis=1)
962 962
963 963
964 964 xdB = 10*numpy.log10(x)
965 965
966 966 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
967 967 title = wintitle + " Power Profile %s" %(thisDatetime.strftime("%d-%b-%Y"))
968 968 xlabel = "dB"
969 969 ylabel = "Range (Km)"
970 970
971 971 if not self.isConfig:
972 972
973 973 nplots = 1
974 974
975 975 self.setup(id=id,
976 976 nplots=nplots,
977 977 wintitle=wintitle,
978 978 show=show)
979 979
980 980 if ymin == None: ymin = numpy.nanmin(y)
981 981 if ymax == None: ymax = numpy.nanmax(y)
982 982 if xmin == None: xmin = numpy.nanmin(xdB)*0.9
983 983 if xmax == None: xmax = numpy.nanmax(xdB)*1.1
984 984
985 985 self.isConfig = True
986 986
987 987 self.setWinTitle(title)
988 988
989 989 title = "Power Profile: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
990 990 axes = self.axesList[0]
991 991
992 992 legendlabels = ["channel %d"%x for x in channelList]
993 993 axes.pmultiline(xdB, y,
994 994 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
995 995 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels,
996 996 ytick_visible=True, nxticks=5,
997 997 grid='x')
998 998
999 999 self.draw()
1000 1000
1001 1001 self.save(figpath=figpath,
1002 1002 figfile=figfile,
1003 1003 save=save,
1004 1004 ftp=ftp,
1005 1005 wr_period=wr_period,
1006 1006 thisDatetime=thisDatetime)
1007 1007
1008 1008 return dataOut
1009 1009
1010 1010 @MPDecorator
1011 class SpectraCutPlot(Figure):
1011 class SpectraCutPlot_(Figure):
1012 1012
1013 1013 isConfig = None
1014 1014 __nsubplots = None
1015 1015
1016 1016 WIDTHPROF = None
1017 1017 HEIGHTPROF = None
1018 1018 PREFIX = 'spc_cut'
1019 1019
1020 1020 def __init__(self):
1021 1021 Figure.__init__(self)
1022 1022 self.isConfig = False
1023 1023 self.__nsubplots = 1
1024 1024
1025 1025 self.PLOT_CODE = POWER_CODE
1026 1026
1027 1027 self.WIDTH = 700
1028 1028 self.HEIGHT = 500
1029 1029 self.counter_imagwr = 0
1030 1030
1031 1031 def getSubplots(self):
1032 1032 ncol = 1
1033 1033 nrow = 1
1034 1034
1035 1035 return nrow, ncol
1036 1036
1037 1037 def setup(self, id, nplots, wintitle, show):
1038 1038
1039 1039 self.nplots = nplots
1040 1040
1041 1041 ncolspan = 1
1042 1042 colspan = 1
1043 1043
1044 1044 self.createFigure(id = id,
1045 1045 wintitle = wintitle,
1046 1046 widthplot = self.WIDTH,
1047 1047 heightplot = self.HEIGHT,
1048 1048 show=show)
1049 1049
1050 1050 nrow, ncol = self.getSubplots()
1051 1051
1052 1052 counter = 0
1053 1053 for y in range(nrow):
1054 1054 for x in range(ncol):
1055 1055 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
1056 1056
1057 1057 def run(self, dataOut, id, wintitle="", channelList=None,
1058 1058 xmin=None, xmax=None, ymin=None, ymax=None,
1059 1059 save=False, figpath='./', figfile=None, show=True,
1060 1060 ftp=False, wr_period=1, server=None,
1061 1061 folder=None, username=None, password=None,
1062 1062 xaxis="frequency"):
1063 1063
1064 1064 if dataOut.flagNoData:
1065 1065 return dataOut
1066 1066
1067 1067 if channelList == None:
1068 1068 channelIndexList = dataOut.channelIndexList
1069 1069 channelList = dataOut.channelList
1070 1070 else:
1071 1071 channelIndexList = []
1072 1072 for channel in channelList:
1073 1073 if channel not in dataOut.channelList:
1074 1074 raise ValueError("Channel %d is not in dataOut.channelList")
1075 1075 channelIndexList.append(dataOut.channelList.index(channel))
1076 1076
1077 1077 factor = dataOut.normFactor
1078 1078
1079 1079 y = dataOut.getHeiRange()
1080 1080
1081 1081 z = dataOut.data_spc/factor
1082 1082 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1083 1083
1084 1084 hei_index = numpy.arange(25)*3 + 20
1085 1085
1086 1086 if xaxis == "frequency":
1087 1087 x = dataOut.getFreqRange()/1000.
1088 1088 zdB = 10*numpy.log10(z[0,:,hei_index])
1089 1089 xlabel = "Frequency (kHz)"
1090 1090 ylabel = "Power (dB)"
1091 1091
1092 1092 elif xaxis == "time":
1093 1093 x = dataOut.getAcfRange()
1094 1094 zdB = z[0,:,hei_index]
1095 1095 xlabel = "Time (ms)"
1096 1096 ylabel = "ACF"
1097 1097
1098 1098 else:
1099 1099 x = dataOut.getVelRange()
1100 1100 zdB = 10*numpy.log10(z[0,:,hei_index])
1101 1101 xlabel = "Velocity (m/s)"
1102 1102 ylabel = "Power (dB)"
1103 1103
1104 1104 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
1105 1105 title = wintitle + " Range Cuts %s" %(thisDatetime.strftime("%d-%b-%Y"))
1106 1106
1107 1107 if not self.isConfig:
1108 1108
1109 1109 nplots = 1
1110 1110
1111 1111 self.setup(id=id,
1112 1112 nplots=nplots,
1113 1113 wintitle=wintitle,
1114 1114 show=show)
1115 1115
1116 1116 if xmin == None: xmin = numpy.nanmin(x)*0.9
1117 1117 if xmax == None: xmax = numpy.nanmax(x)*1.1
1118 1118 if ymin == None: ymin = numpy.nanmin(zdB)
1119 1119 if ymax == None: ymax = numpy.nanmax(zdB)
1120 1120
1121 1121 self.isConfig = True
1122 1122
1123 1123 self.setWinTitle(title)
1124 1124
1125 1125 title = "Spectra Cuts: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
1126 1126 axes = self.axesList[0]
1127 1127
1128 1128 legendlabels = ["Range = %dKm" %y[i] for i in hei_index]
1129 1129
1130 1130 axes.pmultilineyaxis( x, zdB,
1131 1131 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
1132 1132 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels,
1133 1133 ytick_visible=True, nxticks=5,
1134 1134 grid='x')
1135 1135
1136 1136 self.draw()
1137 1137
1138 1138 self.save(figpath=figpath,
1139 1139 figfile=figfile,
1140 1140 save=save,
1141 1141 ftp=ftp,
1142 1142 wr_period=wr_period,
1143 1143 thisDatetime=thisDatetime)
1144 1144
1145 1145 return dataOut
1146 1146
1147 1147 @MPDecorator
1148 class Noise(Figure):
1148 class Noise_(Figure):
1149 1149
1150 1150 isConfig = None
1151 1151 __nsubplots = None
1152 1152
1153 1153 PREFIX = 'noise'
1154 1154
1155 1155
1156 1156 def __init__(self):
1157 1157 Figure.__init__(self)
1158 1158 self.timerange = 24*60*60
1159 1159 self.isConfig = False
1160 1160 self.__nsubplots = 1
1161 1161 self.counter_imagwr = 0
1162 1162 self.WIDTH = 800
1163 1163 self.HEIGHT = 400
1164 1164 self.WIDTHPROF = 120
1165 1165 self.HEIGHTPROF = 0
1166 1166 self.xdata = None
1167 1167 self.ydata = None
1168 1168
1169 1169 self.PLOT_CODE = NOISE_CODE
1170 1170
1171 1171 self.FTP_WEI = None
1172 1172 self.EXP_CODE = None
1173 1173 self.SUB_EXP_CODE = None
1174 1174 self.PLOT_POS = None
1175 1175 self.figfile = None
1176 1176
1177 1177 self.xmin = None
1178 1178 self.xmax = None
1179 1179
1180 1180 def getSubplots(self):
1181 1181
1182 1182 ncol = 1
1183 1183 nrow = 1
1184 1184
1185 1185 return nrow, ncol
1186 1186
1187 1187 def openfile(self, filename):
1188 1188 dirname = os.path.dirname(filename)
1189 1189
1190 1190 if not os.path.exists(dirname):
1191 1191 os.mkdir(dirname)
1192 1192
1193 1193 f = open(filename,'w+')
1194 1194 f.write('\n\n')
1195 1195 f.write('JICAMARCA RADIO OBSERVATORY - Noise \n')
1196 1196 f.write('DD MM YYYY HH MM SS Channel0 Channel1 Channel2 Channel3\n\n' )
1197 1197 f.close()
1198 1198
1199 1199 def save_data(self, filename_phase, data, data_datetime):
1200 1200
1201 1201 f=open(filename_phase,'a')
1202 1202
1203 1203 timetuple_data = data_datetime.timetuple()
1204 1204 day = str(timetuple_data.tm_mday)
1205 1205 month = str(timetuple_data.tm_mon)
1206 1206 year = str(timetuple_data.tm_year)
1207 1207 hour = str(timetuple_data.tm_hour)
1208 1208 minute = str(timetuple_data.tm_min)
1209 1209 second = str(timetuple_data.tm_sec)
1210 1210
1211 1211 data_msg = ''
1212 1212 for i in range(len(data)):
1213 1213 data_msg += str(data[i]) + ' '
1214 1214
1215 1215 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' ' + data_msg + '\n')
1216 1216 f.close()
1217 1217
1218 1218
1219 1219 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1220 1220
1221 1221 self.__showprofile = showprofile
1222 1222 self.nplots = nplots
1223 1223
1224 1224 ncolspan = 7
1225 1225 colspan = 6
1226 1226 self.__nsubplots = 2
1227 1227
1228 1228 self.createFigure(id = id,
1229 1229 wintitle = wintitle,
1230 1230 widthplot = self.WIDTH+self.WIDTHPROF,
1231 1231 heightplot = self.HEIGHT+self.HEIGHTPROF,
1232 1232 show=show)
1233 1233
1234 1234 nrow, ncol = self.getSubplots()
1235 1235
1236 1236 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1237 1237
1238 1238
1239 1239 def run(self, dataOut, id, wintitle="", channelList=None, showprofile='True',
1240 1240 xmin=None, xmax=None, ymin=None, ymax=None,
1241 1241 timerange=None,
1242 1242 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1243 1243 server=None, folder=None, username=None, password=None,
1244 1244 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1245 1245
1246 1246 if dataOut.flagNoData:
1247 1247 return dataOut
1248 1248
1249 1249 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1250 1250 return
1251 1251
1252 1252 if channelList == None:
1253 1253 channelIndexList = dataOut.channelIndexList
1254 1254 channelList = dataOut.channelList
1255 1255 else:
1256 1256 channelIndexList = []
1257 1257 for channel in channelList:
1258 1258 if channel not in dataOut.channelList:
1259 1259 raise ValueError("Channel %d is not in dataOut.channelList")
1260 1260 channelIndexList.append(dataOut.channelList.index(channel))
1261 1261
1262 1262 x = dataOut.getTimeRange()
1263 1263 #y = dataOut.getHeiRange()
1264 1264 factor = dataOut.normFactor
1265 1265 noise = dataOut.noise[channelIndexList]/factor
1266 1266 noisedB = 10*numpy.log10(noise)
1267 1267
1268 1268 thisDatetime = dataOut.datatime
1269 1269
1270 1270 title = wintitle + " Noise" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1271 1271 xlabel = ""
1272 1272 ylabel = "Intensity (dB)"
1273 1273 update_figfile = False
1274 1274
1275 1275 if not self.isConfig:
1276 1276
1277 1277 nplots = 1
1278 1278
1279 1279 self.setup(id=id,
1280 1280 nplots=nplots,
1281 1281 wintitle=wintitle,
1282 1282 showprofile=showprofile,
1283 1283 show=show)
1284 1284
1285 1285 if timerange != None:
1286 1286 self.timerange = timerange
1287 1287
1288 1288 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1289 1289
1290 1290 if ymin == None: ymin = numpy.floor(numpy.nanmin(noisedB)) - 10.0
1291 1291 if ymax == None: ymax = numpy.nanmax(noisedB) + 10.0
1292 1292
1293 1293 self.FTP_WEI = ftp_wei
1294 1294 self.EXP_CODE = exp_code
1295 1295 self.SUB_EXP_CODE = sub_exp_code
1296 1296 self.PLOT_POS = plot_pos
1297 1297
1298 1298
1299 1299 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1300 1300 self.isConfig = True
1301 1301 self.figfile = figfile
1302 1302 self.xdata = numpy.array([])
1303 1303 self.ydata = numpy.array([])
1304 1304
1305 1305 update_figfile = True
1306 1306
1307 1307 #open file beacon phase
1308 1308 path = '%s%03d' %(self.PREFIX, self.id)
1309 1309 noise_file = os.path.join(path,'%s.txt'%self.name)
1310 1310 self.filename_noise = os.path.join(figpath,noise_file)
1311 1311
1312 1312 self.setWinTitle(title)
1313 1313
1314 1314 title = "Noise %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1315 1315
1316 1316 legendlabels = ["channel %d"%(idchannel) for idchannel in channelList]
1317 1317 axes = self.axesList[0]
1318 1318
1319 1319 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1320 1320
1321 1321 if len(self.ydata)==0:
1322 1322 self.ydata = noisedB.reshape(-1,1)
1323 1323 else:
1324 1324 self.ydata = numpy.hstack((self.ydata, noisedB.reshape(-1,1)))
1325 1325
1326 1326
1327 1327 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1328 1328 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1329 1329 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1330 1330 XAxisAsTime=True, grid='both'
1331 1331 )
1332 1332
1333 1333 self.draw()
1334 1334
1335 1335 if dataOut.ltctime >= self.xmax:
1336 1336 self.counter_imagwr = wr_period
1337 1337 self.isConfig = False
1338 1338 update_figfile = True
1339 1339
1340 1340 self.save(figpath=figpath,
1341 1341 figfile=figfile,
1342 1342 save=save,
1343 1343 ftp=ftp,
1344 1344 wr_period=wr_period,
1345 1345 thisDatetime=thisDatetime,
1346 1346 update_figfile=update_figfile)
1347 1347
1348 1348 #store data beacon phase
1349 1349 if save:
1350 1350 self.save_data(self.filename_noise, noisedB, thisDatetime)
1351 1351
1352 1352 return dataOut
1353 1353
1354 1354 @MPDecorator
1355 class BeaconPhase(Figure):
1355 class BeaconPhase_(Figure):
1356 1356
1357 1357 __isConfig = None
1358 1358 __nsubplots = None
1359 1359
1360 1360 PREFIX = 'beacon_phase'
1361 1361
1362 1362 def __init__(self):
1363 1363 Figure.__init__(self)
1364 1364 self.timerange = 24*60*60
1365 1365 self.isConfig = False
1366 1366 self.__nsubplots = 1
1367 1367 self.counter_imagwr = 0
1368 1368 self.WIDTH = 800
1369 1369 self.HEIGHT = 400
1370 1370 self.WIDTHPROF = 120
1371 1371 self.HEIGHTPROF = 0
1372 1372 self.xdata = None
1373 1373 self.ydata = None
1374 1374
1375 1375 self.PLOT_CODE = BEACON_CODE
1376 1376
1377 1377 self.FTP_WEI = None
1378 1378 self.EXP_CODE = None
1379 1379 self.SUB_EXP_CODE = None
1380 1380 self.PLOT_POS = None
1381 1381
1382 1382 self.filename_phase = None
1383 1383
1384 1384 self.figfile = None
1385 1385
1386 1386 self.xmin = None
1387 1387 self.xmax = None
1388 1388
1389 1389 def getSubplots(self):
1390 1390
1391 1391 ncol = 1
1392 1392 nrow = 1
1393 1393
1394 1394 return nrow, ncol
1395 1395
1396 1396 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1397 1397
1398 1398 self.__showprofile = showprofile
1399 1399 self.nplots = nplots
1400 1400
1401 1401 ncolspan = 7
1402 1402 colspan = 6
1403 1403 self.__nsubplots = 2
1404 1404
1405 1405 self.createFigure(id = id,
1406 1406 wintitle = wintitle,
1407 1407 widthplot = self.WIDTH+self.WIDTHPROF,
1408 1408 heightplot = self.HEIGHT+self.HEIGHTPROF,
1409 1409 show=show)
1410 1410
1411 1411 nrow, ncol = self.getSubplots()
1412 1412
1413 1413 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1414 1414
1415 1415 def save_phase(self, filename_phase):
1416 1416 f = open(filename_phase,'w+')
1417 1417 f.write('\n\n')
1418 1418 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
1419 1419 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
1420 1420 f.close()
1421 1421
1422 1422 def save_data(self, filename_phase, data, data_datetime):
1423 1423 f=open(filename_phase,'a')
1424 1424 timetuple_data = data_datetime.timetuple()
1425 1425 day = str(timetuple_data.tm_mday)
1426 1426 month = str(timetuple_data.tm_mon)
1427 1427 year = str(timetuple_data.tm_year)
1428 1428 hour = str(timetuple_data.tm_hour)
1429 1429 minute = str(timetuple_data.tm_min)
1430 1430 second = str(timetuple_data.tm_sec)
1431 1431 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
1432 1432 f.close()
1433 1433
1434 1434
1435 1435 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1436 1436 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
1437 1437 timerange=None,
1438 1438 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1439 1439 server=None, folder=None, username=None, password=None,
1440 1440 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1441 1441
1442 1442 if dataOut.flagNoData:
1443 1443 return dataOut
1444 1444
1445 1445 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1446 1446 return
1447 1447
1448 1448 if pairsList == None:
1449 1449 pairsIndexList = dataOut.pairsIndexList[:10]
1450 1450 else:
1451 1451 pairsIndexList = []
1452 1452 for pair in pairsList:
1453 1453 if pair not in dataOut.pairsList:
1454 1454 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
1455 1455 pairsIndexList.append(dataOut.pairsList.index(pair))
1456 1456
1457 1457 if pairsIndexList == []:
1458 1458 return
1459 1459
1460 1460 # if len(pairsIndexList) > 4:
1461 1461 # pairsIndexList = pairsIndexList[0:4]
1462 1462
1463 1463 hmin_index = None
1464 1464 hmax_index = None
1465 1465
1466 1466 if hmin != None and hmax != None:
1467 1467 indexes = numpy.arange(dataOut.nHeights)
1468 1468 hmin_list = indexes[dataOut.heightList >= hmin]
1469 1469 hmax_list = indexes[dataOut.heightList <= hmax]
1470 1470
1471 1471 if hmin_list.any():
1472 1472 hmin_index = hmin_list[0]
1473 1473
1474 1474 if hmax_list.any():
1475 1475 hmax_index = hmax_list[-1]+1
1476 1476
1477 1477 x = dataOut.getTimeRange()
1478 1478 #y = dataOut.getHeiRange()
1479 1479
1480 1480
1481 1481 thisDatetime = dataOut.datatime
1482 1482
1483 1483 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1484 1484 xlabel = "Local Time"
1485 1485 ylabel = "Phase (degrees)"
1486 1486
1487 1487 update_figfile = False
1488 1488
1489 1489 nplots = len(pairsIndexList)
1490 1490 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1491 1491 phase_beacon = numpy.zeros(len(pairsIndexList))
1492 1492 for i in range(nplots):
1493 1493 pair = dataOut.pairsList[pairsIndexList[i]]
1494 1494 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
1495 1495 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
1496 1496 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
1497 1497 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
1498 1498 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
1499 1499
1500 1500 #print "Phase %d%d" %(pair[0], pair[1])
1501 1501 #print phase[dataOut.beacon_heiIndexList]
1502 1502
1503 1503 if dataOut.beacon_heiIndexList:
1504 1504 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
1505 1505 else:
1506 1506 phase_beacon[i] = numpy.average(phase)
1507 1507
1508 1508 if not self.isConfig:
1509 1509
1510 1510 nplots = len(pairsIndexList)
1511 1511
1512 1512 self.setup(id=id,
1513 1513 nplots=nplots,
1514 1514 wintitle=wintitle,
1515 1515 showprofile=showprofile,
1516 1516 show=show)
1517 1517
1518 1518 if timerange != None:
1519 1519 self.timerange = timerange
1520 1520
1521 1521 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1522 1522
1523 1523 if ymin == None: ymin = 0
1524 1524 if ymax == None: ymax = 360
1525 1525
1526 1526 self.FTP_WEI = ftp_wei
1527 1527 self.EXP_CODE = exp_code
1528 1528 self.SUB_EXP_CODE = sub_exp_code
1529 1529 self.PLOT_POS = plot_pos
1530 1530
1531 1531 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1532 1532 self.isConfig = True
1533 1533 self.figfile = figfile
1534 1534 self.xdata = numpy.array([])
1535 1535 self.ydata = numpy.array([])
1536 1536
1537 1537 update_figfile = True
1538 1538
1539 1539 #open file beacon phase
1540 1540 path = '%s%03d' %(self.PREFIX, self.id)
1541 1541 beacon_file = os.path.join(path,'%s.txt'%self.name)
1542 1542 self.filename_phase = os.path.join(figpath,beacon_file)
1543 1543 #self.save_phase(self.filename_phase)
1544 1544
1545 1545
1546 1546 #store data beacon phase
1547 1547 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1548 1548
1549 1549 self.setWinTitle(title)
1550 1550
1551 1551
1552 1552 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1553 1553
1554 1554 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
1555 1555
1556 1556 axes = self.axesList[0]
1557 1557
1558 1558 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1559 1559
1560 1560 if len(self.ydata)==0:
1561 1561 self.ydata = phase_beacon.reshape(-1,1)
1562 1562 else:
1563 1563 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1564 1564
1565 1565
1566 1566 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1567 1567 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1568 1568 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1569 1569 XAxisAsTime=True, grid='both'
1570 1570 )
1571 1571
1572 1572 self.draw()
1573 1573
1574 1574 if dataOut.ltctime >= self.xmax:
1575 1575 self.counter_imagwr = wr_period
1576 1576 self.isConfig = False
1577 1577 update_figfile = True
1578 1578
1579 1579 self.save(figpath=figpath,
1580 1580 figfile=figfile,
1581 1581 save=save,
1582 1582 ftp=ftp,
1583 1583 wr_period=wr_period,
1584 1584 thisDatetime=thisDatetime,
1585 1585 update_figfile=update_figfile)
1586 1586
1587 1587 return dataOut No newline at end of file
@@ -1,232 +1,232
1 1 '''
2 2 Created on Jul 9, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import os
7 7 import datetime
8 8 import numpy
9 9 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator #YONG
10 10 from schainpy.utils import log
11 11 from .figure import Figure
12 12
13 13
14 14 @MPDecorator
15 class Scope(Figure):
15 class Scope_(Figure):
16 16
17 17 isConfig = None
18 18
19 19 def __init__(self):#, **kwargs): #YONG
20 20 Figure.__init__(self)#, **kwargs)
21 21 self.isConfig = False
22 22 self.WIDTH = 300
23 23 self.HEIGHT = 200
24 24 self.counter_imagwr = 0
25 25
26 26 def getSubplots(self):
27 27
28 28 nrow = self.nplots
29 29 ncol = 3
30 30 return nrow, ncol
31 31
32 32 def setup(self, id, nplots, wintitle, show):
33 33
34 34 self.nplots = nplots
35 35
36 36 self.createFigure(id=id,
37 37 wintitle=wintitle,
38 38 show=show)
39 39
40 40 nrow,ncol = self.getSubplots()
41 41 colspan = 3
42 42 rowspan = 1
43 43
44 44 for i in range(nplots):
45 45 self.addAxes(nrow, ncol, i, 0, colspan, rowspan)
46 46
47 47 def plot_iq(self, x, y, id, channelIndexList, thisDatetime, wintitle, show, xmin, xmax, ymin, ymax):
48 48 yreal = y[channelIndexList,:].real
49 49 yimag = y[channelIndexList,:].imag
50 50
51 51 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
52 52 xlabel = "Range (Km)"
53 53 ylabel = "Intensity - IQ"
54 54
55 55 if not self.isConfig:
56 56 nplots = len(channelIndexList)
57 57
58 58 self.setup(id=id,
59 59 nplots=nplots,
60 60 wintitle='',
61 61 show=show)
62 62
63 63 if xmin == None: xmin = numpy.nanmin(x)
64 64 if xmax == None: xmax = numpy.nanmax(x)
65 65 if ymin == None: ymin = min(numpy.nanmin(yreal),numpy.nanmin(yimag))
66 66 if ymax == None: ymax = max(numpy.nanmax(yreal),numpy.nanmax(yimag))
67 67
68 68 self.isConfig = True
69 69
70 70 self.setWinTitle(title)
71 71
72 72 for i in range(len(self.axesList)):
73 73 title = "Channel %d" %(i)
74 74 axes = self.axesList[i]
75 75
76 76 axes.pline(x, yreal[i,:],
77 77 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
78 78 xlabel=xlabel, ylabel=ylabel, title=title)
79 79
80 80 axes.addpline(x, yimag[i,:], idline=1, color="red", linestyle="solid", lw=2)
81 81
82 82 def plot_power(self, x, y, id, channelIndexList, thisDatetime, wintitle, show, xmin, xmax, ymin, ymax):
83 83 y = y[channelIndexList,:] * numpy.conjugate(y[channelIndexList,:])
84 84 yreal = y.real
85 85
86 86 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
87 87 xlabel = "Range (Km)"
88 88 ylabel = "Intensity"
89 89
90 90 if not self.isConfig:
91 91 nplots = len(channelIndexList)
92 92
93 93 self.setup(id=id,
94 94 nplots=nplots,
95 95 wintitle='',
96 96 show=show)
97 97
98 98 if xmin == None: xmin = numpy.nanmin(x)
99 99 if xmax == None: xmax = numpy.nanmax(x)
100 100 if ymin == None: ymin = numpy.nanmin(yreal)
101 101 if ymax == None: ymax = numpy.nanmax(yreal)
102 102
103 103 self.isConfig = True
104 104
105 105 self.setWinTitle(title)
106 106
107 107 for i in range(len(self.axesList)):
108 108 title = "Channel %d" %(i)
109 109 axes = self.axesList[i]
110 110 ychannel = yreal[i,:]
111 111 axes.pline(x, ychannel,
112 112 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
113 113 xlabel=xlabel, ylabel=ylabel, title=title)
114 114
115 115
116 116 def run(self, dataOut, id, wintitle="", channelList=None,
117 117 xmin=None, xmax=None, ymin=None, ymax=None, save=False,
118 118 figpath='./', figfile=None, show=True, wr_period=1,
119 119 ftp=False, server=None, folder=None, username=None, password=None, type='power', **kwargs):
120 120
121 121 """
122 122
123 123 Input:
124 124 dataOut :
125 125 id :
126 126 wintitle :
127 127 channelList :
128 128 xmin : None,
129 129 xmax : None,
130 130 ymin : None,
131 131 ymax : None,
132 132 """
133 133 if dataOut.flagNoData:
134 134 return dataOut
135 135
136 136 if channelList == None:
137 137 channelIndexList = dataOut.channelIndexList
138 138 else:
139 139 channelIndexList = []
140 140 for channel in channelList:
141 141 if channel not in dataOut.channelList:
142 142 raise ValueError("Channel %d is not in dataOut.channelList")
143 143 channelIndexList.append(dataOut.channelList.index(channel))
144 144
145 145 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[0])
146 146
147 147 if dataOut.flagDataAsBlock:
148 148
149 149 for i in range(dataOut.nProfiles):
150 150
151 151 wintitle1 = wintitle + " [Profile = %d] " %i
152 152
153 153 if type == "power":
154 154 self.plot_power(dataOut.heightList,
155 155 dataOut.data[:,i,:],
156 156 id,
157 157 channelIndexList,
158 158 thisDatetime,
159 159 wintitle1,
160 160 show,
161 161 xmin,
162 162 xmax,
163 163 ymin,
164 164 ymax)
165 165
166 166 if type == "iq":
167 167 self.plot_iq(dataOut.heightList,
168 168 dataOut.data[:,i,:],
169 169 id,
170 170 channelIndexList,
171 171 thisDatetime,
172 172 wintitle1,
173 173 show,
174 174 xmin,
175 175 xmax,
176 176 ymin,
177 177 ymax)
178 178
179 179 self.draw()
180 180
181 181 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
182 182 figfile = self.getFilename(name = str_datetime) + "_" + str(i)
183 183
184 184 self.save(figpath=figpath,
185 185 figfile=figfile,
186 186 save=save,
187 187 ftp=ftp,
188 188 wr_period=wr_period,
189 189 thisDatetime=thisDatetime)
190 190
191 191 else:
192 192 wintitle += " [Profile = %d] " %dataOut.profileIndex
193 193
194 194 if type == "power":
195 195 self.plot_power(dataOut.heightList,
196 196 dataOut.data,
197 197 id,
198 198 channelIndexList,
199 199 thisDatetime,
200 200 wintitle,
201 201 show,
202 202 xmin,
203 203 xmax,
204 204 ymin,
205 205 ymax)
206 206
207 207 if type == "iq":
208 208 self.plot_iq(dataOut.heightList,
209 209 dataOut.data,
210 210 id,
211 211 channelIndexList,
212 212 thisDatetime,
213 213 wintitle,
214 214 show,
215 215 xmin,
216 216 xmax,
217 217 ymin,
218 218 ymax)
219 219
220 220 self.draw()
221 221
222 222 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S") + "_" + str(dataOut.profileIndex)
223 223 figfile = self.getFilename(name = str_datetime)
224 224
225 225 self.save(figpath=figpath,
226 226 figfile=figfile,
227 227 save=save,
228 228 ftp=ftp,
229 229 wr_period=wr_period,
230 230 thisDatetime=thisDatetime)
231 231
232 232 return dataOut No newline at end of file
@@ -1,367 +1,376
1 1 '''
2 2 Updated for multiprocessing
3 3 Author : Sergio Cortez
4 4 Jan 2018
5 5 Abstract:
6 6 Base class for processing units and operations. A decorator provides multiprocessing features and interconnect the processes created.
7 7 The argument (kwargs) sent from the controller is parsed and filtered via the decorator for each processing unit or operation instantiated.
8 8 The decorator handle also the methods inside the processing unit to be called from the main script (not as operations) (OPERATION -> type ='self').
9 9
10 10 Based on:
11 11 $Author: murco $
12 12 $Id: jroproc_base.py 1 2012-11-12 18:56:07Z murco $
13 13 '''
14 from platform import python_version
14
15 15 import inspect
16 16 import zmq
17 17 import time
18 18 import pickle
19 19 import os
20 20 from multiprocessing import Process
21 from zmq.utils.monitor import recv_monitor_message
22
21 23 from schainpy.utils import log
22 24
23 25
24 26 class ProcessingUnit(object):
25 27
26 28 """
27 29 Update - Jan 2018 - MULTIPROCESSING
28 30 All the "call" methods present in the previous base were removed.
29 31 The majority of operations are independant processes, thus
30 32 the decorator is in charge of communicate the operation processes
31 33 with the proccessing unit via IPC.
32 34
33 35 The constructor does not receive any argument. The remaining methods
34 36 are related with the operations to execute.
35 37
36 38
37 39 """
38
39 METHODS = {}
40 dataIn = None
41 dataInList = []
42 id = None
43 inputId = None
44 dataOut = None
45 dictProcs = None
46 isConfig = False
47 40
48 41 def __init__(self):
49 42
50 43 self.dataIn = None
51 44 self.dataOut = None
52 45 self.isConfig = False
53 46 self.operations = []
47 self.plots = []
54 48
55 49 def getAllowedArgs(self):
56 50 if hasattr(self, '__attrs__'):
57 51 return self.__attrs__
58 52 else:
59 53 return inspect.getargspec(self.run).args
60
61 def addOperation(self, conf, operation):
62 54
55 def addOperation(self, conf, operation):
63 56 """
64 57 This method is used in the controller, and update the dictionary containing the operations to execute. The dict
65 58 posses the id of the operation process (IPC purposes)
66 59
67 60 Agrega un objeto del tipo "Operation" (opObj) a la lista de objetos "self.objectList" y retorna el
68 61 identificador asociado a este objeto.
69 62
70 63 Input:
71 64
72 65 object : objeto de la clase "Operation"
73 66
74 67 Return:
75 68
76 69 objId : identificador del objeto, necesario para comunicar con master(procUnit)
77 70 """
78 71
79 self.operations.append((operation, conf.type, conf.id, conf.getKwargs()))
72 self.operations.append(
73 (operation, conf.type, conf.id, conf.getKwargs()))
74
75 if 'plot' in self.name.lower():
76 self.plots.append(operation.CODE)
80 77
81 78 def getOperationObj(self, objId):
82 79
83 80 if objId not in list(self.operations.keys()):
84 81 return None
85 82
86 83 return self.operations[objId]
87 84
88 85 def operation(self, **kwargs):
89
90 86 """
91 87 Operacion directa sobre la data (dataOut.data). Es necesario actualizar los valores de los
92 88 atributos del objeto dataOut
93 89
94 90 Input:
95 91
96 92 **kwargs : Diccionario de argumentos de la funcion a ejecutar
97 93 """
98 94
99 raise NotImplementedError
95 raise NotImplementedError
100 96
101 97 def setup(self):
102 98
103 99 raise NotImplementedError
104 100
105 101 def run(self):
106 102
107 103 raise NotImplementedError
108 104
109 105 def close(self):
110 #Close every thread, queue or any other object here is it is neccesary.
106
111 107 return
112
108
109
113 110 class Operation(object):
114 111
115 112 """
116 113 Update - Jan 2018 - MULTIPROCESSING
117 114
118 115 Most of the methods remained the same. The decorator parse the arguments and executed the run() method for each process.
119 116 The constructor doe snot receive any argument, neither the baseclass.
120 117
121 118
122 119 Clase base para definir las operaciones adicionales que se pueden agregar a la clase ProcessingUnit
123 120 y necesiten acumular informacion previa de los datos a procesar. De preferencia usar un buffer de
124 121 acumulacion dentro de esta clase
125 122
126 123 Ejemplo: Integraciones coherentes, necesita la informacion previa de los n perfiles anteriores (bufffer)
127 124
128 125 """
129 id = None
130 __buffer = None
131 dest = None
132 isConfig = False
133 readyFlag = None
134 126
135 127 def __init__(self):
136 128
137 self.buffer = None
138 self.dest = None
129 self.id = None
139 130 self.isConfig = False
140 self.readyFlag = False
141 131
142 132 if not hasattr(self, 'name'):
143 133 self.name = self.__class__.__name__
144
134
145 135 def getAllowedArgs(self):
146 136 if hasattr(self, '__attrs__'):
147 137 return self.__attrs__
148 138 else:
149 139 return inspect.getargspec(self.run).args
150 140
151 141 def setup(self):
152 142
153 143 self.isConfig = True
154 144
155 145 raise NotImplementedError
156 146
157
158 147 def run(self, dataIn, **kwargs):
159
160 148 """
161 149 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
162 150 atributos del objeto dataIn.
163 151
164 152 Input:
165 153
166 154 dataIn : objeto del tipo JROData
167 155
168 156 Return:
169 157
170 158 None
171 159
172 160 Affected:
173 161 __buffer : buffer de recepcion de datos.
174 162
175 163 """
176 164 if not self.isConfig:
177 165 self.setup(**kwargs)
178 166
179 167 raise NotImplementedError
180 168
181 169 def close(self):
182 170
183 pass
171 return
184 172
185 173
186 174 def MPDecorator(BaseClass):
187
188 175 """
189 176 Multiprocessing class decorator
190 177
191 178 This function add multiprocessing features to a BaseClass. Also, it handle
192 179 the communication beetween processes (readers, procUnits and operations).
193 180 """
194
181
195 182 class MPClass(BaseClass, Process):
196 183
197 184 def __init__(self, *args, **kwargs):
198 185 super(MPClass, self).__init__()
199 186 Process.__init__(self)
200 187 self.operationKwargs = {}
201 188 self.args = args
202 189 self.kwargs = kwargs
203 190 self.sender = None
204 191 self.receiver = None
205 192 self.name = BaseClass.__name__
193 self.start_time = time.time()
206 194
207 195 if len(self.args) is 3:
208 196 self.typeProc = "ProcUnit"
209 self.id = args[0]
210 self.inputId = args[1]
211 self.project_id = args[2]
212 else:
197 self.id = args[0]
198 self.inputId = args[1]
199 self.project_id = args[2]
200 elif len(self.args) is 2:
213 201 self.id = args[0]
214 202 self.inputId = args[0]
215 203 self.project_id = args[1]
216 204 self.typeProc = "Operation"
217 205
218 def getAllowedArgs(self):
219
220 if hasattr(self, '__attrs__'):
221 return self.__attrs__
222 else:
223 return inspect.getargspec(BaseClass.run).args
224
225 206 def subscribe(self):
226 207 '''
227 208 This function create a socket to receive objects from the
228 209 topic `inputId`.
229 210 '''
230
211
231 212 c = zmq.Context()
232 213 self.receiver = c.socket(zmq.SUB)
233 self.receiver.connect('ipc:///tmp/schain/{}_pub'.format(self.project_id))
214 self.receiver.connect(
215 'ipc:///tmp/schain/{}_pub'.format(self.project_id))
234 216 self.receiver.setsockopt(zmq.SUBSCRIBE, self.inputId.encode())
235 217
236 218 def listen(self):
237 219 '''
238 220 This function waits for objects and deserialize using pickle
239 221 '''
240
241 data = pickle.loads(self.receiver.recv_multipart()[1])
222
223 data = pickle.loads(self.receiver.recv_multipart()[1])
224
242 225 return data
243 226
244 227 def set_publisher(self):
245 228 '''
246 229 This function create a socket for publishing purposes.
247 230 '''
248 231
249 232 time.sleep(1)
250 233 c = zmq.Context()
251 self.sender = c.socket(zmq.PUB)
252 self.sender.connect('ipc:///tmp/schain/{}_sub'.format(self.project_id))
234 self.sender = c.socket(zmq.PUB)
235 self.sender.connect(
236 'ipc:///tmp/schain/{}_sub'.format(self.project_id))
253 237
254 def publish(self, data, id):
238 def publish(self, data, id):
255 239 '''
256 240 This function publish an object, to a specific topic.
257 241 '''
258
259 242 self.sender.send_multipart([str(id).encode(), pickle.dumps(data)])
260 243
261 244 def runReader(self):
262 245 '''
263 246 Run fuction for read units
264 247 '''
265 248 while True:
266
267 BaseClass.run(self, **self.kwargs)
268 249
269 if self.dataOut.error[0] == -1:
270 log.error(self.dataOut.error[1])
271 self.publish('end', self.id)
272 #self.sender.send_multipart([str(self.project_id).encode(), 'end'.encode()])
273 break
250 BaseClass.run(self, **self.kwargs)
274 251
275 for op, optype, id, kwargs in self.operations:
276 if optype=='self':
252 for op, optype, opId, kwargs in self.operations:
253 if optype == 'self':
277 254 op(**kwargs)
278 elif optype=='other':
255 elif optype == 'other':
279 256 self.dataOut = op.run(self.dataOut, **self.kwargs)
280 elif optype=='external':
257 elif optype == 'external':
281 258 self.publish(self.dataOut, opId)
282 259
283 if self.dataOut.flagNoData:
260 if self.dataOut.flagNoData and self.dataOut.error is None:
284 261 continue
285
286 self.publish(self.dataOut, self.id)
287
262
263 self.publish(self.dataOut, self.id)
264
265 if self.dataOut.error:
266 if self.dataOut.error[0] == -1:
267 log.error(self.dataOut.error[1], self.name)
268 if self.dataOut.error[0] == 1:
269 log.success(self.dataOut.error[1], self.name)
270 # self.sender.send_multipart([str(self.project_id).encode(), 'end'.encode()])
271 break
272
273 time.sleep(1)
274
288 275 def runProc(self):
289 276 '''
290 277 Run function for proccessing units
291 278 '''
292 279
293 280 while True:
294 281 self.dataIn = self.listen()
295 282
296 if self.dataIn == 'end':
297 self.publish('end', self.id)
298 for op, optype, opId, kwargs in self.operations:
299 if optype == 'external':
300 self.publish('end', opId)
301 break
302
303 if self.dataIn.flagNoData:
283 if self.dataIn.flagNoData and self.dataIn.error is None:
304 284 continue
305 285
306 286 BaseClass.run(self, **self.kwargs)
307 287
308 288 for op, optype, opId, kwargs in self.operations:
309 if optype=='self':
289 if optype == 'self':
310 290 op(**kwargs)
311 elif optype=='other':
291 elif optype == 'other':
312 292 self.dataOut = op.run(self.dataOut, **kwargs)
313 elif optype=='external':
293 elif optype == 'external':
314 294 self.publish(self.dataOut, opId)
315 295
316 if self.dataOut.flagNoData:
317 continue
318
319 296 self.publish(self.dataOut, self.id)
297 if self.dataIn.error:
298 break
299
300 time.sleep(1)
320 301
321 302 def runOp(self):
322 303 '''
323 Run function for operations
304 Run function for external operations (this operations just receive data
305 ex: plots, writers, publishers)
324 306 '''
325 307
326 308 while True:
327 309
328 310 dataOut = self.listen()
329 311
330 if dataOut == 'end':
331 break
332
333 312 BaseClass.run(self, dataOut, **self.kwargs)
334
313
314 if dataOut.error:
315 break
316 time.sleep(1)
317
335 318 def run(self):
336
319
337 320 if self.typeProc is "ProcUnit":
338
321
339 322 if self.inputId is not None:
340 323 self.subscribe()
341 324 self.set_publisher()
342 325
343 326 if 'Reader' not in BaseClass.__name__:
344 327 self.runProc()
345 328 else:
346 329 self.runReader()
347 330
348 331 elif self.typeProc is "Operation":
349
332
350 333 self.subscribe()
351 334 self.runOp()
352 335
353 336 else:
354 337 raise ValueError("Unknown type")
355 338
356 print("%s done" % BaseClass.__name__)
357 339 self.close()
358 340
341 def event_monitor(self, monitor):
342
343 events = {}
344
345 for name in dir(zmq):
346 if name.startswith('EVENT_'):
347 value = getattr(zmq, name)
348 events[value] = name
349
350 while monitor.poll():
351 evt = recv_monitor_message(monitor)
352 if evt['event'] == 32:
353 self.connections += 1
354 if evt['event'] == 512:
355 pass
356
357 evt.update({'description': events[evt['event']]})
358
359 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
360 break
361 monitor.close()
362 print('event monitor thread done!')
363
359 364 def close(self):
360
365
366 BaseClass.close(self)
367
361 368 if self.sender:
362 369 self.sender.close()
363
370
364 371 if self.receiver:
365 372 self.receiver.close()
366 373
367 return MPClass No newline at end of file
374 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
375
376 return MPClass
This diff has been collapsed as it changes many lines, (612 lines changed) Show them Hide them
@@ -1,869 +1,309
1 1 '''
2 2 @author: Juan C. Espinoza
3 3 '''
4 4
5 5 import os
6 6 import glob
7 7 import time
8 8 import json
9 9 import numpy
10 import paho.mqtt.client as mqtt
11 10 import zmq
12 11 import datetime
13 12 import ftplib
14 from zmq.utils.monitor import recv_monitor_message
15 13 from functools import wraps
16 14 from threading import Thread
17 15 from multiprocessing import Process
18 16
19 17 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
20 18 from schainpy.model.data.jrodata import JROData
21 19 from schainpy.utils import log
22 20
23 21 MAXNUMX = 500
24 22 MAXNUMY = 500
25 23
26 24 PLOT_CODES = {
27 25 'rti': 0, # Range time intensity (RTI).
28 26 'spc': 1, # Spectra (and Cross-spectra) information.
29 27 'cspc': 2, # Cross-Correlation information.
30 28 'coh': 3, # Coherence map.
31 29 'base': 4, # Base lines graphic.
32 30 'row': 5, # Row Spectra.
33 31 'total': 6, # Total Power.
34 32 'drift': 7, # Drifts graphics.
35 33 'height': 8, # Height profile.
36 34 'phase': 9, # Signal Phase.
37 35 'power': 16,
38 36 'noise': 17,
39 37 'beacon': 18,
40 38 'wind': 22,
41 39 'skymap': 23,
42 40 'Unknown': 24,
43 41 'V-E': 25, # PIP Velocity.
44 42 'Z-E': 26, # PIP Reflectivity.
45 43 'V-A': 27, # RHI Velocity.
46 44 'Z-A': 28, # RHI Reflectivity.
47 45 }
48 46
49 47 def get_plot_code(s):
50 48 label = s.split('_')[0]
51 49 codes = [key for key in PLOT_CODES if key in label]
52 50 if codes:
53 51 return PLOT_CODES[codes[0]]
54 52 else:
55 53 return 24
56 54
57 def roundFloats(obj):
58 if isinstance(obj, list):
59 return list(map(roundFloats, obj))
60 elif isinstance(obj, float):
61 return round(obj, 2)
62
63 55 def decimate(z, MAXNUMY):
64 56 dy = int(len(z[0])/MAXNUMY) + 1
65 57
66 58 return z[::, ::dy]
67 59
68 class throttle(object):
69 '''
70 Decorator that prevents a function from being called more than once every
71 time period.
72 To create a function that cannot be called more than once a minute, but
73 will sleep until it can be called:
74 @throttle(minutes=1)
75 def foo():
76 pass
77
78 for i in range(10):
79 foo()
80 print "This function has run %s times." % i
81 '''
82
83 def __init__(self, seconds=0, minutes=0, hours=0):
84 self.throttle_period = datetime.timedelta(
85 seconds=seconds, minutes=minutes, hours=hours
86 )
87
88 self.time_of_last_call = datetime.datetime.min
89
90 def __call__(self, fn):
91 @wraps(fn)
92 def wrapper(*args, **kwargs):
93 coerce = kwargs.pop('coerce', None)
94 if coerce:
95 self.time_of_last_call = datetime.datetime.now()
96 return fn(*args, **kwargs)
97 else:
98 now = datetime.datetime.now()
99 time_since_last_call = now - self.time_of_last_call
100 time_left = self.throttle_period - time_since_last_call
101
102 if time_left > datetime.timedelta(seconds=0):
103 return
104
105 self.time_of_last_call = datetime.datetime.now()
106 return fn(*args, **kwargs)
107
108 return wrapper
109
110 class Data(object):
111 '''
112 Object to hold data to be plotted
113 '''
114
115 def __init__(self, plottypes, throttle_value, exp_code, buffering=True):
116 self.plottypes = plottypes
117 self.throttle = throttle_value
118 self.exp_code = exp_code
119 self.buffering = buffering
120 self.ended = False
121 self.localtime = False
122 self.meta = {}
123 self.__times = []
124 self.__heights = []
125
126 def __str__(self):
127 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
128 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
129
130 def __len__(self):
131 return len(self.__times)
132
133 def __getitem__(self, key):
134 if key not in self.data:
135 raise KeyError(log.error('Missing key: {}'.format(key)))
136
137 if 'spc' in key or not self.buffering:
138 ret = self.data[key]
139 else:
140 ret = numpy.array([self.data[key][x] for x in self.times])
141 if ret.ndim > 1:
142 ret = numpy.swapaxes(ret, 0, 1)
143 return ret
144
145 def __contains__(self, key):
146 return key in self.data
147
148 def setup(self):
149 '''
150 Configure object
151 '''
152
153 self.type = ''
154 self.ended = False
155 self.data = {}
156 self.__times = []
157 self.__heights = []
158 self.__all_heights = set()
159 for plot in self.plottypes:
160 if 'snr' in plot:
161 plot = 'snr'
162 self.data[plot] = {}
163
164 def shape(self, key):
165 '''
166 Get the shape of the one-element data for the given key
167 '''
168
169 if len(self.data[key]):
170 if 'spc' in key or not self.buffering:
171 return self.data[key].shape
172 return self.data[key][self.__times[0]].shape
173 return (0,)
174
175 def update(self, dataOut, tm):
176 '''
177 Update data object with new dataOut
178 '''
179
180 if tm in self.__times:
181 return
182
183 self.type = dataOut.type
184 self.parameters = getattr(dataOut, 'parameters', [])
185 if hasattr(dataOut, 'pairsList'):
186 self.pairs = dataOut.pairsList
187 if hasattr(dataOut, 'meta'):
188 self.meta = dataOut.meta
189 self.channels = dataOut.channelList
190 self.interval = dataOut.getTimeInterval()
191 self.localtime = dataOut.useLocalTime
192 if 'spc' in self.plottypes or 'cspc' in self.plottypes:
193 self.xrange = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
194 self.__heights.append(dataOut.heightList)
195 self.__all_heights.update(dataOut.heightList)
196 self.__times.append(tm)
197
198 for plot in self.plottypes:
199 if plot == 'spc':
200 z = dataOut.data_spc/dataOut.normFactor
201 buffer = 10*numpy.log10(z)
202 if plot == 'cspc':
203 buffer = dataOut.data_cspc
204 if plot == 'noise':
205 buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
206 if plot == 'rti':
207 buffer = dataOut.getPower()
208 if plot == 'snr_db':
209 buffer = dataOut.data_SNR
210 if plot == 'snr':
211 buffer = 10*numpy.log10(dataOut.data_SNR)
212 if plot == 'dop':
213 buffer = 10*numpy.log10(dataOut.data_DOP)
214 if plot == 'mean':
215 buffer = dataOut.data_MEAN
216 if plot == 'std':
217 buffer = dataOut.data_STD
218 if plot == 'coh':
219 buffer = dataOut.getCoherence()
220 if plot == 'phase':
221 buffer = dataOut.getCoherence(phase=True)
222 if plot == 'output':
223 buffer = dataOut.data_output
224 if plot == 'param':
225 buffer = dataOut.data_param
226
227 if 'spc' in plot:
228 self.data[plot] = buffer
229 else:
230 if self.buffering:
231 self.data[plot][tm] = buffer
232 else:
233 self.data[plot] = buffer
234
235 def normalize_heights(self):
236 '''
237 Ensure same-dimension of the data for different heighList
238 '''
239
240 H = numpy.array(list(self.__all_heights))
241 H.sort()
242 for key in self.data:
243 shape = self.shape(key)[:-1] + H.shape
244 for tm, obj in list(self.data[key].items()):
245 h = self.__heights[self.__times.index(tm)]
246 if H.size == h.size:
247 continue
248 index = numpy.where(numpy.in1d(H, h))[0]
249 dummy = numpy.zeros(shape) + numpy.nan
250 if len(shape) == 2:
251 dummy[:, index] = obj
252 else:
253 dummy[index] = obj
254 self.data[key][tm] = dummy
255
256 self.__heights = [H for tm in self.__times]
257
258 def jsonify(self, decimate=False):
259 '''
260 Convert data to json
261 '''
262
263 data = {}
264 tm = self.times[-1]
265 dy = int(self.heights.size/MAXNUMY) + 1
266 for key in self.data:
267 if key in ('spc', 'cspc') or not self.buffering:
268 dx = int(self.data[key].shape[1]/MAXNUMX) + 1
269 data[key] = roundFloats(self.data[key][::, ::dx, ::dy].tolist())
270 else:
271 data[key] = roundFloats(self.data[key][tm].tolist())
272
273 ret = {'data': data}
274 ret['exp_code'] = self.exp_code
275 ret['time'] = tm
276 ret['interval'] = self.interval
277 ret['localtime'] = self.localtime
278 ret['yrange'] = roundFloats(self.heights[::dy].tolist())
279 if 'spc' in self.data or 'cspc' in self.data:
280 ret['xrange'] = roundFloats(self.xrange[2][::dx].tolist())
281 else:
282 ret['xrange'] = []
283 if hasattr(self, 'pairs'):
284 ret['pairs'] = self.pairs
285 else:
286 ret['pairs'] = []
287
288 for key, value in list(self.meta.items()):
289 ret[key] = value
290
291 return json.dumps(ret)
292
293 @property
294 def times(self):
295 '''
296 Return the list of times of the current data
297 '''
298
299 ret = numpy.array(self.__times)
300 ret.sort()
301 return ret
302
303 @property
304 def heights(self):
305 '''
306 Return the list of heights of the current data
307 '''
308
309 return numpy.array(self.__heights[-1])
310 60
311 61 class PublishData(Operation):
312 62 '''
313 63 Operation to send data over zmq.
314 64 '''
315 65
316 __attrs__ = ['host', 'port', 'delay', 'zeromq', 'mqtt', 'verbose']
66 __attrs__ = ['host', 'port', 'delay', 'verbose']
317 67
318 68 def __init__(self, **kwargs):
319 69 """Inicio."""
320 70 Operation.__init__(self, **kwargs)
321 71 self.isConfig = False
322 self.client = None
323 self.zeromq = None
324 self.mqtt = None
325 72
326 def on_disconnect(self, client, userdata, rc):
327 if rc != 0:
328 log.warning('Unexpected disconnection.')
329 self.connect()
330
331 def connect(self):
332 log.warning('trying to connect')
333 try:
334 self.client.connect(
335 host=self.host,
336 port=self.port,
337 keepalive=60*10,
338 bind_address='')
339 self.client.loop_start()
340 # self.client.publish(
341 # self.topic + 'SETUP',
342 # json.dumps(setup),
343 # retain=True
344 # )
345 except:
346 log.error('MQTT Conection error.')
347 self.client = False
348
349 def setup(self, port=1883, username=None, password=None, clientId="user", zeromq=1, verbose=True, **kwargs):
73 def setup(self, server='zmq.pipe', delay=0, verbose=True, **kwargs):
350 74 self.counter = 0
351 self.topic = kwargs.get('topic', 'schain')
352 75 self.delay = kwargs.get('delay', 0)
353 self.plottype = kwargs.get('plottype', 'spectra')
354 self.host = kwargs.get('host', "10.10.10.82")
355 self.port = kwargs.get('port', 3000)
356 self.clientId = clientId
357 76 self.cnt = 0
358 self.zeromq = zeromq
359 self.mqtt = kwargs.get('plottype', 0)
360 self.client = None
361 77 self.verbose = verbose
362 78 setup = []
363 if mqtt is 1:
364 self.client = mqtt.Client(
365 client_id=self.clientId + self.topic + 'SCHAIN',
366 clean_session=True)
367 self.client.on_disconnect = self.on_disconnect
368 self.connect()
369 for plot in self.plottype:
370 setup.append({
371 'plot': plot,
372 'topic': self.topic + plot,
373 'title': getattr(self, plot + '_' + 'title', False),
374 'xlabel': getattr(self, plot + '_' + 'xlabel', False),
375 'ylabel': getattr(self, plot + '_' + 'ylabel', False),
376 'xrange': getattr(self, plot + '_' + 'xrange', False),
377 'yrange': getattr(self, plot + '_' + 'yrange', False),
378 'zrange': getattr(self, plot + '_' + 'zrange', False),
379 })
380 if zeromq is 1:
381 context = zmq.Context()
382 self.zmq_socket = context.socket(zmq.PUSH)
383 server = kwargs.get('server', 'zmq.pipe')
384
385 if 'tcp://' in server:
386 address = server
387 else:
388 address = 'ipc:///tmp/%s' % server
389
390 self.zmq_socket.connect(address)
391 time.sleep(1)
79 context = zmq.Context()
80 self.zmq_socket = context.socket(zmq.PUSH)
81 server = kwargs.get('server', 'zmq.pipe')
82
83 if 'tcp://' in server:
84 address = server
85 else:
86 address = 'ipc:///tmp/%s' % server
87
88 self.zmq_socket.connect(address)
89 time.sleep(1)
392 90
393 91
394 92 def publish_data(self):
395 93 self.dataOut.finished = False
396 if self.mqtt is 1:
397 yData = self.dataOut.heightList[:2].tolist()
398 if self.plottype == 'spectra':
399 data = getattr(self.dataOut, 'data_spc')
400 z = data/self.dataOut.normFactor
401 zdB = 10*numpy.log10(z)
402 xlen, ylen = zdB[0].shape
403 dx = int(xlen/MAXNUMX) + 1
404 dy = int(ylen/MAXNUMY) + 1
405 Z = [0 for i in self.dataOut.channelList]
406 for i in self.dataOut.channelList:
407 Z[i] = zdB[i][::dx, ::dy].tolist()
408 payload = {
409 'timestamp': self.dataOut.utctime,
410 'data': roundFloats(Z),
411 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
412 'interval': self.dataOut.getTimeInterval(),
413 'type': self.plottype,
414 'yData': yData
415 }
416
417 elif self.plottype in ('rti', 'power'):
418 data = getattr(self.dataOut, 'data_spc')
419 z = data/self.dataOut.normFactor
420 avg = numpy.average(z, axis=1)
421 avgdB = 10*numpy.log10(avg)
422 xlen, ylen = z[0].shape
423 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
424 AVG = [0 for i in self.dataOut.channelList]
425 for i in self.dataOut.channelList:
426 AVG[i] = avgdB[i][::dy].tolist()
427 payload = {
428 'timestamp': self.dataOut.utctime,
429 'data': roundFloats(AVG),
430 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
431 'interval': self.dataOut.getTimeInterval(),
432 'type': self.plottype,
433 'yData': yData
434 }
435 elif self.plottype == 'noise':
436 noise = self.dataOut.getNoise()/self.dataOut.normFactor
437 noisedB = 10*numpy.log10(noise)
438 payload = {
439 'timestamp': self.dataOut.utctime,
440 'data': roundFloats(noisedB.reshape(-1, 1).tolist()),
441 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
442 'interval': self.dataOut.getTimeInterval(),
443 'type': self.plottype,
444 'yData': yData
445 }
446 elif self.plottype == 'snr':
447 data = getattr(self.dataOut, 'data_SNR')
448 avgdB = 10*numpy.log10(data)
449
450 ylen = data[0].size
451 dy = numpy.floor(ylen/self.__MAXNUMY) + 1
452 AVG = [0 for i in self.dataOut.channelList]
453 for i in self.dataOut.channelList:
454 AVG[i] = avgdB[i][::dy].tolist()
455 payload = {
456 'timestamp': self.dataOut.utctime,
457 'data': roundFloats(AVG),
458 'channels': ['Ch %s' % ch for ch in self.dataOut.channelList],
459 'type': self.plottype,
460 'yData': yData
461 }
462 else:
463 print("Tipo de grafico invalido")
464 payload = {
465 'data': 'None',
466 'timestamp': 'None',
467 'type': None
468 }
469
470 self.client.publish(self.topic + self.plottype, json.dumps(payload), qos=0)
471
472 if self.zeromq is 1:
473 if self.verbose:
474 log.log(
475 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
476 self.name
477 )
478 self.zmq_socket.send_pyobj(self.dataOut)
94
95 if self.verbose:
96 log.log(
97 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
98 self.name
99 )
100 self.zmq_socket.send_pyobj(self.dataOut)
479 101
480 102 def run(self, dataOut, **kwargs):
481 103 self.dataOut = dataOut
482 104 if not self.isConfig:
483 105 self.setup(**kwargs)
484 106 self.isConfig = True
485 107
486 108 self.publish_data()
487 109 time.sleep(self.delay)
488 110
489 111 def close(self):
490 if self.zeromq is 1:
491 self.dataOut.finished = True
492 self.zmq_socket.send_pyobj(self.dataOut)
493 time.sleep(0.1)
494 self.zmq_socket.close()
495 if self.client:
496 self.client.loop_stop()
497 self.client.disconnect()
498
112
113 self.dataOut.finished = True
114 self.zmq_socket.send_pyobj(self.dataOut)
115 time.sleep(0.1)
116 self.zmq_socket.close()
117
499 118
500 119 class ReceiverData(ProcessingUnit):
501 120
502 121 __attrs__ = ['server']
503 122
504 123 def __init__(self, **kwargs):
505 124
506 125 ProcessingUnit.__init__(self, **kwargs)
507 126
508 127 self.isConfig = False
509 128 server = kwargs.get('server', 'zmq.pipe')
510 129 if 'tcp://' in server:
511 130 address = server
512 131 else:
513 132 address = 'ipc:///tmp/%s' % server
514 133
515 134 self.address = address
516 135 self.dataOut = JROData()
517 136
518 137 def setup(self):
519 138
520 139 self.context = zmq.Context()
521 140 self.receiver = self.context.socket(zmq.PULL)
522 141 self.receiver.bind(self.address)
523 142 time.sleep(0.5)
524 143 log.success('ReceiverData from {}'.format(self.address))
525 144
526 145
527 146 def run(self):
528 147
529 148 if not self.isConfig:
530 149 self.setup()
531 150 self.isConfig = True
532 151
533 152 self.dataOut = self.receiver.recv_pyobj()
534 153 log.log('{} - {}'.format(self.dataOut.type,
535 154 self.dataOut.datatime.ctime(),),
536 155 'Receiving')
537 156
538 157
539 class PlotterReceiver(ProcessingUnit, Process):
540
541 throttle_value = 5
542 __attrs__ = ['server', 'plottypes', 'realtime', 'localtime', 'throttle',
543 'exp_code', 'web_server', 'buffering']
544
545 def __init__(self, **kwargs):
546
547 ProcessingUnit.__init__(self, **kwargs)
548 Process.__init__(self)
549 self.mp = False
550 self.isConfig = False
551 self.isWebConfig = False
552 self.connections = 0
553 server = kwargs.get('server', 'zmq.pipe')
554 web_server = kwargs.get('web_server', None)
555 if 'tcp://' in server:
556 address = server
557 else:
558 address = 'ipc:///tmp/%s' % server
559 self.address = address
560 self.web_address = web_server
561 self.plottypes = [s.strip() for s in kwargs.get('plottypes', 'rti').split(',')]
562 self.realtime = kwargs.get('realtime', False)
563 self.localtime = kwargs.get('localtime', True)
564 self.buffering = kwargs.get('buffering', True)
565 self.throttle_value = kwargs.get('throttle', 5)
566 self.exp_code = kwargs.get('exp_code', None)
567 self.sendData = self.initThrottle(self.throttle_value)
568 self.dates = []
569 self.setup()
570
571 def setup(self):
572
573 self.data = Data(self.plottypes, self.throttle_value, self.exp_code, self.buffering)
574 self.isConfig = True
575
576 def event_monitor(self, monitor):
577
578 events = {}
579
580 for name in dir(zmq):
581 if name.startswith('EVENT_'):
582 value = getattr(zmq, name)
583 events[value] = name
584
585 while monitor.poll():
586 evt = recv_monitor_message(monitor)
587 if evt['event'] == 32:
588 self.connections += 1
589 if evt['event'] == 512:
590 pass
591
592 evt.update({'description': events[evt['event']]})
593
594 if evt['event'] == zmq.EVENT_MONITOR_STOPPED:
595 break
596 monitor.close()
597 print('event monitor thread done!')
598
599 def initThrottle(self, throttle_value):
600
601 @throttle(seconds=throttle_value)
602 def sendDataThrottled(fn_sender, data):
603 fn_sender(data)
604
605 return sendDataThrottled
606
607 def send(self, data):
608 log.log('Sending {}'.format(data), self.name)
609 self.sender.send_pyobj(data)
610
611 def run(self):
612
613 log.log(
614 'Starting from {}'.format(self.address),
615 self.name
616 )
617
618 self.context = zmq.Context()
619 self.receiver = self.context.socket(zmq.PULL)
620 self.receiver.bind(self.address)
621 monitor = self.receiver.get_monitor_socket()
622 self.sender = self.context.socket(zmq.PUB)
623 if self.web_address:
624 log.success(
625 'Sending to web: {}'.format(self.web_address),
626 self.name
627 )
628 self.sender_web = self.context.socket(zmq.REQ)
629 self.sender_web.connect(self.web_address)
630 self.poll = zmq.Poller()
631 self.poll.register(self.sender_web, zmq.POLLIN)
632 time.sleep(1)
633
634 if 'server' in self.kwargs:
635 self.sender.bind("ipc:///tmp/{}.plots".format(self.kwargs['server']))
636 else:
637 self.sender.bind("ipc:///tmp/zmq.plots")
638
639 time.sleep(2)
640
641 t = Thread(target=self.event_monitor, args=(monitor,))
642 t.start()
643
644 while True:
645 dataOut = self.receiver.recv_pyobj()
646 if not dataOut.flagNoData:
647 if dataOut.type == 'Parameters':
648 tm = dataOut.utctimeInit
649 else:
650 tm = dataOut.utctime
651 if dataOut.useLocalTime:
652 if not self.localtime:
653 tm += time.timezone
654 dt = datetime.datetime.fromtimestamp(tm).date()
655 else:
656 if self.localtime:
657 tm -= time.timezone
658 dt = datetime.datetime.utcfromtimestamp(tm).date()
659 coerce = False
660 if dt not in self.dates:
661 if self.data:
662 self.data.ended = True
663 self.send(self.data)
664 coerce = True
665 self.data.setup()
666 self.dates.append(dt)
667
668 self.data.update(dataOut, tm)
669
670 if dataOut.finished is True:
671 self.connections -= 1
672 if self.connections == 0 and dt in self.dates:
673 self.data.ended = True
674 self.send(self.data)
675 # self.data.setup()
676 time.sleep(1)
677 break
678 else:
679 if self.realtime:
680 self.send(self.data)
681 if self.web_address:
682 retries = 5
683 while True:
684 self.sender_web.send(self.data.jsonify())
685 socks = dict(self.poll.poll(5000))
686 if socks.get(self.sender_web) == zmq.POLLIN:
687 reply = self.sender_web.recv_string()
688 if reply == 'ok':
689 log.log("Response from server ok", self.name)
690 break
691 else:
692 log.warning("Malformed reply from server: {}".format(reply), self.name)
693
694 else:
695 log.warning("No response from server, retrying...", self.name)
696 self.sender_web.setsockopt(zmq.LINGER, 0)
697 self.sender_web.close()
698 self.poll.unregister(self.sender_web)
699 retries -= 1
700 if retries == 0:
701 log.error("Server seems to be offline, abandoning", self.name)
702 self.sender_web = self.context.socket(zmq.REQ)
703 self.sender_web.connect(self.web_address)
704 self.poll.register(self.sender_web, zmq.POLLIN)
705 time.sleep(1)
706 break
707 self.sender_web = self.context.socket(zmq.REQ)
708 self.sender_web.connect(self.web_address)
709 self.poll.register(self.sender_web, zmq.POLLIN)
710 time.sleep(1)
711 else:
712 self.sendData(self.send, self.data, coerce=coerce)
713 coerce = False
714
715 return
716
717
718 158 class SendToFTP(Operation, Process):
719 159
720 160 '''
721 161 Operation to send data over FTP.
722 162 '''
723 163
724 164 __attrs__ = ['server', 'username', 'password', 'patterns', 'timeout']
725 165
726 166 def __init__(self, **kwargs):
727 167 '''
728 168 patterns = [(local1, remote1, ext, delay, exp_code, sub_exp_code), ...]
729 169 '''
730 170 Operation.__init__(self, **kwargs)
731 171 Process.__init__(self)
732 172 self.server = kwargs.get('server')
733 173 self.username = kwargs.get('username')
734 174 self.password = kwargs.get('password')
735 175 self.patterns = kwargs.get('patterns')
736 176 self.timeout = kwargs.get('timeout', 30)
737 177 self.times = [time.time() for p in self.patterns]
738 178 self.latest = ['' for p in self.patterns]
739 179 self.mp = False
740 180 self.ftp = None
741 181
742 182 def setup(self):
743 183
744 184 log.log('Connecting to ftp://{}'.format(self.server), self.name)
745 185 try:
746 186 self.ftp = ftplib.FTP(self.server, timeout=self.timeout)
747 187 except ftplib.all_errors:
748 188 log.error('Server connection fail: {}'.format(self.server), self.name)
749 189 if self.ftp is not None:
750 190 self.ftp.close()
751 191 self.ftp = None
752 192 self.isConfig = False
753 193 return
754 194
755 195 try:
756 196 self.ftp.login(self.username, self.password)
757 197 except ftplib.all_errors:
758 198 log.error('The given username y/o password are incorrect', self.name)
759 199 if self.ftp is not None:
760 200 self.ftp.close()
761 201 self.ftp = None
762 202 self.isConfig = False
763 203 return
764 204
765 205 log.success('Connection success', self.name)
766 206 self.isConfig = True
767 207 return
768 208
769 209 def check(self):
770 210
771 211 try:
772 212 self.ftp.voidcmd("NOOP")
773 213 except:
774 214 log.warning('Connection lost... trying to reconnect', self.name)
775 215 if self.ftp is not None:
776 216 self.ftp.close()
777 217 self.ftp = None
778 218 self.setup()
779 219
780 220 def find_files(self, path, ext):
781 221
782 222 files = glob.glob1(path, '*{}'.format(ext))
783 223 files.sort()
784 224 if files:
785 225 return files[-1]
786 226 return None
787 227
788 228 def getftpname(self, filename, exp_code, sub_exp_code):
789 229
790 230 thisDatetime = datetime.datetime.strptime(filename.split('_')[1], '%Y%m%d')
791 231 YEAR_STR = '%4.4d'%thisDatetime.timetuple().tm_year
792 232 DOY_STR = '%3.3d'%thisDatetime.timetuple().tm_yday
793 233 exp_code = '%3.3d'%exp_code
794 234 sub_exp_code = '%2.2d'%sub_exp_code
795 235 plot_code = '%2.2d'% get_plot_code(filename)
796 236 name = YEAR_STR + DOY_STR + '00' + exp_code + sub_exp_code + plot_code + '00.png'
797 237 return name
798 238
799 239 def upload(self, src, dst):
800 240
801 241 log.log('Uploading {} '.format(src), self.name, nl=False)
802 242
803 243 fp = open(src, 'rb')
804 244 command = 'STOR {}'.format(dst)
805 245
806 246 try:
807 247 self.ftp.storbinary(command, fp, blocksize=1024)
808 248 except Exception as e:
809 249 log.error('{}'.format(e), self.name)
810 250 if self.ftp is not None:
811 251 self.ftp.close()
812 252 self.ftp = None
813 253 return 0
814 254
815 255 try:
816 256 self.ftp.sendcmd('SITE CHMOD 755 {}'.format(dst))
817 257 except Exception as e:
818 258 log.error('{}'.format(e), self.name)
819 259 if self.ftp is not None:
820 260 self.ftp.close()
821 261 self.ftp = None
822 262 return 0
823 263
824 264 fp.close()
825 265 log.success('OK', tag='')
826 266 return 1
827 267
828 268 def send_files(self):
829 269
830 270 for x, pattern in enumerate(self.patterns):
831 271 local, remote, ext, delay, exp_code, sub_exp_code = pattern
832 272 if time.time()-self.times[x] >= delay:
833 273 srcname = self.find_files(local, ext)
834 274 src = os.path.join(local, srcname)
835 275 if os.path.getmtime(src) < time.time() - 30*60:
836 276 continue
837 277
838 278 if srcname is None or srcname == self.latest[x]:
839 279 continue
840 280
841 281 if 'png' in ext:
842 282 dstname = self.getftpname(srcname, exp_code, sub_exp_code)
843 283 else:
844 284 dstname = srcname
845 285
846 286 dst = os.path.join(remote, dstname)
847 287
848 288 if self.upload(src, dst):
849 289 self.times[x] = time.time()
850 290 self.latest[x] = srcname
851 291 else:
852 292 self.isConfig = False
853 293 break
854 294
855 295 def run(self):
856 296
857 297 while True:
858 298 if not self.isConfig:
859 299 self.setup()
860 300 if self.ftp is not None:
861 301 self.check()
862 302 self.send_files()
863 303 time.sleep(10)
864 304
865 305 def close():
866 306
867 307 if self.ftp is not None:
868 308 self.ftp.close()
869 309 self.terminate() No newline at end of file
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now