##// END OF EJS Templates
Merge branch 'isr' into v3.0-devel
jespinoza -
r1380:a03d3bbf5427 merge
parent child
Show More

The requested changes are too big and content was truncated. Show full diff

This diff has been collapsed as it changes many lines, (1156 lines changed) Show them Hide them
@@ -0,0 +1,1156
1
2 import os
3 import datetime
4 import numpy
5 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator #YONG
6
7 from .jroplot_spectra import RTIPlot, NoisePlot
8
9 from schainpy.utils import log
10 from .plotting_codes import *
11
12 from schainpy.model.graphics.jroplot_base import Plot, plt
13
14 import matplotlib.pyplot as plt
15 import matplotlib.colors as colors
16
17 import time
18 import math
19
20
21 from matplotlib.ticker import MultipleLocator
22
23
24
25 class RTIDPPlot(RTIPlot):
26
27 '''
28 Plot for RTI Double Pulse Experiment
29 '''
30
31 CODE = 'RTIDP'
32 colormap = 'jro'
33 plot_name = 'RTI'
34
35 #cb_label = 'Ne Electron Density (1/cm3)'
36
37 def setup(self):
38 self.xaxis = 'time'
39 self.ncols = 1
40 self.nrows = 3
41 self.nplots = self.nrows
42 #self.height=10
43 if self.showSNR:
44 self.nrows += 1
45 self.nplots += 1
46
47 self.ylabel = 'Height [km]'
48 self.xlabel = 'Time (LT)'
49
50 self.cb_label = 'Intensity (dB)'
51
52
53 #self.cb_label = cb_label
54
55 self.titles = ['{} Channel {}'.format(
56 self.plot_name.upper(), '0x1'),'{} Channel {}'.format(
57 self.plot_name.upper(), '0'),'{} Channel {}'.format(
58 self.plot_name.upper(), '1')]
59
60
61 def plot(self):
62
63 self.data.normalize_heights()
64 self.x = self.data.times
65 self.y = self.data.heights[0:self.data.NDP]
66
67 if self.showSNR:
68 self.z = numpy.concatenate(
69 (self.data[self.CODE], self.data['snr'])
70 )
71 else:
72
73 self.z = self.data[self.CODE]
74 #print(numpy.max(self.z[0,0:]))
75
76 self.z = numpy.ma.masked_invalid(self.z)
77
78 if self.decimation is None:
79 x, y, z = self.fill_gaps(self.x, self.y, self.z)
80 else:
81 x, y, z = self.fill_gaps(*self.decimate())
82
83 for n, ax in enumerate(self.axes):
84
85
86 self.zmax = self.zmax if self.zmax is not None else numpy.max(
87 self.z[1][0,12:40])
88 self.zmin = self.zmin if self.zmin is not None else numpy.min(
89 self.z[1][0,12:40])
90
91
92
93 if ax.firsttime:
94
95 if self.zlimits is not None:
96 self.zmin, self.zmax = self.zlimits[n]
97
98
99 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
100 vmin=self.zmin,
101 vmax=self.zmax,
102 cmap=self.cmaps[n]
103 )
104 #plt.tight_layout()
105 else:
106 if self.zlimits is not None:
107 self.zmin, self.zmax = self.zlimits[n]
108 ax.collections.remove(ax.collections[0])
109 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
110 vmin=self.zmin,
111 vmax=self.zmax,
112 cmap=self.cmaps[n]
113 )
114 #plt.tight_layout()
115
116
117 class RTILPPlot(RTIPlot):
118
119 '''
120 Plot for RTI Long Pulse
121 '''
122
123 CODE = 'RTILP'
124 colormap = 'jro'
125 plot_name = 'RTI LP'
126
127 #cb_label = 'Ne Electron Density (1/cm3)'
128
129 def setup(self):
130 self.xaxis = 'time'
131 self.ncols = 1
132 self.nrows = 4
133 self.nplots = self.nrows
134 if self.showSNR:
135 self.nrows += 1
136 self.nplots += 1
137
138 self.ylabel = 'Height [km]'
139 self.xlabel = 'Time (LT)'
140
141 self.cb_label = 'Intensity (dB)'
142
143
144
145 #self.cb_label = cb_label
146
147 self.titles = ['{} Channel {}'.format(
148 self.plot_name.upper(), '0'),'{} Channel {}'.format(
149 self.plot_name.upper(), '1'),'{} Channel {}'.format(
150 self.plot_name.upper(), '2'),'{} Channel {}'.format(
151 self.plot_name.upper(), '3')]
152
153
154 def plot(self):
155
156 self.data.normalize_heights()
157 self.x = self.data.times
158 self.y = self.data.heights[0:self.data.NRANGE]
159
160 if self.showSNR:
161 self.z = numpy.concatenate(
162 (self.data[self.CODE], self.data['snr'])
163 )
164 else:
165
166 self.z = self.data[self.CODE]
167 #print(numpy.max(self.z[0,0:]))
168
169 self.z = numpy.ma.masked_invalid(self.z)
170
171 if self.decimation is None:
172 x, y, z = self.fill_gaps(self.x, self.y, self.z)
173 else:
174 x, y, z = self.fill_gaps(*self.decimate())
175
176 for n, ax in enumerate(self.axes):
177
178
179 self.zmax = self.zmax if self.zmax is not None else numpy.max(
180 self.z[1][0,12:40])
181 self.zmin = self.zmin if self.zmin is not None else numpy.min(
182 self.z[1][0,12:40])
183
184 if ax.firsttime:
185
186 if self.zlimits is not None:
187 self.zmin, self.zmax = self.zlimits[n]
188
189
190 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
191 vmin=self.zmin,
192 vmax=self.zmax,
193 cmap=self.cmaps[n]
194 )
195 #plt.tight_layout()
196 else:
197 if self.zlimits is not None:
198 self.zmin, self.zmax = self.zlimits[n]
199 ax.collections.remove(ax.collections[0])
200 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
201 vmin=self.zmin,
202 vmax=self.zmax,
203 cmap=self.cmaps[n]
204 )
205 #plt.tight_layout()
206
207
208 class DenRTIPlot(RTIPlot):
209
210 '''
211 Plot for Den
212 '''
213
214 CODE = 'denrti'
215 colormap = 'jro'
216 plot_name = 'Electron Density'
217
218 #cb_label = 'Ne Electron Density (1/cm3)'
219
220 def setup(self):
221 self.xaxis = 'time'
222 self.ncols = 1
223 self.nrows = self.data.shape(self.CODE)[0]
224 self.nplots = self.nrows
225 if self.showSNR:
226 self.nrows += 1
227 self.nplots += 1
228
229 self.ylabel = 'Height [km]'
230 self.xlabel = 'Time (LT)'
231
232 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
233
234 if self.CODE == 'denrti' or self.CODE=='denrtiLP':
235 self.cb_label = r'$\mathrm{N_e}$ Electron Density ($\mathrm{1/cm^3}$)'
236
237 #self.cb_label = cb_label
238 if not self.titles:
239 self.titles = self.data.parameters \
240 if self.data.parameters else ['{}'.format(self.plot_name)]
241 if self.showSNR:
242 self.titles.append('SNR')
243
244 def plot(self):
245
246 self.data.normalize_heights()
247 self.x = self.data.times
248 self.y = self.data.heights
249
250
251
252 if self.showSNR:
253 self.z = numpy.concatenate(
254 (self.data[self.CODE], self.data['snr'])
255 )
256 else:
257 self.z = self.data[self.CODE]
258
259 self.z = numpy.ma.masked_invalid(self.z)
260
261 if self.decimation is None:
262 x, y, z = self.fill_gaps(self.x, self.y, self.z)
263 else:
264 x, y, z = self.fill_gaps(*self.decimate())
265
266 for n, ax in enumerate(self.axes):
267
268 self.zmax = self.zmax if self.zmax is not None else numpy.max(
269 self.z[n])
270 self.zmin = self.zmin if self.zmin is not None else numpy.min(
271 self.z[n])
272
273 if ax.firsttime:
274
275 if self.zlimits is not None:
276 self.zmin, self.zmax = self.zlimits[n]
277 if numpy.log10(self.zmin)<0:
278 self.zmin=1
279 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
280 vmin=self.zmin,
281 vmax=self.zmax,
282 cmap=self.cmaps[n],
283 norm=colors.LogNorm()
284 )
285 #plt.tight_layout()
286
287 else:
288 if self.zlimits is not None:
289 self.zmin, self.zmax = self.zlimits[n]
290 ax.collections.remove(ax.collections[0])
291 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
292 vmin=self.zmin,
293 vmax=self.zmax,
294 cmap=self.cmaps[n],
295 norm=colors.LogNorm()
296 )
297 #plt.tight_layout()
298
299
300
301 class DenRTILPPlot(DenRTIPlot):
302
303 '''
304 Plot for Electron Temperature
305 '''
306
307 CODE = 'denrtiLP'
308 colormap = 'jro'
309 plot_name = 'Electron Density'
310
311
312 class ETempRTIPlot(RTIPlot):
313
314 '''
315 Plot for Electron Temperature
316 '''
317
318 CODE = 'ETemp'
319 colormap = 'jet'
320 plot_name = 'Electron Temperature'
321
322 #cb_label = 'Ne Electron Density (1/cm3)'
323
324 def setup(self):
325 self.xaxis = 'time'
326 self.ncols = 1
327 self.nrows = self.data.shape(self.CODE)[0]
328 self.nplots = self.nrows
329 if self.showSNR:
330 self.nrows += 1
331 self.nplots += 1
332
333 self.ylabel = 'Height [km]'
334 self.xlabel = 'Time (LT)'
335 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
336 if self.CODE == 'ETemp' or self.CODE == 'ETempLP':
337 self.cb_label = 'Electron Temperature (K)'
338 if self.CODE == 'ITemp' or self.CODE == 'ITempLP':
339 self.cb_label = 'Ion Temperature (K)'
340
341
342 if not self.titles:
343 self.titles = self.data.parameters \
344 if self.data.parameters else ['{}'.format(self.plot_name)]
345 if self.showSNR:
346 self.titles.append('SNR')
347
348 def plot(self):
349
350 self.data.normalize_heights()
351 self.x = self.data.times
352 self.y = self.data.heights
353
354 if self.showSNR:
355 self.z = numpy.concatenate(
356 (self.data[self.CODE], self.data['snr'])
357 )
358 else:
359 self.z = self.data[self.CODE]
360
361 self.z = numpy.ma.masked_invalid(self.z)
362
363 if self.decimation is None:
364 x, y, z = self.fill_gaps(self.x, self.y, self.z)
365 else:
366 x, y, z = self.fill_gaps(*self.decimate())
367
368 for n, ax in enumerate(self.axes):
369
370 self.zmax = self.zmax if self.zmax is not None else numpy.max(
371 self.z[n])
372 self.zmin = self.zmin if self.zmin is not None else numpy.min(
373 self.z[n])
374
375 if ax.firsttime:
376
377 if self.zlimits is not None:
378 self.zmin, self.zmax = self.zlimits[n]
379
380 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
381 vmin=self.zmin,
382 vmax=self.zmax,
383 cmap=self.cmaps[n]
384 )
385 #plt.tight_layout()
386
387 else:
388 if self.zlimits is not None:
389 self.zmin, self.zmax = self.zlimits[n]
390 ax.collections.remove(ax.collections[0])
391 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
392 vmin=self.zmin,
393 vmax=self.zmax,
394 cmap=self.cmaps[n]
395 )
396 #plt.tight_layout()
397
398
399
400 class ITempRTIPlot(ETempRTIPlot):
401
402 '''
403 Plot for Ion Temperature
404 '''
405
406 CODE = 'ITemp'
407 colormap = 'jet'
408 plot_name = 'Ion Temperature'
409
410
411 class ElectronTempLPPlot(ETempRTIPlot):
412
413 '''
414 Plot for Electron Temperature LP
415 '''
416
417 CODE = 'ETempLP'
418 colormap = 'jet'
419 plot_name = 'Electron Temperature'
420
421
422 class IonTempLPPlot(ETempRTIPlot):
423
424 '''
425 Plot for Ion Temperature LP
426 '''
427
428 CODE = 'ITempLP'
429 colormap = 'jet'
430 plot_name = 'Ion Temperature'
431
432
433 class HFracRTIPlot(ETempRTIPlot):
434
435 '''
436 Plot for H+ LP
437 '''
438
439 CODE = 'HFracLP'
440 colormap = 'jet'
441 plot_name = 'H+ Frac'
442
443
444 class HeFracRTIPlot(ETempRTIPlot):
445
446 '''
447 Plot for He+ LP
448 '''
449
450 CODE = 'HeFracLP'
451 colormap = 'jet'
452 plot_name = 'He+ Frac'
453
454
455 class TempsDPPlot(Plot):
456 '''
457 Plot for Electron - Ion Temperatures
458 '''
459
460 CODE = 'tempsDP'
461 plot_name = 'Temperatures'
462 plot_type = 'scatterbuffer'
463
464
465 def setup(self):
466
467 self.ncols = 1
468 self.nrows = 1
469 self.nplots = 1
470 self.ylabel = 'Range [km]'
471 self.xlabel = 'Temperature (K)'
472 self.width = 3.5
473 self.height = 5.5
474 self.colorbar = False
475 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
476 if not self.titles:
477 self.titles = self.data.parameters \
478 if self.data.parameters else ['{}'.format(self.CODE.upper())]
479
480 def plot(self):
481
482 self.x = self.data['tempsDP'][:,-1]
483 self.y = self.data.heights[0:self.data.NSHTS]
484
485 self.xmin = -100
486 self.xmax = 5000
487 ax = self.axes[0]
488
489 if ax.firsttime:
490
491 ax.errorbar(self.x, self.y, xerr=self.data.ete2, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='Te')
492 ax.errorbar(self.data.ti2, self.y, fmt='k^', xerr=self.data.eti2,elinewidth=1.0,color='b',linewidth=2.0, label='Ti')
493 plt.legend(loc='lower right')
494 self.ystep_given = 50
495 ax.yaxis.set_minor_locator(MultipleLocator(15))
496 ax.grid(which='minor')
497 #plt.tight_layout()
498
499
500 else:
501 self.clear_figures()
502 ax.errorbar(self.x, self.y, xerr=self.data.ete2, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='Te')
503 ax.errorbar(self.data.ti2, self.y, fmt='k^', xerr=self.data.eti2,elinewidth=1.0,color='b',linewidth=2.0, label='Ti')
504 plt.legend(loc='lower right')
505 ax.yaxis.set_minor_locator(MultipleLocator(15))
506 #plt.tight_layout()
507
508
509 class TempsHPPlot(Plot):
510 '''
511 Plot for Temperatures Hybrid Experiment
512 '''
513
514 CODE = 'temps_LP'
515 plot_name = 'Temperatures'
516 plot_type = 'scatterbuffer'
517
518
519 def setup(self):
520
521 self.ncols = 1
522 self.nrows = 1
523 self.nplots = 1
524 self.ylabel = 'Range [km]'
525 self.xlabel = 'Temperature (K)'
526 self.width = 3.5
527 self.height = 6.5
528 self.colorbar = False
529 if not self.titles:
530 self.titles = self.data.parameters \
531 if self.data.parameters else ['{}'.format(self.CODE.upper())]
532
533 def plot(self):
534
535 self.x = self.data['temps_LP'][:,-1]
536 self.y = self.data.heights[0:self.data.NACF]
537 self.xmin = -100
538 self.xmax = 4500
539 ax = self.axes[0]
540
541 if ax.firsttime:
542
543 ax.errorbar(self.x, self.y, xerr=self.data.ete, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='Te')
544 ax.errorbar(self.data.ti, self.y, fmt='k^', xerr=self.data.eti,elinewidth=1.0,color='b',linewidth=2.0, label='Ti')
545 plt.legend(loc='lower right')
546 self.ystep_given = 200
547 ax.yaxis.set_minor_locator(MultipleLocator(15))
548 ax.grid(which='minor')
549 #plt.tight_layout()
550
551
552 else:
553 self.clear_figures()
554 ax.errorbar(self.x, self.y, xerr=self.data.ete, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='Te')
555 ax.errorbar(self.data.ti, self.y, fmt='k^', xerr=self.data.eti,elinewidth=1.0,color='b',linewidth=2.0, label='Ti')
556 plt.legend(loc='lower right')
557 ax.yaxis.set_minor_locator(MultipleLocator(15))
558 #plt.tight_layout()
559
560
561 class FracsHPPlot(Plot):
562 '''
563 Plot for Composition LP
564 '''
565
566 CODE = 'fracs_LP'
567 plot_name = 'Composition'
568 plot_type = 'scatterbuffer'
569
570
571 def setup(self):
572
573 self.ncols = 1
574 self.nrows = 1
575 self.nplots = 1
576 self.ylabel = 'Range [km]'
577 self.xlabel = 'Frac'
578 self.width = 3.5
579 self.height = 6.5
580 self.colorbar = False
581 if not self.titles:
582 self.titles = self.data.parameters \
583 if self.data.parameters else ['{}'.format(self.CODE.upper())]
584
585 def plot(self):
586
587 self.x = self.data['fracs_LP'][:,-1]
588 self.y = self.data.heights[0:self.data.NACF]
589
590 self.xmin = 0
591 self.xmax = 1
592 ax = self.axes[0]
593
594 if ax.firsttime:
595
596 ax.errorbar(self.x, self.y[self.data.cut:], xerr=self.data.eph, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='H+')
597 ax.errorbar(self.data.phe, self.y[self.data.cut:], fmt='k^', xerr=self.data.ephe,elinewidth=1.0,color='b',linewidth=2.0, label='He+')
598 plt.legend(loc='lower right')
599 self.xstep_given = 0.2
600 self.ystep_given = 200
601 ax.yaxis.set_minor_locator(MultipleLocator(15))
602 ax.grid(which='minor')
603 #plt.tight_layout()
604
605
606 else:
607 self.clear_figures()
608 ax.errorbar(self.x, self.y[self.data.cut:], xerr=self.data.eph, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='H+')
609 ax.errorbar(self.data.phe, self.y[self.data.cut:], fmt='k^', xerr=self.data.ephe,elinewidth=1.0,color='b',linewidth=2.0, label='He+')
610 plt.legend(loc='lower right')
611 ax.yaxis.set_minor_locator(MultipleLocator(15))
612 #plt.tight_layout()
613
614
615
616 class EDensityPlot(Plot):
617 '''
618 Plot for electron density
619 '''
620
621 CODE = 'den'
622 plot_name = 'Electron Density'
623 plot_type = 'scatterbuffer'
624
625
626 def setup(self):
627
628 self.ncols = 1
629 self.nrows = 1
630 self.nplots = 1
631 self.ylabel = 'Range [km]'
632 self.xlabel = r'$\mathrm{N_e}$ Electron Density ($\mathrm{1/cm^3}$)'
633 self.width = 4
634 self.height = 6.5
635 self.colorbar = False
636 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
637 if not self.titles:
638 self.titles = self.data.parameters \
639 if self.data.parameters else ['{}'.format(self.CODE.upper())]
640
641 def plot(self):
642
643
644 self.x = self.data[self.CODE]
645 self.y = self.data.heights
646 self.xmin = 1000
647 self.xmax = 10000000
648 ax = self.axes[0]
649
650 if ax.firsttime:
651 self.autoxticks=False
652 #if self.CODE=='den':
653 ax.errorbar(self.data.dphi, self.y[:self.data.NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
654 #ax.errorbar(self.data.dphi, self.y[:self.data.NSHTS], xerr=self.data.sdn1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
655
656 ax.errorbar(self.x[:,-1], self.y[:self.data.NSHTS], fmt='k^-', xerr=self.data.sdp2,elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
657 #else:
658 #ax.errorbar(self.data.dphi[:self.data.cut], self.y[:self.data.cut], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
659 #ax.errorbar(self.x[:self.data.cut,-1], self.y[:self.data.cut], fmt='k^-', xerr=self.data.sdp2[:self.data.cut],elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
660
661 if self.CODE=='denLP':
662 ax.errorbar(self.data.ne[self.data.cut:], self.y[self.data.cut:], xerr=self.data.ene[self.data.cut:], fmt='r^-',elinewidth=1.0,color='r',linewidth=1.0, label='LP Profile',markersize=2)
663
664 plt.legend(loc='upper right')
665 ax.set_xscale("log", nonposx='clip')
666 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
667 self.ystep_given=100
668 if self.CODE=='denLP':
669 self.ystep_given=200
670 ax.set_yticks(grid_y_ticks,minor=True)
671 ax.grid(which='minor')
672 #plt.tight_layout()
673
674
675
676 else:
677
678 self.clear_figures()
679 #if self.CODE=='den':
680 ax.errorbar(self.data.dphi, self.y[:self.data.NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
681 #ax.errorbar(self.data.dphi, self.y[:self.data.NSHTS], xerr=self.data.sdn1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
682
683 ax.errorbar(self.x[:,-1], self.y[:self.data.NSHTS], fmt='k^-', xerr=self.data.sdp2,elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
684 ax.errorbar(self.x[:,-2], self.y[:self.data.NSHTS], elinewidth=1.0,color='r',linewidth=0.5,linestyle="dashed")
685 #else:
686 #ax.errorbar(self.data.dphi[:self.data.cut], self.y[:self.data.cut], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
687 #ax.errorbar(self.x[:self.data.cut,-1], self.y[:self.data.cut], fmt='k^-', xerr=self.data.sdp2[:self.data.cut],elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
688 #ax.errorbar(self.x[:self.data.cut,-2], self.y[:self.data.cut], elinewidth=1.0,color='r',linewidth=0.5,linestyle="dashed")
689
690 if self.CODE=='denLP':
691 ax.errorbar(self.data.ne[self.data.cut:], self.y[self.data.cut:], fmt='r^-', xerr=self.data.ene[self.data.cut:],elinewidth=1.0,color='r',linewidth=1.0, label='LP Profile',markersize=2)
692
693 ax.set_xscale("log", nonposx='clip')
694 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
695 ax.set_yticks(grid_y_ticks,minor=True)
696 ax.grid(which='minor')
697 plt.legend(loc='upper right')
698 #plt.tight_layout()
699
700 class FaradayAnglePlot(Plot):
701 '''
702 Plot for electron density
703 '''
704
705 CODE = 'FaradayAngle'
706 plot_name = 'Faraday Angle'
707 plot_type = 'scatterbuffer'
708
709
710 def setup(self):
711
712 self.ncols = 1
713 self.nrows = 1
714 self.nplots = 1
715 self.ylabel = 'Range [km]'
716 self.xlabel = 'Faraday Angle (º)'
717 self.width = 4
718 self.height = 6.5
719 self.colorbar = False
720 if not self.titles:
721 self.titles = self.data.parameters \
722 if self.data.parameters else ['{}'.format(self.CODE.upper())]
723
724 def plot(self):
725
726
727 self.x = self.data[self.CODE]
728 self.y = self.data.heights
729 self.xmin = -180
730 self.xmax = 180
731 ax = self.axes[0]
732
733 if ax.firsttime:
734 self.autoxticks=False
735 #if self.CODE=='den':
736 ax.plot(self.x, self.y,marker='o',color='g',linewidth=1.0,markersize=2)
737
738 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
739 self.ystep_given=100
740 if self.CODE=='denLP':
741 self.ystep_given=200
742 ax.set_yticks(grid_y_ticks,minor=True)
743 ax.grid(which='minor')
744 #plt.tight_layout()
745 else:
746
747 self.clear_figures()
748 #if self.CODE=='den':
749 #print(numpy.shape(self.x))
750 ax.plot(self.x[:,-1], self.y, marker='o',color='g',linewidth=1.0, markersize=2)
751
752 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
753 ax.set_yticks(grid_y_ticks,minor=True)
754 ax.grid(which='minor')
755
756 class EDensityHPPlot(EDensityPlot):
757
758 '''
759 Plot for Electron Density Hybrid Experiment
760 '''
761
762 CODE = 'denLP'
763 plot_name = 'Electron Density'
764 plot_type = 'scatterbuffer'
765
766
767 class ACFsPlot(Plot):
768 '''
769 Plot for ACFs Double Pulse Experiment
770 '''
771
772 CODE = 'acfs'
773 plot_name = 'ACF'
774 plot_type = 'scatterbuffer'
775
776
777 def setup(self):
778 #self.xaxis = 'time'
779 self.ncols = 1
780 self.nrows = 1
781 self.nplots = 1
782 self.ylabel = 'Range [km]'
783 self.xlabel = 'lags (ms)'
784 self.width = 3.5
785 self.height = 6
786 self.colorbar = False
787 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
788 if not self.titles:
789 self.titles = self.data.parameters \
790 if self.data.parameters else ['{}'.format(self.CODE.upper())]
791
792 def plot(self):
793
794 self.x = self.data.lags_to_plot
795 self.y = self.data['acfs'][:,-1]
796
797
798 self.xmin = 0.0
799 self.xmax = 2.0
800
801 ax = self.axes[0]
802
803 if ax.firsttime:
804
805 for i in range(self.data.NSHTS):
806 x_aux = numpy.isfinite(self.x[i,:])
807 y_aux = numpy.isfinite(self.y[i,:])
808 yerr_aux = numpy.isfinite(self.data.acfs_error_to_plot[i,:])
809 x_igcej_aux = numpy.isfinite(self.data.x_igcej_to_plot[i,:])
810 y_igcej_aux = numpy.isfinite(self.data.y_igcej_to_plot[i,:])
811 x_ibad_aux = numpy.isfinite(self.data.x_ibad_to_plot[i,:])
812 y_ibad_aux = numpy.isfinite(self.data.y_ibad_to_plot[i,:])
813 if self.x[i,:][~numpy.isnan(self.x[i,:])].shape[0]>2:
814 ax.errorbar(self.x[i,x_aux], self.y[i,y_aux], yerr=self.data.acfs_error_to_plot[i,x_aux],color='b',marker='o',linewidth=1.0,markersize=2)
815 ax.plot(self.data.x_igcej_to_plot[i,x_igcej_aux],self.data.y_igcej_to_plot[i,y_igcej_aux],'x',color='red',markersize=2)
816 ax.plot(self.data.x_ibad_to_plot[i,x_ibad_aux],self.data.y_ibad_to_plot[i,y_ibad_aux],'X',color='red',markersize=2)
817
818 self.xstep_given = (self.xmax-self.xmin)/(self.data.DPL-1)
819 self.ystep_given = 50
820 ax.yaxis.set_minor_locator(MultipleLocator(15))
821 ax.grid(which='minor')
822
823
824
825 else:
826 self.clear_figures()
827
828 for i in range(self.data.NSHTS):
829 x_aux = numpy.isfinite(self.x[i,:])
830 y_aux = numpy.isfinite(self.y[i,:])
831 yerr_aux = numpy.isfinite(self.data.acfs_error_to_plot[i,:])
832 x_igcej_aux = numpy.isfinite(self.data.x_igcej_to_plot[i,:])
833 y_igcej_aux = numpy.isfinite(self.data.y_igcej_to_plot[i,:])
834 x_ibad_aux = numpy.isfinite(self.data.x_ibad_to_plot[i,:])
835 y_ibad_aux = numpy.isfinite(self.data.y_ibad_to_plot[i,:])
836 if self.x[i,:][~numpy.isnan(self.x[i,:])].shape[0]>2:
837 ax.errorbar(self.x[i,x_aux], self.y[i,y_aux], yerr=self.data.acfs_error_to_plot[i,x_aux],linewidth=1.0,markersize=2,color='b',marker='o')
838 ax.plot(self.data.x_igcej_to_plot[i,x_igcej_aux],self.data.y_igcej_to_plot[i,y_igcej_aux],'x',color='red',markersize=2)
839 ax.plot(self.data.x_ibad_to_plot[i,x_ibad_aux],self.data.y_ibad_to_plot[i,y_ibad_aux],'X',color='red',markersize=2)
840 ax.yaxis.set_minor_locator(MultipleLocator(15))
841
842
843
844
845 class ACFsLPPlot(Plot):
846 '''
847 Plot for ACFs Double Pulse Experiment
848 '''
849
850 CODE = 'acfs_LP'
851 plot_name = 'ACF'
852 plot_type = 'scatterbuffer'
853
854
855 def setup(self):
856 #self.xaxis = 'time'
857 self.ncols = 1
858 self.nrows = 1
859 self.nplots = 1
860 self.ylabel = 'Range [km]'
861 self.xlabel = 'lags (ms)'
862 self.width = 3.5
863 self.height = 7
864 self.colorbar = False
865 if not self.titles:
866 self.titles = self.data.parameters \
867 if self.data.parameters else ['{}'.format(self.CODE.upper())]
868
869
870
871 def plot(self):
872
873 self.x = self.data.lags_LP_to_plot
874 self.y = self.data['acfs_LP'][:,-1]
875
876 self.xmin = 0.0
877 self.xmax = 1.5
878
879 ax = self.axes[0]
880
881 if ax.firsttime:
882
883 for i in range(self.data.NACF):
884 x_aux = numpy.isfinite(self.x[i,:])
885 y_aux = numpy.isfinite(self.y[i,:])
886 yerr_aux = numpy.isfinite(self.data.errors[i,:])
887
888 if self.x[i,:][~numpy.isnan(self.x[i,:])].shape[0]>2:
889 ax.errorbar(self.x[i,x_aux], self.y[i,y_aux], yerr=self.data.errors[i,x_aux],color='b',linewidth=1.0,markersize=2,ecolor='r')
890
891 #self.xstep_given = (self.xmax-self.xmin)/(self.data.NLAG-1)
892 self.xstep_given=0.3
893 self.ystep_given = 200
894 ax.yaxis.set_minor_locator(MultipleLocator(15))
895 ax.grid(which='minor')
896
897 else:
898 self.clear_figures()
899
900 for i in range(self.data.NACF):
901 x_aux = numpy.isfinite(self.x[i,:])
902 y_aux = numpy.isfinite(self.y[i,:])
903 yerr_aux = numpy.isfinite(self.data.errors[i,:])
904
905 if self.x[i,:][~numpy.isnan(self.x[i,:])].shape[0]>2:
906 ax.errorbar(self.x[i,x_aux], self.y[i,y_aux], yerr=self.data.errors[i,x_aux],color='b',linewidth=1.0,markersize=2,ecolor='r')
907
908 ax.yaxis.set_minor_locator(MultipleLocator(15))
909
910
911 class CrossProductsPlot(Plot):
912 '''
913 Plot for cross products
914 '''
915
916 CODE = 'crossprod'
917 plot_name = 'Cross Products'
918 plot_type = 'scatterbuffer'
919
920
921 def setup(self):
922
923 self.ncols = 3
924 self.nrows = 1
925 self.nplots = 3
926 self.ylabel = 'Range [km]'
927
928 self.width = 3.5*self.nplots
929 self.height = 5.5
930 self.colorbar = False
931 self.titles = []
932
933 def plot(self):
934
935 self.x = self.data['crossprod'][:,-1,:,:,:,:]
936
937
938
939
940 self.y = self.data.heights[0:self.data.NDP]
941
942
943
944 for n, ax in enumerate(self.axes):
945
946 self.xmin=numpy.min(numpy.concatenate((self.x[n][0,20:30,0,0],self.x[n][1,20:30,0,0],self.x[n][2,20:30,0,0],self.x[n][3,20:30,0,0])))
947 self.xmax=numpy.max(numpy.concatenate((self.x[n][0,20:30,0,0],self.x[n][1,20:30,0,0],self.x[n][2,20:30,0,0],self.x[n][3,20:30,0,0])))
948
949
950 if ax.firsttime:
951
952 self.autoxticks=False
953 if n==0:
954 label1='kax'
955 label2='kay'
956 label3='kbx'
957 label4='kby'
958 self.xlimits=[(self.xmin,self.xmax)]
959 elif n==1:
960 label1='kax2'
961 label2='kay2'
962 label3='kbx2'
963 label4='kby2'
964 self.xlimits.append((self.xmin,self.xmax))
965 elif n==2:
966 label1='kaxay'
967 label2='kbxby'
968 label3='kaxbx'
969 label4='kaxby'
970 self.xlimits.append((self.xmin,self.xmax))
971
972
973 ax.plotline1 = ax.plot(self.x[n][0,:,0,0], self.y, color='r',linewidth=2.0, label=label1)
974 ax.plotline2 = ax.plot(self.x[n][1,:,0,0], self.y, color='k',linewidth=2.0, label=label2)
975 ax.plotline3 = ax.plot(self.x[n][2,:,0,0], self.y, color='b',linewidth=2.0, label=label3)
976 ax.plotline4 = ax.plot(self.x[n][3,:,0,0], self.y, color='m',linewidth=2.0, label=label4)
977 ax.legend(loc='upper right')
978 ax.set_xlim(self.xmin, self.xmax)
979 self.titles.append('{}'.format(self.plot_name.upper()))
980 #plt.tight_layout()
981
982
983 else:
984
985 if n==0:
986 self.xlimits=[(self.xmin,self.xmax)]
987 else:
988 self.xlimits.append((self.xmin,self.xmax))
989
990 ax.set_xlim(self.xmin, self.xmax)
991
992
993 ax.plotline1[0].set_data(self.x[n][0,:,0,0],self.y)
994 ax.plotline2[0].set_data(self.x[n][1,:,0,0],self.y)
995 ax.plotline3[0].set_data(self.x[n][2,:,0,0],self.y)
996 ax.plotline4[0].set_data(self.x[n][3,:,0,0],self.y)
997 self.titles.append('{}'.format(self.plot_name.upper()))
998 #plt.tight_layout()
999
1000
1001
1002 class CrossProductsLPPlot(Plot):
1003 '''
1004 Plot for cross products LP
1005 '''
1006
1007 CODE = 'crossprodlp'
1008 plot_name = 'Cross Products LP'
1009 plot_type = 'scatterbuffer'
1010
1011
1012 def setup(self):
1013
1014 self.ncols = 2
1015 self.nrows = 1
1016 self.nplots = 2
1017 self.ylabel = 'Range [km]'
1018 self.xlabel = 'dB'
1019 self.width = 3.5*self.nplots
1020 self.height = 5.5
1021 self.colorbar = False
1022 self.titles = []
1023 self.plotline_array=numpy.zeros((2,self.data.NLAG),dtype=object)
1024 def plot(self):
1025
1026
1027 self.x = self.data[self.CODE][:,-1,:,:]
1028
1029
1030 self.y = self.data.heights[0:self.data.NRANGE]
1031
1032
1033 label_array=numpy.array(['lag '+ str(x) for x in range(self.data.NLAG)])
1034 color_array=['r','k','g','b','c','m','y','orange','steelblue','purple','peru','darksalmon','grey','limegreen','olive','midnightblue']
1035
1036
1037 for n, ax in enumerate(self.axes):
1038
1039 self.xmin=30
1040 self.xmax=70
1041 #print(self.x[0,12:15,n])
1042 #input()
1043 #self.xmin=numpy.min(numpy.concatenate((self.x[0,:,n],self.x[1,:,n])))
1044 #self.xmax=numpy.max(numpy.concatenate((self.x[0,:,n],self.x[1,:,n])))
1045
1046 #print("before",self.plotline_array)
1047
1048 if ax.firsttime:
1049
1050 self.autoxticks=False
1051
1052
1053 for i in range(self.data.NLAG):
1054 #print(i)
1055 #print(numpy.shape(self.x))
1056 self.plotline_array[n,i], = ax.plot(self.x[i,:,n], self.y, color=color_array[i],linewidth=1.0, label=label_array[i])
1057 #ax.plotline1 = ax.plot(self.x[0,:,n], self.y, color='r',linewidth=2.0, label=label_array[0])
1058 #ax.plotline2 = ax.plot(self.x[n][1,:,0,0], self.y, color='k',linewidth=2.0, label=label2)
1059 #ax.plotline3 = ax.plot(self.x[n][2,:,0,0], self.y, color='b',linewidth=2.0, label=label3)
1060 #ax.plotline4 = ax.plot(self.x[n][3,:,0,0], self.y, color='m',linewidth=2.0, label=label4)
1061
1062
1063 #print(self.plotline_array)
1064
1065
1066
1067 ax.legend(loc='upper right')
1068 ax.set_xlim(self.xmin, self.xmax)
1069 if n==0:
1070 self.titles.append('{} CH0'.format(self.plot_name.upper()))
1071 if n==1:
1072 self.titles.append('{} CH1'.format(self.plot_name.upper()))
1073
1074 #plt.tight_layout()
1075
1076 else:
1077 #print(self.plotline_array)
1078 for i in range(self.data.NLAG):
1079
1080 self.plotline_array[n,i].set_data(self.x[i,:,n],self.y)
1081
1082
1083
1084 #ax.plotline1[0].set_data(self.x[n][0,:,0,0],self.y)
1085 #ax.plotline2[0].set_data(self.x[n][1,:,0,0],self.y)
1086 #ax.plotline3[0].set_data(self.x[n][2,:,0,0],self.y)
1087 #ax.plotline4[0].set_data(self.x[n][3,:,0,0],self.y)
1088
1089 if n==0:
1090 self.titles.append('{} CH0'.format(self.plot_name.upper()))
1091 if n==1:
1092 self.titles.append('{} CH1'.format(self.plot_name.upper()))
1093
1094 #plt.tight_layout()
1095
1096
1097 class NoiseDPPlot(NoisePlot):
1098 '''
1099 Plot for noise Double Pulse
1100 '''
1101
1102 CODE = 'noisedp'
1103 plot_name = 'Noise'
1104 plot_type = 'scatterbuffer'
1105
1106
1107 class XmitWaveformPlot(Plot):
1108 '''
1109 Plot for xmit waveform
1110 '''
1111
1112 CODE = 'xmit'
1113 plot_name = 'Xmit Waveform'
1114 plot_type = 'scatterbuffer'
1115
1116
1117 def setup(self):
1118
1119 self.ncols = 1
1120 self.nrows = 1
1121 self.nplots = 1
1122 self.ylabel = ''
1123 self.xlabel = 'Number of Lag'
1124 self.width = 5.5
1125 self.height = 3.5
1126 self.colorbar = False
1127 if not self.titles:
1128 self.titles = self.data.parameters \
1129 if self.data.parameters else ['{}'.format(self.plot_name.upper())]
1130
1131 def plot(self):
1132
1133 self.x = numpy.arange(0,self.data.NLAG,1,'float32')
1134 self.y = self.data['xmit'][:,-1,:]
1135
1136 self.xmin = 0
1137 self.xmax = self.data.NLAG-1
1138 self.ymin = -1.0
1139 self.ymax = 1.0
1140 ax = self.axes[0]
1141
1142 if ax.firsttime:
1143 ax.plotline0=ax.plot(self.x,self.y[0,:],color='blue')
1144 ax.plotline1=ax.plot(self.x,self.y[1,:],color='red')
1145 secax=ax.secondary_xaxis(location=0.5)
1146 secax.xaxis.tick_bottom()
1147 secax.tick_params( labelleft=False, labeltop=False,
1148 labelright=False, labelbottom=False)
1149
1150 self.xstep_given = 3
1151 self.ystep_given = .25
1152 secax.set_xticks(numpy.linspace(self.xmin, self.xmax, 6)) #only works on matplotlib.version>3.2
1153
1154 else:
1155 ax.plotline0[0].set_data(self.x,self.y[0,:])
1156 ax.plotline1[0].set_data(self.x,self.y[1,:])
This diff has been collapsed as it changes many lines, (683 lines changed) Show them Hide them
@@ -0,0 +1,683
1 '''
2 Created on Jun 9, 2020
3
4 @author: Roberto Flores
5 '''
6
7 import os
8 import sys
9 import time
10
11 import struct
12
13
14 import datetime
15
16 import numpy
17
18
19 import schainpy.admin
20 from schainpy.model.io.jroIO_base import LOCALTIME, Reader
21 from schainpy.model.data.jroheaderIO import BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
22 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
23 from schainpy.model.data.jrodata import Voltage, Parameters
24 from schainpy.utils import log
25
26
27 class DatReader(Reader, ProcessingUnit):
28
29 def __init__(self):
30
31 ProcessingUnit.__init__(self)
32 self.basicHeaderObj = BasicHeader(LOCALTIME)
33 self.systemHeaderObj = SystemHeader()
34 self.radarControllerHeaderObj = RadarControllerHeader()
35 self.processingHeaderObj = ProcessingHeader()
36 self.dataOut = Parameters()
37 #print(self.basicHeaderObj.timezone)
38 #self.counter_block=0
39 self.format='dat'
40 self.flagNoMoreFiles = 0
41 self.filename = None
42 self.intervals = set()
43 #self.datatime = datetime.datetime(1900,1,1)
44
45 self.filefmt = "***%Y%m%d*******"
46
47 self.padding=numpy.zeros(1,'int32')
48 self.hsize=numpy.zeros(1,'int32')
49 self.bufsize=numpy.zeros(1,'int32')
50 self.nr=numpy.zeros(1,'int32')
51 self.ngates=numpy.zeros(1,'int32') ### ### ### 2
52 self.time1=numpy.zeros(1,'uint64') # pos 3
53 self.time2=numpy.zeros(1,'uint64') # pos 4
54 self.lcounter=numpy.zeros(1,'int32')
55 self.groups=numpy.zeros(1,'int32')
56 self.system=numpy.zeros(4,'int8') # pos 7
57 self.h0=numpy.zeros(1,'float32')
58 self.dh=numpy.zeros(1,'float32')
59 self.ipp=numpy.zeros(1,'float32')
60 self.process=numpy.zeros(1,'int32')
61 self.tx=numpy.zeros(1,'int32')
62
63 self.ngates1=numpy.zeros(1,'int32') ### ### ### 13
64 self.time0=numpy.zeros(1,'uint64') # pos 14
65 self.nlags=numpy.zeros(1,'int32')
66 self.nlags1=numpy.zeros(1,'int32')
67 self.txb=numpy.zeros(1,'float32') ### ### ### 17
68 self.time3=numpy.zeros(1,'uint64') # pos 18
69 self.time4=numpy.zeros(1,'uint64') # pos 19
70 self.h0_=numpy.zeros(1,'float32')
71 self.dh_=numpy.zeros(1,'float32')
72 self.ipp_=numpy.zeros(1,'float32')
73 self.txa_=numpy.zeros(1,'float32')
74
75 self.pad=numpy.zeros(100,'int32')
76
77 self.nbytes=numpy.zeros(1,'int32')
78 self.limits=numpy.zeros(1,'int32')
79 self.ngroups=numpy.zeros(1,'int32') ### ### ### 27
80 #Make the header list
81 #header=[hsize,bufsize,nr,ngates,time1,time2,lcounter,groups,system,h0,dh,ipp,process,tx,padding,ngates1,time0,nlags,nlags1,padding,txb,time3,time4,h0_,dh_,ipp_,txa_,pad,nbytes,limits,padding,ngroups]
82 self.header=[self.hsize,self.bufsize,self.nr,self.ngates,self.time1,self.time2,self.lcounter,self.groups,self.system,self.h0,self.dh,self.ipp,self.process,self.tx,self.ngates1,self.padding,self.time0,self.nlags,self.nlags1,self.padding,self.txb,self.time3,self.time4,self.h0_,self.dh_,self.ipp_,self.txa_,self.pad,self.nbytes,self.limits,self.padding,self.ngroups]
83
84
85
86 def setup(self, **kwargs):
87
88 self.set_kwargs(**kwargs)
89
90
91 if self.path is None:
92 raise ValueError('The path is not valid')
93
94 self.open_file = open
95 self.open_mode = 'rb'
96
97
98
99 if self.format is None:
100 raise ValueError('The format is not valid')
101 elif self.format.lower() in ('dat'):
102 self.ext = '.dat'
103 elif self.format.lower() in ('out'):
104 self.ext = '.out'
105
106
107 log.log("Searching files in {}".format(self.path), self.name)
108 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
109 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
110 #print(self.path)
111 #print(self.filenameList)
112 #input()
113
114
115 self.setNextFile()
116
117 def readFirstHeader(self):
118 '''Read header and data'''
119
120 #self.flag_same_file=1
121 self.counter_block=0
122 self.parseHeader()
123 self.parseData()
124 self.blockIndex = 0
125
126 return
127
128 def parseHeader(self):
129 '''
130 '''
131
132 for i in range(len(self.header)):
133 for j in range(len(self.header[i])):
134 #print("len(header[i]) ",len(header[i]))
135 #input()
136 temp=self.fp.read(int(self.header[i].itemsize))
137 if isinstance(self.header[i][0], numpy.int32):
138 #print(struct.unpack('i', temp)[0])
139 self.header[i][0]=struct.unpack('i', temp)[0]
140 if isinstance(self.header[i][0], numpy.uint64):
141 self.header[i][0]=struct.unpack('q', temp)[0]
142 if isinstance(self.header[i][0], numpy.int8):
143 self.header[i][0]=struct.unpack('B', temp)[0]
144 if isinstance(self.header[i][0], numpy.float32):
145 self.header[i][0]=struct.unpack('f', temp)[0]
146
147 self.fp.seek(0,0)
148 if int(self.header[1][0])==int(81864):
149 self.experiment='DP'
150
151 elif int(self.header[1][0])==int(185504):
152 self.experiment='HP'
153
154
155 self.total_blocks=os.stat(self.filename).st_size//self.header[1][0]
156
157
158 def parseData(self):
159 '''
160 '''
161 if self.experiment=='DP':
162 self.header[15][0]=66
163 self.header[18][0]=16
164 self.header[17][0]=11
165 self.header[2][0]=2
166
167
168 self.noise=numpy.zeros(self.header[2][0],'float32') #self.header[2][0]
169 #tmpx=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
170 self.kax=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
171 self.kay=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
172 self.kbx=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
173 self.kby=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
174 self.kax2=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
175 self.kay2=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
176 self.kbx2=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
177 self.kby2=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
178 self.kaxbx=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
179 self.kaxby=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
180 self.kaybx=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
181 self.kayby=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
182 self.kaxay=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
183 self.kbxby=numpy.zeros((self.header[15][0],self.header[17][0],2),'float32')
184 self.output_LP_real=numpy.zeros((self.header[18][0],200,self.header[2][0]),'float32')
185 self.output_LP_imag=numpy.zeros((self.header[18][0],200,self.header[2][0]),'float32')
186 self.final_cross_products=[self.kax,self.kay,self.kbx,self.kby,self.kax2,self.kay2,self.kbx2,self.kby2,self.kaxbx,self.kaxby,self.kaybx,self.kayby,self.kaxay,self.kbxby]
187 #self.final_cross_products=[tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx,tmpx]
188
189 #print("pos: ",self.fp.tell())
190
191
192 def readNextBlock(self):
193
194 while True:
195 self.flagDiscontinuousBlock = 0
196 #print(os.stat(self.filename).st_size)
197 #print(os.stat(self.filename).st_size//self.header[1][0])
198 #os.stat(self.fp)
199 if self.counter_block == self.total_blocks:
200
201 self.setNextFile()
202
203 self.readBlock()
204 #self.counter_block+=1
205
206 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
207 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
208
209 #print(self.datatime)
210 #print(datetime.datetime.combine(self.startDate, self.startTime))
211 #print(datetime.datetime.combine(self.endDate, self.endTime))
212 #print("warning")
213 log.warning(
214 'Reading Block No. {}/{} -> {} [Skipping]'.format(
215 self.counter_block,
216 self.total_blocks,
217 self.datatime.ctime()),
218 'DATReader')
219 continue
220 break
221
222 log.log(
223 'Reading Block No. {}/{} -> {}'.format(
224 self.counter_block,
225 self.total_blocks,
226 self.datatime.ctime()),
227 'DATReader')
228
229 return 1
230
231 def readBlock(self):
232 '''
233 '''
234
235 self.npos=self.counter_block*self.header[1][0]
236 #print(self.counter_block)
237 self.fp.seek(self.npos, 0)
238 self.counter_block+=1
239 #print("fpos1: ",self.fp.tell())
240
241 self.read_header()
242
243 #put by hand because old files didn't save it in the header
244 if self.experiment=='DP':
245 self.header[15][0]=66
246 self.header[18][0]=16
247 self.header[17][0]=11
248 self.header[2][0]=2
249 #########################################
250
251 if self.experiment=="HP":
252 self.long_pulse_products()
253
254 self.read_cross_products()
255
256
257 self.read_noise()
258
259
260 return
261
262
263
264 def read_header(self):
265
266
267 for i in range(len(self.header)):
268 for j in range(len(self.header[i])):
269 #print("len(header[i]) ",len(header[i]))
270 #input()
271 temp=self.fp.read(int(self.header[i].itemsize))
272 #if(b''==temp):
273 # self.setNextFile()
274 # self.flag_same_file=0
275 if isinstance(self.header[i][0], numpy.int32):
276 #print(struct.unpack('i', temp)[0])
277 self.header[i][0]=struct.unpack('i', temp)[0]
278 if isinstance(self.header[i][0], numpy.uint64):
279 self.header[i][0]=struct.unpack('q', temp)[0]
280 if isinstance(self.header[i][0], numpy.int8):
281 self.header[i][0]=struct.unpack('B', temp)[0]
282 if isinstance(self.header[i][0], numpy.float32):
283 self.header[i][0]=struct.unpack('f', temp)[0]
284 #else:
285 # continue
286 #self.fp.seek(self.npos_aux, 0)
287 # break
288
289 #print("fpos2: ",self.fp.tell())
290 #log.success('Parameters found: {}'.format(self.parameters),
291 # 'DATReader')
292 #print("Success")
293 #self.TimeBlockSeconds_for_dp_power = self.header[4][0]#-((self.dataOut.nint-1)*self.dataOut.NAVG*2)
294 #print(dataOut.TimeBlockSeconds_for_dp_power)
295
296 #self.datatime=datetime.datetime.fromtimestamp(self.header[4][0]).strftime("%Y-%m-%d %H:%M:%S")
297 #print(self.header[4][0])
298 self.datatime=datetime.datetime.fromtimestamp(self.header[4][0])
299 #print(self.header[1][0])
300
301 def long_pulse_products(self):
302 temp=self.fp.read(self.header[18][0]*self.header[2][0]*200*8)
303 ii=0
304
305 for l in range(self.header[18][0]): #lag
306 for r in range(self.header[2][0]): # channels
307 for k in range(200): #RANGE## generalizar
308 self.output_LP_real[l,k,r]=struct.unpack('f', temp[ii:ii+4])[0]
309 ii=ii+4
310 self.output_LP_imag[l,k,r]=struct.unpack('f', temp[ii:ii+4])[0]
311 ii=ii+4
312
313 #print(self.output_LP_real[1,1,1])
314 #print(self.output_LP_imag[1,1,1])
315 def read_cross_products(self):
316
317 for ind in range(len(self.final_cross_products)): #final cross products
318 temp=self.fp.read(self.header[17][0]*2*self.header[15][0]*4) #*4 bytes
319 #if(b''==temp):
320 # self.setNextFile()
321 # self.flag_same_file=0
322 ii=0
323 #print("kabxys.shape ",kabxys.shape)
324 #print(kabxys)
325 #print("fpos3: ",self.fp.tell())
326 for l in range(self.header[17][0]): #lag
327 #print("fpos3: ",self.fp.tell())
328 for fl in range(2): # unflip and flip
329 for k in range(self.header[15][0]): #RANGE
330 #print("fpos3: ",self.fp.tell())
331 self.final_cross_products[ind][k,l,fl]=struct.unpack('f', temp[ii:ii+4])[0]
332 ii=ii+4
333 #print("fpos2: ",self.fp.tell())
334
335
336
337 def read_noise(self):
338
339 temp=self.fp.read(self.header[2][0]*4) #*4 bytes self.header[2][0]
340 for ii in range(self.header[2][0]): #self.header[2][0]
341 self.noise[ii]=struct.unpack('f', temp[ii*4:(ii+1)*4])[0]
342
343 #print("fpos5: ",self.fp.tell())
344
345
346
347 def set_output(self):
348 '''
349 Storing data from buffer to dataOut object
350 '''
351 #print("fpos2: ",self.fp.tell())
352 ##self.dataOut.header = self.header
353 #this is put by hand because it isn't saved in the header
354 if self.experiment=='DP':
355 self.dataOut.NRANGE=0
356 self.dataOut.NSCAN=132
357 self.dataOut.heightList=self.header[10][0]*(numpy.arange(self.header[15][0]))
358 elif self.experiment=='HP':
359 self.dataOut.output_LP=self.output_LP_real+1.j*self.output_LP_imag
360 self.dataOut.NRANGE=200
361 self.dataOut.NSCAN=128
362 self.dataOut.heightList=self.header[10][0]*(numpy.arange(90)) #NEEEDS TO BE GENERALIZED
363 #########################################
364 #print(self.dataOut.output_LP[1,1,1])
365 self.dataOut.MAXNRANGENDT=self.header[3][0]
366 self.dataOut.NDP=self.header[15][0]
367 self.dataOut.DPL=self.header[17][0]
368 self.dataOut.DH=self.header[10][0]
369 self.dataOut.NAVG=self.header[7][0]
370 self.dataOut.H0=self.header[9][0]
371 self.dataOut.NR=self.header[2][0]
372 self.dataOut.NLAG=self.header[18][0]
373 #self.dataOut.tmpx=self.tmpx
374 #self.dataOut.timeZone = 5
375 #self.dataOut.final_cross_products=self.final_cross_products
376 self.dataOut.kax=self.kax
377 #print(self.dataOut.kax[1,1,1])
378 self.dataOut.kay=self.kay
379 self.dataOut.kbx=self.kbx
380 self.dataOut.kby=self.kby
381 self.dataOut.kax2=self.kax2
382 self.dataOut.kay2=self.kay2
383 self.dataOut.kbx2=self.kbx2
384 self.dataOut.kby2=self.kby2
385 self.dataOut.kaxbx=self.kaxbx
386 self.dataOut.kaxby=self.kaxby
387 self.dataOut.kaybx=self.kaybx
388 self.dataOut.kayby=self.kayby
389 self.dataOut.kaxay=self.kaxay
390 self.dataOut.kbxby=self.kbxby
391 self.dataOut.noise_final=self.noise
392 #print("NOISE",self.noise)
393
394
395 self.dataOut.useLocalTime=True
396
397 #self.dataOut.experiment=self.experiment
398 #print(self.datatime)
399 #print(self.dataOut.datatime)
400
401
402 #self.dataOut.utctime = (self.datatime - datetime.datetime(1970, 1, 1)).total_seconds()
403 #self.dataOut.utctimeInit = self.dataOut.utctime
404
405
406
407 self.dataOut.lt=self.datatime.hour
408
409
410 #print(RadarControllerHeader().ippSeconds)
411 #print(RadarControllerHeader().ipp)
412 #self.dataOut.utctime=time.gmtime(self.header[4][0])- datetime.datetime(1970, 1, 1)
413 #self.dataOut.utctime=self.dataOut.utctime.total_seconds()
414 #time1 = self.header[4][0] # header.time1
415 #print("time1: ",time1)
416 #print(self.header[4][0])
417 #date = time.ctime(time1)
418 #print("DADSADA",time.strptime(date))
419 #print("date_before: ",date)
420 #bd_time=time.gmtime(time1)
421 #print(time.mktime(bd_time))
422 #self.dataOut.utctime=time.mktime(bd_time)
423 self.dataOut.utctime = self.header[4][0]
424 #self.dataOut.datatime=a
425 #print(datetime.datetime.utcfromtimestamp(self.dataOut.utctime))
426 #self.dataOut.TimeBlockDate=self.datatime.ctime()
427 self.dataOut.TimeBlockSeconds=time.mktime(time.strptime(self.dataOut.datatime.ctime()))
428
429 #self.dataOut.heightList = self.ranges
430 #self.dataOut.utctime = (self.datatime - datetime.datetime(1970, 1, 1)).total_seconds()
431 #self.dataOut.utctimeInit = self.dataOut.utctime
432 #self.dataOut.paramInterval = min(self.intervals)
433 #self.dataOut.useLocalTime = False
434 self.dataOut.flagNoData = False
435 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
436 #print(self.dataOut.channelIndexList)
437 self.dataOut.channelList=list(range(0,self.header[2][0]))
438 #print(self.dataOut.channelList)
439 #print(self.datatime)
440 #print(self.dataOut.final_cross_products[0])
441
442
443 #self.dataOut.heightList=self.header[10][0]*(numpy.arange(self.header[15][0]))
444
445 #print(numpy.shape(self.dataOut.heightList))
446
447
448 def getData(self):
449 '''
450 Storing data from databuffer to dataOut object
451 '''
452
453 if not self.readNextBlock():
454 self.dataOut.flagNoData = True
455 return 0
456
457 self.set_output()
458
459 return 1
460
461 def run(self, **kwargs):
462
463 if not(self.isConfig):
464 self.setup(**kwargs)
465 self.isConfig = True
466 #print("fpos1: ",self.fp.tell())
467 self.getData()
468
469 return
470
471 @MPDecorator
472 class DatWriter(Operation):
473
474
475 def __init__(self):
476
477 Operation.__init__(self)
478 #self.dataOut = Voltage()
479 self.counter = 0
480 self.path = None
481 self.fp = None
482 return
483 #self.ext= '.dat'
484
485 def run(self, dataOut, path, format='dat', experiment=None, **kwargs):
486 print(dataOut.flagNoData)
487 print(dataOut.datatime.ctime())
488 print(dataOut.TimeBlockDate)
489 input()
490 #if dataOut.flag_save:
491 self.experiment=experiment
492 self.path=path
493 if self.experiment=='DP':
494 dataOut.header[1][0]=81864
495 elif self.experiment=='HP':
496 dataOut.header[1][0]=185504#173216
497 #dataOut.header[1][0]=bufsize
498 self.dataOut = dataOut
499 #print(self.dataOut.nint)
500 #self.bufsize=bufsize
501 if format == 'dat':
502 self.ext = '.dat'
503 if format == 'out':
504 self.ext = '.out'
505 self.putData()
506
507 return
508
509
510
511 def setFile(self):
512 '''
513 Create new out file object
514 '''
515
516 #self.dataOut.TimeBlockSeconds=time.mktime(time.strptime(self.dataOut.TimeBlockDate))
517 date = datetime.datetime.fromtimestamp(self.dataOut.TimeBlockSeconds)
518
519 #print("date",date)
520
521 filename = '{}{}{}'.format('jro',
522 date.strftime('%Y%m%d_%H%M%S'),
523 self.ext)
524 #print(filename)
525 #print(self.path)
526
527 self.fullname = os.path.join(self.path, filename)
528
529 if os.path.isfile(self.fullname) :
530 log.warning(
531 'Destination file {} already exists, previous file deleted.'.format(
532 self.fullname),
533 'DatWriter')
534 os.remove(self.fullname)
535
536 try:
537 log.success(
538 'Creating file: {}'.format(self.fullname),
539 'DatWriter')
540 if not os.path.exists(self.path):
541 os.makedirs(self.path)
542 #self.fp = madrigal.cedar.MadrigalCedarFile(self.fullname, True)
543 self.fp = open(self.fullname,'wb')
544
545 except ValueError as e:
546 log.error(
547 'Impossible to create *.out file',
548 'DatWriter')
549 return
550
551 return 1
552
553 def writeBlock(self):
554
555 #self.dataOut.paramInterval=2
556 #startTime = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
557 #print(startTime)
558 #endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
559
560 self.dataOut.header[0].astype('int32').tofile(self.fp)
561 self.dataOut.header[1].astype('int32').tofile(self.fp)
562 self.dataOut.header[2].astype('int32').tofile(self.fp)
563 self.dataOut.header[3].astype('int32').tofile(self.fp)
564 self.dataOut.header[4].astype('uint64').tofile(self.fp)
565 self.dataOut.header[5].astype('uint64').tofile(self.fp)
566 self.dataOut.header[6].astype('int32').tofile(self.fp)
567 self.dataOut.header[7].astype('int32').tofile(self.fp)
568 #print(dataOut.header[7])
569 self.dataOut.header[8].astype('int8').tofile(self.fp)
570 self.dataOut.header[9].astype('float32').tofile(self.fp)
571 self.dataOut.header[10].astype('float32').tofile(self.fp)
572 self.dataOut.header[11].astype('float32').tofile(self.fp)
573 self.dataOut.header[12].astype('int32').tofile(self.fp)
574 self.dataOut.header[13].astype('int32').tofile(self.fp)
575 self.dataOut.header[14].astype('int32').tofile(self.fp)
576 self.dataOut.header[15].astype('int32').tofile(self.fp)
577 self.dataOut.header[16].astype('uint64').tofile(self.fp)
578 self.dataOut.header[17].astype('int32').tofile(self.fp)
579 self.dataOut.header[18].astype('int32').tofile(self.fp)
580 self.dataOut.header[19].astype('int32').tofile(self.fp)
581 self.dataOut.header[20].astype('float32').tofile(self.fp)
582 self.dataOut.header[21].astype('uint64').tofile(self.fp)
583 self.dataOut.header[22].astype('uint64').tofile(self.fp)
584 self.dataOut.header[23].astype('float32').tofile(self.fp)
585 self.dataOut.header[24].astype('float32').tofile(self.fp)
586 self.dataOut.header[25].astype('float32').tofile(self.fp)
587 self.dataOut.header[26].astype('float32').tofile(self.fp)
588 self.dataOut.header[27].astype('int32').tofile(self.fp)
589 self.dataOut.header[28].astype('int32').tofile(self.fp)
590 self.dataOut.header[29].astype('int32').tofile(self.fp)
591 self.dataOut.header[30].astype('int32').tofile(self.fp)
592 self.dataOut.header[31].astype('int32').tofile(self.fp)
593 #print("tell before 1 ",self.fp.tell())
594 #input()
595
596 if self.experiment=="HP":
597 #print("INSIDE")
598 #tmp=numpy.zeros(1,dtype='complex64')
599 #print("tmp ",tmp)
600 #input()
601 #print(dataOut.NLAG)
602 #print(dataOut.NR)
603 #print(dataOut.NRANGE)
604 for l in range(self.dataOut.NLAG): #lag
605 for r in range(self.dataOut.NR): # unflip and flip
606 for k in range(self.dataOut.NRANGE): #RANGE
607 self.dataOut.output_LP.real[l,k,r].astype('float32').tofile(self.fp)
608 self.dataOut.output_LP.imag[l,k,r].astype('float32').tofile(self.fp)
609
610
611 #print("tell before 2 ",self.outputfile.tell())
612
613
614
615
616
617 #print(self.dataOut.output_LP[1,1,1])
618
619 #print(self.dataOut.kax)
620 final_cross_products=[self.dataOut.kax,self.dataOut.kay,self.dataOut.kbx,self.dataOut.kby,
621 self.dataOut.kax2,self.dataOut.kay2,self.dataOut.kbx2,self.dataOut.kby2,
622 self.dataOut.kaxbx,self.dataOut.kaxby,self.dataOut.kaybx,self.dataOut.kayby,
623 self.dataOut.kaxay,self.dataOut.kbxby]
624
625 #print(self.dataOut.kax)
626 #print("tell before crossp saving ",self.outputfile.tell())
627 for kabxys in final_cross_products:
628
629 for l in range(self.dataOut.DPL): #lag
630 for fl in range(2): # unflip and flip
631 for k in range(self.dataOut.NDT): #RANGE
632 kabxys[k,l,fl].astype('float32').tofile(self.fp)
633
634
635 #print("tell before noise saving ",self.outputfile.tell())
636
637
638 for nch in range(self.dataOut.NR):
639 self.dataOut.noise_final[nch].astype('float32').tofile(self.fp)
640
641 #print("tell before noise saving ",self.fp.tell())
642 #input()
643
644
645
646
647 log.log(
648 'Writing {} blocks'.format(
649 self.counter+1),
650 'DatWriter')
651
652
653
654
655
656
657 def putData(self):
658 #print("flagNoData",self.dataOut.flagNoData)
659 #print("flagDiscontinuousBlock",self.dataOut.flagDiscontinuousBlock)
660 #print(self.dataOut.flagNoData)
661
662 if self.dataOut.flagNoData:
663 return 0
664
665 if self.dataOut.flagDiscontinuousBlock:
666
667 self.counter = 0
668
669 if self.counter == 0:
670 self.setFile()
671 #if self.experiment=="HP":
672 #if self.dataOut.debris_activated==0:
673 #self.writeBlock()
674 #self.counter += 1
675 #else:
676 self.writeBlock()
677 self.counter += 1
678
679 def close(self):
680
681 if self.counter > 0:
682 self.fp.close()
683 log.success('Closing file {}'.format(self.fullname), 'DatWriter')
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,1069 +1,1169
1 1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Definition of diferent Data objects for different types of data
6 6
7 7 Here you will find the diferent data objects for the different types
8 8 of data, this data objects must be used as dataIn or dataOut objects in
9 9 processing units and operations. Currently the supported data objects are:
10 10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
11 11 """
12 12
13 13 import copy
14 14 import numpy
15 15 import datetime
16 16 import json
17 17
18 18 import schainpy.admin
19 19 from schainpy.utils import log
20 20 from .jroheaderIO import SystemHeader, RadarControllerHeader
21 21 from schainpy.model.data import _noise
22 22
23 23
24 24 def getNumpyDtype(dataTypeCode):
25 25
26 26 if dataTypeCode == 0:
27 27 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
28 28 elif dataTypeCode == 1:
29 29 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
30 30 elif dataTypeCode == 2:
31 31 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
32 32 elif dataTypeCode == 3:
33 33 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
34 34 elif dataTypeCode == 4:
35 35 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
36 36 elif dataTypeCode == 5:
37 37 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
38 38 else:
39 39 raise ValueError('dataTypeCode was not defined')
40 40
41 41 return numpyDtype
42 42
43 43
44 44 def getDataTypeCode(numpyDtype):
45 45
46 46 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
47 47 datatype = 0
48 48 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
49 49 datatype = 1
50 50 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
51 51 datatype = 2
52 52 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
53 53 datatype = 3
54 54 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
55 55 datatype = 4
56 56 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
57 57 datatype = 5
58 58 else:
59 59 datatype = None
60 60
61 61 return datatype
62 62
63 63
64 64 def hildebrand_sekhon(data, navg):
65 65 """
66 66 This method is for the objective determination of the noise level in Doppler spectra. This
67 67 implementation technique is based on the fact that the standard deviation of the spectral
68 68 densities is equal to the mean spectral density for white Gaussian noise
69 69
70 70 Inputs:
71 71 Data : heights
72 72 navg : numbers of averages
73 73
74 74 Return:
75 75 mean : noise's level
76 76 """
77 77
78 78 sortdata = numpy.sort(data, axis=None)
79 #print(numpy.shape(data))
80 #exit()
79 81 '''
80 82 lenOfData = len(sortdata)
81 83 nums_min = lenOfData*0.2
82 84
83 85 if nums_min <= 5:
84 86
85 87 nums_min = 5
86 88
87 89 sump = 0.
88 90 sumq = 0.
89 91
90 92 j = 0
91 93 cont = 1
92 94
93 95 while((cont == 1)and(j < lenOfData)):
94 96
95 97 sump += sortdata[j]
96 98 sumq += sortdata[j]**2
97 99
98 100 if j > nums_min:
99 101 rtest = float(j)/(j-1) + 1.0/navg
100 102 if ((sumq*j) > (rtest*sump**2)):
101 103 j = j - 1
102 104 sump = sump - sortdata[j]
103 105 sumq = sumq - sortdata[j]**2
104 106 cont = 0
105 107
106 108 j += 1
107 109
108 110 lnoise = sump / j
109 111 '''
110 112 return _noise.hildebrand_sekhon(sortdata, navg)
111 113
112 114
113 115 class Beam:
114 116
115 117 def __init__(self):
116 118 self.codeList = []
117 119 self.azimuthList = []
118 120 self.zenithList = []
119 121
120 122
121 123 class GenericData(object):
122 124
123 125 flagNoData = True
124 126
125 127 def copy(self, inputObj=None):
126 128
127 129 if inputObj == None:
128 130 return copy.deepcopy(self)
129 131
130 132 for key in list(inputObj.__dict__.keys()):
131 133
132 134 attribute = inputObj.__dict__[key]
133 135
134 136 # If this attribute is a tuple or list
135 137 if type(inputObj.__dict__[key]) in (tuple, list):
136 138 self.__dict__[key] = attribute[:]
137 139 continue
138 140
139 141 # If this attribute is another object or instance
140 142 if hasattr(attribute, '__dict__'):
141 143 self.__dict__[key] = attribute.copy()
142 144 continue
143 145
144 146 self.__dict__[key] = inputObj.__dict__[key]
145 147
146 148 def deepcopy(self):
147 149
148 150 return copy.deepcopy(self)
149 151
150 152 def isEmpty(self):
151 153
152 154 return self.flagNoData
153 155
154 156 def isReady(self):
155 157
156 158 return not self.flagNoData
157 159
158 160
159 161 class JROData(GenericData):
160 162
161 163 systemHeaderObj = SystemHeader()
162 164 radarControllerHeaderObj = RadarControllerHeader()
163 165 type = None
164 166 datatype = None # dtype but in string
165 167 nProfiles = None
166 168 heightList = None
167 169 channelList = None
168 170 flagDiscontinuousBlock = False
169 171 useLocalTime = False
170 172 utctime = None
171 173 timeZone = None
172 174 dstFlag = None
173 175 errorCount = None
174 176 blocksize = None
175 177 flagDecodeData = False # asumo q la data no esta decodificada
176 178 flagDeflipData = False # asumo q la data no esta sin flip
177 179 flagShiftFFT = False
178 180 nCohInt = None
179 181 windowOfFilter = 1
180 182 C = 3e8
181 183 frequency = 49.92e6
182 184 realtime = False
183 185 beacon_heiIndexList = None
184 186 last_block = None
185 187 blocknow = None
186 188 azimuth = None
187 189 zenith = None
188 190 beam = Beam()
189 191 profileIndex = None
190 192 error = None
191 193 data = None
192 194 nmodes = None
193 195 metadata_list = ['heightList', 'timeZone', 'type']
194 196
195 197 def __str__(self):
196 198
197 199 return '{} - {}'.format(self.type, self.datatime())
198 200
199 201 def getNoise(self):
200 202
201 203 raise NotImplementedError
202 204
203 205 @property
204 206 def nChannels(self):
205 207
206 208 return len(self.channelList)
207 209
208 210 @property
209 211 def channelIndexList(self):
210 212
211 213 return list(range(self.nChannels))
212 214
213 215 @property
214 216 def nHeights(self):
215 217
216 218 return len(self.heightList)
217 219
218 220 def getDeltaH(self):
219 221
220 222 return self.heightList[1] - self.heightList[0]
221 223
222 224 @property
223 225 def ltctime(self):
224 226
225 227 if self.useLocalTime:
226 228 return self.utctime - self.timeZone * 60
227 229
228 230 return self.utctime
229 231
230 232 @property
231 233 def datatime(self):
232 234
233 235 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
234 236 return datatimeValue
235 237
236 238 def getTimeRange(self):
237 239
238 240 datatime = []
239 241
240 242 datatime.append(self.ltctime)
241 243 datatime.append(self.ltctime + self.timeInterval + 1)
242 244
243 245 datatime = numpy.array(datatime)
244 246
245 247 return datatime
246 248
247 249 def getFmaxTimeResponse(self):
248 250
249 251 period = (10**-6) * self.getDeltaH() / (0.15)
250 252
251 253 PRF = 1. / (period * self.nCohInt)
252 254
253 255 fmax = PRF
254 256
255 257 return fmax
256 258
257 259 def getFmax(self):
258 260 PRF = 1. / (self.ippSeconds * self.nCohInt)
259 261
260 262 fmax = PRF
261 263 return fmax
262 264
263 265 def getVmax(self):
264 266
265 267 _lambda = self.C / self.frequency
266 268
267 269 vmax = self.getFmax() * _lambda / 2
268 270
269 271 return vmax
270 272
271 273 @property
272 274 def ippSeconds(self):
273 275 '''
274 276 '''
275 277 return self.radarControllerHeaderObj.ippSeconds
276 278
277 279 @ippSeconds.setter
278 280 def ippSeconds(self, ippSeconds):
279 281 '''
280 282 '''
281 283 self.radarControllerHeaderObj.ippSeconds = ippSeconds
282 284
283 285 @property
284 286 def code(self):
285 287 '''
286 288 '''
287 289 return self.radarControllerHeaderObj.code
288 290
289 291 @code.setter
290 292 def code(self, code):
291 293 '''
292 294 '''
293 295 self.radarControllerHeaderObj.code = code
294 296
295 297 @property
296 298 def nCode(self):
297 299 '''
298 300 '''
299 301 return self.radarControllerHeaderObj.nCode
300 302
301 303 @nCode.setter
302 304 def nCode(self, ncode):
303 305 '''
304 306 '''
305 307 self.radarControllerHeaderObj.nCode = ncode
306 308
307 309 @property
308 310 def nBaud(self):
309 311 '''
310 312 '''
311 313 return self.radarControllerHeaderObj.nBaud
312 314
313 315 @nBaud.setter
314 316 def nBaud(self, nbaud):
315 317 '''
316 318 '''
317 319 self.radarControllerHeaderObj.nBaud = nbaud
318 320
319 321 @property
320 322 def ipp(self):
321 323 '''
322 324 '''
323 325 return self.radarControllerHeaderObj.ipp
324 326
325 327 @ipp.setter
326 328 def ipp(self, ipp):
327 329 '''
328 330 '''
329 331 self.radarControllerHeaderObj.ipp = ipp
330 332
331 333 @property
332 334 def metadata(self):
333 335 '''
334 336 '''
335 337
336 338 return {attr: getattr(self, attr) for attr in self.metadata_list}
337 339
338 340
339 341 class Voltage(JROData):
340 342
341 343 dataPP_POW = None
342 344 dataPP_DOP = None
343 345 dataPP_WIDTH = None
344 346 dataPP_SNR = None
345 347
346 348 def __init__(self):
347 349 '''
348 350 Constructor
349 351 '''
350 352
351 353 self.useLocalTime = True
352 354 self.radarControllerHeaderObj = RadarControllerHeader()
353 355 self.systemHeaderObj = SystemHeader()
354 356 self.type = "Voltage"
355 357 self.data = None
356 358 self.nProfiles = None
357 359 self.heightList = None
358 360 self.channelList = None
359 361 self.flagNoData = True
360 362 self.flagDiscontinuousBlock = False
361 363 self.utctime = None
362 364 self.timeZone = 0
363 365 self.dstFlag = None
364 366 self.errorCount = None
365 367 self.nCohInt = None
366 368 self.blocksize = None
367 369 self.flagCohInt = False
368 370 self.flagDecodeData = False # asumo q la data no esta decodificada
369 371 self.flagDeflipData = False # asumo q la data no esta sin flip
370 372 self.flagShiftFFT = False
371 373 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
372 374 self.profileIndex = 0
373 375 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
374 376 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
375 377
376 378 def getNoisebyHildebrand(self, channel=None):
377 379 """
378 380 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
379 381
380 382 Return:
381 383 noiselevel
382 384 """
383 385
384 386 if channel != None:
385 387 data = self.data[channel]
386 388 nChannels = 1
387 389 else:
388 390 data = self.data
389 391 nChannels = self.nChannels
390 392
391 393 noise = numpy.zeros(nChannels)
392 394 power = data * numpy.conjugate(data)
393 395
394 396 for thisChannel in range(nChannels):
395 397 if nChannels == 1:
396 398 daux = power[:].real
397 399 else:
398 400 daux = power[thisChannel, :].real
399 401 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
400 402
401 403 return noise
402 404
403 405 def getNoise(self, type=1, channel=None):
404 406
405 407 if type == 1:
406 408 noise = self.getNoisebyHildebrand(channel)
407 409
408 410 return noise
409 411
410 412 def getPower(self, channel=None):
411 413
412 414 if channel != None:
413 415 data = self.data[channel]
414 416 else:
415 417 data = self.data
416 418
417 419 power = data * numpy.conjugate(data)
418 420 powerdB = 10 * numpy.log10(power.real)
419 421 powerdB = numpy.squeeze(powerdB)
420 422
421 423 return powerdB
422 424
423 425 @property
424 426 def timeInterval(self):
425 427
426 428 return self.ippSeconds * self.nCohInt
427 429
428 430 noise = property(getNoise, "I'm the 'nHeights' property.")
429 431
430 432
433 class CrossProds(JROData):
434
435 # data es un numpy array de 2 dmensiones (canales, alturas)
436 data = None
437
438 def __init__(self):
439 '''
440 Constructor
441 '''
442
443 self.useLocalTime = True
444 '''
445 self.radarControllerHeaderObj = RadarControllerHeader()
446 self.systemHeaderObj = SystemHeader()
447 self.type = "Voltage"
448 self.data = None
449 # self.dtype = None
450 # self.nChannels = 0
451 # self.nHeights = 0
452 self.nProfiles = None
453 self.heightList = None
454 self.channelList = None
455 # self.channelIndexList = None
456 self.flagNoData = True
457 self.flagDiscontinuousBlock = False
458 self.utctime = None
459 self.timeZone = None
460 self.dstFlag = None
461 self.errorCount = None
462 self.nCohInt = None
463 self.blocksize = None
464 self.flagDecodeData = False # asumo q la data no esta decodificada
465 self.flagDeflipData = False # asumo q la data no esta sin flip
466 self.flagShiftFFT = False
467 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
468 self.profileIndex = 0
469
470
471 def getNoisebyHildebrand(self, channel=None):
472
473
474 if channel != None:
475 data = self.data[channel]
476 nChannels = 1
477 else:
478 data = self.data
479 nChannels = self.nChannels
480
481 noise = numpy.zeros(nChannels)
482 power = data * numpy.conjugate(data)
483
484 for thisChannel in range(nChannels):
485 if nChannels == 1:
486 daux = power[:].real
487 else:
488 daux = power[thisChannel, :].real
489 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
490
491 return noise
492
493 def getNoise(self, type=1, channel=None):
494
495 if type == 1:
496 noise = self.getNoisebyHildebrand(channel)
497
498 return noise
499
500 def getPower(self, channel=None):
501
502 if channel != None:
503 data = self.data[channel]
504 else:
505 data = self.data
506
507 power = data * numpy.conjugate(data)
508 powerdB = 10 * numpy.log10(power.real)
509 powerdB = numpy.squeeze(powerdB)
510
511 return powerdB
512
513 def getTimeInterval(self):
514
515 timeInterval = self.ippSeconds * self.nCohInt
516
517 return timeInterval
518
519 noise = property(getNoise, "I'm the 'nHeights' property.")
520 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
521 '''
522 def getTimeInterval(self):
523
524 timeInterval = self.ippSeconds * self.nCohInt
525
526 return timeInterval
527
528
529
431 530 class Spectra(JROData):
432 531
433 532 def __init__(self):
434 533 '''
435 534 Constructor
436 535 '''
437 536
438 537 self.data_dc = None
439 538 self.data_spc = None
440 539 self.data_cspc = None
441 540 self.useLocalTime = True
442 541 self.radarControllerHeaderObj = RadarControllerHeader()
443 542 self.systemHeaderObj = SystemHeader()
444 543 self.type = "Spectra"
445 544 self.timeZone = 0
446 545 self.nProfiles = None
447 546 self.heightList = None
448 547 self.channelList = None
449 548 self.pairsList = None
450 549 self.flagNoData = True
451 550 self.flagDiscontinuousBlock = False
452 551 self.utctime = None
453 552 self.nCohInt = None
454 553 self.nIncohInt = None
455 554 self.blocksize = None
456 555 self.nFFTPoints = None
457 556 self.wavelength = None
458 557 self.flagDecodeData = False # asumo q la data no esta decodificada
459 558 self.flagDeflipData = False # asumo q la data no esta sin flip
460 559 self.flagShiftFFT = False
461 560 self.ippFactor = 1
462 561 self.beacon_heiIndexList = []
463 562 self.noise_estimation = None
464 563 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
465 564 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp','nIncohInt', 'nFFTPoints', 'nProfiles']
466 565
467 566 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
468 567 """
469 568 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
470 569
471 570 Return:
472 571 noiselevel
473 572 """
474 573
475 574 noise = numpy.zeros(self.nChannels)
476 575
477 576 for channel in range(self.nChannels):
478 577 daux = self.data_spc[channel,
479 578 xmin_index:xmax_index, ymin_index:ymax_index]
480 579 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
481 580
482 581 return noise
483 582
484 583 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
485 584
486 585 if self.noise_estimation is not None:
487 586 # this was estimated by getNoise Operation defined in jroproc_spectra.py
488 587 return self.noise_estimation
489 588 else:
490 589 noise = self.getNoisebyHildebrand(
491 590 xmin_index, xmax_index, ymin_index, ymax_index)
492 591 return noise
493 592
494 593 def getFreqRangeTimeResponse(self, extrapoints=0):
495 594
496 595 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
497 596 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
498 597
499 598 return freqrange
500 599
501 600 def getAcfRange(self, extrapoints=0):
502 601
503 602 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
504 603 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
505 604
506 605 return freqrange
507 606
508 607 def getFreqRange(self, extrapoints=0):
509 608
510 609 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
511 610 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
512 611
513 612 return freqrange
514 613
515 614 def getVelRange(self, extrapoints=0):
516 615
517 616 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
518 617 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
519 618
520 619 if self.nmodes:
521 620 return velrange/self.nmodes
522 621 else:
523 622 return velrange
524 623
525 624 @property
526 625 def nPairs(self):
527 626
528 627 return len(self.pairsList)
529 628
530 629 @property
531 630 def pairsIndexList(self):
532 631
533 632 return list(range(self.nPairs))
534 633
535 634 @property
536 635 def normFactor(self):
537 636
538 637 pwcode = 1
539 638
540 639 if self.flagDecodeData:
541 640 pwcode = numpy.sum(self.code[0]**2)
542 641 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
543 642 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
544 643
545 644 return normFactor
546 645
547 646 @property
548 647 def flag_cspc(self):
549 648
550 649 if self.data_cspc is None:
551 650 return True
552 651
553 652 return False
554 653
555 654 @property
556 655 def flag_dc(self):
557 656
558 657 if self.data_dc is None:
559 658 return True
560 659
561 660 return False
562 661
563 662 @property
564 663 def timeInterval(self):
565 664
566 665 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
567 666 if self.nmodes:
568 667 return self.nmodes*timeInterval
569 668 else:
570 669 return timeInterval
571 670
572 671 def getPower(self):
573 672
574 673 factor = self.normFactor
575 674 z = self.data_spc / factor
576 675 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
577 676 avg = numpy.average(z, axis=1)
578 677
579 678 return 10 * numpy.log10(avg)
580 679
581 680 def getCoherence(self, pairsList=None, phase=False):
582 681
583 682 z = []
584 683 if pairsList is None:
585 684 pairsIndexList = self.pairsIndexList
586 685 else:
587 686 pairsIndexList = []
588 687 for pair in pairsList:
589 688 if pair not in self.pairsList:
590 689 raise ValueError("Pair %s is not in dataOut.pairsList" % (
591 690 pair))
592 691 pairsIndexList.append(self.pairsList.index(pair))
593 692 for i in range(len(pairsIndexList)):
594 693 pair = self.pairsList[pairsIndexList[i]]
595 694 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
596 695 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
597 696 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
598 697 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
599 698 if phase:
600 699 data = numpy.arctan2(avgcoherenceComplex.imag,
601 700 avgcoherenceComplex.real) * 180 / numpy.pi
602 701 else:
603 702 data = numpy.abs(avgcoherenceComplex)
604 703
605 704 z.append(data)
606 705
607 706 return numpy.array(z)
608 707
609 708 def setValue(self, value):
610 709
611 710 print("This property should not be initialized")
612 711
613 712 return
614 713
615 714 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
616 715
617 716
618 717 class SpectraHeis(Spectra):
619 718
620 719 def __init__(self):
621 720
622 721 self.radarControllerHeaderObj = RadarControllerHeader()
623 722 self.systemHeaderObj = SystemHeader()
624 723 self.type = "SpectraHeis"
625 724 self.nProfiles = None
626 725 self.heightList = None
627 726 self.channelList = None
628 727 self.flagNoData = True
629 728 self.flagDiscontinuousBlock = False
630 729 self.utctime = None
631 730 self.blocksize = None
632 731 self.profileIndex = 0
633 732 self.nCohInt = 1
634 733 self.nIncohInt = 1
635 734
636 735 @property
637 736 def normFactor(self):
638 737 pwcode = 1
639 738 if self.flagDecodeData:
640 739 pwcode = numpy.sum(self.code[0]**2)
641 740
642 741 normFactor = self.nIncohInt * self.nCohInt * pwcode
643 742
644 743 return normFactor
645 744
646 745 @property
647 746 def timeInterval(self):
648 747
649 748 return self.ippSeconds * self.nCohInt * self.nIncohInt
650 749
651 750
652 751 class Fits(JROData):
653 752
654 753 def __init__(self):
655 754
656 755 self.type = "Fits"
657 756 self.nProfiles = None
658 757 self.heightList = None
659 758 self.channelList = None
660 759 self.flagNoData = True
661 760 self.utctime = None
662 761 self.nCohInt = 1
663 762 self.nIncohInt = 1
664 763 self.useLocalTime = True
665 764 self.profileIndex = 0
666 765 self.timeZone = 0
667 766
668 767 def getTimeRange(self):
669 768
670 769 datatime = []
671 770
672 771 datatime.append(self.ltctime)
673 772 datatime.append(self.ltctime + self.timeInterval)
674 773
675 774 datatime = numpy.array(datatime)
676 775
677 776 return datatime
678 777
679 778 def getChannelIndexList(self):
680 779
681 780 return list(range(self.nChannels))
682 781
683 782 def getNoise(self, type=1):
684 783
685 784
686 785 if type == 1:
687 786 noise = self.getNoisebyHildebrand()
688 787
689 788 if type == 2:
690 789 noise = self.getNoisebySort()
691 790
692 791 if type == 3:
693 792 noise = self.getNoisebyWindow()
694 793
695 794 return noise
696 795
697 796 @property
698 797 def timeInterval(self):
699 798
700 799 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
701 800
702 801 return timeInterval
703 802
704 803 @property
705 804 def ippSeconds(self):
706 805 '''
707 806 '''
708 807 return self.ipp_sec
709 808
710 809 noise = property(getNoise, "I'm the 'nHeights' property.")
711 810
712 811
713 812 class Correlation(JROData):
714 813
715 814 def __init__(self):
716 815 '''
717 816 Constructor
718 817 '''
719 818 self.radarControllerHeaderObj = RadarControllerHeader()
720 819 self.systemHeaderObj = SystemHeader()
721 820 self.type = "Correlation"
722 821 self.data = None
723 822 self.dtype = None
724 823 self.nProfiles = None
725 824 self.heightList = None
726 825 self.channelList = None
727 826 self.flagNoData = True
728 827 self.flagDiscontinuousBlock = False
729 828 self.utctime = None
730 829 self.timeZone = 0
731 830 self.dstFlag = None
732 831 self.errorCount = None
733 832 self.blocksize = None
734 833 self.flagDecodeData = False # asumo q la data no esta decodificada
735 834 self.flagDeflipData = False # asumo q la data no esta sin flip
736 835 self.pairsList = None
737 836 self.nPoints = None
738 837
739 838 def getPairsList(self):
740 839
741 840 return self.pairsList
742 841
743 842 def getNoise(self, mode=2):
744 843
745 844 indR = numpy.where(self.lagR == 0)[0][0]
746 845 indT = numpy.where(self.lagT == 0)[0][0]
747 846
748 847 jspectra0 = self.data_corr[:, :, indR, :]
749 848 jspectra = copy.copy(jspectra0)
750 849
751 850 num_chan = jspectra.shape[0]
752 851 num_hei = jspectra.shape[2]
753 852
754 853 freq_dc = jspectra.shape[1] / 2
755 854 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
756 855
757 856 if ind_vel[0] < 0:
758 857 ind_vel[list(range(0, 1))] = ind_vel[list(
759 858 range(0, 1))] + self.num_prof
760 859
761 860 if mode == 1:
762 861 jspectra[:, freq_dc, :] = (
763 862 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
764 863
765 864 if mode == 2:
766 865
767 866 vel = numpy.array([-2, -1, 1, 2])
768 867 xx = numpy.zeros([4, 4])
769 868
770 869 for fil in range(4):
771 870 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
772 871
773 872 xx_inv = numpy.linalg.inv(xx)
774 873 xx_aux = xx_inv[0, :]
775 874
776 875 for ich in range(num_chan):
777 876 yy = jspectra[ich, ind_vel, :]
778 877 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
779 878
780 879 junkid = jspectra[ich, freq_dc, :] <= 0
781 880 cjunkid = sum(junkid)
782 881
783 882 if cjunkid.any():
784 883 jspectra[ich, freq_dc, junkid.nonzero()] = (
785 884 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
786 885
787 886 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
788 887
789 888 return noise
790 889
791 890 @property
792 891 def timeInterval(self):
793 892
794 893 return self.ippSeconds * self.nCohInt * self.nProfiles
795 894
796 895 def splitFunctions(self):
797 896
798 897 pairsList = self.pairsList
799 898 ccf_pairs = []
800 899 acf_pairs = []
801 900 ccf_ind = []
802 901 acf_ind = []
803 902 for l in range(len(pairsList)):
804 903 chan0 = pairsList[l][0]
805 904 chan1 = pairsList[l][1]
806 905
807 906 # Obteniendo pares de Autocorrelacion
808 907 if chan0 == chan1:
809 908 acf_pairs.append(chan0)
810 909 acf_ind.append(l)
811 910 else:
812 911 ccf_pairs.append(pairsList[l])
813 912 ccf_ind.append(l)
814 913
815 914 data_acf = self.data_cf[acf_ind]
816 915 data_ccf = self.data_cf[ccf_ind]
817 916
818 917 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
819 918
820 919 @property
821 920 def normFactor(self):
822 921 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
823 922 acf_pairs = numpy.array(acf_pairs)
824 923 normFactor = numpy.zeros((self.nPairs, self.nHeights))
825 924
826 925 for p in range(self.nPairs):
827 926 pair = self.pairsList[p]
828 927
829 928 ch0 = pair[0]
830 929 ch1 = pair[1]
831 930
832 931 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
833 932 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
834 933 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
835 934
836 935 return normFactor
837 936
838 937
839 938 class Parameters(Spectra):
840 939
841 940 groupList = None # List of Pairs, Groups, etc
842 941 data_param = None # Parameters obtained
843 942 data_pre = None # Data Pre Parametrization
844 943 data_SNR = None # Signal to Noise Ratio
845 944 abscissaList = None # Abscissa, can be velocities, lags or time
846 945 utctimeInit = None # Initial UTC time
847 946 paramInterval = None # Time interval to calculate Parameters in seconds
848 947 useLocalTime = True
849 948 # Fitting
850 949 data_error = None # Error of the estimation
851 950 constants = None
852 951 library = None
853 952 # Output signal
854 953 outputInterval = None # Time interval to calculate output signal in seconds
855 954 data_output = None # Out signal
856 955 nAvg = None
857 956 noise_estimation = None
858 957 GauSPC = None # Fit gaussian SPC
859 958
860 959 def __init__(self):
861 960 '''
862 961 Constructor
863 962 '''
864 963 self.radarControllerHeaderObj = RadarControllerHeader()
865 964 self.systemHeaderObj = SystemHeader()
866 965 self.type = "Parameters"
867 966 self.timeZone = 0
868 967
869 968 def getTimeRange1(self, interval):
870 969
871 970 datatime = []
872 971
873 972 if self.useLocalTime:
874 973 time1 = self.utctimeInit - self.timeZone * 60
875 974 else:
876 975 time1 = self.utctimeInit
877 976
878 977 datatime.append(time1)
879 978 datatime.append(time1 + interval)
880 979 datatime = numpy.array(datatime)
881 980
882 981 return datatime
883 982
884 983 @property
885 984 def timeInterval(self):
886 985
887 986 if hasattr(self, 'timeInterval1'):
888 987 return self.timeInterval1
889 988 else:
890 989 return self.paramInterval
891 990
991
892 992 def setValue(self, value):
893 993
894 994 print("This property should not be initialized")
895 995
896 996 return
897 997
898 998 def getNoise(self):
899 999
900 1000 return self.spc_noise
901 1001
902 1002 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
903 1003
904 1004
905 1005 class PlotterData(object):
906 1006 '''
907 1007 Object to hold data to be plotted
908 1008 '''
909 1009
910 1010 MAXNUMX = 200
911 1011 MAXNUMY = 200
912 1012
913 1013 def __init__(self, code, exp_code, localtime=True):
914 1014
915 1015 self.key = code
916 1016 self.exp_code = exp_code
917 1017 self.ready = False
918 1018 self.flagNoData = False
919 1019 self.localtime = localtime
920 1020 self.data = {}
921 1021 self.meta = {}
922 1022 self.__heights = []
923 1023
924 1024 def __str__(self):
925 1025 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
926 1026 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
927 1027
928 1028 def __len__(self):
929 1029 return len(self.data)
930 1030
931 1031 def __getitem__(self, key):
932 1032 if isinstance(key, int):
933 1033 return self.data[self.times[key]]
934 1034 elif isinstance(key, str):
935 1035 ret = numpy.array([self.data[x][key] for x in self.times])
936 1036 if ret.ndim > 1:
937 1037 ret = numpy.swapaxes(ret, 0, 1)
938 1038 return ret
939 1039
940 1040 def __contains__(self, key):
941 1041 return key in self.data[self.min_time]
942 1042
943 1043 def setup(self):
944 1044 '''
945 1045 Configure object
946 1046 '''
947 1047 self.type = ''
948 1048 self.ready = False
949 1049 del self.data
950 1050 self.data = {}
951 1051 self.__heights = []
952 1052 self.__all_heights = set()
953 1053
954 1054 def shape(self, key):
955 1055 '''
956 1056 Get the shape of the one-element data for the given key
957 1057 '''
958 1058
959 1059 if len(self.data[self.min_time][key]):
960 1060 return self.data[self.min_time][key].shape
961 1061 return (0,)
962 1062
963 1063 def update(self, data, tm, meta={}):
964 1064 '''
965 1065 Update data object with new dataOut
966 1066 '''
967 1067
968 1068 self.data[tm] = data
969 1069
970 1070 for key, value in meta.items():
971 1071 setattr(self, key, value)
972 1072
973 1073 def normalize_heights(self):
974 1074 '''
975 1075 Ensure same-dimension of the data for different heighList
976 1076 '''
977 1077
978 1078 H = numpy.array(list(self.__all_heights))
979 1079 H.sort()
980 1080 for key in self.data:
981 1081 shape = self.shape(key)[:-1] + H.shape
982 1082 for tm, obj in list(self.data[key].items()):
983 1083 h = self.__heights[self.times.tolist().index(tm)]
984 1084 if H.size == h.size:
985 1085 continue
986 1086 index = numpy.where(numpy.in1d(H, h))[0]
987 1087 dummy = numpy.zeros(shape) + numpy.nan
988 1088 if len(shape) == 2:
989 1089 dummy[:, index] = obj
990 1090 else:
991 1091 dummy[index] = obj
992 1092 self.data[key][tm] = dummy
993 1093
994 1094 self.__heights = [H for tm in self.times]
995 1095
996 1096 def jsonify(self, tm, plot_name, plot_type, decimate=False):
997 1097 '''
998 1098 Convert data to json
999 1099 '''
1000 1100
1001 1101 meta = {}
1002 1102 meta['xrange'] = []
1003 1103 dy = int(len(self.yrange)/self.MAXNUMY) + 1
1004 1104 tmp = self.data[tm][self.key]
1005 1105 shape = tmp.shape
1006 1106 if len(shape) == 2:
1007 1107 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1008 1108 elif len(shape) == 3:
1009 1109 dx = int(self.data[tm][self.key].shape[1]/self.MAXNUMX) + 1
1010 1110 data = self.roundFloats(
1011 1111 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1012 1112 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1013 1113 else:
1014 1114 data = self.roundFloats(self.data[tm][self.key].tolist())
1015 1115
1016 1116 ret = {
1017 1117 'plot': plot_name,
1018 1118 'code': self.exp_code,
1019 1119 'time': float(tm),
1020 1120 'data': data,
1021 1121 }
1022 1122 meta['type'] = plot_type
1023 1123 meta['interval'] = float(self.interval)
1024 1124 meta['localtime'] = self.localtime
1025 1125 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1026 1126 meta.update(self.meta)
1027 1127 ret['metadata'] = meta
1028 1128 return json.dumps(ret)
1029 1129
1030 1130 @property
1031 1131 def times(self):
1032 1132 '''
1033 1133 Return the list of times of the current data
1034 1134 '''
1035 1135
1036 1136 ret = [t for t in self.data]
1037 1137 ret.sort()
1038 1138 return numpy.array(ret)
1039 1139
1040 1140 @property
1041 1141 def min_time(self):
1042 1142 '''
1043 1143 Return the minimun time value
1044 1144 '''
1045 1145
1046 1146 return self.times[0]
1047 1147
1048 1148 @property
1049 1149 def max_time(self):
1050 1150 '''
1051 1151 Return the maximun time value
1052 1152 '''
1053 1153
1054 1154 return self.times[-1]
1055 1155
1056 1156 # @property
1057 1157 # def heights(self):
1058 1158 # '''
1059 1159 # Return the list of heights of the current data
1060 1160 # '''
1061 1161
1062 1162 # return numpy.array(self.__heights[-1])
1063 1163
1064 1164 @staticmethod
1065 1165 def roundFloats(obj):
1066 1166 if isinstance(obj, list):
1067 1167 return list(map(PlotterData.roundFloats, obj))
1068 1168 elif isinstance(obj, float):
1069 1169 return round(obj, 2)
@@ -1,906 +1,909
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JROHeaderIO.py 151 2012-10-31 19:00:51Z murco $
5 5 '''
6 6 import sys
7 7 import numpy
8 8 import copy
9 9 import datetime
10 10 import inspect
11 11 from schainpy.utils import log
12 12
13 13 SPEED_OF_LIGHT = 299792458
14 14 SPEED_OF_LIGHT = 3e8
15 15
16 16 BASIC_STRUCTURE = numpy.dtype([
17 17 ('nSize', '<u4'),
18 18 ('nVersion', '<u2'),
19 19 ('nDataBlockId', '<u4'),
20 20 ('nUtime', '<u4'),
21 21 ('nMilsec', '<u2'),
22 22 ('nTimezone', '<i2'),
23 23 ('nDstflag', '<i2'),
24 24 ('nErrorCount', '<u4')
25 25 ])
26 26
27 27 SYSTEM_STRUCTURE = numpy.dtype([
28 28 ('nSize', '<u4'),
29 29 ('nNumSamples', '<u4'),
30 30 ('nNumProfiles', '<u4'),
31 31 ('nNumChannels', '<u4'),
32 32 ('nADCResolution', '<u4'),
33 33 ('nPCDIOBusWidth', '<u4'),
34 34 ])
35 35
36 36 RADAR_STRUCTURE = numpy.dtype([
37 37 ('nSize', '<u4'),
38 38 ('nExpType', '<u4'),
39 39 ('nNTx', '<u4'),
40 40 ('fIpp', '<f4'),
41 41 ('fTxA', '<f4'),
42 42 ('fTxB', '<f4'),
43 43 ('nNumWindows', '<u4'),
44 44 ('nNumTaus', '<u4'),
45 45 ('nCodeType', '<u4'),
46 46 ('nLine6Function', '<u4'),
47 47 ('nLine5Function', '<u4'),
48 48 ('fClock', '<f4'),
49 49 ('nPrePulseBefore', '<u4'),
50 50 ('nPrePulseAfter', '<u4'),
51 51 ('sRangeIPP', '<a20'),
52 52 ('sRangeTxA', '<a20'),
53 53 ('sRangeTxB', '<a20'),
54 54 ])
55 55
56 56 SAMPLING_STRUCTURE = numpy.dtype(
57 57 [('h0', '<f4'), ('dh', '<f4'), ('nsa', '<u4')])
58 58
59 59
60 60 PROCESSING_STRUCTURE = numpy.dtype([
61 61 ('nSize', '<u4'),
62 62 ('nDataType', '<u4'),
63 63 ('nSizeOfDataBlock', '<u4'),
64 64 ('nProfilesperBlock', '<u4'),
65 65 ('nDataBlocksperFile', '<u4'),
66 66 ('nNumWindows', '<u4'),
67 67 ('nProcessFlags', '<u4'),
68 68 ('nCoherentIntegrations', '<u4'),
69 69 ('nIncoherentIntegrations', '<u4'),
70 70 ('nTotalSpectra', '<u4')
71 71 ])
72 72
73 73
74 74 class Header(object):
75 75
76 76 def __init__(self):
77 77 raise NotImplementedError
78 78
79 79 def copy(self):
80 80 return copy.deepcopy(self)
81 81
82 82 def read(self):
83 83
84 84 raise NotImplementedError
85 85
86 86 def write(self):
87 87
88 88 raise NotImplementedError
89 89
90 90 def getAllowedArgs(self):
91 91 args = inspect.getargspec(self.__init__).args
92 92 try:
93 93 args.remove('self')
94 94 except:
95 95 pass
96 96 return args
97 97
98 98 def getAsDict(self):
99 99 args = self.getAllowedArgs()
100 100 asDict = {}
101 101 for x in args:
102 102 asDict[x] = self[x]
103 103 return asDict
104 104
105 105 def __getitem__(self, name):
106 106 return getattr(self, name)
107 107
108 108 def printInfo(self):
109 109
110 110 message = "#" * 50 + "\n"
111 111 message += self.__class__.__name__.upper() + "\n"
112 112 message += "#" * 50 + "\n"
113 113
114 114 keyList = list(self.__dict__.keys())
115 115 keyList.sort()
116 116
117 117 for key in keyList:
118 118 message += "%s = %s" % (key, self.__dict__[key]) + "\n"
119 119
120 120 if "size" not in keyList:
121 121 attr = getattr(self, "size")
122 122
123 123 if attr:
124 124 message += "%s = %s" % ("size", attr) + "\n"
125 125
126 126 print(message)
127 127
128 128
129 129 class BasicHeader(Header):
130 130
131 131 size = None
132 132 version = None
133 133 dataBlock = None
134 134 utc = None
135 135 ltc = None
136 136 miliSecond = None
137 137 timeZone = None
138 138 dstFlag = None
139 139 errorCount = None
140 datatime = None
140 F = None
141 141 structure = BASIC_STRUCTURE
142 142 __LOCALTIME = None
143 143
144 144 def __init__(self, useLocalTime=True):
145 145
146 146 self.size = 24
147 147 self.version = 0
148 148 self.dataBlock = 0
149 149 self.utc = 0
150 150 self.miliSecond = 0
151 151 self.timeZone = 0
152 152 self.dstFlag = 0
153 153 self.errorCount = 0
154 154
155 155 self.useLocalTime = useLocalTime
156 156
157 157 def read(self, fp):
158 158
159 159 self.length = 0
160 160 try:
161 161 if hasattr(fp, 'read'):
162 162 header = numpy.fromfile(fp, BASIC_STRUCTURE, 1)
163 163 else:
164 164 header = numpy.fromstring(fp, BASIC_STRUCTURE, 1)
165 165 except Exception as e:
166 166 print("BasicHeader: ")
167 167 print(e)
168 168 return 0
169 169
170 170 self.size = int(header['nSize'][0])
171 171 self.version = int(header['nVersion'][0])
172 172 self.dataBlock = int(header['nDataBlockId'][0])
173 173 self.utc = int(header['nUtime'][0])
174 174 self.miliSecond = int(header['nMilsec'][0])
175 175 self.timeZone = int(header['nTimezone'][0])
176 176 self.dstFlag = int(header['nDstflag'][0])
177 177 self.errorCount = int(header['nErrorCount'][0])
178 178
179 179 if self.size < 24:
180 180 return 0
181 181
182 182 self.length = header.nbytes
183 183 return 1
184 184
185 185 def write(self, fp):
186 186
187 187 headerTuple = (self.size, self.version, self.dataBlock, self.utc,
188 188 self.miliSecond, self.timeZone, self.dstFlag, self.errorCount)
189 189 header = numpy.array(headerTuple, BASIC_STRUCTURE)
190 190 header.tofile(fp)
191 191
192 192 return 1
193 193
194 194 def get_ltc(self):
195 195
196 196 return self.utc - self.timeZone * 60
197 197
198 198 def set_ltc(self, value):
199 199
200 200 self.utc = value + self.timeZone * 60
201 201
202 202 def get_datatime(self):
203 203
204 204 return datetime.datetime.utcfromtimestamp(self.ltc)
205 205
206 206 ltc = property(get_ltc, set_ltc)
207 207 datatime = property(get_datatime)
208 208
209 209
210 210 class SystemHeader(Header):
211 211
212 212 size = None
213 213 nSamples = None
214 214 nProfiles = None
215 215 nChannels = None
216 216 adcResolution = None
217 217 pciDioBusWidth = None
218 218 structure = SYSTEM_STRUCTURE
219 219
220 220 def __init__(self, nSamples=0, nProfiles=0, nChannels=0, adcResolution=14, pciDioBusWidth=0):
221 221
222 222 self.size = 24
223 223 self.nSamples = nSamples
224 224 self.nProfiles = nProfiles
225 225 self.nChannels = nChannels
226 226 self.adcResolution = adcResolution
227 227 self.pciDioBusWidth = pciDioBusWidth
228 228
229 229 def read(self, fp):
230 230 self.length = 0
231 231 try:
232 232 startFp = fp.tell()
233 233 except Exception as e:
234 234 startFp = None
235 235 pass
236 236
237 237 try:
238 238 if hasattr(fp, 'read'):
239 239 header = numpy.fromfile(fp, SYSTEM_STRUCTURE, 1)
240 240 else:
241 241 header = numpy.fromstring(fp, SYSTEM_STRUCTURE, 1)
242 242 except Exception as e:
243 243 print("System Header: " + str(e))
244 244 return 0
245 245
246 246 self.size = header['nSize'][0]
247 247 self.nSamples = header['nNumSamples'][0]
248 248 self.nProfiles = header['nNumProfiles'][0]
249 249 self.nChannels = header['nNumChannels'][0]
250 250 self.adcResolution = header['nADCResolution'][0]
251 251 self.pciDioBusWidth = header['nPCDIOBusWidth'][0]
252 252
253 253 if startFp is not None:
254 254 endFp = self.size + startFp
255 255
256 256 if fp.tell() > endFp:
257 257 sys.stderr.write(
258 258 "Warning %s: Size value read from System Header is lower than it has to be\n" % fp.name)
259 259 return 0
260 260
261 261 if fp.tell() < endFp:
262 262 sys.stderr.write(
263 263 "Warning %s: Size value read from System Header size is greater than it has to be\n" % fp.name)
264 264 return 0
265 265
266 266 self.length = header.nbytes
267 267 return 1
268 268
269 269 def write(self, fp):
270 270
271 271 headerTuple = (self.size, self.nSamples, self.nProfiles,
272 272 self.nChannels, self.adcResolution, self.pciDioBusWidth)
273 273 header = numpy.array(headerTuple, SYSTEM_STRUCTURE)
274 274 header.tofile(fp)
275 275
276 276 return 1
277 277
278 278
279 279 class RadarControllerHeader(Header):
280 280
281 281 expType = None
282 282 nTx = None
283 283 ipp = None
284 284 txA = None
285 285 txB = None
286 286 nWindows = None
287 287 numTaus = None
288 288 codeType = None
289 289 line6Function = None
290 290 line5Function = None
291 291 fClock = None
292 292 prePulseBefore = None
293 293 prePulseAfter = None
294 294 rangeIpp = None
295 295 rangeTxA = None
296 296 rangeTxB = None
297 297 structure = RADAR_STRUCTURE
298 298 __size = None
299 299
300 300 def __init__(self, expType=2, nTx=1,
301 301 ipp=None, txA=0, txB=0,
302 302 nWindows=None, nHeights=None, firstHeight=None, deltaHeight=None,
303 303 numTaus=0, line6Function=0, line5Function=0, fClock=None,
304 304 prePulseBefore=0, prePulseAfter=0,
305 305 codeType=0, nCode=0, nBaud=0, code=[],
306 306 flip1=0, flip2=0):
307 307
308 308 # self.size = 116
309 309 self.expType = expType
310 310 self.nTx = nTx
311 311 self.ipp = ipp
312 312 self.txA = txA
313 313 self.txB = txB
314 314 self.rangeIpp = ipp
315 315 self.rangeTxA = txA
316 316 self.rangeTxB = txB
317 317
318 318 self.nWindows = nWindows
319 319 self.numTaus = numTaus
320 320 self.codeType = codeType
321 321 self.line6Function = line6Function
322 322 self.line5Function = line5Function
323 323 self.fClock = fClock
324 324 self.prePulseBefore = prePulseBefore
325 325 self.prePulseAfter = prePulseAfter
326 326
327 327 self.nHeights = nHeights
328 328 self.firstHeight = firstHeight
329 329 self.deltaHeight = deltaHeight
330 330 self.samplesWin = nHeights
331 331
332 332 self.nCode = nCode
333 333 self.nBaud = nBaud
334 334 self.code = code
335 335 self.flip1 = flip1
336 336 self.flip2 = flip2
337 337
338 338 self.code_size = int(numpy.ceil(self.nBaud / 32.)) * self.nCode * 4
339 339 # self.dynamic = numpy.array([],numpy.dtype('byte'))
340 340
341 341 if self.fClock is None and self.deltaHeight is not None:
342 342 self.fClock = 0.15 / (deltaHeight * 1e-6) # 0.15Km / (height * 1u)
343 343
344 344 def read(self, fp):
345 345 self.length = 0
346 346 try:
347 347 startFp = fp.tell()
348 348 except Exception as e:
349 349 startFp = None
350 350 pass
351 351
352 352 try:
353 353 if hasattr(fp, 'read'):
354 354 header = numpy.fromfile(fp, RADAR_STRUCTURE, 1)
355 355 else:
356 356 header = numpy.fromstring(fp, RADAR_STRUCTURE, 1)
357 357 self.length += header.nbytes
358 358 except Exception as e:
359 359 print("RadarControllerHeader: " + str(e))
360 360 return 0
361 361
362 362 size = int(header['nSize'][0])
363 363 self.expType = int(header['nExpType'][0])
364 364 self.nTx = int(header['nNTx'][0])
365 365 self.ipp = float(header['fIpp'][0])
366 #print(self.ipp)
366 367 self.txA = float(header['fTxA'][0])
367 368 self.txB = float(header['fTxB'][0])
368 369 self.nWindows = int(header['nNumWindows'][0])
369 370 self.numTaus = int(header['nNumTaus'][0])
370 371 self.codeType = int(header['nCodeType'][0])
371 372 self.line6Function = int(header['nLine6Function'][0])
372 373 self.line5Function = int(header['nLine5Function'][0])
373 374 self.fClock = float(header['fClock'][0])
374 375 self.prePulseBefore = int(header['nPrePulseBefore'][0])
375 376 self.prePulseAfter = int(header['nPrePulseAfter'][0])
376 377 self.rangeIpp = header['sRangeIPP'][0]
377 378 self.rangeTxA = header['sRangeTxA'][0]
378 379 self.rangeTxB = header['sRangeTxB'][0]
379 380
380 381 try:
381 382 if hasattr(fp, 'read'):
382 383 samplingWindow = numpy.fromfile(
383 384 fp, SAMPLING_STRUCTURE, self.nWindows)
384 385 else:
385 386 samplingWindow = numpy.fromstring(
386 387 fp[self.length:], SAMPLING_STRUCTURE, self.nWindows)
387 388 self.length += samplingWindow.nbytes
388 389 except Exception as e:
389 390 print("RadarControllerHeader: " + str(e))
390 391 return 0
391 392 self.nHeights = int(numpy.sum(samplingWindow['nsa']))
392 393 self.firstHeight = samplingWindow['h0']
393 394 self.deltaHeight = samplingWindow['dh']
394 395 self.samplesWin = samplingWindow['nsa']
395 396
396 397 try:
397 398 if hasattr(fp, 'read'):
398 399 self.Taus = numpy.fromfile(fp, '<f4', self.numTaus)
399 400 else:
400 401 self.Taus = numpy.fromstring(
401 402 fp[self.length:], '<f4', self.numTaus)
402 403 self.length += self.Taus.nbytes
403 404 except Exception as e:
404 405 print("RadarControllerHeader: " + str(e))
405 406 return 0
406 407
407 408 self.code_size = 0
408 409 if self.codeType != 0:
409 410
410 411 try:
411 412 if hasattr(fp, 'read'):
412 413 self.nCode = numpy.fromfile(fp, '<u4', 1)[0]
413 414 self.length += self.nCode.nbytes
414 415 self.nBaud = numpy.fromfile(fp, '<u4', 1)[0]
415 416 self.length += self.nBaud.nbytes
416 417 else:
417 418 self.nCode = numpy.fromstring(
418 419 fp[self.length:], '<u4', 1)[0]
419 420 self.length += self.nCode.nbytes
420 421 self.nBaud = numpy.fromstring(
421 422 fp[self.length:], '<u4', 1)[0]
422 423 self.length += self.nBaud.nbytes
423 424 except Exception as e:
424 425 print("RadarControllerHeader: " + str(e))
425 426 return 0
426 427 code = numpy.empty([self.nCode, self.nBaud], dtype='i1')
427 428
428 429 for ic in range(self.nCode):
429 430 try:
430 431 if hasattr(fp, 'read'):
431 432 temp = numpy.fromfile(fp, 'u4', int(
432 433 numpy.ceil(self.nBaud / 32.)))
433 434 else:
434 435 temp = numpy.fromstring(
435 436 fp, 'u4', int(numpy.ceil(self.nBaud / 32.)))
436 437 self.length += temp.nbytes
437 438 except Exception as e:
438 439 print("RadarControllerHeader: " + str(e))
439 440 return 0
440 441
441 442 for ib in range(self.nBaud - 1, -1, -1):
442 443 code[ic, ib] = temp[int(ib / 32)] % 2
443 444 temp[int(ib / 32)] = temp[int(ib / 32)] / 2
444 445
445 446 self.code = 2.0 * code - 1.0
446 447 self.code_size = int(numpy.ceil(self.nBaud / 32.)) * self.nCode * 4
447 448
448 449 # if self.line5Function == RCfunction.FLIP:
449 450 # self.flip1 = numpy.fromfile(fp,'<u4',1)
450 451 #
451 452 # if self.line6Function == RCfunction.FLIP:
452 453 # self.flip2 = numpy.fromfile(fp,'<u4',1)
453 454 if startFp is not None:
454 455 endFp = size + startFp
455 456
456 457 if fp.tell() != endFp:
457 458 # fp.seek(endFp)
458 459 print("%s: Radar Controller Header size is not consistent: from data [%d] != from header field [%d]" % (fp.name, fp.tell() - startFp, size))
459 460 # return 0
460 461
461 462 if fp.tell() > endFp:
462 463 sys.stderr.write(
463 464 "Warning %s: Size value read from Radar Controller header is lower than it has to be\n" % fp.name)
464 465 # return 0
465 466
466 467 if fp.tell() < endFp:
467 468 sys.stderr.write(
468 469 "Warning %s: Size value read from Radar Controller header is greater than it has to be\n" % fp.name)
469 470
470 471 return 1
471 472
472 473 def write(self, fp):
473 474
474 475 headerTuple = (self.size,
475 476 self.expType,
476 477 self.nTx,
477 478 self.ipp,
478 479 self.txA,
479 480 self.txB,
480 481 self.nWindows,
481 482 self.numTaus,
482 483 self.codeType,
483 484 self.line6Function,
484 485 self.line5Function,
485 486 self.fClock,
486 487 self.prePulseBefore,
487 488 self.prePulseAfter,
488 489 self.rangeIpp,
489 490 self.rangeTxA,
490 491 self.rangeTxB)
491 492
492 493 header = numpy.array(headerTuple, RADAR_STRUCTURE)
493 494 header.tofile(fp)
494 495
495 496 sampleWindowTuple = (
496 497 self.firstHeight, self.deltaHeight, self.samplesWin)
497 498 samplingWindow = numpy.array(sampleWindowTuple, SAMPLING_STRUCTURE)
498 499 samplingWindow.tofile(fp)
499 500
500 501 if self.numTaus > 0:
501 502 self.Taus.tofile(fp)
502 503
503 504 if self.codeType != 0:
504 505 nCode = numpy.array(self.nCode, '<u4')
505 506 nCode.tofile(fp)
506 507 nBaud = numpy.array(self.nBaud, '<u4')
507 508 nBaud.tofile(fp)
508 509 code1 = (self.code + 1.0) / 2.
509 510
510 511 for ic in range(self.nCode):
511 512 tempx = numpy.zeros(int(numpy.ceil(self.nBaud / 32.)))
512 513 start = 0
513 514 end = 32
514 515 for i in range(len(tempx)):
515 516 code_selected = code1[ic, start:end]
516 517 for j in range(len(code_selected) - 1, -1, -1):
517 518 if code_selected[j] == 1:
518 519 tempx[i] = tempx[i] + \
519 520 2**(len(code_selected) - 1 - j)
520 521 start = start + 32
521 522 end = end + 32
522 523
523 524 tempx = tempx.astype('u4')
524 525 tempx.tofile(fp)
525 526
526 527 # if self.line5Function == RCfunction.FLIP:
527 528 # self.flip1.tofile(fp)
528 529 #
529 530 # if self.line6Function == RCfunction.FLIP:
530 531 # self.flip2.tofile(fp)
531 532
532 533 return 1
533 534
534 535 def get_ippSeconds(self):
535 536 '''
536 537 '''
538
537 539 ippSeconds = 2.0 * 1000 * self.ipp / SPEED_OF_LIGHT
538 540
539 541 return ippSeconds
540 542
541 543 def set_ippSeconds(self, ippSeconds):
542 544 '''
543 545 '''
544 546
545 547 self.ipp = ippSeconds * SPEED_OF_LIGHT / (2.0 * 1000)
546 548
547 549 return
548 550
549 551 def get_size(self):
550 552
551 553 self.__size = 116 + 12 * self.nWindows + 4 * self.numTaus
552 554
553 555 if self.codeType != 0:
554 556 self.__size += 4 + 4 + 4 * self.nCode * \
555 557 numpy.ceil(self.nBaud / 32.)
556 558
557 559 return self.__size
558 560
559 561 def set_size(self, value):
560 562
561 563 raise IOError("size is a property and it cannot be set, just read")
562 564
563 565 return
564 566
565 567 ippSeconds = property(get_ippSeconds, set_ippSeconds)
566 568 size = property(get_size, set_size)
567 569
568 570
569 571 class ProcessingHeader(Header):
570 572
571 573 # size = None
572 574 dtype = None
573 575 blockSize = None
574 576 profilesPerBlock = None
575 577 dataBlocksPerFile = None
576 578 nWindows = None
577 579 processFlags = None
578 580 nCohInt = None
579 581 nIncohInt = None
580 582 totalSpectra = None
581 583 structure = PROCESSING_STRUCTURE
582 584 flag_dc = None
583 585 flag_cspc = None
584 586
585 587 def __init__(self, dtype=0, blockSize=0, profilesPerBlock=0, dataBlocksPerFile=0, nWindows=0, processFlags=0, nCohInt=0,
586 588 nIncohInt=0, totalSpectra=0, nHeights=0, firstHeight=0, deltaHeight=0, samplesWin=0, spectraComb=0, nCode=0,
587 589 code=0, nBaud=None, shif_fft=False, flag_dc=False, flag_cspc=False, flag_decode=False, flag_deflip=False
588 590 ):
589 591
590 592 # self.size = 0
591 593 self.dtype = dtype
592 594 self.blockSize = blockSize
593 595 self.profilesPerBlock = 0
594 596 self.dataBlocksPerFile = 0
595 597 self.nWindows = 0
596 598 self.processFlags = 0
597 599 self.nCohInt = 0
598 600 self.nIncohInt = 0
599 601 self.totalSpectra = 0
600 602
601 603 self.nHeights = 0
602 604 self.firstHeight = 0
603 605 self.deltaHeight = 0
604 606 self.samplesWin = 0
605 607 self.spectraComb = 0
606 608 self.nCode = None
607 609 self.code = None
608 610 self.nBaud = None
609 611
610 612 self.shif_fft = False
611 613 self.flag_dc = False
612 614 self.flag_cspc = False
613 615 self.flag_decode = False
614 616 self.flag_deflip = False
615 617 self.length = 0
616 618
617 619 def read(self, fp):
618 620 self.length = 0
619 621 try:
620 622 startFp = fp.tell()
621 623 except Exception as e:
622 624 startFp = None
623 625 pass
624 626
625 627 try:
626 628 if hasattr(fp, 'read'):
627 629 header = numpy.fromfile(fp, PROCESSING_STRUCTURE, 1)
628 630 else:
629 631 header = numpy.fromstring(fp, PROCESSING_STRUCTURE, 1)
630 632 self.length += header.nbytes
631 633 except Exception as e:
632 634 print("ProcessingHeader: " + str(e))
633 635 return 0
634 636
635 637 size = int(header['nSize'][0])
636 638 self.dtype = int(header['nDataType'][0])
637 639 self.blockSize = int(header['nSizeOfDataBlock'][0])
638 640 self.profilesPerBlock = int(header['nProfilesperBlock'][0])
639 641 self.dataBlocksPerFile = int(header['nDataBlocksperFile'][0])
640 642 self.nWindows = int(header['nNumWindows'][0])
641 643 self.processFlags = header['nProcessFlags']
642 644 self.nCohInt = int(header['nCoherentIntegrations'][0])
645
643 646 self.nIncohInt = int(header['nIncoherentIntegrations'][0])
644 647 self.totalSpectra = int(header['nTotalSpectra'][0])
645 648
646 649 try:
647 650 if hasattr(fp, 'read'):
648 651 samplingWindow = numpy.fromfile(
649 652 fp, SAMPLING_STRUCTURE, self.nWindows)
650 653 else:
651 654 samplingWindow = numpy.fromstring(
652 655 fp[self.length:], SAMPLING_STRUCTURE, self.nWindows)
653 656 self.length += samplingWindow.nbytes
654 657 except Exception as e:
655 658 print("ProcessingHeader: " + str(e))
656 659 return 0
657 660
658 661 self.nHeights = int(numpy.sum(samplingWindow['nsa']))
659 662 self.firstHeight = float(samplingWindow['h0'][0])
660 663 self.deltaHeight = float(samplingWindow['dh'][0])
661 664 self.samplesWin = samplingWindow['nsa'][0]
662 665
663 666 try:
664 667 if hasattr(fp, 'read'):
665 668 self.spectraComb = numpy.fromfile(
666 669 fp, 'u1', 2 * self.totalSpectra)
667 670 else:
668 671 self.spectraComb = numpy.fromstring(
669 672 fp[self.length:], 'u1', 2 * self.totalSpectra)
670 673 self.length += self.spectraComb.nbytes
671 674 except Exception as e:
672 675 print("ProcessingHeader: " + str(e))
673 676 return 0
674 677
675 678 if ((self.processFlags & PROCFLAG.DEFINE_PROCESS_CODE) == PROCFLAG.DEFINE_PROCESS_CODE):
676 679 self.nCode = int(numpy.fromfile(fp, '<u4', 1))
677 680 self.nBaud = int(numpy.fromfile(fp, '<u4', 1))
678 681 self.code = numpy.fromfile(
679 682 fp, '<f4', self.nCode * self.nBaud).reshape(self.nCode, self.nBaud)
680 683
681 684 if ((self.processFlags & PROCFLAG.EXP_NAME_ESP) == PROCFLAG.EXP_NAME_ESP):
682 685 exp_name_len = int(numpy.fromfile(fp, '<u4', 1))
683 686 exp_name = numpy.fromfile(fp, 'u1', exp_name_len + 1)
684 687
685 688 if ((self.processFlags & PROCFLAG.SHIFT_FFT_DATA) == PROCFLAG.SHIFT_FFT_DATA):
686 689 self.shif_fft = True
687 690 else:
688 691 self.shif_fft = False
689 692
690 693 if ((self.processFlags & PROCFLAG.SAVE_CHANNELS_DC) == PROCFLAG.SAVE_CHANNELS_DC):
691 694 self.flag_dc = True
692 695 else:
693 696 self.flag_dc = False
694 697
695 698 if ((self.processFlags & PROCFLAG.DECODE_DATA) == PROCFLAG.DECODE_DATA):
696 699 self.flag_decode = True
697 700 else:
698 701 self.flag_decode = False
699 702
700 703 if ((self.processFlags & PROCFLAG.DEFLIP_DATA) == PROCFLAG.DEFLIP_DATA):
701 704 self.flag_deflip = True
702 705 else:
703 706 self.flag_deflip = False
704 707
705 708 nChannels = 0
706 709 nPairs = 0
707 710 pairList = []
708 711
709 712 for i in range(0, self.totalSpectra * 2, 2):
710 713 if self.spectraComb[i] == self.spectraComb[i + 1]:
711 714 nChannels = nChannels + 1 # par de canales iguales
712 715 else:
713 716 nPairs = nPairs + 1 # par de canales diferentes
714 717 pairList.append((self.spectraComb[i], self.spectraComb[i + 1]))
715 718
716 719 self.flag_cspc = False
717 720 if nPairs > 0:
718 721 self.flag_cspc = True
719 722
720 723 if startFp is not None:
721 724 endFp = size + startFp
722 725 if fp.tell() > endFp:
723 726 sys.stderr.write(
724 727 "Warning: Processing header size is lower than it has to be")
725 728 return 0
726 729
727 730 if fp.tell() < endFp:
728 731 sys.stderr.write(
729 732 "Warning: Processing header size is greater than it is considered")
730 733
731 734 return 1
732 735
733 736 def write(self, fp):
734 737 # Clear DEFINE_PROCESS_CODE
735 738 self.processFlags = self.processFlags & (~PROCFLAG.DEFINE_PROCESS_CODE)
736 739
737 740 headerTuple = (self.size,
738 741 self.dtype,
739 742 self.blockSize,
740 743 self.profilesPerBlock,
741 744 self.dataBlocksPerFile,
742 745 self.nWindows,
743 746 self.processFlags,
744 747 self.nCohInt,
745 748 self.nIncohInt,
746 749 self.totalSpectra)
747 750
748 751 header = numpy.array(headerTuple, PROCESSING_STRUCTURE)
749 752 header.tofile(fp)
750 753
751 754 if self.nWindows != 0:
752 755 sampleWindowTuple = (
753 756 self.firstHeight, self.deltaHeight, self.samplesWin)
754 757 samplingWindow = numpy.array(sampleWindowTuple, SAMPLING_STRUCTURE)
755 758 samplingWindow.tofile(fp)
756 759
757 760 if self.totalSpectra != 0:
758 761 # spectraComb = numpy.array([],numpy.dtype('u1'))
759 762 spectraComb = self.spectraComb
760 763 spectraComb.tofile(fp)
761 764
762 765 # if self.processFlags & PROCFLAG.DEFINE_PROCESS_CODE == PROCFLAG.DEFINE_PROCESS_CODE:
763 766 # nCode = numpy.array([self.nCode], numpy.dtype('u4')) #Probar con un dato que almacene codigo, hasta el momento no se hizo la prueba
764 767 # nCode.tofile(fp)
765 768 #
766 769 # nBaud = numpy.array([self.nBaud], numpy.dtype('u4'))
767 770 # nBaud.tofile(fp)
768 771 #
769 772 # code = self.code.reshape(self.nCode*self.nBaud)
770 773 # code = code.astype(numpy.dtype('<f4'))
771 774 # code.tofile(fp)
772 775
773 776 return 1
774 777
775 778 def get_size(self):
776 779
777 780 self.__size = 40 + 12 * self.nWindows + 2 * self.totalSpectra
778 781
779 782 # if self.processFlags & PROCFLAG.DEFINE_PROCESS_CODE == PROCFLAG.DEFINE_PROCESS_CODE:
780 783 # self.__size += 4 + 4 + 4*self.nCode*numpy.ceil(self.nBaud/32.)
781 784 # self.__size += 4 + 4 + 4 * self.nCode * self.nBaud
782 785
783 786 return self.__size
784 787
785 788 def set_size(self, value):
786 789
787 790 raise IOError("size is a property and it cannot be set, just read")
788 791
789 792 return
790 793
791 794 size = property(get_size, set_size)
792 795
793 796
794 797 class RCfunction:
795 798 NONE = 0
796 799 FLIP = 1
797 800 CODE = 2
798 801 SAMPLING = 3
799 802 LIN6DIV256 = 4
800 803 SYNCHRO = 5
801 804
802 805
803 806 class nCodeType:
804 807 NONE = 0
805 808 USERDEFINE = 1
806 809 BARKER2 = 2
807 810 BARKER3 = 3
808 811 BARKER4 = 4
809 812 BARKER5 = 5
810 813 BARKER7 = 6
811 814 BARKER11 = 7
812 815 BARKER13 = 8
813 816 AC128 = 9
814 817 COMPLEMENTARYCODE2 = 10
815 818 COMPLEMENTARYCODE4 = 11
816 819 COMPLEMENTARYCODE8 = 12
817 820 COMPLEMENTARYCODE16 = 13
818 821 COMPLEMENTARYCODE32 = 14
819 822 COMPLEMENTARYCODE64 = 15
820 823 COMPLEMENTARYCODE128 = 16
821 824 CODE_BINARY28 = 17
822 825
823 826
824 827 class PROCFLAG:
825 828
826 829 COHERENT_INTEGRATION = numpy.uint32(0x00000001)
827 830 DECODE_DATA = numpy.uint32(0x00000002)
828 831 SPECTRA_CALC = numpy.uint32(0x00000004)
829 832 INCOHERENT_INTEGRATION = numpy.uint32(0x00000008)
830 833 POST_COHERENT_INTEGRATION = numpy.uint32(0x00000010)
831 834 SHIFT_FFT_DATA = numpy.uint32(0x00000020)
832 835
833 836 DATATYPE_CHAR = numpy.uint32(0x00000040)
834 837 DATATYPE_SHORT = numpy.uint32(0x00000080)
835 838 DATATYPE_LONG = numpy.uint32(0x00000100)
836 839 DATATYPE_INT64 = numpy.uint32(0x00000200)
837 840 DATATYPE_FLOAT = numpy.uint32(0x00000400)
838 841 DATATYPE_DOUBLE = numpy.uint32(0x00000800)
839 842
840 843 DATAARRANGE_CONTIGUOUS_CH = numpy.uint32(0x00001000)
841 844 DATAARRANGE_CONTIGUOUS_H = numpy.uint32(0x00002000)
842 845 DATAARRANGE_CONTIGUOUS_P = numpy.uint32(0x00004000)
843 846
844 847 SAVE_CHANNELS_DC = numpy.uint32(0x00008000)
845 848 DEFLIP_DATA = numpy.uint32(0x00010000)
846 849 DEFINE_PROCESS_CODE = numpy.uint32(0x00020000)
847 850
848 851 ACQ_SYS_NATALIA = numpy.uint32(0x00040000)
849 852 ACQ_SYS_ECHOTEK = numpy.uint32(0x00080000)
850 853 ACQ_SYS_ADRXD = numpy.uint32(0x000C0000)
851 854 ACQ_SYS_JULIA = numpy.uint32(0x00100000)
852 855 ACQ_SYS_XXXXXX = numpy.uint32(0x00140000)
853 856
854 857 EXP_NAME_ESP = numpy.uint32(0x00200000)
855 858 CHANNEL_NAMES_ESP = numpy.uint32(0x00400000)
856 859
857 860 OPERATION_MASK = numpy.uint32(0x0000003F)
858 861 DATATYPE_MASK = numpy.uint32(0x00000FC0)
859 862 DATAARRANGE_MASK = numpy.uint32(0x00007000)
860 863 ACQ_SYS_MASK = numpy.uint32(0x001C0000)
861 864
862 865
863 866 dtype0 = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
864 867 dtype1 = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
865 868 dtype2 = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
866 869 dtype3 = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
867 870 dtype4 = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
868 871 dtype5 = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
869 872
870 873 NUMPY_DTYPE_LIST = [dtype0, dtype1, dtype2, dtype3, dtype4, dtype5]
871 874
872 875 PROCFLAG_DTYPE_LIST = [PROCFLAG.DATATYPE_CHAR,
873 876 PROCFLAG.DATATYPE_SHORT,
874 877 PROCFLAG.DATATYPE_LONG,
875 878 PROCFLAG.DATATYPE_INT64,
876 879 PROCFLAG.DATATYPE_FLOAT,
877 880 PROCFLAG.DATATYPE_DOUBLE]
878 881
879 882 DTYPE_WIDTH = [1, 2, 4, 8, 4, 8]
880 883
881 884
882 885 def get_dtype_index(numpy_dtype):
883 886
884 887 index = None
885 888
886 889 for i in range(len(NUMPY_DTYPE_LIST)):
887 890 if numpy_dtype == NUMPY_DTYPE_LIST[i]:
888 891 index = i
889 892 break
890 893
891 894 return index
892 895
893 896
894 897 def get_numpy_dtype(index):
895 898
896 899 return NUMPY_DTYPE_LIST[index]
897 900
898 901
899 902 def get_procflag_dtype(index):
900 903
901 904 return PROCFLAG_DTYPE_LIST[index]
902 905
903 906
904 907 def get_dtype_width(index):
905 908
906 909 return DTYPE_WIDTH[index]
@@ -1,5 +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 from .jroplot_voltage_lags import *
@@ -1,693 +1,697
1 1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Base class to create plot operations
6 6
7 7 """
8 8
9 9 import os
10 10 import sys
11 11 import zmq
12 12 import time
13 13 import numpy
14 14 import datetime
15 15 from collections import deque
16 16 from functools import wraps
17 17 from threading import Thread
18 18 import matplotlib
19 19
20 20 if 'BACKEND' in os.environ:
21 21 matplotlib.use(os.environ['BACKEND'])
22 22 elif 'linux' in sys.platform:
23 23 matplotlib.use("TkAgg")
24 24 elif 'darwin' in sys.platform:
25 25 matplotlib.use('MacOSX')
26 26 else:
27 27 from schainpy.utils import log
28 28 log.warning('Using default Backend="Agg"', 'INFO')
29 29 matplotlib.use('Agg')
30 30
31 31 import matplotlib.pyplot as plt
32 32 from matplotlib.patches import Polygon
33 33 from mpl_toolkits.axes_grid1 import make_axes_locatable
34 34 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
35 35
36 36 from schainpy.model.data.jrodata import PlotterData
37 37 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
38 38 from schainpy.utils import log
39 39
40 40 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
41 41 blu_values = matplotlib.pyplot.get_cmap(
42 42 'seismic_r', 20)(numpy.arange(20))[10:15]
43 43 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
44 44 'jro', numpy.vstack((blu_values, jet_values)))
45 45 matplotlib.pyplot.register_cmap(cmap=ncmap)
46 46
47 47 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
48 48 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
49 49
50 50 EARTH_RADIUS = 6.3710e3
51 51
52 52 def ll2xy(lat1, lon1, lat2, lon2):
53 53
54 54 p = 0.017453292519943295
55 55 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
56 56 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
57 57 r = 12742 * numpy.arcsin(numpy.sqrt(a))
58 58 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
59 59 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
60 60 theta = -theta + numpy.pi/2
61 61 return r*numpy.cos(theta), r*numpy.sin(theta)
62 62
63 63
64 64 def km2deg(km):
65 65 '''
66 66 Convert distance in km to degrees
67 67 '''
68 68
69 69 return numpy.rad2deg(km/EARTH_RADIUS)
70 70
71 71
72 72 def figpause(interval):
73 73 backend = plt.rcParams['backend']
74 74 if backend in matplotlib.rcsetup.interactive_bk:
75 75 figManager = matplotlib._pylab_helpers.Gcf.get_active()
76 76 if figManager is not None:
77 77 canvas = figManager.canvas
78 78 if canvas.figure.stale:
79 79 canvas.draw()
80 80 try:
81 81 canvas.start_event_loop(interval)
82 82 except:
83 83 pass
84 84 return
85 85
86 86 def popup(message):
87 87 '''
88 88 '''
89 89
90 90 fig = plt.figure(figsize=(12, 8), facecolor='r')
91 91 text = '\n'.join([s.strip() for s in message.split(':')])
92 92 fig.text(0.01, 0.5, text, ha='left', va='center',
93 93 size='20', weight='heavy', color='w')
94 94 fig.show()
95 95 figpause(1000)
96 96
97 97
98 98 class Throttle(object):
99 99 '''
100 100 Decorator that prevents a function from being called more than once every
101 101 time period.
102 102 To create a function that cannot be called more than once a minute, but
103 103 will sleep until it can be called:
104 104 @Throttle(minutes=1)
105 105 def foo():
106 106 pass
107 107
108 108 for i in range(10):
109 109 foo()
110 110 print "This function has run %s times." % i
111 111 '''
112 112
113 113 def __init__(self, seconds=0, minutes=0, hours=0):
114 114 self.throttle_period = datetime.timedelta(
115 115 seconds=seconds, minutes=minutes, hours=hours
116 116 )
117 117
118 118 self.time_of_last_call = datetime.datetime.min
119 119
120 120 def __call__(self, fn):
121 121 @wraps(fn)
122 122 def wrapper(*args, **kwargs):
123 123 coerce = kwargs.pop('coerce', None)
124 124 if coerce:
125 125 self.time_of_last_call = datetime.datetime.now()
126 126 return fn(*args, **kwargs)
127 127 else:
128 128 now = datetime.datetime.now()
129 129 time_since_last_call = now - self.time_of_last_call
130 130 time_left = self.throttle_period - time_since_last_call
131 131
132 132 if time_left > datetime.timedelta(seconds=0):
133 133 return
134 134
135 135 self.time_of_last_call = datetime.datetime.now()
136 136 return fn(*args, **kwargs)
137 137
138 138 return wrapper
139 139
140 140 def apply_throttle(value):
141 141
142 142 @Throttle(seconds=value)
143 143 def fnThrottled(fn):
144 144 fn()
145 145
146 146 return fnThrottled
147 147
148 148
149 149 @MPDecorator
150 150 class Plot(Operation):
151 151 """Base class for Schain plotting operations
152 152
153 153 This class should never be use directtly you must subclass a new operation,
154 154 children classes must be defined as follow:
155 155
156 156 ExamplePlot(Plot):
157 157
158 158 CODE = 'code'
159 159 colormap = 'jet'
160 160 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
161 161
162 162 def setup(self):
163 163 pass
164 164
165 165 def plot(self):
166 166 pass
167 167
168 168 """
169 169
170 170 CODE = 'Figure'
171 171 colormap = 'jet'
172 172 bgcolor = 'white'
173 173 buffering = True
174 174 __missing = 1E30
175 175
176 176 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
177 177 'showprofile']
178 178
179 179 def __init__(self):
180 180
181 181 Operation.__init__(self)
182 182 self.isConfig = False
183 183 self.isPlotConfig = False
184 184 self.save_time = 0
185 185 self.sender_time = 0
186 186 self.data = None
187 187 self.firsttime = True
188 188 self.sender_queue = deque(maxlen=10)
189 189 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
190 190
191 191 def __fmtTime(self, x, pos):
192 192 '''
193 193 '''
194 194
195 195 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
196 196
197 197 def __setup(self, **kwargs):
198 198 '''
199 199 Initialize variables
200 200 '''
201 201
202 202 self.figures = []
203 203 self.axes = []
204 204 self.cb_axes = []
205 205 self.localtime = kwargs.pop('localtime', True)
206 206 self.show = kwargs.get('show', True)
207 207 self.save = kwargs.get('save', False)
208 208 self.save_period = kwargs.get('save_period', 0)
209 209 self.colormap = kwargs.get('colormap', self.colormap)
210 210 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
211 211 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
212 212 self.colormaps = kwargs.get('colormaps', None)
213 213 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
214 214 self.showprofile = kwargs.get('showprofile', False)
215 215 self.title = kwargs.get('wintitle', self.CODE.upper())
216 216 self.cb_label = kwargs.get('cb_label', None)
217 217 self.cb_labels = kwargs.get('cb_labels', None)
218 218 self.labels = kwargs.get('labels', None)
219 219 self.xaxis = kwargs.get('xaxis', 'frequency')
220 220 self.zmin = kwargs.get('zmin', None)
221 221 self.zmax = kwargs.get('zmax', None)
222 222 self.zlimits = kwargs.get('zlimits', None)
223 self.xlimits = kwargs.get('xlimits', None)
224 self.xstep_given = kwargs.get('xstep_given', None)
225 self.ystep_given = kwargs.get('ystep_given', None)
226 self.autoxticks = kwargs.get('autoxticks', True)
223 227 self.xmin = kwargs.get('xmin', None)
224 228 self.xmax = kwargs.get('xmax', None)
225 229 self.xrange = kwargs.get('xrange', 12)
226 230 self.xscale = kwargs.get('xscale', None)
227 231 self.ymin = kwargs.get('ymin', None)
228 232 self.ymax = kwargs.get('ymax', None)
229 233 self.yscale = kwargs.get('yscale', None)
230 234 self.xlabel = kwargs.get('xlabel', None)
231 235 self.attr_time = kwargs.get('attr_time', 'utctime')
232 236 self.attr_data = kwargs.get('attr_data', 'data_param')
233 237 self.decimation = kwargs.get('decimation', None)
234 238 self.oneFigure = kwargs.get('oneFigure', True)
235 239 self.width = kwargs.get('width', None)
236 240 self.height = kwargs.get('height', None)
237 241 self.colorbar = kwargs.get('colorbar', True)
238 242 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
239 243 self.channels = kwargs.get('channels', None)
240 244 self.titles = kwargs.get('titles', [])
241 245 self.polar = False
242 246 self.type = kwargs.get('type', 'iq')
243 247 self.grid = kwargs.get('grid', False)
244 248 self.pause = kwargs.get('pause', False)
245 249 self.save_code = kwargs.get('save_code', self.CODE)
246 250 self.throttle = kwargs.get('throttle', 0)
247 251 self.exp_code = kwargs.get('exp_code', None)
248 252 self.server = kwargs.get('server', False)
249 253 self.sender_period = kwargs.get('sender_period', 60)
250 254 self.tag = kwargs.get('tag', '')
251 255 self.height_index = kwargs.get('height_index', None)
252 256 self.__throttle_plot = apply_throttle(self.throttle)
253 257 code = self.attr_data if self.attr_data else self.CODE
254 258 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
255 259
256 260 if self.server:
257 261 if not self.server.startswith('tcp://'):
258 262 self.server = 'tcp://{}'.format(self.server)
259 263 log.success(
260 264 'Sending to server: {}'.format(self.server),
261 265 self.name
262 266 )
263 267
264 268 if isinstance(self.attr_data, str):
265 269 self.attr_data = [self.attr_data]
266 270
267 271 def __setup_plot(self):
268 272 '''
269 273 Common setup for all figures, here figures and axes are created
270 274 '''
271 275
272 276 self.setup()
273 277
274 278 self.time_label = 'LT' if self.localtime else 'UTC'
275 279
276 280 if self.width is None:
277 281 self.width = 8
278 282
279 283 self.figures = []
280 284 self.axes = []
281 285 self.cb_axes = []
282 286 self.pf_axes = []
283 287 self.cmaps = []
284 288
285 289 size = '15%' if self.ncols == 1 else '30%'
286 290 pad = '4%' if self.ncols == 1 else '8%'
287 291
288 292 if self.oneFigure:
289 293 if self.height is None:
290 294 self.height = 1.4 * self.nrows + 1
291 295 fig = plt.figure(figsize=(self.width, self.height),
292 296 edgecolor='k',
293 297 facecolor='w')
294 298 self.figures.append(fig)
295 299 for n in range(self.nplots):
296 300 ax = fig.add_subplot(self.nrows, self.ncols,
297 301 n + 1, polar=self.polar)
298 302 ax.tick_params(labelsize=8)
299 303 ax.firsttime = True
300 304 ax.index = 0
301 305 ax.press = None
302 306 self.axes.append(ax)
303 307 if self.showprofile:
304 308 cax = self.__add_axes(ax, size=size, pad=pad)
305 309 cax.tick_params(labelsize=8)
306 310 self.pf_axes.append(cax)
307 311 else:
308 312 if self.height is None:
309 313 self.height = 3
310 314 for n in range(self.nplots):
311 315 fig = plt.figure(figsize=(self.width, self.height),
312 316 edgecolor='k',
313 317 facecolor='w')
314 318 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
315 319 ax.tick_params(labelsize=8)
316 320 ax.firsttime = True
317 321 ax.index = 0
318 322 ax.press = None
319 323 self.figures.append(fig)
320 324 self.axes.append(ax)
321 325 if self.showprofile:
322 326 cax = self.__add_axes(ax, size=size, pad=pad)
323 327 cax.tick_params(labelsize=8)
324 328 self.pf_axes.append(cax)
325 329
326 330 for n in range(self.nrows):
327 331 if self.colormaps is not None:
328 332 cmap = plt.get_cmap(self.colormaps[n])
329 333 else:
330 334 cmap = plt.get_cmap(self.colormap)
331 335 cmap.set_bad(self.bgcolor, 1.)
332 336 self.cmaps.append(cmap)
333 337
334 338 def __add_axes(self, ax, size='30%', pad='8%'):
335 339 '''
336 340 Add new axes to the given figure
337 341 '''
338 342 divider = make_axes_locatable(ax)
339 343 nax = divider.new_horizontal(size=size, pad=pad)
340 344 ax.figure.add_axes(nax)
341 345 return nax
342 346
343 347 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
344 348 '''
345 349 Create a masked array for missing data
346 350 '''
347 351 if x_buffer.shape[0] < 2:
348 352 return x_buffer, y_buffer, z_buffer
349 353
350 354 deltas = x_buffer[1:] - x_buffer[0:-1]
351 355 x_median = numpy.median(deltas)
352 356
353 357 index = numpy.where(deltas > 5 * x_median)
354 358
355 359 if len(index[0]) != 0:
356 360 z_buffer[::, index[0], ::] = self.__missing
357 361 z_buffer = numpy.ma.masked_inside(z_buffer,
358 362 0.99 * self.__missing,
359 363 1.01 * self.__missing)
360 364
361 365 return x_buffer, y_buffer, z_buffer
362 366
363 367 def decimate(self):
364 368
365 369 # dx = int(len(self.x)/self.__MAXNUMX) + 1
366 370 dy = int(len(self.y) / self.decimation) + 1
367 371
368 372 # x = self.x[::dx]
369 373 x = self.x
370 374 y = self.y[::dy]
371 375 z = self.z[::, ::, ::dy]
372 376
373 377 return x, y, z
374 378
375 379 def format(self):
376 380 '''
377 381 Set min and max values, labels, ticks and titles
378 382 '''
379 383
380 384 for n, ax in enumerate(self.axes):
381 385 if ax.firsttime:
382 386 if self.xaxis != 'time':
383 387 xmin = self.xmin
384 388 xmax = self.xmax
385 389 else:
386 390 xmin = self.tmin
387 391 xmax = self.tmin + self.xrange*60*60
388 392 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
389 393 ax.xaxis.set_major_locator(LinearLocator(9))
390 394 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
391 395 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
392 396 ax.set_facecolor(self.bgcolor)
393 397 if self.xscale:
394 398 ax.xaxis.set_major_formatter(FuncFormatter(
395 399 lambda x, pos: '{0:g}'.format(x*self.xscale)))
396 400 if self.yscale:
397 401 ax.yaxis.set_major_formatter(FuncFormatter(
398 402 lambda x, pos: '{0:g}'.format(x*self.yscale)))
399 403 if self.xlabel is not None:
400 404 ax.set_xlabel(self.xlabel)
401 405 if self.ylabel is not None:
402 406 ax.set_ylabel(self.ylabel)
403 407 if self.showprofile:
404 408 self.pf_axes[n].set_ylim(ymin, ymax)
405 409 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
406 410 self.pf_axes[n].set_xlabel('dB')
407 411 self.pf_axes[n].grid(b=True, axis='x')
408 412 [tick.set_visible(False)
409 413 for tick in self.pf_axes[n].get_yticklabels()]
410 414 if self.colorbar:
411 415 ax.cbar = plt.colorbar(
412 416 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
413 417 ax.cbar.ax.tick_params(labelsize=8)
414 418 ax.cbar.ax.press = None
415 419 if self.cb_label:
416 420 ax.cbar.set_label(self.cb_label, size=8)
417 421 elif self.cb_labels:
418 422 ax.cbar.set_label(self.cb_labels[n], size=8)
419 423 else:
420 424 ax.cbar = None
421 425 ax.set_xlim(xmin, xmax)
422 426 ax.set_ylim(ymin, ymax)
423 427 ax.firsttime = False
424 428 if self.grid:
425 429 ax.grid(True)
426 430 if not self.polar:
427 431 ax.set_title('{} {} {}'.format(
428 432 self.titles[n],
429 433 self.getDateTime(self.data.max_time).strftime(
430 434 '%Y-%m-%d %H:%M:%S'),
431 435 self.time_label),
432 436 size=8)
433 437 else:
434 438 ax.set_title('{}'.format(self.titles[n]), size=8)
435 439 ax.set_ylim(0, 90)
436 440 ax.set_yticks(numpy.arange(0, 90, 20))
437 441 ax.yaxis.labelpad = 40
438 442
439 443 if self.firsttime:
440 444 for n, fig in enumerate(self.figures):
441 445 fig.subplots_adjust(**self.plots_adjust)
442 446 self.firsttime = False
443 447
444 448 def clear_figures(self):
445 449 '''
446 450 Reset axes for redraw plots
447 451 '''
448 452
449 453 for ax in self.axes+self.pf_axes+self.cb_axes:
450 454 ax.clear()
451 455 ax.firsttime = True
452 456 if hasattr(ax, 'cbar') and ax.cbar:
453 457 ax.cbar.remove()
454 458
455 459 def __plot(self):
456 460 '''
457 461 Main function to plot, format and save figures
458 462 '''
459 463
460 464 self.plot()
461 465 self.format()
462 466
463 467 for n, fig in enumerate(self.figures):
464 468 if self.nrows == 0 or self.nplots == 0:
465 469 log.warning('No data', self.name)
466 470 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
467 471 fig.canvas.manager.set_window_title(self.CODE)
468 472 continue
469 473
470 474 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
471 475 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
472 476 fig.canvas.draw()
473 477 if self.show:
474 478 fig.show()
475 479 figpause(0.01)
476 480
477 481 if self.save:
478 482 self.save_figure(n)
479 483
480 484 if self.server:
481 485 self.send_to_server()
482 486
483 487 def __update(self, dataOut, timestamp):
484 488 '''
485 489 '''
486 490
487 491 metadata = {
488 492 'yrange': dataOut.heightList,
489 493 'interval': dataOut.timeInterval,
490 494 'channels': dataOut.channelList
491 495 }
492 496
493 497 data, meta = self.update(dataOut)
494 498 metadata.update(meta)
495 499 self.data.update(data, timestamp, metadata)
496 500
497 501 def save_figure(self, n):
498 502 '''
499 503 '''
500 504
501 505 if (self.data.max_time - self.save_time) <= self.save_period:
502 506 return
503 507
504 508 self.save_time = self.data.max_time
505 509
506 510 fig = self.figures[n]
507 511
508 512 if self.throttle == 0:
509 513 figname = os.path.join(
510 514 self.save,
511 515 self.save_code,
512 516 '{}_{}.png'.format(
513 517 self.save_code,
514 518 self.getDateTime(self.data.max_time).strftime(
515 519 '%Y%m%d_%H%M%S'
516 520 ),
517 521 )
518 522 )
519 523 log.log('Saving figure: {}'.format(figname), self.name)
520 524 if not os.path.isdir(os.path.dirname(figname)):
521 525 os.makedirs(os.path.dirname(figname))
522 526 fig.savefig(figname)
523 527
524 528 figname = os.path.join(
525 529 self.save,
530 self.save_code,
526 531 '{}_{}.png'.format(
527 532 self.save_code,
528 533 self.getDateTime(self.data.min_time).strftime(
529 534 '%Y%m%d'
530 535 ),
531 536 )
532 537 )
533 538 log.log('Saving figure: {}'.format(figname), self.name)
534 539 if not os.path.isdir(os.path.dirname(figname)):
535 540 os.makedirs(os.path.dirname(figname))
536 541 fig.savefig(figname)
537 542
538 543 def send_to_server(self):
539 544 '''
540 545 '''
541 546
542 547 if self.exp_code == None:
543 548 log.warning('Missing `exp_code` skipping sending to server...')
544 549
545 550 last_time = self.data.max_time
546 551 interval = last_time - self.sender_time
547 552 if interval < self.sender_period:
548 553 return
549 554
550 555 self.sender_time = last_time
551 556
552 557 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
553 558 for attr in attrs:
554 559 value = getattr(self, attr)
555 560 if value:
556 561 if isinstance(value, (numpy.float32, numpy.float64)):
557 562 value = round(float(value), 2)
558 563 self.data.meta[attr] = value
559 564 if self.colormap == 'jet':
560 565 self.data.meta['colormap'] = 'Jet'
561 566 elif 'RdBu' in self.colormap:
562 567 self.data.meta['colormap'] = 'RdBu'
563 568 else:
564 569 self.data.meta['colormap'] = 'Viridis'
565 570 self.data.meta['interval'] = int(interval)
566 571
567 572 self.sender_queue.append(last_time)
568 573
569 574 while True:
570 575 try:
571 576 tm = self.sender_queue.popleft()
572 577 except IndexError:
573 578 break
574 579 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
575 580 self.socket.send_string(msg)
576 581 socks = dict(self.poll.poll(2000))
577 582 if socks.get(self.socket) == zmq.POLLIN:
578 583 reply = self.socket.recv_string()
579 584 if reply == 'ok':
580 585 log.log("Response from server ok", self.name)
581 586 time.sleep(0.1)
582 587 continue
583 588 else:
584 589 log.warning(
585 590 "Malformed reply from server: {}".format(reply), self.name)
586 591 else:
587 592 log.warning(
588 593 "No response from server, retrying...", self.name)
589 594 self.sender_queue.appendleft(tm)
590 595 self.socket.setsockopt(zmq.LINGER, 0)
591 596 self.socket.close()
592 597 self.poll.unregister(self.socket)
593 598 self.socket = self.context.socket(zmq.REQ)
594 599 self.socket.connect(self.server)
595 600 self.poll.register(self.socket, zmq.POLLIN)
596 601 break
597 602
598 603 def setup(self):
599 604 '''
600 605 This method should be implemented in the child class, the following
601 606 attributes should be set:
602 607
603 608 self.nrows: number of rows
604 609 self.ncols: number of cols
605 610 self.nplots: number of plots (channels or pairs)
606 611 self.ylabel: label for Y axes
607 612 self.titles: list of axes title
608 613
609 614 '''
610 615 raise NotImplementedError
611 616
612 617 def plot(self):
613 618 '''
614 619 Must be defined in the child class, the actual plotting method
615 620 '''
616 621 raise NotImplementedError
617 622
618 623 def update(self, dataOut):
619 624 '''
620 625 Must be defined in the child class, update self.data with new data
621 626 '''
622 627
623 628 data = {
624 629 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
625 630 }
626 631 meta = {}
627 632
628 633 return data, meta
629 634
630 635 def run(self, dataOut, **kwargs):
631 636 '''
632 637 Main plotting routine
633 638 '''
634 639
635 640 if self.isConfig is False:
636 641 self.__setup(**kwargs)
637 642
638 643 if self.localtime:
639 644 self.getDateTime = datetime.datetime.fromtimestamp
640 645 else:
641 646 self.getDateTime = datetime.datetime.utcfromtimestamp
642 647
643 648 self.data.setup()
644 649 self.isConfig = True
645 650 if self.server:
646 651 self.context = zmq.Context()
647 652 self.socket = self.context.socket(zmq.REQ)
648 653 self.socket.connect(self.server)
649 654 self.poll = zmq.Poller()
650 655 self.poll.register(self.socket, zmq.POLLIN)
651 656
652 657 tm = getattr(dataOut, self.attr_time)
653 658
654 659 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
655 660 self.save_time = tm
656 661 self.__plot()
657 662 self.tmin += self.xrange*60*60
658 663 self.data.setup()
659 664 self.clear_figures()
660 665
661 666 self.__update(dataOut, tm)
662 667
663 668 if self.isPlotConfig is False:
664 669 self.__setup_plot()
665 670 self.isPlotConfig = True
666 671 if self.xaxis == 'time':
667 672 dt = self.getDateTime(tm)
668 673 if self.xmin is None:
669 674 self.tmin = tm
670 675 self.xmin = dt.hour
671 676 minutes = (self.xmin-int(self.xmin)) * 60
672 677 seconds = (minutes - int(minutes)) * 60
673 678 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
674 679 datetime.datetime(1970, 1, 1)).total_seconds()
675 680 if self.localtime:
676 681 self.tmin += time.timezone
677 682
678 683 if self.xmin is not None and self.xmax is not None:
679 684 self.xrange = self.xmax - self.xmin
680 685
681 686 if self.throttle == 0:
682 687 self.__plot()
683 688 else:
684 689 self.__throttle_plot(self.__plot)#, coerce=coerce)
685 690
686 691 def close(self):
687 692
688 693 if self.data and not self.data.flagNoData:
689 694 self.save_time = 0
690 695 self.__plot()
691 696 if self.data and not self.data.flagNoData and self.pause:
692 697 figpause(10)
693
@@ -1,370 +1,381
1 1 import os
2 2 import datetime
3 3 import numpy
4 4
5 5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
7 7 from schainpy.utils import log
8 8
9 9 EARTH_RADIUS = 6.3710e3
10 10
11 11
12 12 def ll2xy(lat1, lon1, lat2, lon2):
13 13
14 14 p = 0.017453292519943295
15 15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
16 16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
17 17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
18 18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
19 19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
20 20 theta = -theta + numpy.pi/2
21 21 return r*numpy.cos(theta), r*numpy.sin(theta)
22 22
23 23
24 24 def km2deg(km):
25 25 '''
26 26 Convert distance in km to degrees
27 27 '''
28 28
29 29 return numpy.rad2deg(km/EARTH_RADIUS)
30 30
31 31
32 32
33 33 class SpectralMomentsPlot(SpectraPlot):
34 34 '''
35 35 Plot for Spectral Moments
36 36 '''
37 37 CODE = 'spc_moments'
38 38 # colormap = 'jet'
39 39 # plot_type = 'pcolor'
40 40
41 41 class DobleGaussianPlot(SpectraPlot):
42 42 '''
43 43 Plot for Double Gaussian Plot
44 44 '''
45 45 CODE = 'gaussian_fit'
46 46 # colormap = 'jet'
47 47 # plot_type = 'pcolor'
48 48
49
49 50 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
50 51 '''
51 52 Plot SpectraCut with Double Gaussian Fit
52 53 '''
53 54 CODE = 'cut_gaussian_fit'
54 55
56
57 class SpectralFitObliquePlot(SpectraPlot):
58 '''
59 Plot for Spectral Oblique
60 '''
61 CODE = 'spc_moments'
62 colormap = 'jet'
63 plot_type = 'pcolor'
64
65
66
55 67 class SnrPlot(RTIPlot):
56 68 '''
57 69 Plot for SNR Data
58 70 '''
59 71
60 72 CODE = 'snr'
61 73 colormap = 'jet'
62 74
63 75 def update(self, dataOut):
64 76
65 77 data = {
66 78 'snr': 10*numpy.log10(dataOut.data_snr)
67 79 }
68 80
69 81 return data, {}
70 82
71 83 class DopplerPlot(RTIPlot):
72 84 '''
73 85 Plot for DOPPLER Data (1st moment)
74 86 '''
75 87
76 88 CODE = 'dop'
77 89 colormap = 'jet'
78 90
79 91 def update(self, dataOut):
80 92
81 93 data = {
82 94 'dop': 10*numpy.log10(dataOut.data_dop)
83 95 }
84 96
85 97 return data, {}
86 98
87 99 class PowerPlot(RTIPlot):
88 100 '''
89 101 Plot for Power Data (0 moment)
90 102 '''
91 103
92 104 CODE = 'pow'
93 105 colormap = 'jet'
94 106
95 107 def update(self, dataOut):
96 108
97 109 data = {
98 110 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
99 111 }
100 112
101 113 return data, {}
102 114
103 115 class SpectralWidthPlot(RTIPlot):
104 116 '''
105 117 Plot for Spectral Width Data (2nd moment)
106 118 '''
107 119
108 120 CODE = 'width'
109 121 colormap = 'jet'
110 122
111 123 def update(self, dataOut):
112 124
113 125 data = {
114 126 'width': dataOut.data_width
115 127 }
116 128
117 129 return data, {}
118 130
119 131 class SkyMapPlot(Plot):
120 132 '''
121 133 Plot for meteors detection data
122 134 '''
123 135
124 136 CODE = 'param'
125 137
126 138 def setup(self):
127 139
128 140 self.ncols = 1
129 141 self.nrows = 1
130 142 self.width = 7.2
131 143 self.height = 7.2
132 144 self.nplots = 1
133 145 self.xlabel = 'Zonal Zenith Angle (deg)'
134 146 self.ylabel = 'Meridional Zenith Angle (deg)'
135 147 self.polar = True
136 148 self.ymin = -180
137 149 self.ymax = 180
138 150 self.colorbar = False
139 151
140 152 def plot(self):
141 153
142 154 arrayParameters = numpy.concatenate(self.data['param'])
143 155 error = arrayParameters[:, -1]
144 156 indValid = numpy.where(error == 0)[0]
145 157 finalMeteor = arrayParameters[indValid, :]
146 158 finalAzimuth = finalMeteor[:, 3]
147 159 finalZenith = finalMeteor[:, 4]
148 160
149 161 x = finalAzimuth * numpy.pi / 180
150 162 y = finalZenith
151 163
152 164 ax = self.axes[0]
153 165
154 166 if ax.firsttime:
155 167 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
156 168 else:
157 169 ax.plot.set_data(x, y)
158 170
159 171 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
160 172 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
161 173 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
162 174 dt2,
163 175 len(x))
164 176 self.titles[0] = title
165 177
166 178
167 179 class GenericRTIPlot(Plot):
168 180 '''
169 181 Plot for data_xxxx object
170 182 '''
171 183
172 184 CODE = 'param'
173 185 colormap = 'viridis'
174 186 plot_type = 'pcolorbuffer'
175 187
176 188 def setup(self):
177 189 self.xaxis = 'time'
178 190 self.ncols = 1
179 191 self.nrows = self.data.shape('param')[0]
180 192 self.nplots = self.nrows
181 193 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
182 194
183 195 if not self.xlabel:
184 196 self.xlabel = 'Time'
185 197
186 198 self.ylabel = 'Range [km]'
187 199 if not self.titles:
188 200 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
189 201
190 202 def update(self, dataOut):
191 203
192 204 data = {
193 205 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
194 206 }
195 207
196 208 meta = {}
197 209
198 210 return data, meta
199 211
200 212 def plot(self):
201 213 # self.data.normalize_heights()
202 214 self.x = self.data.times
203 215 self.y = self.data.yrange
204 216 self.z = self.data['param']
205 217
206 218 self.z = numpy.ma.masked_invalid(self.z)
207 219
208 220 if self.decimation is None:
209 221 x, y, z = self.fill_gaps(self.x, self.y, self.z)
210 222 else:
211 223 x, y, z = self.fill_gaps(*self.decimate())
212 224
213 225 for n, ax in enumerate(self.axes):
214 226
215 227 self.zmax = self.zmax if self.zmax is not None else numpy.max(
216 228 self.z[n])
217 229 self.zmin = self.zmin if self.zmin is not None else numpy.min(
218 230 self.z[n])
219 231
220 232 if ax.firsttime:
221 233 if self.zlimits is not None:
222 234 self.zmin, self.zmax = self.zlimits[n]
223 235
224 236 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
225 237 vmin=self.zmin,
226 238 vmax=self.zmax,
227 239 cmap=self.cmaps[n]
228 240 )
229 241 else:
230 242 if self.zlimits is not None:
231 243 self.zmin, self.zmax = self.zlimits[n]
232 244 ax.collections.remove(ax.collections[0])
233 245 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
234 246 vmin=self.zmin,
235 247 vmax=self.zmax,
236 248 cmap=self.cmaps[n]
237 249 )
238 250
239 251
240 252 class PolarMapPlot(Plot):
241 253 '''
242 254 Plot for weather radar
243 255 '''
244 256
245 257 CODE = 'param'
246 258 colormap = 'seismic'
247 259
248 260 def setup(self):
249 261 self.ncols = 1
250 262 self.nrows = 1
251 263 self.width = 9
252 264 self.height = 8
253 265 self.mode = self.data.meta['mode']
254 266 if self.channels is not None:
255 267 self.nplots = len(self.channels)
256 268 self.nrows = len(self.channels)
257 269 else:
258 270 self.nplots = self.data.shape(self.CODE)[0]
259 271 self.nrows = self.nplots
260 272 self.channels = list(range(self.nplots))
261 273 if self.mode == 'E':
262 274 self.xlabel = 'Longitude'
263 275 self.ylabel = 'Latitude'
264 276 else:
265 277 self.xlabel = 'Range (km)'
266 278 self.ylabel = 'Height (km)'
267 279 self.bgcolor = 'white'
268 280 self.cb_labels = self.data.meta['units']
269 281 self.lat = self.data.meta['latitude']
270 282 self.lon = self.data.meta['longitude']
271 283 self.xmin, self.xmax = float(
272 284 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
273 285 self.ymin, self.ymax = float(
274 286 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
275 287 # self.polar = True
276 288
277 289 def plot(self):
278 290
279 291 for n, ax in enumerate(self.axes):
280 292 data = self.data['param'][self.channels[n]]
281 293
282 294 zeniths = numpy.linspace(
283 295 0, self.data.meta['max_range'], data.shape[1])
284 296 if self.mode == 'E':
285 297 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
286 298 r, theta = numpy.meshgrid(zeniths, azimuths)
287 299 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
288 300 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
289 301 x = km2deg(x) + self.lon
290 302 y = km2deg(y) + self.lat
291 303 else:
292 304 azimuths = numpy.radians(self.data.yrange)
293 305 r, theta = numpy.meshgrid(zeniths, azimuths)
294 306 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
295 307 self.y = zeniths
296 308
297 309 if ax.firsttime:
298 310 if self.zlimits is not None:
299 311 self.zmin, self.zmax = self.zlimits[n]
300 312 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
301 313 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
302 314 vmin=self.zmin,
303 315 vmax=self.zmax,
304 316 cmap=self.cmaps[n])
305 317 else:
306 318 if self.zlimits is not None:
307 319 self.zmin, self.zmax = self.zlimits[n]
308 320 ax.collections.remove(ax.collections[0])
309 321 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
310 322 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
311 323 vmin=self.zmin,
312 324 vmax=self.zmax,
313 325 cmap=self.cmaps[n])
314 326
315 327 if self.mode == 'A':
316 328 continue
317 329
318 330 # plot district names
319 331 f = open('/data/workspace/schain_scripts/distrito.csv')
320 332 for line in f:
321 333 label, lon, lat = [s.strip() for s in line.split(',') if s]
322 334 lat = float(lat)
323 335 lon = float(lon)
324 336 # ax.plot(lon, lat, '.b', ms=2)
325 337 ax.text(lon, lat, label.decode('utf8'), ha='center',
326 338 va='bottom', size='8', color='black')
327 339
328 340 # plot limites
329 341 limites = []
330 342 tmp = []
331 343 for line in open('/data/workspace/schain_scripts/lima.csv'):
332 344 if '#' in line:
333 345 if tmp:
334 346 limites.append(tmp)
335 347 tmp = []
336 348 continue
337 349 values = line.strip().split(',')
338 350 tmp.append((float(values[0]), float(values[1])))
339 351 for points in limites:
340 352 ax.add_patch(
341 353 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
342 354
343 355 # plot Cuencas
344 356 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
345 357 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
346 358 values = [line.strip().split(',') for line in f]
347 359 points = [(float(s[0]), float(s[1])) for s in values]
348 360 ax.add_patch(Polygon(points, ec='b', fc='none'))
349 361
350 362 # plot grid
351 363 for r in (15, 30, 45, 60):
352 364 ax.add_artist(plt.Circle((self.lon, self.lat),
353 365 km2deg(r), color='0.6', fill=False, lw=0.2))
354 366 ax.text(
355 367 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
356 368 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
357 369 '{}km'.format(r),
358 370 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
359 371
360 372 if self.mode == 'E':
361 373 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
362 374 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
363 375 else:
364 376 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
365 377 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
366 378
367 379 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
368 380 self.titles = ['{} {}'.format(
369 381 self.data.parameters[x], title) for x in self.channels]
370
This diff has been collapsed as it changes many lines, (521 lines changed) Show them Hide them
@@ -1,743 +1,1254
1 1 # Copyright (c) 2012-2021 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Classes to plot Spectra data
6 6
7 7 """
8 8
9 9 import os
10 10 import numpy
11 11
12 12 from schainpy.model.graphics.jroplot_base import Plot, plt, log
13 13
14 14
15 15 class SpectraPlot(Plot):
16 16 '''
17 17 Plot for Spectra data
18 18 '''
19 19
20 20 CODE = 'spc'
21 21 colormap = 'jet'
22 22 plot_type = 'pcolor'
23 23 buffering = False
24 24
25 25 def setup(self):
26
26 27 self.nplots = len(self.data.channels)
27 28 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
28 29 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
29 30 self.height = 2.6 * self.nrows
30 31 self.cb_label = 'dB'
31 32 if self.showprofile:
32 33 self.width = 4 * self.ncols
33 34 else:
34 35 self.width = 3.5 * self.ncols
35 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
36 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
36 37 self.ylabel = 'Range [km]'
37 38
38 39 def update(self, dataOut):
39 40
40 41 data = {}
41 42 meta = {}
42 43 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
43 44 data['spc'] = spc
44 45 data['rti'] = dataOut.getPower()
45 46 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
46 47 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
47 48
48 49 if self.CODE == 'spc_moments':
49 50 data['moments'] = dataOut.moments
50 51 # data['spc'] = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
51 52 if self.CODE == 'gaussian_fit':
52 53 # data['moments'] = dataOut.moments
53 54 data['gaussfit'] = dataOut.DGauFitParams
54 55 # data['spc'] = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
55 56
56 57 return data, meta
57 58
58 59 def plot(self):
60
61 #print(self.xaxis)
62 #exit(1)
59 63 if self.xaxis == "frequency":
60 64 x = self.data.xrange[0]
61 65 self.xlabel = "Frequency (kHz)"
62 66 elif self.xaxis == "time":
63 67 x = self.data.xrange[1]
64 68 self.xlabel = "Time (ms)"
65 69 else:
66 70 x = self.data.xrange[2]
67 71 self.xlabel = "Velocity (m/s)"
68 72
69 73 if (self.CODE == 'spc_moments') | (self.CODE == 'gaussian_fit'):
70 74 x = self.data.xrange[2]
71 75 self.xlabel = "Velocity (m/s)"
72 76
73 77 self.titles = []
74 78
75 79 y = self.data.yrange
76 80 self.y = y
77 81
78 82 data = self.data[-1]
79 83 z = data['spc']
80 84
85 self.CODE2 = 'spc_oblique'
86
87
81 88 for n, ax in enumerate(self.axes):
82 89 noise = data['noise'][n]
83 90 if self.CODE == 'spc_moments':
84 91 mean = data['moments'][n, 1]
85 92 if self.CODE == 'gaussian_fit':
86 93 # mean = data['moments'][n, 1]
87 94 gau0 = data['gaussfit'][n][2,:,0]
88 95 gau1 = data['gaussfit'][n][2,:,1]
89 96 if ax.firsttime:
90 97 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
91 98 self.xmin = self.xmin if self.xmin else -self.xmax
92 99 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
93 100 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
101 #print(numpy.shape(x))
94 102 ax.plt = ax.pcolormesh(x, y, z[n].T,
95 103 vmin=self.zmin,
96 104 vmax=self.zmax,
97 105 cmap=plt.get_cmap(self.colormap)
98 106 )
99 107
100 108 if self.showprofile:
101 109 ax.plt_profile = self.pf_axes[n].plot(
102 110 data['rti'][n], y)[0]
103 111 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
104 112 color="k", linestyle="dashed", lw=1)[0]
105 113 if self.CODE == 'spc_moments':
106 114 ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
107 115 if self.CODE == 'gaussian_fit':
108 # ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
109 116 ax.plt_gau0 = ax.plot(gau0, y, color='r', lw=1)[0]
110 117 ax.plt_gau1 = ax.plot(gau1, y, color='y', lw=1)[0]
111 118 else:
112 119 ax.plt.set_array(z[n].T.ravel())
113 120 if self.showprofile:
114 121 ax.plt_profile.set_data(data['rti'][n], y)
115 122 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
116 123 if self.CODE == 'spc_moments':
117 124 ax.plt_mean.set_data(mean, y)
118 125 if self.CODE == 'gaussian_fit':
119 # ax.plt_mean.set_data(mean, y)
120 126 ax.plt_gau0.set_data(gau0, y)
121 127 ax.plt_gau1.set_data(gau1, y)
122 128 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
123 129
130 class SpectraObliquePlot(Plot):
131 '''
132 Plot for Spectra data
133 '''
134
135 CODE = 'spc'
136 colormap = 'jet'
137 plot_type = 'pcolor'
138
139 def setup(self):
140 self.xaxis = "oblique"
141 self.nplots = len(self.data.channels)
142 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
143 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
144 self.height = 2.6 * self.nrows
145 self.cb_label = 'dB'
146 if self.showprofile:
147 self.width = 4 * self.ncols
148 else:
149 self.width = 3.5 * self.ncols
150 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
151 self.ylabel = 'Range [km]'
152
153 def plot(self):
154
155 #print(self.xaxis)
156 #exit(1)
157 if self.xaxis == "frequency":
158 x = self.data.xrange[0]
159 self.xlabel = "Frequency (kHz)"
160 elif self.xaxis == "time":
161 x = self.data.xrange[1]
162 self.xlabel = "Time (ms)"
163 else:
164 x = self.data.xrange[2]
165 self.xlabel = "Velocity (m/s)"
166
167 if self.CODE == 'spc_moments':
168 x = self.data.xrange[2]
169 self.xlabel = "Velocity (m/s)"
170
171 self.titles = []
172 #self.xlabel = "Velocidad (m/s)"
173 #self.ylabel = 'Rango (km)'
174
175
176 y = self.data.heights
177 self.y = y
178 z = self.data['spc']
179
180 self.CODE2 = 'spc_oblique'
181
182
183 for n, ax in enumerate(self.axes):
184 noise = self.data['noise'][n][-1]
185 if self.CODE == 'spc_moments':
186 mean = self.data['moments'][n, :, 1, :][-1]
187 if self.CODE2 == 'spc_oblique':
188 shift1 = self.data.shift1
189 shift2 = self.data.shift2
190 if ax.firsttime:
191 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
192 self.xmin = self.xmin if self.xmin else -self.xmax
193 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
194 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
195 #print(numpy.shape(x))
196 ax.plt = ax.pcolormesh(x, y, z[n].T,
197 vmin=self.zmin,
198 vmax=self.zmax,
199 cmap=plt.get_cmap(self.colormap)
200 )
201
202 if self.showprofile:
203 ax.plt_profile = self.pf_axes[n].plot(
204 self.data['rti'][n][-1], y)[0]
205 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
206 color="k", linestyle="dashed", lw=1)[0]
207 if self.CODE == 'spc_moments':
208 ax.plt_mean = ax.plot(mean, y, color='k')[0]
209
210 if self.CODE2 == 'spc_oblique':
211 #ax.plt_shift1 = ax.plot(shift1, y, color='k', marker='x', linestyle='None', markersize=0.5)[0]
212 #ax.plt_shift2 = ax.plot(shift2, y, color='m', marker='x', linestyle='None', markersize=0.5)[0]
213 self.ploterr1 = ax.errorbar(shift1, y, xerr=self.data.shift1_error,fmt='k^',elinewidth=0.2,marker='x',linestyle='None',markersize=0.5,capsize=0.3,markeredgewidth=0.2)
214 self.ploterr2 = ax.errorbar(shift2, y, xerr=self.data.shift2_error,fmt='m^',elinewidth=0.2,marker='x',linestyle='None',markersize=0.5,capsize=0.3,markeredgewidth=0.2)
215
216 else:
217 self.ploterr1.remove()
218 self.ploterr2.remove()
219 ax.plt.set_array(z[n].T.ravel())
220 if self.showprofile:
221 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
222 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
223 if self.CODE == 'spc_moments':
224 ax.plt_mean.set_data(mean, y)
225 if self.CODE2 == 'spc_oblique':
226 #ax.plt_shift1.set_data(shift1, y)
227 #ax.plt_shift2.set_data(shift2, y)
228 #ax.clf()
229 self.ploterr1 = ax.errorbar(shift1, y, xerr=self.data.shift1_error,fmt='k^',elinewidth=0.2,marker='x',linestyle='None',markersize=0.5,capsize=0.3,markeredgewidth=0.2)
230 self.ploterr2 = ax.errorbar(shift2, y, xerr=self.data.shift2_error,fmt='m^',elinewidth=0.2,marker='x',linestyle='None',markersize=0.5,capsize=0.3,markeredgewidth=0.2)
231
232 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
233 #self.titles.append('{}'.format('Velocidad Doppler'))
124 234
125 235 class CrossSpectraPlot(Plot):
126 236
127 237 CODE = 'cspc'
128 238 colormap = 'jet'
129 239 plot_type = 'pcolor'
130 240 zmin_coh = None
131 241 zmax_coh = None
132 242 zmin_phase = None
133 243 zmax_phase = None
134 244
135 245 def setup(self):
136 246
137 247 self.ncols = 4
138 248 self.nplots = len(self.data.pairs) * 2
139 249 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
140 250 self.width = 3.1 * self.ncols
141 self.height = 2.6 * self.nrows
251 self.height = 5 * self.nrows
142 252 self.ylabel = 'Range [km]'
143 253 self.showprofile = False
144 254 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
145 255
146 256 def update(self, dataOut):
147 257
148 258 data = {}
149 259 meta = {}
150 260
151 261 spc = dataOut.data_spc
152 262 cspc = dataOut.data_cspc
153 263 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
154 264 meta['pairs'] = dataOut.pairsList
155 265
156 266 tmp = []
157 267
158 268 for n, pair in enumerate(meta['pairs']):
159 269 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
160 270 coh = numpy.abs(out)
161 271 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
162 272 tmp.append(coh)
163 273 tmp.append(phase)
164 274
165 275 data['cspc'] = numpy.array(tmp)
166 276
167 277 return data, meta
168 278
169 279 def plot(self):
170 280
171 281 if self.xaxis == "frequency":
172 282 x = self.data.xrange[0]
173 283 self.xlabel = "Frequency (kHz)"
174 284 elif self.xaxis == "time":
175 285 x = self.data.xrange[1]
176 286 self.xlabel = "Time (ms)"
177 287 else:
178 288 x = self.data.xrange[2]
179 289 self.xlabel = "Velocity (m/s)"
180 290
181 291 self.titles = []
182 292
183 293 y = self.data.yrange
184 294 self.y = y
185 295
186 296 data = self.data[-1]
187 297 cspc = data['cspc']
188 298
189 299 for n in range(len(self.data.pairs)):
190 300 pair = self.data.pairs[n]
191 301 coh = cspc[n*2]
192 302 phase = cspc[n*2+1]
193 303 ax = self.axes[2 * n]
194 304 if ax.firsttime:
195 305 ax.plt = ax.pcolormesh(x, y, coh.T,
196 306 vmin=0,
197 307 vmax=1,
198 308 cmap=plt.get_cmap(self.colormap_coh)
199 309 )
200 310 else:
201 311 ax.plt.set_array(coh.T.ravel())
202 312 self.titles.append(
203 313 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
204 314
205 315 ax = self.axes[2 * n + 1]
206 316 if ax.firsttime:
207 317 ax.plt = ax.pcolormesh(x, y, phase.T,
208 318 vmin=-180,
209 319 vmax=180,
210 320 cmap=plt.get_cmap(self.colormap_phase)
211 321 )
212 322 else:
213 323 ax.plt.set_array(phase.T.ravel())
214 324 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
215 325
216 326
327 class CrossSpectra4Plot(Plot):
328
329 CODE = 'cspc'
330 colormap = 'jet'
331 plot_type = 'pcolor'
332 zmin_coh = None
333 zmax_coh = None
334 zmin_phase = None
335 zmax_phase = None
336
337 def setup(self):
338
339 self.ncols = 4
340 self.nrows = len(self.data.pairs)
341 self.nplots = self.nrows * 4
342 self.width = 3.1 * self.ncols
343 self.height = 5 * self.nrows
344 self.ylabel = 'Range [km]'
345 self.showprofile = False
346 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
347
348 def plot(self):
349
350 if self.xaxis == "frequency":
351 x = self.data.xrange[0]
352 self.xlabel = "Frequency (kHz)"
353 elif self.xaxis == "time":
354 x = self.data.xrange[1]
355 self.xlabel = "Time (ms)"
356 else:
357 x = self.data.xrange[2]
358 self.xlabel = "Velocity (m/s)"
359
360 self.titles = []
361
362
363 y = self.data.heights
364 self.y = y
365 nspc = self.data['spc']
366 #print(numpy.shape(self.data['spc']))
367 spc = self.data['cspc'][0]
368 #print(numpy.shape(nspc))
369 #exit()
370 #nspc[1,:,:] = numpy.flip(nspc[1,:,:],axis=0)
371 #print(numpy.shape(spc))
372 #exit()
373 cspc = self.data['cspc'][1]
374
375 #xflip=numpy.flip(x)
376 #print(numpy.shape(cspc))
377 #exit()
378
379 for n in range(self.nrows):
380 noise = self.data['noise'][:,-1]
381 pair = self.data.pairs[n]
382 #print(pair)
383 #exit()
384 ax = self.axes[4 * n]
385 if ax.firsttime:
386 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
387 self.xmin = self.xmin if self.xmin else -self.xmax
388 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
389 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
390 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
391 vmin=self.zmin,
392 vmax=self.zmax,
393 cmap=plt.get_cmap(self.colormap)
394 )
395 else:
396 #print(numpy.shape(nspc[pair[0]].T))
397 #exit()
398 ax.plt.set_array(nspc[pair[0]].T.ravel())
399 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
400
401 ax = self.axes[4 * n + 1]
402
403 if ax.firsttime:
404 ax.plt = ax.pcolormesh(x , y, numpy.flip(nspc[pair[1]],axis=0).T,
405 vmin=self.zmin,
406 vmax=self.zmax,
407 cmap=plt.get_cmap(self.colormap)
408 )
409 else:
410
411 ax.plt.set_array(numpy.flip(nspc[pair[1]],axis=0).T.ravel())
412 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
413
414 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
415 coh = numpy.abs(out)
416 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
417
418 ax = self.axes[4 * n + 2]
419 if ax.firsttime:
420 ax.plt = ax.pcolormesh(x, y, numpy.flip(coh,axis=0).T,
421 vmin=0,
422 vmax=1,
423 cmap=plt.get_cmap(self.colormap_coh)
424 )
425 else:
426 ax.plt.set_array(numpy.flip(coh,axis=0).T.ravel())
427 self.titles.append(
428 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
429
430 ax = self.axes[4 * n + 3]
431 if ax.firsttime:
432 ax.plt = ax.pcolormesh(x, y, numpy.flip(phase,axis=0).T,
433 vmin=-180,
434 vmax=180,
435 cmap=plt.get_cmap(self.colormap_phase)
436 )
437 else:
438 ax.plt.set_array(numpy.flip(phase,axis=0).T.ravel())
439 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
440
441
442 class CrossSpectra2Plot(Plot):
443
444 CODE = 'cspc'
445 colormap = 'jet'
446 plot_type = 'pcolor'
447 zmin_coh = None
448 zmax_coh = None
449 zmin_phase = None
450 zmax_phase = None
451
452 def setup(self):
453
454 self.ncols = 1
455 self.nrows = len(self.data.pairs)
456 self.nplots = self.nrows * 1
457 self.width = 3.1 * self.ncols
458 self.height = 5 * self.nrows
459 self.ylabel = 'Range [km]'
460 self.showprofile = False
461 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
462
463 def plot(self):
464
465 if self.xaxis == "frequency":
466 x = self.data.xrange[0]
467 self.xlabel = "Frequency (kHz)"
468 elif self.xaxis == "time":
469 x = self.data.xrange[1]
470 self.xlabel = "Time (ms)"
471 else:
472 x = self.data.xrange[2]
473 self.xlabel = "Velocity (m/s)"
474
475 self.titles = []
476
477
478 y = self.data.heights
479 self.y = y
480 #nspc = self.data['spc']
481 #print(numpy.shape(self.data['spc']))
482 #spc = self.data['cspc'][0]
483 #print(numpy.shape(spc))
484 #exit()
485 cspc = self.data['cspc'][1]
486 #print(numpy.shape(cspc))
487 #exit()
488
489 for n in range(self.nrows):
490 noise = self.data['noise'][:,-1]
491 pair = self.data.pairs[n]
492 #print(pair) #exit()
493
494
495
496 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
497
498 #print(out[:,53])
499 #exit()
500 cross = numpy.abs(out)
501 z = cross/self.data.nFactor
502 #print("here")
503 #print(dataOut.data_spc[0,0,0])
504 #exit()
505
506 cross = 10*numpy.log10(z)
507 #print(numpy.shape(cross))
508 #print(cross[0,:])
509 #print(self.data.nFactor)
510 #exit()
511 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
512
513 ax = self.axes[1 * n]
514 if ax.firsttime:
515 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
516 self.xmin = self.xmin if self.xmin else -self.xmax
517 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
518 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
519 ax.plt = ax.pcolormesh(x, y, cross.T,
520 vmin=self.zmin,
521 vmax=self.zmax,
522 cmap=plt.get_cmap(self.colormap)
523 )
524 else:
525 ax.plt.set_array(cross.T.ravel())
526 self.titles.append(
527 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
528
529
530 class CrossSpectra3Plot(Plot):
531
532 CODE = 'cspc'
533 colormap = 'jet'
534 plot_type = 'pcolor'
535 zmin_coh = None
536 zmax_coh = None
537 zmin_phase = None
538 zmax_phase = None
539
540 def setup(self):
541
542 self.ncols = 3
543 self.nrows = len(self.data.pairs)
544 self.nplots = self.nrows * 3
545 self.width = 3.1 * self.ncols
546 self.height = 5 * self.nrows
547 self.ylabel = 'Range [km]'
548 self.showprofile = False
549 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
550
551 def plot(self):
552
553 if self.xaxis == "frequency":
554 x = self.data.xrange[0]
555 self.xlabel = "Frequency (kHz)"
556 elif self.xaxis == "time":
557 x = self.data.xrange[1]
558 self.xlabel = "Time (ms)"
559 else:
560 x = self.data.xrange[2]
561 self.xlabel = "Velocity (m/s)"
562
563 self.titles = []
564
565
566 y = self.data.heights
567 self.y = y
568 #nspc = self.data['spc']
569 #print(numpy.shape(self.data['spc']))
570 #spc = self.data['cspc'][0]
571 #print(numpy.shape(spc))
572 #exit()
573 cspc = self.data['cspc'][1]
574 #print(numpy.shape(cspc))
575 #exit()
576
577 for n in range(self.nrows):
578 noise = self.data['noise'][:,-1]
579 pair = self.data.pairs[n]
580 #print(pair) #exit()
581
582
583
584 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
585
586 #print(out[:,53])
587 #exit()
588 cross = numpy.abs(out)
589 z = cross/self.data.nFactor
590 cross = 10*numpy.log10(z)
591
592 out_r= out.real/self.data.nFactor
593 #out_r = 10*numpy.log10(out_r)
594
595 out_i= out.imag/self.data.nFactor
596 #out_i = 10*numpy.log10(out_i)
597 #print(numpy.shape(cross))
598 #print(cross[0,:])
599 #print(self.data.nFactor)
600 #exit()
601 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
602
603 ax = self.axes[3 * n]
604 if ax.firsttime:
605 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
606 self.xmin = self.xmin if self.xmin else -self.xmax
607 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
608 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
609 ax.plt = ax.pcolormesh(x, y, cross.T,
610 vmin=self.zmin,
611 vmax=self.zmax,
612 cmap=plt.get_cmap(self.colormap)
613 )
614 else:
615 ax.plt.set_array(cross.T.ravel())
616 self.titles.append(
617 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
618
619 ax = self.axes[3 * n + 1]
620 if ax.firsttime:
621 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
622 self.xmin = self.xmin if self.xmin else -self.xmax
623 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
624 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
625 ax.plt = ax.pcolormesh(x, y, out_r.T,
626 vmin=-1.e6,
627 vmax=0,
628 cmap=plt.get_cmap(self.colormap)
629 )
630 else:
631 ax.plt.set_array(out_r.T.ravel())
632 self.titles.append(
633 'Cross Spectra Real Ch{} * Ch{}'.format(pair[0], pair[1]))
634
635 ax = self.axes[3 * n + 2]
636
637
638 if ax.firsttime:
639 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
640 self.xmin = self.xmin if self.xmin else -self.xmax
641 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
642 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
643 ax.plt = ax.pcolormesh(x, y, out_i.T,
644 vmin=-1.e6,
645 vmax=1.e6,
646 cmap=plt.get_cmap(self.colormap)
647 )
648 else:
649 ax.plt.set_array(out_i.T.ravel())
650 self.titles.append(
651 'Cross Spectra Imag Ch{} * Ch{}'.format(pair[0], pair[1]))
652
217 653 class RTIPlot(Plot):
218 654 '''
219 655 Plot for RTI data
220 656 '''
221 657
222 658 CODE = 'rti'
223 659 colormap = 'jet'
224 660 plot_type = 'pcolorbuffer'
225 661
226 662 def setup(self):
227 663 self.xaxis = 'time'
228 664 self.ncols = 1
229 665 self.nrows = len(self.data.channels)
230 666 self.nplots = len(self.data.channels)
231 667 self.ylabel = 'Range [km]'
232 668 self.xlabel = 'Time'
233 669 self.cb_label = 'dB'
234 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
670 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
235 671 self.titles = ['{} Channel {}'.format(
236 672 self.CODE.upper(), x) for x in range(self.nrows)]
237 673
238 674 def update(self, dataOut):
239 675
240 676 data = {}
241 677 meta = {}
242 678 data['rti'] = dataOut.getPower()
243 679 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
244 680
245 681 return data, meta
246 682
247 683 def plot(self):
248 684 self.x = self.data.times
249 685 self.y = self.data.yrange
250 686 self.z = self.data[self.CODE]
687
688 self.z = numpy.ma.masked_invalid(self.z)
689
690 if self.decimation is None:
691 x, y, z = self.fill_gaps(self.x, self.y, self.z)
692 else:
693 x, y, z = self.fill_gaps(*self.decimate())
694
695 for n, ax in enumerate(self.axes):
696 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
697 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
698 if ax.firsttime:
699 ax.plt = ax.pcolormesh(x, y, z[n].T,
700 vmin=self.zmin,
701 vmax=self.zmax,
702 cmap=plt.get_cmap(self.colormap)
703 )
704 if self.showprofile:
705 ax.plot_profile = self.pf_axes[n].plot(
706 self.data['rti'][n][-1], self.y)[0]
707 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
708 color="k", linestyle="dashed", lw=1)[0]
709 else:
710 ax.collections.remove(ax.collections[0])
711 ax.plt = ax.pcolormesh(x, y, z[n].T,
712 vmin=self.zmin,
713 vmax=self.zmax,
714 cmap=plt.get_cmap(self.colormap)
715 )
716 if self.showprofile:
717 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
718 ax.plot_noise.set_data(numpy.repeat(
719 self.data['noise'][n][-1], len(self.y)), self.y)
720
721
722 class SpectrogramPlot(Plot):
723 '''
724 Plot for Spectrogram data
725 '''
726
727 CODE = 'spectrogram'
728 colormap = 'binary'
729 plot_type = 'pcolorbuffer'
730
731 def setup(self):
732 self.xaxis = 'time'
733 self.ncols = 1
734 self.nrows = len(self.data.channels)
735 self.nplots = len(self.data.channels)
736 #print(self.dataOut.heightList)
737 #self.ylabel = 'Range [km]'
738 self.xlabel = 'Time'
739 self.cb_label = 'dB'
740 self.plots_adjust.update({'hspace':1.2, 'left': 0.1, 'bottom': 0.12, 'right':0.95})
741 self.titles = ['{} Channel {} \n H = {} km ({} - {})'.format(
742 self.CODE.upper(), x, self.data.heightList[self.data.hei], self.data.heightList[self.data.hei],self.data.heightList[self.data.hei]+(self.data.DH*self.data.nProfiles)) for x in range(self.nrows)]
743
744 def plot(self):
745 self.x = self.data.times
746 #self.y = self.data.heights
747 self.z = self.data[self.CODE]
748 self.y = self.data.xrange[0]
749 #import time
750 #print(time.ctime(self.x))
751
752 '''
753 print(numpy.shape(self.x))
754 print(numpy.shape(self.y))
755 print(numpy.shape(self.z))
756 '''
757 self.ylabel = "Frequency (kHz)"
758
251 759 self.z = numpy.ma.masked_invalid(self.z)
252 760
253 761 if self.decimation is None:
254 762 x, y, z = self.fill_gaps(self.x, self.y, self.z)
255 763 else:
256 764 x, y, z = self.fill_gaps(*self.decimate())
257 765
258 766 for n, ax in enumerate(self.axes):
259 767 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
260 768 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
261 769 data = self.data[-1]
262 770 if ax.firsttime:
263 771 ax.plt = ax.pcolormesh(x, y, z[n].T,
264 772 vmin=self.zmin,
265 773 vmax=self.zmax,
266 774 cmap=plt.get_cmap(self.colormap)
267 775 )
268 776 if self.showprofile:
269 777 ax.plot_profile = self.pf_axes[n].plot(
270 778 data['rti'][n], self.y)[0]
271 779 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
272 780 color="k", linestyle="dashed", lw=1)[0]
273 781 else:
274 782 ax.collections.remove(ax.collections[0])
275 783 ax.plt = ax.pcolormesh(x, y, z[n].T,
276 784 vmin=self.zmin,
277 785 vmax=self.zmax,
278 786 cmap=plt.get_cmap(self.colormap)
279 787 )
280 788 if self.showprofile:
281 789 ax.plot_profile.set_data(data['rti'][n], self.y)
282 790 ax.plot_noise.set_data(numpy.repeat(
283 791 data['noise'][n], len(self.y)), self.y)
284 792
285 793
286 794 class CoherencePlot(RTIPlot):
287 795 '''
288 796 Plot for Coherence data
289 797 '''
290 798
291 799 CODE = 'coh'
292 800
293 801 def setup(self):
294 802 self.xaxis = 'time'
295 803 self.ncols = 1
296 804 self.nrows = len(self.data.pairs)
297 805 self.nplots = len(self.data.pairs)
298 806 self.ylabel = 'Range [km]'
299 807 self.xlabel = 'Time'
300 808 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
301 809 if self.CODE == 'coh':
302 810 self.cb_label = ''
303 811 self.titles = [
304 812 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
305 813 else:
306 814 self.cb_label = 'Degrees'
307 815 self.titles = [
308 816 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
309 817
310 818 def update(self, dataOut):
311 819
312 820 data = {}
313 821 meta = {}
314 822 data['coh'] = dataOut.getCoherence()
315 823 meta['pairs'] = dataOut.pairsList
316 824
317 825 return data, meta
318 826
319 827 class PhasePlot(CoherencePlot):
320 828 '''
321 829 Plot for Phase map data
322 830 '''
323 831
324 832 CODE = 'phase'
325 833 colormap = 'seismic'
326 834
327 835 def update(self, dataOut):
328 836
329 837 data = {}
330 838 meta = {}
331 839 data['phase'] = dataOut.getCoherence(phase=True)
332 840 meta['pairs'] = dataOut.pairsList
333 841
334 842 return data, meta
335 843
336 844 class NoisePlot(Plot):
337 845 '''
338 846 Plot for noise
339 847 '''
340 848
341 849 CODE = 'noise'
342 850 plot_type = 'scatterbuffer'
343 851
344 852 def setup(self):
345 853 self.xaxis = 'time'
346 854 self.ncols = 1
347 855 self.nrows = 1
348 856 self.nplots = 1
349 857 self.ylabel = 'Intensity [dB]'
350 858 self.xlabel = 'Time'
351 859 self.titles = ['Noise']
352 860 self.colorbar = False
353 861 self.plots_adjust.update({'right': 0.85 })
354 862
355 863 def update(self, dataOut):
356 864
357 865 data = {}
358 866 meta = {}
359 867 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
360 868 meta['yrange'] = numpy.array([])
361 869
362 870 return data, meta
363 871
364 872 def plot(self):
365 873
366 874 x = self.data.times
367 875 xmin = self.data.min_time
368 876 xmax = xmin + self.xrange * 60 * 60
369 877 Y = self.data['noise']
370 878
371 879 if self.axes[0].firsttime:
372 880 self.ymin = numpy.nanmin(Y) - 5
373 881 self.ymax = numpy.nanmax(Y) + 5
374 882 for ch in self.data.channels:
375 883 y = Y[ch]
376 884 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
377 885 plt.legend(bbox_to_anchor=(1.18, 1.0))
378 886 else:
379 887 for ch in self.data.channels:
380 888 y = Y[ch]
381 889 self.axes[0].lines[ch].set_data(x, y)
382 890
891 self.ymin = numpy.nanmin(Y) - 5
892 self.ymax = numpy.nanmax(Y) + 10
893
383 894
384 895 class PowerProfilePlot(Plot):
385 896
386 897 CODE = 'pow_profile'
387 898 plot_type = 'scatter'
388 899
389 900 def setup(self):
390 901
391 902 self.ncols = 1
392 903 self.nrows = 1
393 904 self.nplots = 1
394 905 self.height = 4
395 906 self.width = 3
396 907 self.ylabel = 'Range [km]'
397 908 self.xlabel = 'Intensity [dB]'
398 909 self.titles = ['Power Profile']
399 910 self.colorbar = False
400 911
401 912 def update(self, dataOut):
402 913
403 914 data = {}
404 915 meta = {}
405 916 data[self.CODE] = dataOut.getPower()
406 917
407 918 return data, meta
408 919
409 920 def plot(self):
410 921
411 922 y = self.data.yrange
412 923 self.y = y
413 924
414 925 x = self.data[-1][self.CODE]
415 926
416 927 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
417 928 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
418 929
419 930 if self.axes[0].firsttime:
420 931 for ch in self.data.channels:
421 932 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
422 933 plt.legend()
423 934 else:
424 935 for ch in self.data.channels:
425 936 self.axes[0].lines[ch].set_data(x[ch], y)
426 937
427 938
428 939 class SpectraCutPlot(Plot):
429 940
430 941 CODE = 'spc_cut'
431 942 plot_type = 'scatter'
432 943 buffering = False
433 944
434 945 def setup(self):
435 946
436 947 self.nplots = len(self.data.channels)
437 948 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
438 949 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
439 950 self.width = 3.4 * self.ncols + 1.5
440 951 self.height = 3 * self.nrows
441 952 self.ylabel = 'Power [dB]'
442 953 self.colorbar = False
443 954 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
444 955
445 956 def update(self, dataOut):
446 957
447 958 data = {}
448 959 meta = {}
449 960 spc = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
450 961 data['spc'] = spc
451 962 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
452 963 if self.CODE == 'cut_gaussian_fit':
453 964 data['gauss_fit0'] = 10*numpy.log10(dataOut.GaussFit0/dataOut.normFactor)
454 965 data['gauss_fit1'] = 10*numpy.log10(dataOut.GaussFit1/dataOut.normFactor)
455 966 return data, meta
456 967
457 968 def plot(self):
458 969 if self.xaxis == "frequency":
459 970 x = self.data.xrange[0][1:]
460 971 self.xlabel = "Frequency (kHz)"
461 972 elif self.xaxis == "time":
462 973 x = self.data.xrange[1]
463 974 self.xlabel = "Time (ms)"
464 975 else:
465 976 x = self.data.xrange[2][:-1]
466 977 self.xlabel = "Velocity (m/s)"
467 978
468 979 if self.CODE == 'cut_gaussian_fit':
469 980 x = self.data.xrange[2][:-1]
470 981 self.xlabel = "Velocity (m/s)"
471 982
472 983 self.titles = []
473 984
474 985 y = self.data.yrange
475 986 data = self.data[-1]
476 987 z = data['spc']
477 988
478 989 if self.height_index:
479 990 index = numpy.array(self.height_index)
480 991 else:
481 992 index = numpy.arange(0, len(y), int((len(y))/9))
482 993
483 994 for n, ax in enumerate(self.axes):
484 995 if self.CODE == 'cut_gaussian_fit':
485 996 gau0 = data['gauss_fit0']
486 997 gau1 = data['gauss_fit1']
487 998 if ax.firsttime:
488 999 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
489 1000 self.xmin = self.xmin if self.xmin else -self.xmax
490 1001 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
491 1002 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
492 1003 ax.plt = ax.plot(x, z[n, :, index].T, lw=0.25)
493 1004 if self.CODE == 'cut_gaussian_fit':
494 1005 ax.plt_gau0 = ax.plot(x, gau0[n, :, index].T, lw=1, linestyle='-.')
495 1006 for i, line in enumerate(ax.plt_gau0):
496 1007 line.set_color(ax.plt[i].get_color())
497 1008 ax.plt_gau1 = ax.plot(x, gau1[n, :, index].T, lw=1, linestyle='--')
498 1009 for i, line in enumerate(ax.plt_gau1):
499 1010 line.set_color(ax.plt[i].get_color())
500 1011 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
501 1012 self.figures[0].legend(ax.plt, labels, loc='center right')
502 1013 else:
503 1014 for i, line in enumerate(ax.plt):
504 1015 line.set_data(x, z[n, :, index[i]].T)
505 1016 for i, line in enumerate(ax.plt_gau0):
506 1017 line.set_data(x, gau0[n, :, index[i]].T)
507 1018 line.set_color(ax.plt[i].get_color())
508 1019 for i, line in enumerate(ax.plt_gau1):
509 1020 line.set_data(x, gau1[n, :, index[i]].T)
510 1021 line.set_color(ax.plt[i].get_color())
511 1022 self.titles.append('CH {}'.format(n))
512 1023
513 1024
514 1025 class BeaconPhase(Plot):
515 1026
516 1027 __isConfig = None
517 1028 __nsubplots = None
518 1029
519 1030 PREFIX = 'beacon_phase'
520 1031
521 1032 def __init__(self):
522 1033 Plot.__init__(self)
523 1034 self.timerange = 24*60*60
524 1035 self.isConfig = False
525 1036 self.__nsubplots = 1
526 1037 self.counter_imagwr = 0
527 1038 self.WIDTH = 800
528 1039 self.HEIGHT = 400
529 1040 self.WIDTHPROF = 120
530 1041 self.HEIGHTPROF = 0
531 1042 self.xdata = None
532 1043 self.ydata = None
533 1044
534 1045 self.PLOT_CODE = BEACON_CODE
535 1046
536 1047 self.FTP_WEI = None
537 1048 self.EXP_CODE = None
538 1049 self.SUB_EXP_CODE = None
539 1050 self.PLOT_POS = None
540 1051
541 1052 self.filename_phase = None
542 1053
543 1054 self.figfile = None
544 1055
545 1056 self.xmin = None
546 1057 self.xmax = None
547 1058
548 1059 def getSubplots(self):
549 1060
550 1061 ncol = 1
551 1062 nrow = 1
552 1063
553 1064 return nrow, ncol
554 1065
555 1066 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
556 1067
557 1068 self.__showprofile = showprofile
558 1069 self.nplots = nplots
559 1070
560 1071 ncolspan = 7
561 1072 colspan = 6
562 1073 self.__nsubplots = 2
563 1074
564 1075 self.createFigure(id = id,
565 1076 wintitle = wintitle,
566 1077 widthplot = self.WIDTH+self.WIDTHPROF,
567 1078 heightplot = self.HEIGHT+self.HEIGHTPROF,
568 1079 show=show)
569 1080
570 1081 nrow, ncol = self.getSubplots()
571 1082
572 1083 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
573 1084
574 1085 def save_phase(self, filename_phase):
575 1086 f = open(filename_phase,'w+')
576 1087 f.write('\n\n')
577 1088 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
578 1089 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
579 1090 f.close()
580 1091
581 1092 def save_data(self, filename_phase, data, data_datetime):
582 1093 f=open(filename_phase,'a')
583 1094 timetuple_data = data_datetime.timetuple()
584 1095 day = str(timetuple_data.tm_mday)
585 1096 month = str(timetuple_data.tm_mon)
586 1097 year = str(timetuple_data.tm_year)
587 1098 hour = str(timetuple_data.tm_hour)
588 1099 minute = str(timetuple_data.tm_min)
589 1100 second = str(timetuple_data.tm_sec)
590 1101 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
591 1102 f.close()
592 1103
593 1104 def plot(self):
594 1105 log.warning('TODO: Not yet implemented...')
595 1106
596 1107 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
597 1108 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
598 1109 timerange=None,
599 1110 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
600 1111 server=None, folder=None, username=None, password=None,
601 1112 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
602 1113
603 1114 if dataOut.flagNoData:
604 1115 return dataOut
605 1116
606 1117 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
607 1118 return
608 1119
609 1120 if pairsList == None:
610 1121 pairsIndexList = dataOut.pairsIndexList[:10]
611 1122 else:
612 1123 pairsIndexList = []
613 1124 for pair in pairsList:
614 1125 if pair not in dataOut.pairsList:
615 1126 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
616 1127 pairsIndexList.append(dataOut.pairsList.index(pair))
617 1128
618 1129 if pairsIndexList == []:
619 1130 return
620 1131
621 1132 # if len(pairsIndexList) > 4:
622 1133 # pairsIndexList = pairsIndexList[0:4]
623 1134
624 1135 hmin_index = None
625 1136 hmax_index = None
626 1137
627 1138 if hmin != None and hmax != None:
628 1139 indexes = numpy.arange(dataOut.nHeights)
629 1140 hmin_list = indexes[dataOut.heightList >= hmin]
630 1141 hmax_list = indexes[dataOut.heightList <= hmax]
631 1142
632 1143 if hmin_list.any():
633 1144 hmin_index = hmin_list[0]
634 1145
635 1146 if hmax_list.any():
636 1147 hmax_index = hmax_list[-1]+1
637 1148
638 1149 x = dataOut.getTimeRange()
639 1150
640 1151 thisDatetime = dataOut.datatime
641 1152
642 1153 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
643 1154 xlabel = "Local Time"
644 1155 ylabel = "Phase (degrees)"
645 1156
646 1157 update_figfile = False
647 1158
648 1159 nplots = len(pairsIndexList)
649 1160 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
650 1161 phase_beacon = numpy.zeros(len(pairsIndexList))
651 1162 for i in range(nplots):
652 1163 pair = dataOut.pairsList[pairsIndexList[i]]
653 1164 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
654 1165 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
655 1166 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
656 1167 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
657 1168 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
658 1169
659 1170 if dataOut.beacon_heiIndexList:
660 1171 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
661 1172 else:
662 1173 phase_beacon[i] = numpy.average(phase)
663 1174
664 1175 if not self.isConfig:
665 1176
666 1177 nplots = len(pairsIndexList)
667 1178
668 1179 self.setup(id=id,
669 1180 nplots=nplots,
670 1181 wintitle=wintitle,
671 1182 showprofile=showprofile,
672 1183 show=show)
673 1184
674 1185 if timerange != None:
675 1186 self.timerange = timerange
676 1187
677 1188 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
678 1189
679 1190 if ymin == None: ymin = 0
680 1191 if ymax == None: ymax = 360
681 1192
682 1193 self.FTP_WEI = ftp_wei
683 1194 self.EXP_CODE = exp_code
684 1195 self.SUB_EXP_CODE = sub_exp_code
685 1196 self.PLOT_POS = plot_pos
686 1197
687 1198 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
688 1199 self.isConfig = True
689 1200 self.figfile = figfile
690 1201 self.xdata = numpy.array([])
691 1202 self.ydata = numpy.array([])
692 1203
693 1204 update_figfile = True
694 1205
695 1206 #open file beacon phase
696 1207 path = '%s%03d' %(self.PREFIX, self.id)
697 1208 beacon_file = os.path.join(path,'%s.txt'%self.name)
698 1209 self.filename_phase = os.path.join(figpath,beacon_file)
699 1210 #self.save_phase(self.filename_phase)
700 1211
701 1212
702 1213 #store data beacon phase
703 1214 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
704 1215
705 1216 self.setWinTitle(title)
706 1217
707 1218
708 1219 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
709 1220
710 1221 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
711 1222
712 1223 axes = self.axesList[0]
713 1224
714 1225 self.xdata = numpy.hstack((self.xdata, x[0:1]))
715 1226
716 1227 if len(self.ydata)==0:
717 1228 self.ydata = phase_beacon.reshape(-1,1)
718 1229 else:
719 1230 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
720 1231
721 1232
722 1233 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
723 1234 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
724 1235 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
725 1236 XAxisAsTime=True, grid='both'
726 1237 )
727 1238
728 1239 self.draw()
729 1240
730 1241 if dataOut.ltctime >= self.xmax:
731 1242 self.counter_imagwr = wr_period
732 1243 self.isConfig = False
733 1244 update_figfile = True
734 1245
735 1246 self.save(figpath=figpath,
736 1247 figfile=figfile,
737 1248 save=save,
738 1249 ftp=ftp,
739 1250 wr_period=wr_period,
740 1251 thisDatetime=thisDatetime,
741 1252 update_figfile=update_figfile)
742 1253
743 1254 return dataOut
@@ -1,24 +1,29
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JRODataIO.py 169 2012-11-19 21:57:03Z murco $
5 5 '''
6 6
7 7 from .jroIO_voltage import *
8 8 from .jroIO_spectra import *
9 9 from .jroIO_heispectra import *
10 10 from .jroIO_usrp import *
11 11 from .jroIO_digitalRF import *
12 12 from .jroIO_kamisr import *
13 13 from .jroIO_param import *
14 14 from .jroIO_hf import *
15 15
16 16 from .jroIO_madrigal import *
17 17
18 18 from .bltrIO_param import *
19 19 from .bltrIO_spectra import *
20 20 from .jroIO_mira35c import *
21 21 from .julIO_param import *
22 22
23 23 from .pxIO_param import *
24 24 from .jroIO_simulator import *
25
26 ############DP############
27 from .jroIO_dat import *
28
29 ############DP############
@@ -1,1575 +1,1615
1 1 """
2 2 Created on Jul 2, 2014
3 3
4 4 @author: roj-idl71
5 5 """
6 6 import os
7 7 import sys
8 8 import glob
9 9 import time
10 10 import numpy
11 11 import fnmatch
12 12 import inspect
13 13 import time
14 14 import datetime
15 15 import zmq
16 16
17 17 from schainpy.model.proc.jroproc_base import Operation, MPDecorator
18 18 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
19 19 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
20 20 from schainpy.utils import log
21 21 import schainpy.admin
22 22
23 23 LOCALTIME = True
24 24 DT_DIRECTIVES = {
25 25 '%Y': 4,
26 26 '%y': 2,
27 27 '%m': 2,
28 28 '%d': 2,
29 29 '%j': 3,
30 30 '%H': 2,
31 31 '%M': 2,
32 32 '%S': 2,
33 33 '%f': 6
34 34 }
35 35
36 36
37 37 def isNumber(cad):
38 38 """
39 39 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
40 40
41 41 Excepciones:
42 42 Si un determinado string no puede ser convertido a numero
43 43 Input:
44 44 str, string al cual se le analiza para determinar si convertible a un numero o no
45 45
46 46 Return:
47 47 True : si el string es uno numerico
48 48 False : no es un string numerico
49 49 """
50 50 try:
51 51 float(cad)
52 52 return True
53 53 except:
54 54 return False
55 55
56 56
57 57 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
58 58 """
59 59 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
60 60
61 61 Inputs:
62 62 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
63 63
64 64 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
65 65 segundos contados desde 01/01/1970.
66 66 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
67 67 segundos contados desde 01/01/1970.
68 68
69 69 Return:
70 70 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
71 71 fecha especificado, de lo contrario retorna False.
72 72
73 73 Excepciones:
74 74 Si el archivo no existe o no puede ser abierto
75 75 Si la cabecera no puede ser leida.
76 76
77 77 """
78 78 basicHeaderObj = BasicHeader(LOCALTIME)
79 79
80 80 try:
81
81 82 fp = open(filename, 'rb')
82 83 except IOError:
83 84 print("The file %s can't be opened" % (filename))
84 85 return 0
85 86
86 87 sts = basicHeaderObj.read(fp)
87 88 fp.close()
88 89
89 90 if not(sts):
90 91 print("Skipping the file %s because it has not a valid header" % (filename))
91 92 return 0
92 93
93 94 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
94 95 return 0
95 96
96 97 return 1
97 98
98 99
99 100 def isTimeInRange(thisTime, startTime, endTime):
100 101 if endTime >= startTime:
101 102 if (thisTime < startTime) or (thisTime > endTime):
102 103 return 0
103 104 return 1
104 105 else:
105 106 if (thisTime < startTime) and (thisTime > endTime):
106 107 return 0
107 108 return 1
108 109
109 110
110 111 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
111 112 """
112 113 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
113 114
114 115 Inputs:
115 116 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
116 117
117 118 startDate : fecha inicial del rango seleccionado en formato datetime.date
118 119
119 120 endDate : fecha final del rango seleccionado en formato datetime.date
120 121
121 122 startTime : tiempo inicial del rango seleccionado en formato datetime.time
122 123
123 124 endTime : tiempo final del rango seleccionado en formato datetime.time
124 125
125 126 Return:
126 127 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
127 128 fecha especificado, de lo contrario retorna False.
128 129
129 130 Excepciones:
130 131 Si el archivo no existe o no puede ser abierto
131 132 Si la cabecera no puede ser leida.
132 133
133 134 """
134 135
135 136 try:
136 137 fp = open(filename, 'rb')
137 138 except IOError:
138 139 print("The file %s can't be opened" % (filename))
139 140 return None
140 141
141 142 firstBasicHeaderObj = BasicHeader(LOCALTIME)
142 143 systemHeaderObj = SystemHeader()
144
143 145 radarControllerHeaderObj = RadarControllerHeader()
144 146 processingHeaderObj = ProcessingHeader()
145 147
146 148 lastBasicHeaderObj = BasicHeader(LOCALTIME)
147 149
148 150 sts = firstBasicHeaderObj.read(fp)
149 151
150 152 if not(sts):
151 153 print("[Reading] Skipping the file %s because it has not a valid header" % (filename))
152 154 return None
153 155
154 156 if not systemHeaderObj.read(fp):
155 157 return None
156 158
157 159 if not radarControllerHeaderObj.read(fp):
158 160 return None
159 161
160 162 if not processingHeaderObj.read(fp):
161 163 return None
162 164
163 165 filesize = os.path.getsize(filename)
164 166
165 167 offset = processingHeaderObj.blockSize + 24 # header size
166 168
167 169 if filesize <= offset:
168 170 print("[Reading] %s: This file has not enough data" % filename)
169 171 return None
170 172
171 173 fp.seek(-offset, 2)
172 174
173 175 sts = lastBasicHeaderObj.read(fp)
174 176
175 177 fp.close()
176 178
177 179 thisDatetime = lastBasicHeaderObj.datatime
178 180 thisTime_last_block = thisDatetime.time()
179 181
180 182 thisDatetime = firstBasicHeaderObj.datatime
181 183 thisDate = thisDatetime.date()
182 184 thisTime_first_block = thisDatetime.time()
183 185
184 186 # General case
185 187 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
186 188 #-----------o----------------------------o-----------
187 189 # startTime endTime
188 190
189 191 if endTime >= startTime:
190 192 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
191 193 return None
192 194
193 195 return thisDatetime
194 196
195 197 # If endTime < startTime then endTime belongs to the next day
196 198
197 199 #<<<<<<<<<<<o o>>>>>>>>>>>
198 200 #-----------o----------------------------o-----------
199 201 # endTime startTime
200 202
201 203 if (thisDate == startDate) and (thisTime_last_block < startTime):
202 204 return None
203 205
204 206 if (thisDate == endDate) and (thisTime_first_block > endTime):
205 207 return None
206 208
207 209 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
208 210 return None
209 211
210 212 return thisDatetime
211 213
212 214
213 215 def isFolderInDateRange(folder, startDate=None, endDate=None):
214 216 """
215 217 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
216 218
217 219 Inputs:
218 220 folder : nombre completo del directorio.
219 221 Su formato deberia ser "/path_root/?YYYYDDD"
220 222
221 223 siendo:
222 224 YYYY : Anio (ejemplo 2015)
223 225 DDD : Dia del anio (ejemplo 305)
224 226
225 227 startDate : fecha inicial del rango seleccionado en formato datetime.date
226 228
227 229 endDate : fecha final del rango seleccionado en formato datetime.date
228 230
229 231 Return:
230 232 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
231 233 fecha especificado, de lo contrario retorna False.
232 234 Excepciones:
233 235 Si el directorio no tiene el formato adecuado
234 236 """
235 237
236 238 basename = os.path.basename(folder)
237 239
238 240 if not isRadarFolder(basename):
239 241 print("The folder %s has not the rigth format" % folder)
240 242 return 0
241 243
242 244 if startDate and endDate:
243 245 thisDate = getDateFromRadarFolder(basename)
244 246
245 247 if thisDate < startDate:
246 248 return 0
247 249
248 250 if thisDate > endDate:
249 251 return 0
250 252
251 253 return 1
252 254
253 255
254 256 def isFileInDateRange(filename, startDate=None, endDate=None):
255 257 """
256 258 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
257 259
258 260 Inputs:
259 261 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
260 262
261 263 Su formato deberia ser "?YYYYDDDsss"
262 264
263 265 siendo:
264 266 YYYY : Anio (ejemplo 2015)
265 267 DDD : Dia del anio (ejemplo 305)
266 268 sss : set
267 269
268 270 startDate : fecha inicial del rango seleccionado en formato datetime.date
269 271
270 272 endDate : fecha final del rango seleccionado en formato datetime.date
271 273
272 274 Return:
273 275 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
274 276 fecha especificado, de lo contrario retorna False.
275 277 Excepciones:
276 278 Si el archivo no tiene el formato adecuado
277 279 """
278 280
279 281 basename = os.path.basename(filename)
280 282
281 283 if not isRadarFile(basename):
282 284 print("The filename %s has not the rigth format" % filename)
283 285 return 0
284 286
285 287 if startDate and endDate:
286 288 thisDate = getDateFromRadarFile(basename)
287 289
288 290 if thisDate < startDate:
289 291 return 0
290 292
291 293 if thisDate > endDate:
292 294 return 0
293 295
294 296 return 1
295 297
296 298
297 299 def getFileFromSet(path, ext, set):
298 300 validFilelist = []
299 301 fileList = os.listdir(path)
300 302
301 303 # 0 1234 567 89A BCDE
302 304 # H YYYY DDD SSS .ext
303 305
304 306 for thisFile in fileList:
305 307 try:
306 308 year = int(thisFile[1:5])
307 309 doy = int(thisFile[5:8])
308 310 except:
309 311 continue
310 312
311 313 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
312 314 continue
313 315
314 316 validFilelist.append(thisFile)
315 317
316 318 myfile = fnmatch.filter(
317 319 validFilelist, '*%4.4d%3.3d%3.3d*' % (year, doy, set))
318 320
319 321 if len(myfile) != 0:
320 322 return myfile[0]
321 323 else:
322 324 filename = '*%4.4d%3.3d%3.3d%s' % (year, doy, set, ext.lower())
323 325 print('the filename %s does not exist' % filename)
324 326 print('...going to the last file: ')
325 327
326 328 if validFilelist:
327 329 validFilelist = sorted(validFilelist, key=str.lower)
328 330 return validFilelist[-1]
329 331
330 332 return None
331 333
332 334
333 335 def getlastFileFromPath(path, ext):
334 336 """
335 337 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
336 338 al final de la depuracion devuelve el ultimo file de la lista que quedo.
337 339
338 340 Input:
339 341 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
340 342 ext : extension de los files contenidos en una carpeta
341 343
342 344 Return:
343 345 El ultimo file de una determinada carpeta, no se considera el path.
344 346 """
345 347 validFilelist = []
346 348 fileList = os.listdir(path)
347 349
348 350 # 0 1234 567 89A BCDE
349 351 # H YYYY DDD SSS .ext
350 352
351 353 for thisFile in fileList:
352 354
353 355 year = thisFile[1:5]
354 356 if not isNumber(year):
355 357 continue
356 358
357 359 doy = thisFile[5:8]
358 360 if not isNumber(doy):
359 361 continue
360 362
361 363 year = int(year)
362 364 doy = int(doy)
363 365
364 366 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
365 367 continue
366 368
367 369 validFilelist.append(thisFile)
368 370
369 371 if validFilelist:
370 372 validFilelist = sorted(validFilelist, key=str.lower)
371 373 return validFilelist[-1]
372 374
373 375 return None
374 376
375 377
376 378 def isRadarFolder(folder):
377 379 try:
378 380 year = int(folder[1:5])
379 381 doy = int(folder[5:8])
380 382 except:
381 383 return 0
382 384
383 385 return 1
384 386
385 387
386 388 def isRadarFile(file):
387 389 try:
388 390 year = int(file[1:5])
389 391 doy = int(file[5:8])
390 392 set = int(file[8:11])
391 393 except:
392 394 return 0
393 395
394 396 return 1
395 397
396 398
397 399 def getDateFromRadarFile(file):
398 400 try:
399 401 year = int(file[1:5])
400 402 doy = int(file[5:8])
401 403 set = int(file[8:11])
402 404 except:
403 405 return None
404 406
405 407 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
406 408 return thisDate
407 409
408 410
409 411 def getDateFromRadarFolder(folder):
410 412 try:
411 413 year = int(folder[1:5])
412 414 doy = int(folder[5:8])
413 415 except:
414 416 return None
415 417
416 418 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
417 419 return thisDate
418 420
419 421 def parse_format(s, fmt):
420 422
421 423 for i in range(fmt.count('%')):
422 424 x = fmt.index('%')
423 425 d = DT_DIRECTIVES[fmt[x:x+2]]
424 426 fmt = fmt.replace(fmt[x:x+2], s[x:x+d])
425 427 return fmt
426 428
427 429 class Reader(object):
428 430
429 431 c = 3E8
430 432 isConfig = False
431 433 dtype = None
432 434 pathList = []
433 435 filenameList = []
434 436 datetimeList = []
435 437 filename = None
436 438 ext = None
437 439 flagIsNewFile = 1
438 440 flagDiscontinuousBlock = 0
439 441 flagIsNewBlock = 0
440 442 flagNoMoreFiles = 0
441 443 fp = None
442 444 firstHeaderSize = 0
443 445 basicHeaderSize = 24
444 446 versionFile = 1103
445 447 fileSize = None
446 448 fileSizeByHeader = None
447 449 fileIndex = -1
448 450 profileIndex = None
449 451 blockIndex = 0
450 452 nTotalBlocks = 0
451 453 maxTimeStep = 30
452 454 lastUTTime = None
453 455 datablock = None
454 456 dataOut = None
455 457 getByBlock = False
456 458 path = None
457 459 startDate = None
458 460 endDate = None
459 461 startTime = datetime.time(0, 0, 0)
460 462 endTime = datetime.time(23, 59, 59)
461 463 set = None
462 464 expLabel = ""
463 465 online = False
464 466 delay = 60
465 467 nTries = 3 # quantity tries
466 468 nFiles = 3 # number of files for searching
467 469 walk = True
468 470 getblock = False
469 471 nTxs = 1
470 472 realtime = False
471 473 blocksize = 0
472 474 blocktime = None
473 475 warnings = True
474 476 verbose = True
475 477 server = None
476 478 format = None
477 479 oneDDict = None
478 480 twoDDict = None
479 481 independentParam = None
480 482 filefmt = None
481 483 folderfmt = None
482 484 open_file = open
483 485 open_mode = 'rb'
484 486
485 487 def run(self):
486 488
487 489 raise NotImplementedError
488 490
489 491 def getAllowedArgs(self):
490 492 if hasattr(self, '__attrs__'):
491 493 return self.__attrs__
492 494 else:
493 495 return inspect.getargspec(self.run).args
494 496
495 497 def set_kwargs(self, **kwargs):
496 498
497 499 for key, value in kwargs.items():
498 500 setattr(self, key, value)
499 501
500 502 def find_folders(self, path, startDate, endDate, folderfmt, last=False):
501 503
502 504 folders = [x for f in path.split(',')
503 505 for x in os.listdir(f) if os.path.isdir(os.path.join(f, x))]
504 506 folders.sort()
505 507
506 508 if last:
507 509 folders = [folders[-1]]
508 510
509 511 for folder in folders:
510 512 try:
511 513 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
512 514 if dt >= startDate and dt <= endDate:
513 515 yield os.path.join(path, folder)
514 516 else:
515 517 log.log('Skiping folder {}'.format(folder), self.name)
516 518 except Exception as e:
517 519 log.log('Skiping folder {}'.format(folder), self.name)
518 520 continue
519 521 return
520 522
521 523 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
522 524 expLabel='', last=False):
523 525
524 526 for path in folders:
525 527 files = glob.glob1(path, '*{}'.format(ext))
526 528 files.sort()
527 529 if last:
528 530 if files:
529 531 fo = files[-1]
530 532 try:
531 533 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
532 534 yield os.path.join(path, expLabel, fo)
533 535 except Exception as e:
534 536 pass
535 537 return
536 538 else:
537 539 return
538 540
539 541 for fo in files:
540 542 try:
541 543 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
544 #print(dt)
545 #print(startDate)
546 #print(endDate)
542 547 if dt >= startDate and dt <= endDate:
548
543 549 yield os.path.join(path, expLabel, fo)
550
544 551 else:
552
545 553 log.log('Skiping file {}'.format(fo), self.name)
546 554 except Exception as e:
547 555 log.log('Skiping file {}'.format(fo), self.name)
548 556 continue
549 557
550 558 def searchFilesOffLine(self, path, startDate, endDate,
551 559 expLabel, ext, walk,
552 560 filefmt, folderfmt):
553 561 """Search files in offline mode for the given arguments
554 562
555 563 Return:
556 564 Generator of files
557 565 """
558 566
559 567 if walk:
560 568 folders = self.find_folders(
561 569 path, startDate, endDate, folderfmt)
562 570 else:
563 571 folders = path.split(',')
564 572
565 573 return self.find_files(
566 574 folders, ext, filefmt, startDate, endDate, expLabel)
567 575
568 576 def searchFilesOnLine(self, path, startDate, endDate,
569 577 expLabel, ext, walk,
570 578 filefmt, folderfmt):
571 579 """Search for the last file of the last folder
572 580
573 581 Arguments:
574 582 path : carpeta donde estan contenidos los files que contiene data
575 583 expLabel : Nombre del subexperimento (subfolder)
576 584 ext : extension de los files
577 585 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
578 586
579 587 Return:
580 588 generator with the full path of last filename
581 589 """
582 590
583 591 if walk:
584 592 folders = self.find_folders(
585 593 path, startDate, endDate, folderfmt, last=True)
586 594 else:
587 595 folders = path.split(',')
588 596
589 597 return self.find_files(
590 598 folders, ext, filefmt, startDate, endDate, expLabel, last=True)
591 599
592 600 def setNextFile(self):
593 601 """Set the next file to be readed open it and parse de file header"""
594 602
603 #print("fp: ",self.fp)
595 604 while True:
605
606 #print(self.fp)
596 607 if self.fp != None:
597 608 self.fp.close()
598 609
610 #print("setNextFile")
611 #print("BEFORE OPENING",self.filename)
599 612 if self.online:
600 613 newFile = self.setNextFileOnline()
614
601 615 else:
616
602 617 newFile = self.setNextFileOffline()
603 618
619 #print("newFile: ",newFile)
604 620 if not(newFile):
621
605 622 if self.online:
606 623 raise schainpy.admin.SchainError('Time to wait for new files reach')
607 624 else:
608 625 if self.fileIndex == -1:
626 #print("OKK")
609 627 raise schainpy.admin.SchainWarning('No files found in the given path')
610 628 else:
629
611 630 raise schainpy.admin.SchainWarning('No more files to read')
612 631
613 632 if self.verifyFile(self.filename):
633
614 634 break
615 635
636 ##print("BEFORE OPENING",self.filename)
637
616 638 log.log('Opening file: %s' % self.filename, self.name)
617 639
618 640 self.readFirstHeader()
619 641 self.nReadBlocks = 0
620 642
621 643 def setNextFileOnline(self):
622 644 """Check for the next file to be readed in online mode.
623 645
624 646 Set:
625 647 self.filename
626 648 self.fp
627 649 self.filesize
628 650
629 651 Return:
630 652 boolean
631 653
632 654 """
655
633 656 nextFile = True
634 657 nextDay = False
635 658
636 659 for nFiles in range(self.nFiles+1):
637 660 for nTries in range(self.nTries):
638 661 fullfilename, filename = self.checkForRealPath(nextFile, nextDay)
639 662 if fullfilename is not None:
640 663 break
641 664 log.warning(
642 665 "Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, filename, nTries + 1),
643 666 self.name)
644 667 time.sleep(self.delay)
645 668 nextFile = False
646 669 continue
647 670
648 671 if fullfilename is not None:
649 672 break
650 673
651 self.nTries = 1
674 #self.nTries = 1
652 675 nextFile = True
653 676
654 677 if nFiles == (self.nFiles - 1):
655 678 log.log('Trying with next day...', self.name)
656 679 nextDay = True
657 680 self.nTries = 3
658 681
659 682 if fullfilename:
660 683 self.fileSize = os.path.getsize(fullfilename)
661 684 self.filename = fullfilename
662 685 self.flagIsNewFile = 1
663 686 if self.fp != None:
664 687 self.fp.close()
688 #print(fullfilename)
665 689 self.fp = self.open_file(fullfilename, self.open_mode)
690
666 691 self.flagNoMoreFiles = 0
667 692 self.fileIndex += 1
668 693 return 1
669 694 else:
670 695 return 0
671 696
672 697 def setNextFileOffline(self):
673 698 """Open the next file to be readed in offline mode"""
674 699
675 700 try:
676 701 filename = next(self.filenameList)
677 702 self.fileIndex +=1
678 703 except StopIteration:
679 704 self.flagNoMoreFiles = 1
680 705 return 0
681
706 #print(self.fileIndex)
707 #print(filename)
682 708 self.filename = filename
683 709 self.fileSize = os.path.getsize(filename)
684 710 self.fp = self.open_file(filename, self.open_mode)
685 711 self.flagIsNewFile = 1
686 712
687 713 return 1
688 714
689 715 @staticmethod
690 716 def isDateTimeInRange(dt, startDate, endDate, startTime, endTime):
691 717 """Check if the given datetime is in range"""
692 718
693 719 if startDate <= dt.date() <= endDate:
694 720 if startTime <= dt.time() <= endTime:
695 721 return True
696 722 return False
697 723
698 724 def verifyFile(self, filename):
699 725 """Check for a valid file
700 726
701 727 Arguments:
702 728 filename -- full path filename
703 729
704 730 Return:
705 731 boolean
706 732 """
707 733
708 734 return True
709 735
710 736 def checkForRealPath(self, nextFile, nextDay):
711 737 """Check if the next file to be readed exists"""
712 738
713 739 raise NotImplementedError
714 740
715 741 def readFirstHeader(self):
716 742 """Parse the file header"""
717 743
744
718 745 pass
719 746
720 747 def waitDataBlock(self, pointer_location, blocksize=None):
721 748 """
722 749 """
723 750
724 751 currentPointer = pointer_location
725 752 if blocksize is None:
726 753 neededSize = self.processingHeaderObj.blockSize # + self.basicHeaderSize
727 754 else:
728 755 neededSize = blocksize
729 756
730 757 for nTries in range(self.nTries):
731 758 self.fp.close()
732 759 self.fp = open(self.filename, 'rb')
733 760 self.fp.seek(currentPointer)
734 761
735 762 self.fileSize = os.path.getsize(self.filename)
736 763 currentSize = self.fileSize - currentPointer
737 764
738 765 if (currentSize >= neededSize):
739 766 return 1
740 767
741 768 log.warning(
742 769 "Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1),
743 770 self.name
744 771 )
745 772 time.sleep(self.delay)
746 773
747 774 return 0
748 775
749 776 class JRODataReader(Reader):
750 777
751 778 utc = 0
752 779 nReadBlocks = 0
753 780 foldercounter = 0
754 781 firstHeaderSize = 0
755 782 basicHeaderSize = 24
756 783 __isFirstTimeOnline = 1
757 784 filefmt = "*%Y%j***"
758 785 folderfmt = "*%Y%j"
759 786 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'online', 'delay', 'walk']
760 787
761 788 def getDtypeWidth(self):
762 789
763 790 dtype_index = get_dtype_index(self.dtype)
764 791 dtype_width = get_dtype_width(dtype_index)
765 792
766 793 return dtype_width
767 794
768 795 def checkForRealPath(self, nextFile, nextDay):
769 796 """Check if the next file to be readed exists.
770 797
771 798 Example :
772 799 nombre correcto del file es .../.../D2009307/P2009307367.ext
773 800
774 801 Entonces la funcion prueba con las siguientes combinaciones
775 802 .../.../y2009307367.ext
776 803 .../.../Y2009307367.ext
777 804 .../.../x2009307/y2009307367.ext
778 805 .../.../x2009307/Y2009307367.ext
779 806 .../.../X2009307/y2009307367.ext
780 807 .../.../X2009307/Y2009307367.ext
781 808 siendo para este caso, la ultima combinacion de letras, identica al file buscado
782 809
783 810 Return:
784 811 str -- fullpath of the file
785 812 """
786 813
787 814
788 815 if nextFile:
789 816 self.set += 1
790 817 if nextDay:
791 818 self.set = 0
792 819 self.doy += 1
793 820 foldercounter = 0
794 821 prefixDirList = [None, 'd', 'D']
795 822 if self.ext.lower() == ".r": # voltage
796 823 prefixFileList = ['d', 'D']
797 824 elif self.ext.lower() == ".pdata": # spectra
798 825 prefixFileList = ['p', 'P']
799 826
827 ##############DP##############
828
829 elif self.ext.lower() == ".dat": # dat
830 prefixFileList = ['z', 'Z']
831
832
833
834 ##############DP##############
800 835 # barrido por las combinaciones posibles
801 836 for prefixDir in prefixDirList:
802 837 thispath = self.path
803 838 if prefixDir != None:
804 839 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
805 840 if foldercounter == 0:
806 841 thispath = os.path.join(self.path, "%s%04d%03d" %
807 842 (prefixDir, self.year, self.doy))
808 843 else:
809 844 thispath = os.path.join(self.path, "%s%04d%03d_%02d" % (
810 845 prefixDir, self.year, self.doy, foldercounter))
811 846 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
812 847 # formo el nombre del file xYYYYDDDSSS.ext
813 848 filename = "%s%04d%03d%03d%s" % (prefixFile, self.year, self.doy, self.set, self.ext)
814 849 fullfilename = os.path.join(
815 850 thispath, filename)
816 851
817 852 if os.path.exists(fullfilename):
818 853 return fullfilename, filename
819 854
820 855 return None, filename
821 856
822 857 def __waitNewBlock(self):
823 858 """
824 859 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
825 860
826 861 Si el modo de lectura es OffLine siempre retorn 0
827 862 """
828 863 if not self.online:
829 864 return 0
830 865
831 866 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
832 867 return 0
833 868
834 869 currentPointer = self.fp.tell()
835 870
836 871 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
837 872
838 873 for nTries in range(self.nTries):
839 874
840 875 self.fp.close()
841 876 self.fp = open(self.filename, 'rb')
842 877 self.fp.seek(currentPointer)
843 878
844 879 self.fileSize = os.path.getsize(self.filename)
845 880 currentSize = self.fileSize - currentPointer
846 881
847 882 if (currentSize >= neededSize):
848 883 self.basicHeaderObj.read(self.fp)
849 884 return 1
850 885
851 886 if self.fileSize == self.fileSizeByHeader:
852 887 # self.flagEoF = True
853 888 return 0
854 889
855 890 print("[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1))
891 #print(self.filename)
856 892 time.sleep(self.delay)
857 893
858 894 return 0
859 895
860 896 def __setNewBlock(self):
861 897
862 898 if self.fp == None:
863 899 return 0
864 900
865 901 if self.flagIsNewFile:
866 902 self.lastUTTime = self.basicHeaderObj.utc
867 903 return 1
868 904
869 905 if self.realtime:
870 906 self.flagDiscontinuousBlock = 1
871 907 if not(self.setNextFile()):
872 908 return 0
873 909 else:
874 910 return 1
875 911
876 912 currentSize = self.fileSize - self.fp.tell()
877 913 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
878 914
879 915 if (currentSize >= neededSize):
880 916 self.basicHeaderObj.read(self.fp)
881 917 self.lastUTTime = self.basicHeaderObj.utc
882 918 return 1
883 919
884 920 if self.__waitNewBlock():
885 921 self.lastUTTime = self.basicHeaderObj.utc
886 922 return 1
887 923
888 924 if not(self.setNextFile()):
889 925 return 0
890 926
891 927 deltaTime = self.basicHeaderObj.utc - self.lastUTTime
892 928 self.lastUTTime = self.basicHeaderObj.utc
893 929
894 930 self.flagDiscontinuousBlock = 0
895 931
896 932 if deltaTime > self.maxTimeStep:
897 933 self.flagDiscontinuousBlock = 1
898 934
899 935 return 1
900 936
901 937 def readNextBlock(self):
902 938
903 939 while True:
904 940 if not(self.__setNewBlock()):
905 941 continue
906 942
907 943 if not(self.readBlock()):
908 944 return 0
909 945
910 946 self.getBasicHeader()
911 947
912 948 if not self.isDateTimeInRange(self.dataOut.datatime, self.startDate, self.endDate, self.startTime, self.endTime):
913 949 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.nReadBlocks,
914 950 self.processingHeaderObj.dataBlocksPerFile,
915 951 self.dataOut.datatime.ctime()))
916 952 continue
917 953
918 954 break
919 955
920 956 if self.verbose:
921 957 print("[Reading] Block No. %d/%d -> %s" % (self.nReadBlocks,
922 958 self.processingHeaderObj.dataBlocksPerFile,
923 959 self.dataOut.datatime.ctime()))
960 #################DP#################
961 self.dataOut.TimeBlockDate=self.dataOut.datatime.ctime()
962 self.dataOut.TimeBlockSeconds=time.mktime(time.strptime(self.dataOut.datatime.ctime()))
963 #################DP#################
924 964 return 1
925 965
926 966 def readFirstHeader(self):
927 967
928 968 self.basicHeaderObj.read(self.fp)
929 969 self.systemHeaderObj.read(self.fp)
930 970 self.radarControllerHeaderObj.read(self.fp)
931 971 self.processingHeaderObj.read(self.fp)
932 972 self.firstHeaderSize = self.basicHeaderObj.size
933 973
934 974 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
935 975 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
936 976 if datatype == 0:
937 977 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
938 978 elif datatype == 1:
939 979 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
940 980 elif datatype == 2:
941 981 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
942 982 elif datatype == 3:
943 983 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
944 984 elif datatype == 4:
945 985 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
946 986 elif datatype == 5:
947 987 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
948 988 else:
949 989 raise ValueError('Data type was not defined')
950 990
951 991 self.dtype = datatype_str
952 992 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
953 993 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
954 994 self.firstHeaderSize + self.basicHeaderSize * \
955 995 (self.processingHeaderObj.dataBlocksPerFile - 1)
956 996 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
957 997 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
958 998 self.getBlockDimension()
959 999
960 1000 def verifyFile(self, filename):
961 1001
962 1002 flag = True
963 1003
964 1004 try:
965 1005 fp = open(filename, 'rb')
966 1006 except IOError:
967 1007 log.error("File {} can't be opened".format(filename), self.name)
968 1008 return False
969 1009
970 1010 if self.online and self.waitDataBlock(0):
971 1011 pass
972 1012
973 1013 basicHeaderObj = BasicHeader(LOCALTIME)
974 1014 systemHeaderObj = SystemHeader()
975 1015 radarControllerHeaderObj = RadarControllerHeader()
976 1016 processingHeaderObj = ProcessingHeader()
977 1017
978 1018 if not(basicHeaderObj.read(fp)):
979 1019 flag = False
980 1020 if not(systemHeaderObj.read(fp)):
981 1021 flag = False
982 1022 if not(radarControllerHeaderObj.read(fp)):
983 1023 flag = False
984 1024 if not(processingHeaderObj.read(fp)):
985 1025 flag = False
986 1026 if not self.online:
987 1027 dt1 = basicHeaderObj.datatime
988 1028 pos = self.fileSize-processingHeaderObj.blockSize-24
989 1029 if pos<0:
990 1030 flag = False
991 1031 log.error('Invalid size for file: {}'.format(self.filename), self.name)
992 1032 else:
993 1033 fp.seek(pos)
994 1034 if not(basicHeaderObj.read(fp)):
995 1035 flag = False
996 1036 dt2 = basicHeaderObj.datatime
997 1037 if not self.isDateTimeInRange(dt1, self.startDate, self.endDate, self.startTime, self.endTime) and not \
998 1038 self.isDateTimeInRange(dt2, self.startDate, self.endDate, self.startTime, self.endTime):
999 1039 flag = False
1000 1040
1001 1041 fp.close()
1002 1042 return flag
1003 1043
1004 1044 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1005 1045
1006 1046 path_empty = True
1007 1047
1008 1048 dateList = []
1009 1049 pathList = []
1010 1050
1011 1051 multi_path = path.split(',')
1012 1052
1013 1053 if not walk:
1014 1054
1015 1055 for single_path in multi_path:
1016 1056
1017 1057 if not os.path.isdir(single_path):
1018 1058 continue
1019 1059
1020 1060 fileList = glob.glob1(single_path, "*" + ext)
1021 1061
1022 1062 if not fileList:
1023 1063 continue
1024 1064
1025 1065 path_empty = False
1026 1066
1027 1067 fileList.sort()
1028 1068
1029 1069 for thisFile in fileList:
1030 1070
1031 1071 if not os.path.isfile(os.path.join(single_path, thisFile)):
1032 1072 continue
1033 1073
1034 1074 if not isRadarFile(thisFile):
1035 1075 continue
1036 1076
1037 1077 if not isFileInDateRange(thisFile, startDate, endDate):
1038 1078 continue
1039 1079
1040 1080 thisDate = getDateFromRadarFile(thisFile)
1041 1081
1042 1082 if thisDate in dateList or single_path in pathList:
1043 1083 continue
1044 1084
1045 1085 dateList.append(thisDate)
1046 1086 pathList.append(single_path)
1047 1087
1048 1088 else:
1049 1089 for single_path in multi_path:
1050 1090
1051 1091 if not os.path.isdir(single_path):
1052 1092 continue
1053 1093
1054 1094 dirList = []
1055 1095
1056 1096 for thisPath in os.listdir(single_path):
1057 1097
1058 1098 if not os.path.isdir(os.path.join(single_path, thisPath)):
1059 1099 continue
1060 1100
1061 1101 if not isRadarFolder(thisPath):
1062 1102 continue
1063 1103
1064 1104 if not isFolderInDateRange(thisPath, startDate, endDate):
1065 1105 continue
1066 1106
1067 1107 dirList.append(thisPath)
1068 1108
1069 1109 if not dirList:
1070 1110 continue
1071 1111
1072 1112 dirList.sort()
1073 1113
1074 1114 for thisDir in dirList:
1075 1115
1076 1116 datapath = os.path.join(single_path, thisDir, expLabel)
1077 1117 fileList = glob.glob1(datapath, "*" + ext)
1078 1118
1079 1119 if not fileList:
1080 1120 continue
1081 1121
1082 1122 path_empty = False
1083 1123
1084 1124 thisDate = getDateFromRadarFolder(thisDir)
1085 1125
1086 1126 pathList.append(datapath)
1087 1127 dateList.append(thisDate)
1088 1128
1089 1129 dateList.sort()
1090 1130
1091 1131 if walk:
1092 1132 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1093 1133 else:
1094 1134 pattern_path = multi_path[0]
1095 1135
1096 1136 if path_empty:
1097 1137 raise schainpy.admin.SchainError("[Reading] No *%s files in %s for %s to %s" % (ext, pattern_path, startDate, endDate))
1098 1138 else:
1099 1139 if not dateList:
1100 1140 raise schainpy.admin.SchainError("[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" % (startDate, endDate, ext, path))
1101 1141
1102 1142 if include_path:
1103 1143 return dateList, pathList
1104 1144
1105 1145 return dateList
1106 1146
1107 1147 def setup(self, **kwargs):
1108 1148
1109 1149 self.set_kwargs(**kwargs)
1110 1150 if not self.ext.startswith('.'):
1111 1151 self.ext = '.{}'.format(self.ext)
1112 1152
1113 1153 if self.server is not None:
1114 1154 if 'tcp://' in self.server:
1115 1155 address = server
1116 1156 else:
1117 1157 address = 'ipc:///tmp/%s' % self.server
1118 1158 self.server = address
1119 1159 self.context = zmq.Context()
1120 1160 self.receiver = self.context.socket(zmq.PULL)
1121 1161 self.receiver.connect(self.server)
1122 1162 time.sleep(0.5)
1123 1163 print('[Starting] ReceiverData from {}'.format(self.server))
1124 1164 else:
1125 1165 self.server = None
1126 1166 if self.path == None:
1127 1167 raise ValueError("[Reading] The path is not valid")
1128 1168
1129 1169 if self.online:
1130 1170 log.log("[Reading] Searching files in online mode...", self.name)
1131 1171
1132 1172 for nTries in range(self.nTries):
1133 1173 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1134 1174 self.endDate, self.expLabel, self.ext, self.walk,
1135 1175 self.filefmt, self.folderfmt)
1136 1176
1137 1177 try:
1138 1178 fullpath = next(fullpath)
1139 1179 except:
1140 1180 fullpath = None
1141 1181
1142 1182 if fullpath:
1143 1183 break
1144 1184
1145 1185 log.warning(
1146 1186 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1147 1187 self.delay, self.path, nTries + 1),
1148 1188 self.name)
1149 1189 time.sleep(self.delay)
1150 1190
1151 1191 if not(fullpath):
1152 1192 raise schainpy.admin.SchainError(
1153 1193 'There isn\'t any valid file in {}'.format(self.path))
1154 1194
1155 1195 pathname, filename = os.path.split(fullpath)
1156 1196 self.year = int(filename[1:5])
1157 1197 self.doy = int(filename[5:8])
1158 1198 self.set = int(filename[8:11]) - 1
1159 1199 else:
1160 1200 log.log("Searching files in {}".format(self.path), self.name)
1161 1201 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1162 1202 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1163 1203
1164 1204 self.setNextFile()
1165 1205
1166 1206 return
1167 1207
1168 1208 def getBasicHeader(self):
1169 1209
1170 1210 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond / \
1171 1211 1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1172 1212
1173 1213 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1174 1214
1175 1215 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1176 1216
1177 1217 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1178 1218
1179 1219 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1180 1220
1181 1221 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1182 1222
1183 1223 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
1184 1224
1185 1225 def getFirstHeader(self):
1186 1226
1187 1227 raise NotImplementedError
1188 1228
1189 1229 def getData(self):
1190 1230
1191 1231 raise NotImplementedError
1192 1232
1193 1233 def hasNotDataInBuffer(self):
1194 1234
1195 1235 raise NotImplementedError
1196 1236
1197 1237 def readBlock(self):
1198 1238
1199 1239 raise NotImplementedError
1200 1240
1201 1241 def isEndProcess(self):
1202 1242
1203 1243 return self.flagNoMoreFiles
1204 1244
1205 1245 def printReadBlocks(self):
1206 1246
1207 1247 print("[Reading] Number of read blocks per file %04d" % self.nReadBlocks)
1208 1248
1209 1249 def printTotalBlocks(self):
1210 1250
1211 1251 print("[Reading] Number of read blocks %04d" % self.nTotalBlocks)
1212 1252
1213 1253 def run(self, **kwargs):
1214 1254 """
1215 1255
1216 1256 Arguments:
1217 1257 path :
1218 1258 startDate :
1219 1259 endDate :
1220 1260 startTime :
1221 1261 endTime :
1222 1262 set :
1223 1263 expLabel :
1224 1264 ext :
1225 1265 online :
1226 1266 delay :
1227 1267 walk :
1228 1268 getblock :
1229 1269 nTxs :
1230 1270 realtime :
1231 1271 blocksize :
1232 1272 blocktime :
1233 1273 skip :
1234 1274 cursor :
1235 1275 warnings :
1236 1276 server :
1237 1277 verbose :
1238 1278 format :
1239 1279 oneDDict :
1240 1280 twoDDict :
1241 1281 independentParam :
1242 1282 """
1243 1283
1244 1284 if not(self.isConfig):
1245 1285 self.setup(**kwargs)
1246 1286 self.isConfig = True
1247 1287 if self.server is None:
1248 1288 self.getData()
1249 1289 else:
1250 1290 self.getFromServer()
1251 1291
1252 1292
1253 1293 class JRODataWriter(Reader):
1254 1294
1255 1295 """
1256 1296 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1257 1297 de los datos siempre se realiza por bloques.
1258 1298 """
1259 1299
1260 1300 setFile = None
1261 1301 profilesPerBlock = None
1262 1302 blocksPerFile = None
1263 1303 nWriteBlocks = 0
1264 1304 fileDate = None
1265 1305
1266 1306 def __init__(self, dataOut=None):
1267 1307 raise NotImplementedError
1268 1308
1269 1309 def hasAllDataInBuffer(self):
1270 1310 raise NotImplementedError
1271 1311
1272 1312 def setBlockDimension(self):
1273 1313 raise NotImplementedError
1274 1314
1275 1315 def writeBlock(self):
1276 1316 raise NotImplementedError
1277 1317
1278 1318 def putData(self):
1279 1319 raise NotImplementedError
1280 1320
1281 1321 def getDtypeWidth(self):
1282 1322
1283 1323 dtype_index = get_dtype_index(self.dtype)
1284 1324 dtype_width = get_dtype_width(dtype_index)
1285 1325
1286 1326 return dtype_width
1287 1327
1288 1328 def getProcessFlags(self):
1289 1329
1290 1330 processFlags = 0
1291 1331
1292 1332 dtype_index = get_dtype_index(self.dtype)
1293 1333 procflag_dtype = get_procflag_dtype(dtype_index)
1294 1334
1295 1335 processFlags += procflag_dtype
1296 1336
1297 1337 if self.dataOut.flagDecodeData:
1298 1338 processFlags += PROCFLAG.DECODE_DATA
1299 1339
1300 1340 if self.dataOut.flagDeflipData:
1301 1341 processFlags += PROCFLAG.DEFLIP_DATA
1302 1342
1303 1343 if self.dataOut.code is not None:
1304 1344 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1305 1345
1306 1346 if self.dataOut.nCohInt > 1:
1307 1347 processFlags += PROCFLAG.COHERENT_INTEGRATION
1308 1348
1309 1349 if self.dataOut.type == "Spectra":
1310 1350 if self.dataOut.nIncohInt > 1:
1311 1351 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1312 1352
1313 1353 if self.dataOut.data_dc is not None:
1314 1354 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1315 1355
1316 1356 if self.dataOut.flagShiftFFT:
1317 1357 processFlags += PROCFLAG.SHIFT_FFT_DATA
1318 1358
1319 1359 return processFlags
1320 1360
1321 1361 def setBasicHeader(self):
1322 1362
1323 1363 self.basicHeaderObj.size = self.basicHeaderSize # bytes
1324 1364 self.basicHeaderObj.version = self.versionFile
1325 1365 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1326 1366 utc = numpy.floor(self.dataOut.utctime)
1327 1367 milisecond = (self.dataOut.utctime - utc) * 1000.0
1328 1368 self.basicHeaderObj.utc = utc
1329 1369 self.basicHeaderObj.miliSecond = milisecond
1330 1370 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1331 1371 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1332 1372 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1333 1373
1334 1374 def setFirstHeader(self):
1335 1375 """
1336 1376 Obtiene una copia del First Header
1337 1377
1338 1378 Affected:
1339 1379
1340 1380 self.basicHeaderObj
1341 1381 self.systemHeaderObj
1342 1382 self.radarControllerHeaderObj
1343 1383 self.processingHeaderObj self.
1344 1384
1345 1385 Return:
1346 1386 None
1347 1387 """
1348 1388
1349 1389 raise NotImplementedError
1350 1390
1351 1391 def __writeFirstHeader(self):
1352 1392 """
1353 1393 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1354 1394
1355 1395 Affected:
1356 1396 __dataType
1357 1397
1358 1398 Return:
1359 1399 None
1360 1400 """
1361 1401
1362 1402 # CALCULAR PARAMETROS
1363 1403
1364 1404 sizeLongHeader = self.systemHeaderObj.size + \
1365 1405 self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1366 1406 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1367 1407
1368 1408 self.basicHeaderObj.write(self.fp)
1369 1409 self.systemHeaderObj.write(self.fp)
1370 1410 self.radarControllerHeaderObj.write(self.fp)
1371 1411 self.processingHeaderObj.write(self.fp)
1372 1412
1373 1413 def __setNewBlock(self):
1374 1414 """
1375 1415 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1376 1416
1377 1417 Return:
1378 1418 0 : si no pudo escribir nada
1379 1419 1 : Si escribio el Basic el First Header
1380 1420 """
1381 1421 if self.fp == None:
1382 1422 self.setNextFile()
1383 1423
1384 1424 if self.flagIsNewFile:
1385 1425 return 1
1386 1426
1387 1427 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1388 1428 self.basicHeaderObj.write(self.fp)
1389 1429 return 1
1390 1430
1391 1431 if not(self.setNextFile()):
1392 1432 return 0
1393 1433
1394 1434 return 1
1395 1435
1396 1436 def writeNextBlock(self):
1397 1437 """
1398 1438 Selecciona el bloque siguiente de datos y los escribe en un file
1399 1439
1400 1440 Return:
1401 1441 0 : Si no hizo pudo escribir el bloque de datos
1402 1442 1 : Si no pudo escribir el bloque de datos
1403 1443 """
1404 1444 if not(self.__setNewBlock()):
1405 1445 return 0
1406 1446
1407 1447 self.writeBlock()
1408 1448
1409 1449 print("[Writing] Block No. %d/%d" % (self.blockIndex,
1410 1450 self.processingHeaderObj.dataBlocksPerFile))
1411 1451
1412 1452 return 1
1413 1453
1414 1454 def setNextFile(self):
1415 1455 """Determina el siguiente file que sera escrito
1416 1456
1417 1457 Affected:
1418 1458 self.filename
1419 1459 self.subfolder
1420 1460 self.fp
1421 1461 self.setFile
1422 1462 self.flagIsNewFile
1423 1463
1424 1464 Return:
1425 1465 0 : Si el archivo no puede ser escrito
1426 1466 1 : Si el archivo esta listo para ser escrito
1427 1467 """
1428 1468 ext = self.ext
1429 1469 path = self.path
1430 1470
1431 1471 if self.fp != None:
1432 1472 self.fp.close()
1433 1473
1434 1474 if not os.path.exists(path):
1435 1475 os.mkdir(path)
1436 1476
1437 1477 timeTuple = time.localtime(self.dataOut.utctime)
1438 1478 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
1439 1479
1440 1480 fullpath = os.path.join(path, subfolder)
1441 1481 setFile = self.setFile
1442 1482
1443 1483 if not(os.path.exists(fullpath)):
1444 1484 os.mkdir(fullpath)
1445 1485 setFile = -1 # inicializo mi contador de seteo
1446 1486 else:
1447 1487 filesList = os.listdir(fullpath)
1448 1488 if len(filesList) > 0:
1449 1489 filesList = sorted(filesList, key=str.lower)
1450 1490 filen = filesList[-1]
1451 1491 # el filename debera tener el siguiente formato
1452 1492 # 0 1234 567 89A BCDE (hex)
1453 1493 # x YYYY DDD SSS .ext
1454 1494 if isNumber(filen[8:11]):
1455 1495 # inicializo mi contador de seteo al seteo del ultimo file
1456 1496 setFile = int(filen[8:11])
1457 1497 else:
1458 1498 setFile = -1
1459 1499 else:
1460 1500 setFile = -1 # inicializo mi contador de seteo
1461 1501
1462 1502 setFile += 1
1463 1503
1464 1504 # If this is a new day it resets some values
1465 1505 if self.dataOut.datatime.date() > self.fileDate:
1466 1506 setFile = 0
1467 1507 self.nTotalBlocks = 0
1468 1508
1469 1509 filen = '{}{:04d}{:03d}{:03d}{}'.format(
1470 1510 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
1471 1511
1472 1512 filename = os.path.join(path, subfolder, filen)
1473 1513
1474 1514 fp = open(filename, 'wb')
1475 1515
1476 1516 self.blockIndex = 0
1477 1517 self.filename = filename
1478 1518 self.subfolder = subfolder
1479 1519 self.fp = fp
1480 1520 self.setFile = setFile
1481 1521 self.flagIsNewFile = 1
1482 1522 self.fileDate = self.dataOut.datatime.date()
1483 1523 self.setFirstHeader()
1484 1524
1485 1525 print('[Writing] Opening file: %s' % self.filename)
1486 1526
1487 1527 self.__writeFirstHeader()
1488 1528
1489 1529 return 1
1490 1530
1491 1531 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1492 1532 """
1493 1533 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1494 1534
1495 1535 Inputs:
1496 1536 path : directory where data will be saved
1497 1537 profilesPerBlock : number of profiles per block
1498 1538 set : initial file set
1499 1539 datatype : An integer number that defines data type:
1500 1540 0 : int8 (1 byte)
1501 1541 1 : int16 (2 bytes)
1502 1542 2 : int32 (4 bytes)
1503 1543 3 : int64 (8 bytes)
1504 1544 4 : float32 (4 bytes)
1505 1545 5 : double64 (8 bytes)
1506 1546
1507 1547 Return:
1508 1548 0 : Si no realizo un buen seteo
1509 1549 1 : Si realizo un buen seteo
1510 1550 """
1511 1551
1512 1552 if ext == None:
1513 1553 ext = self.ext
1514 1554
1515 1555 self.ext = ext.lower()
1516 1556
1517 1557 self.path = path
1518 1558
1519 1559 if set is None:
1520 1560 self.setFile = -1
1521 1561 else:
1522 1562 self.setFile = set - 1
1523 1563
1524 1564 self.blocksPerFile = blocksPerFile
1525 1565 self.profilesPerBlock = profilesPerBlock
1526 1566 self.dataOut = dataOut
1527 1567 self.fileDate = self.dataOut.datatime.date()
1528 1568 self.dtype = self.dataOut.dtype
1529 1569
1530 1570 if datatype is not None:
1531 1571 self.dtype = get_numpy_dtype(datatype)
1532 1572
1533 1573 if not(self.setNextFile()):
1534 1574 print("[Writing] There isn't a next file")
1535 1575 return 0
1536 1576
1537 1577 self.setBlockDimension()
1538 1578
1539 1579 return 1
1540 1580
1541 1581 def run(self, dataOut, path, blocksPerFile=100, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1542 1582
1543 1583 if not(self.isConfig):
1544 1584
1545 1585 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock,
1546 1586 set=set, ext=ext, datatype=datatype, **kwargs)
1547 1587 self.isConfig = True
1548 1588
1549 1589 self.dataOut = dataOut
1550 1590 self.putData()
1551 1591 return self.dataOut
1552 1592
1553 1593 @MPDecorator
1554 1594 class printInfo(Operation):
1555 1595
1556 1596 def __init__(self):
1557 1597
1558 1598 Operation.__init__(self)
1559 1599 self.__printInfo = True
1560 1600
1561 1601 def run(self, dataOut, headers = ['systemHeaderObj', 'radarControllerHeaderObj', 'processingHeaderObj']):
1562 1602 if self.__printInfo == False:
1563 1603 return
1564 1604
1565 1605 for header in headers:
1566 1606 if hasattr(dataOut, header):
1567 1607 obj = getattr(dataOut, header)
1568 1608 if hasattr(obj, 'printInfo'):
1569 1609 obj.printInfo()
1570 1610 else:
1571 1611 print(obj)
1572 1612 else:
1573 1613 log.warning('Header {} Not found in object'.format(header))
1574 1614
1575 1615 self.__printInfo = False
@@ -1,595 +1,629
1 1 '''
2 2 Created on Aug 1, 2017
3 3
4 4 @author: Juan C. Espinoza
5 5 '''
6 6
7 7 import os
8 8 import sys
9 9 import time
10 10 import json
11 11 import glob
12 12 import datetime
13 13
14 14 import numpy
15 15 import h5py
16 16
17 17 import schainpy.admin
18 18 from schainpy.model.io.jroIO_base import LOCALTIME, Reader
19 19 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
20 20 from schainpy.model.data.jrodata import Parameters
21 21 from schainpy.utils import log
22 22
23 23 try:
24 24 import madrigal.cedar
25 25 except:
26 26 pass
27 27
28 28 try:
29 29 basestring
30 30 except:
31 31 basestring = str
32 32
33 33 DEF_CATALOG = {
34 34 'principleInvestigator': 'Marco Milla',
35 35 'expPurpose': '',
36 36 'cycleTime': '',
37 37 'correlativeExp': '',
38 38 'sciRemarks': '',
39 39 'instRemarks': ''
40 40 }
41 41
42 42 DEF_HEADER = {
43 43 'kindatDesc': '',
44 44 'analyst': 'Jicamarca User',
45 45 'comments': '',
46 46 'history': ''
47 47 }
48 48
49 49 MNEMONICS = {
50 50 10: 'jro',
51 51 11: 'jbr',
52 52 840: 'jul',
53 53 13: 'jas',
54 54 1000: 'pbr',
55 55 1001: 'hbr',
56 56 1002: 'obr',
57 57 400: 'clr'
58 58
59 59 }
60 60
61 61 UT1970 = datetime.datetime(1970, 1, 1) - datetime.timedelta(seconds=time.timezone)
62 62
63 63 def load_json(obj):
64 64 '''
65 65 Parse json as string instead of unicode
66 66 '''
67 67
68 68 if isinstance(obj, str):
69 69 iterable = json.loads(obj)
70 70 else:
71 71 iterable = obj
72 72
73 73 if isinstance(iterable, dict):
74 74 return {str(k): load_json(v) if isinstance(v, dict) else str(v) if isinstance(v, basestring) else v
75 75 for k, v in list(iterable.items())}
76 76 elif isinstance(iterable, (list, tuple)):
77 77 return [str(v) if isinstance(v, basestring) else v for v in iterable]
78 78
79 79 return iterable
80 80
81 81
82 82 class MADReader(Reader, ProcessingUnit):
83 83
84 84 def __init__(self):
85 85
86 86 ProcessingUnit.__init__(self)
87 87
88 88 self.dataOut = Parameters()
89 89 self.counter_records = 0
90 90 self.nrecords = None
91 91 self.flagNoMoreFiles = 0
92 92 self.filename = None
93 93 self.intervals = set()
94 94 self.datatime = datetime.datetime(1900,1,1)
95 95 self.format = None
96 96 self.filefmt = "***%Y%m%d*******"
97 97
98 98 def setup(self, **kwargs):
99 99
100 100 self.set_kwargs(**kwargs)
101 101 self.oneDDict = load_json(self.oneDDict)
102 102 self.twoDDict = load_json(self.twoDDict)
103 103 self.ind2DList = load_json(self.ind2DList)
104 104 self.independentParam = self.ind2DList[0]
105 105
106 106 if self.path is None:
107 107 raise ValueError('The path is not valid')
108 108
109 109 self.open_file = open
110 110 self.open_mode = 'rb'
111 111
112 112 if self.format is None:
113 113 raise ValueError('The format is not valid choose simple or hdf5')
114 114 elif self.format.lower() in ('simple', 'txt'):
115 115 self.ext = '.txt'
116 116 elif self.format.lower() in ('cedar',):
117 117 self.ext = '.001'
118 118 else:
119 119 self.ext = '.hdf5'
120 120 self.open_file = h5py.File
121 121 self.open_mode = 'r'
122 122
123 123 if self.online:
124 124 log.log("Searching files in online mode...", self.name)
125 125
126 126 for nTries in range(self.nTries):
127 127 fullpath = self.searchFilesOnLine(self.path, self.startDate,
128 128 self.endDate, self.expLabel, self.ext, self.walk,
129 129 self.filefmt, self.folderfmt)
130 130
131 131 try:
132 132 fullpath = next(fullpath)
133 133 except:
134 134 fullpath = None
135 135
136 136 if fullpath:
137 137 break
138 138
139 139 log.warning(
140 140 'Waiting {} sec for a valid file in {}: try {} ...'.format(
141 141 self.delay, self.path, nTries + 1),
142 142 self.name)
143 143 time.sleep(self.delay)
144 144
145 145 if not(fullpath):
146 146 raise schainpy.admin.SchainError(
147 147 'There isn\'t any valid file in {}'.format(self.path))
148 148
149 149 else:
150 150 log.log("Searching files in {}".format(self.path), self.name)
151 151 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
152 152 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
153 153
154 154 self.setNextFile()
155 155
156 156 def readFirstHeader(self):
157 157 '''Read header and data'''
158 158
159 159 self.parseHeader()
160 160 self.parseData()
161 161 self.blockIndex = 0
162 162
163 163 return
164 164
165 165 def parseHeader(self):
166 166 '''
167 167 '''
168 168
169 169 self.output = {}
170 170 self.version = '2'
171 171 s_parameters = None
172 172 if self.ext == '.txt':
173 173 self.parameters = [s.strip().lower() for s in self.fp.readline().decode().strip().split(' ') if s]
174 174 elif self.ext == '.hdf5':
175 175 self.metadata = self.fp['Metadata']
176 176 if '_record_layout' in self.metadata:
177 177 s_parameters = [s[0].lower().decode() for s in self.metadata['Independent Spatial Parameters']]
178 178 self.version = '3'
179 179 self.parameters = [s[0].lower().decode() for s in self.metadata['Data Parameters']]
180 180
181 181 log.success('Parameters found: {}'.format(self.parameters),
182 182 'MADReader')
183 183 if s_parameters:
184 184 log.success('Spatial parameters found: {}'.format(s_parameters),
185 185 'MADReader')
186 186
187 187 for param in list(self.oneDDict.keys()):
188 188 if param.lower() not in self.parameters:
189 189 log.warning(
190 190 'Parameter {} not found will be ignored'.format(
191 191 param),
192 192 'MADReader')
193 193 self.oneDDict.pop(param, None)
194 194
195 195 for param, value in list(self.twoDDict.items()):
196 196 if param.lower() not in self.parameters:
197 197 log.warning(
198 198 'Parameter {} not found, it will be ignored'.format(
199 199 param),
200 200 'MADReader')
201 201 self.twoDDict.pop(param, None)
202 202 continue
203 203 if isinstance(value, list):
204 204 if value[0] not in self.output:
205 205 self.output[value[0]] = []
206 206 self.output[value[0]].append([])
207 207
208 208 def parseData(self):
209 209 '''
210 210 '''
211 211
212 212 if self.ext == '.txt':
213 213 self.data = numpy.genfromtxt(self.fp, missing_values=('missing'))
214 214 self.nrecords = self.data.shape[0]
215 215 self.ranges = numpy.unique(self.data[:,self.parameters.index(self.independentParam.lower())])
216 216 self.counter_records = 0
217 217 elif self.ext == '.hdf5':
218 218 self.data = self.fp['Data']
219 219 self.ranges = numpy.unique(self.data['Table Layout'][self.independentParam.lower()])
220 220 self.times = numpy.unique(self.data['Table Layout']['ut1_unix'])
221 221 self.counter_records = int(self.data['Table Layout']['recno'][0])
222 222 self.nrecords = int(self.data['Table Layout']['recno'][-1])
223 223
224 224 def readNextBlock(self):
225 225
226 226 while True:
227 227 self.flagDiscontinuousBlock = 0
228 228 if self.counter_records == self.nrecords:
229 229 self.setNextFile()
230 230
231 231 self.readBlock()
232 232
233 233 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
234 234 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
235 235 log.warning(
236 236 'Reading Record No. {}/{} -> {} [Skipping]'.format(
237 237 self.counter_records,
238 238 self.nrecords,
239 239 self.datatime.ctime()),
240 240 'MADReader')
241 241 continue
242 242 break
243 243
244 244 log.log(
245 245 'Reading Record No. {}/{} -> {}'.format(
246 246 self.counter_records,
247 247 self.nrecords,
248 248 self.datatime.ctime()),
249 249 'MADReader')
250 250
251 251 return 1
252 252
253 253 def readBlock(self):
254 254 '''
255 255 '''
256 256 dum = []
257 257 if self.ext == '.txt':
258 258 dt = self.data[self.counter_records][:6].astype(int)
259 259 if datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5]).date() > self.datatime.date():
260 260 self.flagDiscontinuousBlock = 1
261 261 self.datatime = datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
262 262 while True:
263 263 dt = self.data[self.counter_records][:6].astype(int)
264 264 datatime = datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
265 265 if datatime == self.datatime:
266 266 dum.append(self.data[self.counter_records])
267 267 self.counter_records += 1
268 268 if self.counter_records == self.nrecords:
269 269 break
270 270 continue
271 271 self.intervals.add((datatime-self.datatime).seconds)
272 272 break
273 273 elif self.ext == '.hdf5':
274 274 datatime = datetime.datetime.utcfromtimestamp(
275 275 self.times[self.counter_records])
276 276 dum = self.data['Table Layout'][self.data['Table Layout']['recno']==self.counter_records]
277 277 self.intervals.add((datatime-self.datatime).seconds)
278 278 if datatime.date()>self.datatime.date():
279 279 self.flagDiscontinuousBlock = 1
280 280 self.datatime = datatime
281 281 self.counter_records += 1
282 282
283 283 self.buffer = numpy.array(dum)
284 284 return
285 285
286 286 def set_output(self):
287 287 '''
288 288 Storing data from buffer to dataOut object
289 289 '''
290 290
291 291 parameters = [None for __ in self.parameters]
292 292
293 293 for param, attr in list(self.oneDDict.items()):
294 294 x = self.parameters.index(param.lower())
295 295 setattr(self.dataOut, attr, self.buffer[0][x])
296 296
297 297 for param, value in list(self.twoDDict.items()):
298 298 dummy = numpy.zeros(self.ranges.shape) + numpy.nan
299 299 if self.ext == '.txt':
300 300 x = self.parameters.index(param.lower())
301 301 y = self.parameters.index(self.independentParam.lower())
302 302 ranges = self.buffer[:,y]
303 303 #if self.ranges.size == ranges.size:
304 304 # continue
305 305 index = numpy.where(numpy.in1d(self.ranges, ranges))[0]
306 306 dummy[index] = self.buffer[:,x]
307 307 else:
308 308 ranges = self.buffer[self.independentParam.lower()]
309 309 index = numpy.where(numpy.in1d(self.ranges, ranges))[0]
310 310 dummy[index] = self.buffer[param.lower()]
311 311
312 312 if isinstance(value, str):
313 313 if value not in self.independentParam:
314 314 setattr(self.dataOut, value, dummy.reshape(1,-1))
315 315 elif isinstance(value, list):
316 316 self.output[value[0]][value[1]] = dummy
317 317 parameters[value[1]] = param
318 318 for key, value in list(self.output.items()):
319 319 setattr(self.dataOut, key, numpy.array(value))
320 320
321 321 self.dataOut.parameters = [s for s in parameters if s]
322 322 self.dataOut.heightList = self.ranges
323 323 self.dataOut.utctime = (self.datatime - datetime.datetime(1970, 1, 1)).total_seconds()
324 324 self.dataOut.utctimeInit = self.dataOut.utctime
325 325 self.dataOut.paramInterval = min(self.intervals)
326 326 self.dataOut.useLocalTime = False
327 327 self.dataOut.flagNoData = False
328 328 self.dataOut.nrecords = self.nrecords
329 329 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
330 330
331 331 def getData(self):
332 332 '''
333 333 Storing data from databuffer to dataOut object
334 334 '''
335 335
336 336 if not self.readNextBlock():
337 337 self.dataOut.flagNoData = True
338 338 return 0
339 339
340 340 self.set_output()
341 341
342 342 return 1
343 343
344 344 def run(self, **kwargs):
345 345
346 346 if not(self.isConfig):
347 347 self.setup(**kwargs)
348 348 self.isConfig = True
349 349
350 350 self.getData()
351 351
352 352 return
353 353
354 354 @MPDecorator
355 355 class MADWriter(Operation):
356 356 '''Writing module for Madrigal files
357 357
358 358 type: external
359 359
360 360 Inputs:
361 361 path path where files will be created
362 362 oneDDict json of one-dimensional parameters in record where keys
363 363 are Madrigal codes (integers or mnemonics) and values the corresponding
364 364 dataOut attribute e.g: {
365 365 'gdlatr': 'lat',
366 366 'gdlonr': 'lon',
367 367 'gdlat2':'lat',
368 368 'glon2':'lon'}
369 369 ind2DList list of independent spatial two-dimensional parameters e.g:
370 370 ['heigthList']
371 371 twoDDict json of two-dimensional parameters in record where keys
372 372 are Madrigal codes (integers or mnemonics) and values the corresponding
373 373 dataOut attribute if multidimensional array specify as tupple
374 374 ('attr', pos) e.g: {
375 375 'gdalt': 'heightList',
376 376 'vn1p2': ('data_output', 0),
377 377 'vn2p2': ('data_output', 1),
378 378 'vn3': ('data_output', 2),
379 379 'snl': ('data_SNR', 'db')
380 380 }
381 381 metadata json of madrigal metadata (kinst, kindat, catalog and header)
382 382 format hdf5, cedar
383 383 blocks number of blocks per file'''
384 384
385 385 __attrs__ = ['path', 'oneDDict', 'ind2DList', 'twoDDict','metadata', 'format', 'blocks']
386 386 missing = -32767
387 387
388 388 def __init__(self):
389 389
390 390 Operation.__init__(self)
391 391 self.dataOut = Parameters()
392 392 self.counter = 0
393 393 self.path = None
394 394 self.fp = None
395 395
396 396 def run(self, dataOut, path, oneDDict, ind2DList='[]', twoDDict='{}',
397 397 metadata='{}', format='cedar', **kwargs):
398 398
399
400 #if dataOut.AUX==1: #Modified
401
399 402 if not self.isConfig:
400 403 self.setup(path, oneDDict, ind2DList, twoDDict, metadata, format, **kwargs)
401 404 self.isConfig = True
402 405
403 406 self.dataOut = dataOut
404 407 self.putData()
408
405 409 return 1
406 410
407 411 def setup(self, path, oneDDict, ind2DList, twoDDict, metadata, format, **kwargs):
408 412 '''
409 413 Configure Operation
410 414 '''
411 415
412 416 self.path = path
413 417 self.blocks = kwargs.get('blocks', None)
414 418 self.counter = 0
415 419 self.oneDDict = load_json(oneDDict)
416 420 self.twoDDict = load_json(twoDDict)
417 421 self.ind2DList = load_json(ind2DList)
418 422 meta = load_json(metadata)
419 423 self.kinst = meta.get('kinst')
420 424 self.kindat = meta.get('kindat')
421 425 self.catalog = meta.get('catalog', DEF_CATALOG)
422 426 self.header = meta.get('header', DEF_HEADER)
423 427 if format == 'cedar':
424 428 self.ext = '.dat'
425 429 self.extra_args = {}
426 430 elif format == 'hdf5':
427 431 self.ext = '.hdf5'
428 432 self.extra_args = {'ind2DList': self.ind2DList}
429 433
430 434 self.keys = [k.lower() for k in self.twoDDict]
431 435 if 'range' in self.keys:
432 436 self.keys.remove('range')
433 437 if 'gdalt' in self.keys:
434 438 self.keys.remove('gdalt')
435 439
436 440 def setFile(self):
437 441 '''
438 442 Create new cedar file object
439 443 '''
440 444
441 445 self.mnemonic = MNEMONICS[self.kinst] #TODO get mnemonic from madrigal
442 446 date = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
447 #if self.dataOut.input_dat_type:
448 #date=datetime.datetime.fromtimestamp(self.dataOut.TimeBlockSeconds_for_dp_power)
449 #print("date",date)
443 450
444 451 filename = '{}{}{}'.format(self.mnemonic,
445 452 date.strftime('%Y%m%d_%H%M%S'),
446 453 self.ext)
447 454
448 455 self.fullname = os.path.join(self.path, filename)
449 456
450 457 if os.path.isfile(self.fullname) :
451 458 log.warning(
452 459 'Destination file {} already exists, previous file deleted.'.format(
453 460 self.fullname),
454 461 'MADWriter')
455 462 os.remove(self.fullname)
456 463
457 464 try:
458 465 log.success(
459 466 'Creating file: {}'.format(self.fullname),
460 467 'MADWriter')
461 468 if not os.path.exists(self.path):
462 469 os.makedirs(self.path)
463 470 self.fp = madrigal.cedar.MadrigalCedarFile(self.fullname, True)
471
472
464 473 except ValueError as e:
465 474 log.error(
466 475 'Impossible to create a cedar object with "madrigal.cedar.MadrigalCedarFile"',
467 476 'MADWriter')
468 477 return
469 478
470 479 return 1
471 480
472 481 def writeBlock(self):
473 482 '''
474 483 Add data records to cedar file taking data from oneDDict and twoDDict
475 484 attributes.
476 485 Allowed parameters in: parcodes.tab
477 486 '''
478
487 #self.dataOut.paramInterval=2
479 488 startTime = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
489
480 490 endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
491
492 #if self.dataOut.input_dat_type:
493 #if self.dataOut.experiment=="DP":
494 #startTime=datetime.datetime.fromtimestamp(self.dataOut.TimeBlockSeconds_for_dp_power)
495 #endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
496
497
498 #print("2: ",startTime)
499 #print(endTime)
481 500 heights = self.dataOut.heightList
482 501
502 #print(self.blocks)
503 #print(startTime)
504 #print(endTime)
505 #print(heights)
506 #input()
483 507 if self.ext == '.dat':
484 508 for key, value in list(self.twoDDict.items()):
485 509 if isinstance(value, str):
486 510 data = getattr(self.dataOut, value)
487 511 invalid = numpy.isnan(data)
488 512 data[invalid] = self.missing
489 513 elif isinstance(value, (tuple, list)):
490 514 attr, key = value
491 515 data = getattr(self.dataOut, attr)
492 516 invalid = numpy.isnan(data)
493 517 data[invalid] = self.missing
494 518
495 519 out = {}
496 520 for key, value in list(self.twoDDict.items()):
497 521 key = key.lower()
498 522 if isinstance(value, str):
499 523 if 'db' in value.lower():
500 524 tmp = getattr(self.dataOut, value.replace('_db', ''))
501 525 SNRavg = numpy.average(tmp, axis=0)
502 526 tmp = 10*numpy.log10(SNRavg)
503 527 else:
504 528 tmp = getattr(self.dataOut, value)
505 529 out[key] = tmp.flatten()[:len(heights)]
506 530 elif isinstance(value, (tuple, list)):
507 531 attr, x = value
508 532 data = getattr(self.dataOut, attr)
533 #print(x)
534 #print(len(heights))
535 #print(data[int(x)][:len(heights)])
536 #print(numpy.shape(out))
537 #print(numpy.shape(data))
538
509 539 out[key] = data[int(x)][:len(heights)]
510 540
511 541 a = numpy.array([out[k] for k in self.keys])
542 #print(a)
512 543 nrows = numpy.array([numpy.isnan(a[:, x]).all() for x in range(len(heights))])
513 544 index = numpy.where(nrows == False)[0]
514 545
546 #print(startTime.minute)
515 547 rec = madrigal.cedar.MadrigalDataRecord(
516 548 self.kinst,
517 549 self.kindat,
518 550 startTime.year,
519 551 startTime.month,
520 552 startTime.day,
521 553 startTime.hour,
522 554 startTime.minute,
523 555 startTime.second,
524 556 startTime.microsecond/10000,
525 557 endTime.year,
526 558 endTime.month,
527 559 endTime.day,
528 560 endTime.hour,
529 561 endTime.minute,
530 562 endTime.second,
531 563 endTime.microsecond/10000,
532 564 list(self.oneDDict.keys()),
533 565 list(self.twoDDict.keys()),
534 566 len(index),
535 567 **self.extra_args
536 568 )
537
569 #print("rec",rec)
538 570 # Setting 1d values
539 571 for key in self.oneDDict:
540 572 rec.set1D(key, getattr(self.dataOut, self.oneDDict[key]))
541 573
542 574 # Setting 2d values
543 575 nrec = 0
544 576 for n in index:
545 577 for key in out:
546 578 rec.set2D(key, nrec, out[key][n])
547 579 nrec += 1
548 580
549 581 self.fp.append(rec)
550 if self.ext == '.hdf5' and self.counter % 500 == 0 and self.counter > 0:
582 if self.ext == '.hdf5' and self.counter %2 == 0 and self.counter > 0:
583 #print("here")
551 584 self.fp.dump()
552 585 if self.counter % 20 == 0 and self.counter > 0:
586 #self.fp.write()
553 587 log.log(
554 588 'Writing {} records'.format(
555 589 self.counter),
556 590 'MADWriter')
557 591
558 592 def setHeader(self):
559 593 '''
560 594 Create an add catalog and header to cedar file
561 595 '''
562 596
563 597 log.success('Closing file {}'.format(self.fullname), 'MADWriter')
564 598
565 599 if self.ext == '.dat':
566 600 self.fp.write()
567 601 else:
568 602 self.fp.dump()
569 603 self.fp.close()
570 604
571 605 header = madrigal.cedar.CatalogHeaderCreator(self.fullname)
572 606 header.createCatalog(**self.catalog)
573 607 header.createHeader(**self.header)
574 608 header.write()
575 609
576 610 def putData(self):
577 611
578 612 if self.dataOut.flagNoData:
579 613 return 0
580 614
581 615 if self.dataOut.flagDiscontinuousBlock or self.counter == self.blocks:
582 616 if self.counter > 0:
583 617 self.setHeader()
584 618 self.counter = 0
585 619
586 620 if self.counter == 0:
587 621 self.setFile()
588 622
589 623 self.writeBlock()
590 624 self.counter += 1
591 625
592 626 def close(self):
593 627
594 628 if self.counter > 0:
595 629 self.setHeader()
1 NO CONTENT: modified file
@@ -1,676 +1,692
1 1 '''
2 2 Created on Jul 2, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6
7 7 import numpy
8 8
9 9 from .jroIO_base import LOCALTIME, JRODataReader, JRODataWriter
10 10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 11 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
12 12 from schainpy.model.data.jrodata import Voltage
13 13
14 14
15 15 class VoltageReader(JRODataReader, ProcessingUnit):
16 16 """
17 17 Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura
18 18 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones:
19 19 perfiles*alturas*canales) son almacenados en la variable "buffer".
20 20
21 21 perfiles * alturas * canales
22 22
23 23 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
24 24 RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la
25 25 cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de
26 26 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
27 27
28 28 Example:
29 29
30 30 dpath = "/home/myuser/data"
31 31
32 32 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
33 33
34 34 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
35 35
36 36 readerObj = VoltageReader()
37 37
38 38 readerObj.setup(dpath, startTime, endTime)
39 39
40 40 while(True):
41 41
42 42 #to get one profile
43 43 profile = readerObj.getData()
44 44
45 45 #print the profile
46 46 print profile
47 47
48 48 #If you want to see all datablock
49 49 print readerObj.datablock
50 50
51 51 if readerObj.flagNoMoreFiles:
52 52 break
53 53
54 54 """
55 55
56 56 def __init__(self):
57 57 """
58 58 Inicializador de la clase VoltageReader para la lectura de datos de voltage.
59 59
60 60 Input:
61 61 dataOut : Objeto de la clase Voltage. Este objeto sera utilizado para
62 62 almacenar un perfil de datos cada vez que se haga un requerimiento
63 63 (getData). El perfil sera obtenido a partir del buffer de datos,
64 64 si el buffer esta vacio se hara un nuevo proceso de lectura de un
65 65 bloque de datos.
66 66 Si este parametro no es pasado se creara uno internamente.
67 67
68 68 Variables afectadas:
69 69 self.dataOut
70 70
71 71 Return:
72 72 None
73 73 """
74 74
75 75 ProcessingUnit.__init__(self)
76 76
77 77 self.ext = ".r"
78 78 self.optchar = "D"
79 79 self.basicHeaderObj = BasicHeader(LOCALTIME)
80 80 self.systemHeaderObj = SystemHeader()
81 81 self.radarControllerHeaderObj = RadarControllerHeader()
82
82 83 self.processingHeaderObj = ProcessingHeader()
83 84 self.lastUTTime = 0
84 85 self.profileIndex = 2**32 - 1
85 86 self.dataOut = Voltage()
86 87 self.selBlocksize = None
87 88 self.selBlocktime = None
88
89 ##print("1--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
89 90 def createObjByDefault(self):
90
91 ##print("2--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
91 92 dataObj = Voltage()
92 93
93 94 return dataObj
94 95
95 96 def __hasNotDataInBuffer(self):
96
97 ##print("3--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
97 98 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock * self.nTxs:
98 99 return 1
99 100
100 101 return 0
101 102
102 103 def getBlockDimension(self):
103 104 """
104 105 Obtiene la cantidad de puntos a leer por cada bloque de datos
105 106
106 107 Affected:
107 108 self.blocksize
108 109
109 110 Return:
110 111 None
111 112 """
113 ##print("4--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
112 114 pts2read = self.processingHeaderObj.profilesPerBlock * \
113 115 self.processingHeaderObj.nHeights * self.systemHeaderObj.nChannels
114 116 self.blocksize = pts2read
115 117
116 118 def readBlock(self):
119
117 120 """
118 121 readBlock lee el bloque de datos desde la posicion actual del puntero del archivo
119 122 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
120 123 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
121 124 es seteado a 0
122 125
123 126 Inputs:
124 127 None
125 128
126 129 Return:
127 130 None
128 131
129 132 Affected:
130 133 self.profileIndex
131 134 self.datablock
132 135 self.flagIsNewFile
133 136 self.flagIsNewBlock
134 137 self.nTotalBlocks
135 138
136 139 Exceptions:
137 140 Si un bloque leido no es un bloque valido
138 141 """
139
142 ##print("5--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
140 143 # if self.server is not None:
141 144 # self.zBlock = self.receiver.recv()
142 145 # self.zHeader = self.zBlock[:24]
143 146 # self.zDataBlock = self.zBlock[24:]
144 147 # junk = numpy.fromstring(self.zDataBlock, numpy.dtype([('real','<i4'),('imag','<i4')]))
145 148 # self.processingHeaderObj.profilesPerBlock = 240
146 149 # self.processingHeaderObj.nHeights = 248
147 150 # self.systemHeaderObj.nChannels
148 151 # else:
149 152 current_pointer_location = self.fp.tell()
150 153 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
151 154
152 155 try:
153 156 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
154 157 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
155 158 except:
156 159 # print "The read block (%3d) has not enough data" %self.nReadBlocks
157 160
158 161 if self.waitDataBlock(pointer_location=current_pointer_location):
159 162 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
160 163 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
161 164 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
162 165 # return 0
163 166
164 167 # Dimensions : nChannels, nProfiles, nSamples
165 168
166 169 junk = numpy.transpose(junk, (2, 0, 1))
167 170 self.datablock = junk['real'] + junk['imag'] * 1j
168 171
169 172 self.profileIndex = 0
170 173
171 174 self.flagIsNewFile = 0
172 175 self.flagIsNewBlock = 1
173 176
174 177 self.nTotalBlocks += 1
175 178 self.nReadBlocks += 1
176 179
177 180 return 1
178 181
179 182 def getFirstHeader(self):
183 ##print("6--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
180 184
181 185 self.getBasicHeader()
182 186
183 187 self.dataOut.processingHeaderObj = self.processingHeaderObj.copy()
184 188
185 189 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
186 190
187 191 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
188 192
193 #self.dataOut.ippSeconds_general=self.radarControllerHeaderObj.ippSeconds
194 #print(self.nTxs)
189 195 if self.nTxs > 1:
196 #print(self.radarControllerHeaderObj.ippSeconds)
190 197 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
198 #print(self.radarControllerHeaderObj.ippSeconds)
191 199 # Time interval and code are propierties of dataOut. Its value depends of radarControllerHeaderObj.
192 200
193 201 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt
194 202 #
195 203 # if self.radarControllerHeaderObj.code is not None:
196 204 #
197 205 # self.dataOut.nCode = self.radarControllerHeaderObj.nCode
198 206 #
199 207 # self.dataOut.nBaud = self.radarControllerHeaderObj.nBaud
200 208 #
201 209 # self.dataOut.code = self.radarControllerHeaderObj.code
202 210
203 211 self.dataOut.dtype = self.dtype
204 212
205 213 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
206 214
207 215 self.dataOut.heightList = numpy.arange(
208 216 self.processingHeaderObj.nHeights) * self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
209 217
210 218 self.dataOut.channelList = list(range(self.systemHeaderObj.nChannels))
211 219
212 220 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
213 221
214 222 # asumo q la data no esta decodificada
215 223 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode
216 224
217 225 # asumo q la data no esta sin flip
218 226 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip
219 227
220 228 self.dataOut.flagShiftFFT = self.processingHeaderObj.shif_fft
221 229
222 230 def reshapeData(self):
223
231 ##print("7--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
224 232 if self.nTxs < 0:
225 233 return
226 234
227 235 if self.nTxs == 1:
228 236 return
229 237
230 238 if self.nTxs < 1 and self.processingHeaderObj.profilesPerBlock % (1. / self.nTxs) != 0:
231 239 raise ValueError("1./nTxs (=%f), should be a multiple of nProfiles (=%d)" % (
232 240 1. / self.nTxs, self.processingHeaderObj.profilesPerBlock))
233 241
234 242 if self.nTxs > 1 and self.processingHeaderObj.nHeights % self.nTxs != 0:
235 243 raise ValueError("nTxs (=%d), should be a multiple of nHeights (=%d)" % (
236 244 self.nTxs, self.processingHeaderObj.nHeights))
237 245
238 246 self.datablock = self.datablock.reshape(
239 247 (self.systemHeaderObj.nChannels, self.processingHeaderObj.profilesPerBlock * self.nTxs, int(self.processingHeaderObj.nHeights / self.nTxs)))
240 248
241 249 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock * self.nTxs
242 250 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights / self.nTxs) * \
243 251 self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
244 252 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
245 253
246 254 return
247 255
248 256 def readFirstHeaderFromServer(self):
249 257
258 ##print("8--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
250 259 self.getFirstHeader()
251 260
252 261 self.firstHeaderSize = self.basicHeaderObj.size
253 262
254 263 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
255 264 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
256 265 if datatype == 0:
257 266 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
258 267 elif datatype == 1:
259 268 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
260 269 elif datatype == 2:
261 270 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
262 271 elif datatype == 3:
263 272 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
264 273 elif datatype == 4:
265 274 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
266 275 elif datatype == 5:
267 276 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
268 277 else:
269 278 raise ValueError('Data type was not defined')
270 279
271 280 self.dtype = datatype_str
272 281 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
273 282 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
274 283 self.firstHeaderSize + self.basicHeaderSize * \
275 284 (self.processingHeaderObj.dataBlocksPerFile - 1)
276 285 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
277 286 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
278 287 self.getBlockDimension()
279 288
280 289 def getFromServer(self):
290 ##print("9--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
281 291 self.flagDiscontinuousBlock = 0
282 292 self.profileIndex = 0
283 293 self.flagIsNewBlock = 1
284 294 self.dataOut.flagNoData = False
285 295 self.nTotalBlocks += 1
286 296 self.nReadBlocks += 1
287 297 self.blockPointer = 0
288 298
289 299 block = self.receiver.recv()
290 300
291 301 self.basicHeaderObj.read(block[self.blockPointer:])
292 302 self.blockPointer += self.basicHeaderObj.length
293 303 self.systemHeaderObj.read(block[self.blockPointer:])
294 304 self.blockPointer += self.systemHeaderObj.length
295 305 self.radarControllerHeaderObj.read(block[self.blockPointer:])
296 306 self.blockPointer += self.radarControllerHeaderObj.length
297 307 self.processingHeaderObj.read(block[self.blockPointer:])
298 308 self.blockPointer += self.processingHeaderObj.length
299 309 self.readFirstHeaderFromServer()
300 310
301 311 timestamp = self.basicHeaderObj.get_datatime()
302 312 print('[Reading] - Block {} - {}'.format(self.nTotalBlocks, timestamp))
303 313 current_pointer_location = self.blockPointer
304 314 junk = numpy.fromstring(
305 315 block[self.blockPointer:], self.dtype, self.blocksize)
306 316
307 317 try:
308 318 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
309 319 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
310 320 except:
311 321 # print "The read block (%3d) has not enough data" %self.nReadBlocks
312 322 if self.waitDataBlock(pointer_location=current_pointer_location):
313 323 junk = numpy.fromstring(
314 324 block[self.blockPointer:], self.dtype, self.blocksize)
315 325 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
316 326 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
317 327 # return 0
318 328
319 329 # Dimensions : nChannels, nProfiles, nSamples
320 330
321 331 junk = numpy.transpose(junk, (2, 0, 1))
322 332 self.datablock = junk['real'] + junk['imag'] * 1j
323 333 self.profileIndex = 0
324 334 if self.selBlocksize == None:
325 335 self.selBlocksize = self.dataOut.nProfiles
326 336 if self.selBlocktime != None:
327 337 if self.dataOut.nCohInt is not None:
328 338 nCohInt = self.dataOut.nCohInt
329 339 else:
330 340 nCohInt = 1
331 341 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
332 342 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
333 343 self.dataOut.data = self.datablock[:,
334 344 self.profileIndex:self.profileIndex + self.selBlocksize, :]
335 345 datasize = self.dataOut.data.shape[1]
336 346 if datasize < self.selBlocksize:
337 347 buffer = numpy.zeros(
338 348 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
339 349 buffer[:, :datasize, :] = self.dataOut.data
340 350 self.dataOut.data = buffer
341 351 self.profileIndex = blockIndex
342 352
343 353 self.dataOut.flagDataAsBlock = True
344 354 self.flagIsNewBlock = 1
345 355 self.dataOut.realtime = self.online
346 356
347 357 return self.dataOut.data
348 358
349 359 def getData(self):
350 360 """
351 361 getData obtiene una unidad de datos del buffer de lectura, un perfil, y la copia al objeto self.dataOut
352 362 del tipo "Voltage" con todos los parametros asociados a este (metadata). cuando no hay datos
353 363 en el buffer de lectura es necesario hacer una nueva lectura de los bloques de datos usando
354 364 "readNextBlock"
355 365
356 366 Ademas incrementa el contador del buffer "self.profileIndex" en 1.
357 367
358 368 Return:
359 369
360 370 Si el flag self.getByBlock ha sido seteado el bloque completo es copiado a self.dataOut y el self.profileIndex
361 371 es igual al total de perfiles leidos desde el archivo.
362 372
363 373 Si self.getByBlock == False:
364 374
365 375 self.dataOut.data = buffer[:, thisProfile, :]
366 376
367 377 shape = [nChannels, nHeis]
368 378
369 379 Si self.getByBlock == True:
370 380
371 381 self.dataOut.data = buffer[:, :, :]
372 382
373 383 shape = [nChannels, nProfiles, nHeis]
374 384
375 385 Variables afectadas:
376 386 self.dataOut
377 387 self.profileIndex
378 388
379 389 Affected:
380 390 self.dataOut
381 391 self.profileIndex
382 392 self.flagDiscontinuousBlock
383 393 self.flagIsNewBlock
384 394 """
395
396 ##print("10--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
385 397 if self.flagNoMoreFiles:
386 398 self.dataOut.flagNoData = True
387 399 return 0
388 400 self.flagDiscontinuousBlock = 0
389 401 self.flagIsNewBlock = 0
390 402 if self.__hasNotDataInBuffer():
391 403 if not(self.readNextBlock()):
392 404 return 0
393 405
394 406 self.getFirstHeader()
395 407
396 408 self.reshapeData()
397 409 if self.datablock is None:
398 410 self.dataOut.flagNoData = True
399 411 return 0
400 412
401 413 if not self.getByBlock:
402 414
403 415 """
404 416 Return profile by profile
405 417
406 418 If nTxs > 1 then one profile is divided by nTxs and number of total
407 419 blocks is increased by nTxs (nProfiles *= nTxs)
408 420 """
409 421 self.dataOut.flagDataAsBlock = False
410 422 self.dataOut.data = self.datablock[:, self.profileIndex, :]
411 423 self.dataOut.profileIndex = self.profileIndex
412 424
425
413 426 self.profileIndex += 1
414 427
415 428 else:
416 429 """
417 430 Return a block
418 431 """
419 432 if self.selBlocksize == None:
420 433 self.selBlocksize = self.dataOut.nProfiles
421 434 if self.selBlocktime != None:
422 435 if self.dataOut.nCohInt is not None:
423 436 nCohInt = self.dataOut.nCohInt
424 437 else:
425 438 nCohInt = 1
426 439 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
427 440 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
428 441
429 442 self.dataOut.data = self.datablock[:,
430 443 self.profileIndex:self.profileIndex + self.selBlocksize, :]
431 444 self.profileIndex += self.selBlocksize
432 445 datasize = self.dataOut.data.shape[1]
433 446
434 447 if datasize < self.selBlocksize:
435 448 buffer = numpy.zeros(
436 449 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
437 450 buffer[:, :datasize, :] = self.dataOut.data
438 451
439 452 while datasize < self.selBlocksize: # Not enough profiles to fill the block
440 453 if not(self.readNextBlock()):
441 454 return 0
442 455 self.getFirstHeader()
443 456 self.reshapeData()
444 457 if self.datablock is None:
445 458 self.dataOut.flagNoData = True
446 459 return 0
447 460 # stack data
448 461 blockIndex = self.selBlocksize - datasize
449 462 datablock1 = self.datablock[:, :blockIndex, :]
450 463
451 464 buffer[:, datasize:datasize +
452 465 datablock1.shape[1], :] = datablock1
453 466 datasize += datablock1.shape[1]
454 467
455 468 self.dataOut.data = buffer
456 469 self.profileIndex = blockIndex
457 470
458 471 self.dataOut.flagDataAsBlock = True
459 472 self.dataOut.nProfiles = self.dataOut.data.shape[1]
460 473
474 #######################DP#######################
475 self.dataOut.CurrentBlock=self.nReadBlocks
476 self.dataOut.LastBlock=self.processingHeaderObj.dataBlocksPerFile
477 #######################DP#######################
461 478 self.dataOut.flagNoData = False
462 479
463 self.getBasicHeader()
480 #self.getBasicHeader()
464 481
465 482 self.dataOut.realtime = self.online
466 483
467 484 return self.dataOut.data
468 485
469 486
470 487 @MPDecorator
471 488 class VoltageWriter(JRODataWriter, Operation):
472 489 """
473 490 Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura
474 491 de los datos siempre se realiza por bloques.
475 492 """
476 493
477 494 ext = ".r"
478 495
479 496 optchar = "D"
480 497
481 498 shapeBuffer = None
482 499
483 500 def __init__(self):#, **kwargs):
484 501 """
485 502 Inicializador de la clase VoltageWriter para la escritura de datos de espectros.
486 503
487 504 Affected:
488 505 self.dataOut
489 506
490 507 Return: None
491 508 """
492 509 Operation.__init__(self)#, **kwargs)
493 510
494 511 self.nTotalBlocks = 0
495 512
496 513 self.profileIndex = 0
497 514
498 515 self.isConfig = False
499 516
500 517 self.fp = None
501 518
502 519 self.flagIsNewFile = 1
503 520
504 521 self.blockIndex = 0
505 522
506 523 self.flagIsNewBlock = 0
507 524
508 525 self.setFile = None
509 526
510 527 self.dtype = None
511 528
512 529 self.path = None
513 530
514 531 self.filename = None
515 532
516 533 self.basicHeaderObj = BasicHeader(LOCALTIME)
517 534
518 535 self.systemHeaderObj = SystemHeader()
519 536
520 537 self.radarControllerHeaderObj = RadarControllerHeader()
521 538
522 539 self.processingHeaderObj = ProcessingHeader()
523 540
524 541 def hasAllDataInBuffer(self):
525 542 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock:
526 543 return 1
527 544 return 0
528 545
529 546 def setBlockDimension(self):
530 547 """
531 548 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
532 549
533 550 Affected:
534 551 self.shape_spc_Buffer
535 552 self.shape_cspc_Buffer
536 553 self.shape_dc_Buffer
537 554
538 555 Return: None
539 556 """
540 557 self.shapeBuffer = (self.processingHeaderObj.profilesPerBlock,
541 558 self.processingHeaderObj.nHeights,
542 559 self.systemHeaderObj.nChannels)
543 560
544 561 self.datablock = numpy.zeros((self.systemHeaderObj.nChannels,
545 562 self.processingHeaderObj.profilesPerBlock,
546 563 self.processingHeaderObj.nHeights),
547 564 dtype=numpy.dtype('complex64'))
548 565
549 566 def writeBlock(self):
550 567 """
551 568 Escribe el buffer en el file designado
552 569
553 570 Affected:
554 571 self.profileIndex
555 572 self.flagIsNewFile
556 573 self.flagIsNewBlock
557 574 self.nTotalBlocks
558 575 self.blockIndex
559 576
560 577 Return: None
561 578 """
562 579 data = numpy.zeros(self.shapeBuffer, self.dtype)
563 580
564 581 junk = numpy.transpose(self.datablock, (1, 2, 0))
565 582
566 583 data['real'] = junk.real
567 584 data['imag'] = junk.imag
568 585
569 586 data = data.reshape((-1))
570 587
571 588 data.tofile(self.fp)
572 589
573 590 self.datablock.fill(0)
574 591
575 592 self.profileIndex = 0
576 593 self.flagIsNewFile = 0
577 594 self.flagIsNewBlock = 1
578 595
579 596 self.blockIndex += 1
580 597 self.nTotalBlocks += 1
581 598
582 599 # print "[Writing] Block = %04d" %self.blockIndex
583 600
584 601 def putData(self):
585 602 """
586 603 Setea un bloque de datos y luego los escribe en un file
587 604
588 605 Affected:
589 606 self.flagIsNewBlock
590 607 self.profileIndex
591 608
592 609 Return:
593 610 0 : Si no hay data o no hay mas files que puedan escribirse
594 611 1 : Si se escribio la data de un bloque en un file
595 612 """
596 613 if self.dataOut.flagNoData:
597 614 return 0
598 615
599 616 self.flagIsNewBlock = 0
600 617
601 618 if self.dataOut.flagDiscontinuousBlock:
602 619 self.datablock.fill(0)
603 620 self.profileIndex = 0
604 621 self.setNextFile()
605 622
606 623 if self.profileIndex == 0:
607 624 self.setBasicHeader()
608 625
609 626 self.datablock[:, self.profileIndex, :] = self.dataOut.data
610 627
611 628 self.profileIndex += 1
612 629
613 630 if self.hasAllDataInBuffer():
614 631 # if self.flagIsNewFile:
615 632 self.writeNextBlock()
616 633 # self.setFirstHeader()
617 634
618 635 return 1
619 636
620 637 def __getBlockSize(self):
621 638 '''
622 639 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Voltage
623 640 '''
624 641
625 642 dtype_width = self.getDtypeWidth()
626 643
627 644 blocksize = int(self.dataOut.nHeights * self.dataOut.nChannels *
628 645 self.profilesPerBlock * dtype_width * 2)
629 646
630 647 return blocksize
631 648
632 649 def setFirstHeader(self):
633 650 """
634 651 Obtiene una copia del First Header
635 652
636 653 Affected:
637 654 self.systemHeaderObj
638 655 self.radarControllerHeaderObj
639 656 self.dtype
640 657
641 658 Return:
642 659 None
643 660 """
644 661
645 662 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
646 663 self.systemHeaderObj.nChannels = self.dataOut.nChannels
647 664 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
648 665
649 666 self.processingHeaderObj.dtype = 0 # Voltage
650 667 self.processingHeaderObj.blockSize = self.__getBlockSize()
651 668 self.processingHeaderObj.profilesPerBlock = self.profilesPerBlock
652 669 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
653 670 # podria ser 1 o self.dataOut.processingHeaderObj.nWindows
654 671 self.processingHeaderObj.nWindows = 1
655 672 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt
656 673 # Cuando la data de origen es de tipo Voltage
657 674 self.processingHeaderObj.nIncohInt = 1
658 675 # Cuando la data de origen es de tipo Voltage
659 676 self.processingHeaderObj.totalSpectra = 0
660 677
661 678 if self.dataOut.code is not None:
662 679 self.processingHeaderObj.code = self.dataOut.code
663 680 self.processingHeaderObj.nCode = self.dataOut.nCode
664 681 self.processingHeaderObj.nBaud = self.dataOut.nBaud
665 682
666 683 if self.processingHeaderObj.nWindows != 0:
667 684 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
668 685 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - \
669 686 self.dataOut.heightList[0]
670 687 self.processingHeaderObj.nHeights = self.dataOut.nHeights
671 688 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
672 689
673 690 self.processingHeaderObj.processFlags = self.getProcessFlags()
674 691
675 692 self.setBasicHeader()
676 No newline at end of file
@@ -1,16 +1,22
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: Processor.py 1 2012-11-12 18:56:07Z murco $
5 5 '''
6 6
7 7 from .jroproc_voltage import *
8 8 from .jroproc_spectra import *
9 9 from .jroproc_heispectra import *
10 10 from .jroproc_amisr import *
11 11 from .jroproc_correlation import *
12 12 from .jroproc_parameters import *
13 13 from .jroproc_spectra_lags import *
14 14 from .jroproc_spectra_acf import *
15 15 from .bltrproc_parameters import *
16 16 from .pxproc_parameters import *
17
18
19 ###########DP###########
20 from .jroproc_voltage_lags import *
21 ###########DP###########
22 from .jroproc_spectra_lags_faraday import *
1 NO CONTENT: modified file
1 NO CONTENT: modified file chmod 100755 => 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
1 NO CONTENT: modified file
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now