##// END OF EJS Templates
isr commit
rflores -
r1377:5453f456345b
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,1193 +1,1592
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 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
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.useLocalTime = True
439 538 self.radarControllerHeaderObj = RadarControllerHeader()
440 539 self.systemHeaderObj = SystemHeader()
441 540 self.type = "Spectra"
442 541 self.timeZone = 0
443 542 self.nProfiles = None
444 543 self.heightList = None
445 544 self.channelList = None
446 545 self.pairsList = None
447 546 self.flagNoData = True
448 547 self.flagDiscontinuousBlock = False
449 548 self.utctime = None
450 549 self.nCohInt = None
451 550 self.nIncohInt = None
452 551 self.blocksize = None
453 552 self.nFFTPoints = None
454 553 self.wavelength = None
455 554 self.flagDecodeData = False # asumo q la data no esta decodificada
456 555 self.flagDeflipData = False # asumo q la data no esta sin flip
457 556 self.flagShiftFFT = False
458 557 self.ippFactor = 1
459 558 self.beacon_heiIndexList = []
460 559 self.noise_estimation = None
461 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
560 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
462 561 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp','nIncohInt', 'nFFTPoints', 'nProfiles']
463 562
464 563 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
465 564 """
466 565 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
467 566
468 567 Return:
469 568 noiselevel
470 569 """
471 570
472 571 noise = numpy.zeros(self.nChannels)
473 572
474 573 for channel in range(self.nChannels):
475 574 daux = self.data_spc[channel,
476 575 xmin_index:xmax_index, ymin_index:ymax_index]
477 576 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
478 577
479 578 return noise
480 579
481 580 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
482 581
483 582 if self.noise_estimation is not None:
484 583 # this was estimated by getNoise Operation defined in jroproc_spectra.py
485 584 return self.noise_estimation
486 585 else:
487 586 noise = self.getNoisebyHildebrand(
488 587 xmin_index, xmax_index, ymin_index, ymax_index)
489 588 return noise
490 589
491 590 def getFreqRangeTimeResponse(self, extrapoints=0):
492 591
493 592 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
494 593 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
495 594
496 595 return freqrange
497 596
498 597 def getAcfRange(self, extrapoints=0):
499 598
500 599 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
501 600 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
502 601
503 602 return freqrange
504 603
505 604 def getFreqRange(self, extrapoints=0):
506 605
507 606 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
508 607 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
509 608
510 609 return freqrange
511 610
512 611 def getVelRange(self, extrapoints=0):
513 612
514 613 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
515 614 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
516 615
517 616 if self.nmodes:
518 617 return velrange/self.nmodes
519 618 else:
520 619 return velrange
521 620
522 621 @property
523 622 def nPairs(self):
524 623
525 624 return len(self.pairsList)
526 625
527 626 @property
528 627 def pairsIndexList(self):
529 628
530 629 return list(range(self.nPairs))
531 630
532 631 @property
533 632 def normFactor(self):
534 633
535 634 pwcode = 1
536 635
537 636 if self.flagDecodeData:
538 637 pwcode = numpy.sum(self.code[0]**2)
539 638 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
540 639 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
541 640
542 641 return normFactor
543 642
544 643 @property
545 644 def flag_cspc(self):
546 645
547 646 if self.data_cspc is None:
548 647 return True
549 648
550 649 return False
551 650
552 651 @property
553 652 def flag_dc(self):
554 653
555 654 if self.data_dc is None:
556 655 return True
557 656
558 657 return False
559 658
560 659 @property
561 660 def timeInterval(self):
562 661
563 662 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
564 663 if self.nmodes:
565 664 return self.nmodes*timeInterval
566 665 else:
567 666 return timeInterval
568 667
569 668 def getPower(self):
570 669
571 670 factor = self.normFactor
572 671 z = self.data_spc / factor
573 672 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
574 673 avg = numpy.average(z, axis=1)
575 674
576 675 return 10 * numpy.log10(avg)
577 676
578 677 def getCoherence(self, pairsList=None, phase=False):
579 678
580 679 z = []
581 680 if pairsList is None:
582 681 pairsIndexList = self.pairsIndexList
583 682 else:
584 683 pairsIndexList = []
585 684 for pair in pairsList:
586 685 if pair not in self.pairsList:
587 686 raise ValueError("Pair %s is not in dataOut.pairsList" % (
588 687 pair))
589 688 pairsIndexList.append(self.pairsList.index(pair))
590 689 for i in range(len(pairsIndexList)):
591 690 pair = self.pairsList[pairsIndexList[i]]
592 691 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
593 692 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
594 693 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
595 694 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
596 695 if phase:
597 696 data = numpy.arctan2(avgcoherenceComplex.imag,
598 697 avgcoherenceComplex.real) * 180 / numpy.pi
599 698 else:
600 699 data = numpy.abs(avgcoherenceComplex)
601 700
602 701 z.append(data)
603 702
604 703 return numpy.array(z)
605 704
606 705 def setValue(self, value):
607 706
608 707 print("This property should not be initialized")
609 708
610 709 return
611
710
612 711 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
613 712
614 713
615 714 class SpectraHeis(Spectra):
616 715
617 716 def __init__(self):
618 717
619 718 self.radarControllerHeaderObj = RadarControllerHeader()
620 719 self.systemHeaderObj = SystemHeader()
621 720 self.type = "SpectraHeis"
622 721 self.nProfiles = None
623 722 self.heightList = None
624 723 self.channelList = None
625 724 self.flagNoData = True
626 725 self.flagDiscontinuousBlock = False
627 726 self.utctime = None
628 727 self.blocksize = None
629 728 self.profileIndex = 0
630 729 self.nCohInt = 1
631 730 self.nIncohInt = 1
632 731
633 732 @property
634 733 def normFactor(self):
635 734 pwcode = 1
636 735 if self.flagDecodeData:
637 736 pwcode = numpy.sum(self.code[0]**2)
638 737
639 738 normFactor = self.nIncohInt * self.nCohInt * pwcode
640 739
641 740 return normFactor
642 741
643 742 @property
644 743 def timeInterval(self):
645 744
646 745 return self.ippSeconds * self.nCohInt * self.nIncohInt
647 746
648 747
649 748 class Fits(JROData):
650 749
651 750 def __init__(self):
652 751
653 752 self.type = "Fits"
654 753 self.nProfiles = None
655 754 self.heightList = None
656 755 self.channelList = None
657 756 self.flagNoData = True
658 757 self.utctime = None
659 758 self.nCohInt = 1
660 759 self.nIncohInt = 1
661 760 self.useLocalTime = True
662 761 self.profileIndex = 0
663 762 self.timeZone = 0
664 763
665 764 def getTimeRange(self):
666 765
667 766 datatime = []
668 767
669 768 datatime.append(self.ltctime)
670 769 datatime.append(self.ltctime + self.timeInterval)
671 770
672 771 datatime = numpy.array(datatime)
673 772
674 773 return datatime
675 774
676 775 def getChannelIndexList(self):
677 776
678 777 return list(range(self.nChannels))
679 778
680 779 def getNoise(self, type=1):
681 780
682 781
683 782 if type == 1:
684 783 noise = self.getNoisebyHildebrand()
685 784
686 785 if type == 2:
687 786 noise = self.getNoisebySort()
688 787
689 788 if type == 3:
690 789 noise = self.getNoisebyWindow()
691 790
692 791 return noise
693 792
694 793 @property
695 794 def timeInterval(self):
696 795
697 796 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
698 797
699 798 return timeInterval
700 799
701 800 @property
702 801 def ippSeconds(self):
703 802 '''
704 803 '''
705 804 return self.ipp_sec
706 805
707 806 noise = property(getNoise, "I'm the 'nHeights' property.")
708
807
709 808
710 809 class Correlation(JROData):
711 810
712 811 def __init__(self):
713 812 '''
714 813 Constructor
715 814 '''
716 815 self.radarControllerHeaderObj = RadarControllerHeader()
717 816 self.systemHeaderObj = SystemHeader()
718 817 self.type = "Correlation"
719 818 self.data = None
720 819 self.dtype = None
721 820 self.nProfiles = None
722 821 self.heightList = None
723 822 self.channelList = None
724 823 self.flagNoData = True
725 824 self.flagDiscontinuousBlock = False
726 825 self.utctime = None
727 826 self.timeZone = 0
728 827 self.dstFlag = None
729 828 self.errorCount = None
730 829 self.blocksize = None
731 830 self.flagDecodeData = False # asumo q la data no esta decodificada
732 831 self.flagDeflipData = False # asumo q la data no esta sin flip
733 832 self.pairsList = None
734 833 self.nPoints = None
735 834
736 835 def getPairsList(self):
737 836
738 837 return self.pairsList
739 838
740 839 def getNoise(self, mode=2):
741 840
742 841 indR = numpy.where(self.lagR == 0)[0][0]
743 842 indT = numpy.where(self.lagT == 0)[0][0]
744 843
745 844 jspectra0 = self.data_corr[:, :, indR, :]
746 845 jspectra = copy.copy(jspectra0)
747 846
748 847 num_chan = jspectra.shape[0]
749 848 num_hei = jspectra.shape[2]
750 849
751 850 freq_dc = jspectra.shape[1] / 2
752 851 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
753 852
754 853 if ind_vel[0] < 0:
755 854 ind_vel[list(range(0, 1))] = ind_vel[list(
756 855 range(0, 1))] + self.num_prof
757 856
758 857 if mode == 1:
759 858 jspectra[:, freq_dc, :] = (
760 859 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
761 860
762 861 if mode == 2:
763 862
764 863 vel = numpy.array([-2, -1, 1, 2])
765 864 xx = numpy.zeros([4, 4])
766 865
767 866 for fil in range(4):
768 867 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
769 868
770 869 xx_inv = numpy.linalg.inv(xx)
771 870 xx_aux = xx_inv[0, :]
772 871
773 872 for ich in range(num_chan):
774 873 yy = jspectra[ich, ind_vel, :]
775 874 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
776 875
777 876 junkid = jspectra[ich, freq_dc, :] <= 0
778 877 cjunkid = sum(junkid)
779 878
780 879 if cjunkid.any():
781 880 jspectra[ich, freq_dc, junkid.nonzero()] = (
782 881 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
783 882
784 883 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
785 884
786 885 return noise
787 886
788 887 @property
789 888 def timeInterval(self):
790 889
791 890 return self.ippSeconds * self.nCohInt * self.nProfiles
792 891
793 892 def splitFunctions(self):
794 893
795 894 pairsList = self.pairsList
796 895 ccf_pairs = []
797 896 acf_pairs = []
798 897 ccf_ind = []
799 898 acf_ind = []
800 899 for l in range(len(pairsList)):
801 900 chan0 = pairsList[l][0]
802 901 chan1 = pairsList[l][1]
803 902
804 903 # Obteniendo pares de Autocorrelacion
805 904 if chan0 == chan1:
806 905 acf_pairs.append(chan0)
807 906 acf_ind.append(l)
808 907 else:
809 908 ccf_pairs.append(pairsList[l])
810 909 ccf_ind.append(l)
811 910
812 911 data_acf = self.data_cf[acf_ind]
813 912 data_ccf = self.data_cf[ccf_ind]
814 913
815 914 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
816 915
817 916 @property
818 917 def normFactor(self):
819 918 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
820 919 acf_pairs = numpy.array(acf_pairs)
821 920 normFactor = numpy.zeros((self.nPairs, self.nHeights))
822 921
823 922 for p in range(self.nPairs):
824 923 pair = self.pairsList[p]
825 924
826 925 ch0 = pair[0]
827 926 ch1 = pair[1]
828 927
829 928 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
830 929 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
831 930 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
832 931
833 932 return normFactor
834 933
835 934
836 935 class Parameters(Spectra):
837 936
838 937 groupList = None # List of Pairs, Groups, etc
839 938 data_param = None # Parameters obtained
840 939 data_pre = None # Data Pre Parametrization
841 940 data_SNR = None # Signal to Noise Ratio
842 941 abscissaList = None # Abscissa, can be velocities, lags or time
843 942 utctimeInit = None # Initial UTC time
844 943 paramInterval = None # Time interval to calculate Parameters in seconds
845 944 useLocalTime = True
846 945 # Fitting
847 946 data_error = None # Error of the estimation
848 947 constants = None
849 948 library = None
850 949 # Output signal
851 950 outputInterval = None # Time interval to calculate output signal in seconds
852 951 data_output = None # Out signal
853 952 nAvg = None
854 953 noise_estimation = None
855 954 GauSPC = None # Fit gaussian SPC
856 955
857 956 def __init__(self):
858 957 '''
859 958 Constructor
860 959 '''
861 960 self.radarControllerHeaderObj = RadarControllerHeader()
862 961 self.systemHeaderObj = SystemHeader()
863 962 self.type = "Parameters"
864 963 self.timeZone = 0
865 964
866 965 def getTimeRange1(self, interval):
867 966
868 967 datatime = []
869 968
870 969 if self.useLocalTime:
871 970 time1 = self.utctimeInit - self.timeZone * 60
872 971 else:
873 972 time1 = self.utctimeInit
874 973
875 974 datatime.append(time1)
876 975 datatime.append(time1 + interval)
877 976 datatime = numpy.array(datatime)
878 977
879 978 return datatime
880 979
881 980 @property
882 981 def timeInterval(self):
883 982
884 983 if hasattr(self, 'timeInterval1'):
885 984 return self.timeInterval1
886 985 else:
887 986 return self.paramInterval
888 987
988
889 989 def setValue(self, value):
890 990
891 991 print("This property should not be initialized")
892 992
893 993 return
894 994
895 995 def getNoise(self):
896 996
897 997 return self.spc_noise
898 998
899 999 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
900 1000
901 1001
902 1002 class PlotterData(object):
903 1003 '''
904 1004 Object to hold data to be plotted
905 1005 '''
906 1006
907 1007 MAXNUMX = 200
908 1008 MAXNUMY = 200
909 1009
910 1010 def __init__(self, code, throttle_value, exp_code, localtime=True, buffering=True, snr=False):
911 1011
912 1012 self.key = code
913 1013 self.throttle = throttle_value
914 1014 self.exp_code = exp_code
915 1015 self.buffering = buffering
916 1016 self.ready = False
917 1017 self.flagNoData = False
918 1018 self.localtime = localtime
919 1019 self.data = {}
920 1020 self.meta = {}
921 1021 self.__heights = []
922 1022
923 1023 if 'snr' in code:
924 1024 self.plottypes = ['snr']
925 1025 elif code == 'spc':
926 1026 self.plottypes = ['spc', 'noise', 'rti']
927 1027 elif code == 'cspc':
928 1028 self.plottypes = ['cspc', 'spc', 'noise', 'rti']
929 1029 elif code == 'rti':
930 1030 self.plottypes = ['noise', 'rti']
1031 elif code == 'crossprod':
1032 self.plottypes = ['crossprod', 'kay']
1033 elif code == 'spectrogram':
1034 self.plottypes = ['spc', 'spectrogram']
931 1035 else:
932 1036 self.plottypes = [code]
933 1037
934 1038 if 'snr' not in self.plottypes and snr:
935 1039 self.plottypes.append('snr')
936 1040
937 1041 for plot in self.plottypes:
938 1042 self.data[plot] = {}
939 1043
940 1044 def __str__(self):
941 1045 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
942 1046 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
943 1047
944 1048 def __len__(self):
945 1049 return len(self.data[self.key])
946 1050
947 1051 def __getitem__(self, key):
948 1052
949 1053 if key not in self.data:
950 1054 raise KeyError(log.error('Missing key: {}'.format(key)))
951 1055 if 'spc' in key or not self.buffering:
952 1056 ret = self.data[key][self.tm]
953 1057 elif 'scope' in key:
954 1058 ret = numpy.array(self.data[key][float(self.tm)])
955 1059 else:
956 1060 ret = numpy.array([self.data[key][x] for x in self.times])
957 1061 if ret.ndim > 1:
958 1062 ret = numpy.swapaxes(ret, 0, 1)
959 1063 return ret
960 1064
961 1065 def __contains__(self, key):
962 1066 return key in self.data
963 1067
964 1068 def setup(self):
965 1069 '''
966 1070 Configure object
967 1071 '''
968 1072 self.type = ''
969 1073 self.ready = False
970 1074 del self.data
971 1075 self.data = {}
972 1076 self.__heights = []
973 1077 self.__all_heights = set()
974 1078 for plot in self.plottypes:
975 1079 if 'snr' in plot:
976 1080 plot = 'snr'
977 1081 elif 'spc_moments' == plot:
978 1082 plot = 'moments'
1083 elif 'spc_oblique' == plot:
1084 plot = 'oblique'
979 1085 self.data[plot] = {}
980 1086
981 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data or 'moments' in self.data:
1087 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data or 'moments' in self.data or 'oblique' in self.data:
982 1088 self.data['noise'] = {}
983 1089 self.data['rti'] = {}
984 1090 if 'noise' not in self.plottypes:
985 1091 self.plottypes.append('noise')
986 1092 if 'rti' not in self.plottypes:
987 1093 self.plottypes.append('rti')
988 1094
989 1095 def shape(self, key):
990 1096 '''
991 1097 Get the shape of the one-element data for the given key
992 1098 '''
993 1099
994 1100 if len(self.data[key]):
995 1101 if 'spc' in key or not self.buffering:
996 1102 return self.data[key].shape
997 1103 return self.data[key][self.times[0]].shape
998 1104 return (0,)
999 1105
1000 1106 def update(self, dataOut, tm):
1001 1107 '''
1002 1108 Update data object with new dataOut
1003 1109 '''
1004 1110
1005 1111 self.profileIndex = dataOut.profileIndex
1006 1112 self.tm = tm
1007 1113 self.type = dataOut.type
1008 1114 self.parameters = getattr(dataOut, 'parameters', [])
1009 1115
1010 1116 if hasattr(dataOut, 'meta'):
1011 1117 self.meta.update(dataOut.meta)
1012 1118
1013 1119 if hasattr(dataOut, 'pairsList'):
1014 1120 self.pairs = dataOut.pairsList
1015 1121
1016 1122 self.interval = dataOut.timeInterval
1017 1123 if True in ['spc' in ptype for ptype in self.plottypes]:
1018 1124 self.xrange = (dataOut.getFreqRange(1)/1000.,
1019 1125 dataOut.getAcfRange(1), dataOut.getVelRange(1))
1020 1126 self.__heights.append(dataOut.heightList)
1021 1127 self.__all_heights.update(dataOut.heightList)
1022 1128
1129
1130
1023 1131 for plot in self.plottypes:
1024 if plot in ('spc', 'spc_moments', 'spc_cut'):
1132 if plot in ('spc', 'spc_moments', 'spc_cut', 'spc_oblique'):
1133
1134
1135 self.shift1 = dataOut.Oblique_params[0][1]
1136 self.shift2 = dataOut.Oblique_params[0][4]
1137 self.shift1_error = dataOut.Oblique_param_errors[0][1]
1138 self.shift2_error = dataOut.Oblique_param_errors[0][4]
1139
1025 1140 z = dataOut.data_spc/dataOut.normFactor
1141 #print(dataOut.normFactor)
1142 #print(z[0,3,15])
1143 #print("here")
1144 #print(dataOut.data_spc[0,0,0])
1145 #exit()
1026 1146 buffer = 10*numpy.log10(z)
1027 1147 if plot == 'cspc':
1028 1148 buffer = (dataOut.data_spc, dataOut.data_cspc)
1149 self.nFactor=dataOut.normFactor
1029 1150 if plot == 'noise':
1030 1151 buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
1031 1152 if plot in ('rti', 'spcprofile'):
1032 1153 buffer = dataOut.getPower()
1154 #print(buffer[0,0])
1155 #exit()
1033 1156 if plot == 'snr_db':
1034 1157 buffer = dataOut.data_SNR
1035 1158 if plot == 'snr':
1036 1159 buffer = 10*numpy.log10(dataOut.data_SNR)
1037 1160 if plot == 'dop':
1038 1161 buffer = dataOut.data_DOP
1039 1162 if plot == 'pow':
1040 1163 buffer = 10*numpy.log10(dataOut.data_POW)
1041 1164 if plot == 'width':
1042 1165 buffer = dataOut.data_WIDTH
1043 1166 if plot == 'coh':
1044 1167 buffer = dataOut.getCoherence()
1045 1168 if plot == 'phase':
1046 1169 buffer = dataOut.getCoherence(phase=True)
1047 1170 if plot == 'output':
1048 1171 buffer = dataOut.data_output
1049 1172 if plot == 'param':
1050 1173 buffer = dataOut.data_param
1174 if plot == 'spectrogram':
1175 maxHei = 1350 #11
1176 #maxHei = 2500
1177 maxHei = 0
1178 #maxHei = 990 #12
1179 ###maxHei = 990
1180 indb = numpy.where(dataOut.heightList <= maxHei)
1181 hei = indb[0][-1]
1182 #hei = 19
1183 print(hei)
1184 #hei = 0
1185 factor = dataOut.nIncohInt
1186 #print(factor)
1187
1188 #exit(1)
1189 z = dataOut.data_spc[:,:,hei] / factor
1190
1191 #for j in range(z.shape[1]):
1192 #z[:,j] = z[:,j]/hildebrand_sekhon(z[], self.nCohInt)
1193
1194 ##z = z/hildebrand_sekhon(z, factor)
1195 noise = numpy.zeros(dataOut.nChannels)
1196 for i in range(dataOut.nChannels):
1197 #daux = numpy.sort(pair0[i,:,:],axis= None)
1198 noise[i]=hildebrand_sekhon( z[i,:] ,dataOut.nIncohInt)
1199 #for j in range(z.shape[1]):
1200 #z[:,j] = z[:,j]/noise
1201
1202 #print(z.shape[1])
1203 norm_factor = numpy.copy(z[:,int(z.shape[1]/2)])#/z[:,int(z.shape[1]/2)])*8000
1204 #print(norm_factor)
1205 #print(z[0,315:325])
1206 #norm_factor = norm_factor.reshape((z.shape[0],z.shape[1]))
1207 #print(norm_factor)
1208 #exit(1)
1209 #print(z.shape[1])
1210
1211 #for j in range(z.shape[1]):
1212 #z[:,j] = z[:,j]/norm_factor
1213
1214 #print(z[0,315:325])
1215 #exit(1)
1216
1217 #z = numpy.mean(dataOut.data_spc[:,:,:],axis=2) / factor
1218 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1219 #avg = numpy.average(z, axis=1)
1220 #print((dataOut.data_spc.shape))
1221 #exit(1)
1222 self.hei = hei
1223 self.heightList = dataOut.heightList
1224 self.DH = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
1225 self.nProfiles = dataOut.nProfiles
1226 #print(dataOut.heightList)
1227
1228
1229 buffer = 10 * numpy.log10(z)
1230
1231
1232 ###buffer = z
1233 import matplotlib.pyplot as plt
1234 fig, axes = plt.subplots(figsize=(14, 10))
1235 x = numpy.linspace(0,20,numpy.shape(buffer)[1])
1236 x = numpy.fft.fftfreq(numpy.shape(buffer)[1],0.00001)
1237 x = numpy.fft.fftshift(x)
1238
1239 plt.plot(x,buffer[0,:])
1240 axes = plt.gca()
1241 axes.set_xlim([-10000,10000])
1242
1243 #axes.set_xlim([0,30000])
1244 #axes.set_ylim([-100,0.0025*1e10])
1245 plt.show()
1246 import time
1247 #time.sleep(20)
1248 #exit(1)
1249
1250
1251
1252 #if dataOut.profileIndex
1253
1254 if plot == 'xmit':
1255 y_1=numpy.arctan2(dataOut.output_LP[:,0,2].imag,dataOut.output_LP[:,0,2].real)* 180 / (numpy.pi*10)
1256 y_2=numpy.abs(dataOut.output_LP[:,0,2])
1257 norm=numpy.max(y_2)
1258 norm=max(norm,0.1)
1259 y_2=y_2/norm
1260
1261 buffer = numpy.vstack((y_1,y_2))
1262 self.NLAG = dataOut.NLAG
1263
1264 if plot == 'crossprod':
1265 buffer = dataOut.crossprods
1266 self.NDP = dataOut.NDP
1267
1268 if plot == 'crossprodlp':
1269 buffer = 10*numpy.log10(numpy.abs(dataOut.output_LP))
1270 self.NRANGE = dataOut.NRANGE
1271 self.NLAG = dataOut.NLAG
1272
1273
1274 if plot == 'noisedp':
1275 buffer = 10*numpy.log10(dataOut.noise_final)
1276 #print(buffer)
1277
1278 if plot == 'FaradayAngle':
1279 buffer = numpy.degrees(dataOut.phi)
1280 #print(buffer)
1281
1282 if plot == 'RTIDP':
1283 buffer = dataOut.data_for_RTI_DP
1284 self.NDP = dataOut.NDP
1285
1286 if plot == 'RTILP':
1287 buffer = dataOut.data_for_RTI_LP
1288 self.NRANGE = dataOut.NRANGE
1289
1290
1291 if plot == 'denrti':
1292 buffer = dataOut.DensityFinal
1293
1294
1295 if plot == 'denrtiLP':
1296
1297 #buffer = numpy.reshape(numpy.concatenate((dataOut.ph2[:dataOut.cut],dataOut.ne[dataOut.cut:dataOut.NACF])),(1,-1))
1298 buffer = dataOut.DensityFinal
1299 #self.flagDataAsBlock = dataOut.flagDataAsBlock
1300 #self.NDP = dataOut.NDP
1301 if plot == 'den':
1302 buffer = dataOut.ph2[:dataOut.NSHTS]
1303 self.dphi=dataOut.dphi[:dataOut.NSHTS]
1304 self.sdp2=dataOut.sdp2[:dataOut.NSHTS]
1305 self.sdn1=dataOut.sdn1[:dataOut.NSHTS]#/self.dphi
1306 self.NSHTS=dataOut.NSHTS
1307 '''
1308 flag1=False
1309 flag0=True
1310 for i in range(12,dataOut.NSHTS):
1311 print("H: ",i*15)
1312 print(abs((dataOut.sdn1[i]/(dataOut.dphi[i]**2))*100))
1313 if flag0:
1314 if abs((dataOut.sdn1[i]/dataOut.dphi[i]))<0.0005*abs(dataOut.dphi[i]):
1315 print("***************************** FIRST: ",(i)*15,"*****************************")
1316 flag1=True
1317 flag0=False
1318 #pass
1319 #print("****************************************GOOD****************************************")
1320 #else:
1321 #print("****************************************",(i-1)*15,"****************************************")
1322 #break
1323 if flag1:
1324 if abs((dataOut.sdn1[i]/dataOut.dphi[i]))>0.0005*abs(dataOut.dphi[i]):
1325 print("***************************** LAST: ",(i-1)*15,"*****************************")
1326 break
1327 #print("H: ",i*15)
1328 #print(dataOut.sdn1[i])
1329 '''
1330 if plot == 'denLP':
1331 buffer = dataOut.ph2[:dataOut.NSHTS]
1332 self.dphi=dataOut.dphi[:dataOut.NSHTS]
1333 self.sdp2=dataOut.sdp2[:dataOut.NSHTS]
1334 self.ne=dataOut.ne[:dataOut.NACF]
1335 self.ene=dataOut.ene[:dataOut.NACF]*dataOut.ne[:dataOut.NACF]*0.434
1336 #self.ene=10**dataOut.ene[:dataOut.NACF]
1337 self.NSHTS=dataOut.NSHTS
1338 self.cut=dataOut.cut
1339
1340 if plot == 'ETemp':
1341 #buffer = dataOut.ElecTempClean
1342 buffer = dataOut.ElecTempFinal
1343 if plot == 'ITemp':
1344 #buffer = dataOut.IonTempClean
1345 buffer = dataOut.IonTempFinal
1346 if plot == 'ETempLP':
1347 #buffer = dataOut.IonTempClean
1348 #buffer = numpy.reshape(numpy.concatenate((dataOut.te2[:dataOut.cut],dataOut.te[dataOut.cut:])),(1,-1))
1349 buffer = dataOut.ElecTempFinal
1350 #print(buffer)
1351 if plot == 'ITempLP':
1352 #buffer = dataOut.IonTempClean
1353 #buffer = numpy.reshape(numpy.concatenate((dataOut.ti2[:dataOut.cut],dataOut.ti[dataOut.cut:])),(1,-1))
1354 buffer = dataOut.IonTempFinal
1355
1356 if plot == 'HFracLP':
1357 #buffer = dataOut.IonTempClean
1358 #buffer = numpy.reshape(numpy.concatenate((dataOut.phy2[:dataOut.cut],dataOut.ph[dataOut.cut:])),(1,-1))
1359 buffer = dataOut.PhyFinal
1360 if plot == 'HeFracLP':
1361 #buffer = dataOut.IonTempClean
1362 #nan_array=numpy.empty((dataOut.cut))
1363 #nan_array[:]=numpy.nan
1364 #buffer = numpy.reshape(numpy.concatenate((nan_array,dataOut.phe[dataOut.cut:])),(1,-1))
1365 buffer = dataOut.PheFinal
1366
1367
1368
1369
1370
1371 if plot =='acfs':
1372 buffer = dataOut.acfs_to_plot
1373 self.acfs_error_to_plot=dataOut.acfs_error_to_plot
1374 self.lags_to_plot=dataOut.lags_to_plot
1375 self.x_igcej_to_plot=dataOut.x_igcej_to_plot
1376 self.x_ibad_to_plot=dataOut.x_ibad_to_plot
1377 self.y_igcej_to_plot=dataOut.y_igcej_to_plot
1378 self.y_ibad_to_plot=dataOut.y_ibad_to_plot
1379 self.NSHTS = dataOut.NSHTS
1380 self.DPL = dataOut.DPL
1381 if plot =='acfs_LP':
1382
1383 aux=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1384 self.errors=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1385 self.lags_LP_to_plot=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1386 '''
1387 for i in range(dataOut.NACF):
1388 for j in range(dataOut.IBITS):
1389 aux[i,j]=dataOut.fit_array_real[i,j]/dataOut.fit_array_real[i,0]
1390 aux[i,j]=max(min(aux[i,j],1.0),-1.0)*dataOut.DH+dataOut.heightList[i]
1391 '''
1392 for i in range(dataOut.NACF):
1393 for j in range(dataOut.IBITS):
1394 if numpy.abs(dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0])<1.0:
1395 aux[i,j]=dataOut.output_LP_integrated.real[j,i,0]/dataOut.output_LP_integrated.real[0,i,0]
1396 aux[i,j]=max(min(aux[i,j],1.0),-1.0)*dataOut.DH+dataOut.heightList[i]
1397 self.lags_LP_to_plot[i,j]=dataOut.lags_LP[j]
1398 self.errors[i,j]=dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0]*dataOut.DH
1399 else:
1400 aux[i,j]=numpy.nan
1401 self.lags_LP_to_plot[i,j]=numpy.nan
1402 self.errors[i,j]=numpy.nan
1403
1404
1405
1406 buffer = aux
1407
1408 #self.lags_LP_to_plot=dataOut.lags_LP
1409
1410 self.NACF = dataOut.NACF
1411 self.NLAG = dataOut.NLAG
1412
1413 if plot == 'tempsDP':
1414
1415 buffer = dataOut.te2
1416 self.ete2 = dataOut.ete2
1417 self.ti2 = dataOut.ti2
1418 self.eti2 = dataOut.eti2
1419
1420 self.NSHTS = dataOut.NSHTS
1421
1422 if plot == 'temps_LP':
1423
1424 buffer = numpy.concatenate((dataOut.te2[:dataOut.cut],dataOut.te[dataOut.cut:]))
1425 self.ete = numpy.concatenate((dataOut.ete2[:dataOut.cut],dataOut.ete[dataOut.cut:]))
1426 self.ti = numpy.concatenate((dataOut.ti2[:dataOut.cut],dataOut.ti[dataOut.cut:]))
1427 self.eti = numpy.concatenate((dataOut.eti2[:dataOut.cut],dataOut.eti[dataOut.cut:]))
1428
1429 self.NACF = dataOut.NACF
1430
1431
1432 if plot == 'fracs_LP':
1433
1434 aux_nan=numpy.zeros(dataOut.cut,'float32')
1435 aux_nan[:]=numpy.nan
1436 buffer = numpy.concatenate((aux_nan,dataOut.ph[dataOut.cut:]))
1437 self.eph = numpy.concatenate((aux_nan,dataOut.eph[dataOut.cut:]))
1438 self.phe = dataOut.phe[dataOut.cut:]
1439 self.ephe = dataOut.ephe[dataOut.cut:]
1440
1441 self.NACF = dataOut.NACF
1442 self.cut = dataOut.cut
1443
1444
1051 1445 if plot == 'scope':
1052 1446 buffer = dataOut.data
1053 1447 self.flagDataAsBlock = dataOut.flagDataAsBlock
1054 1448 self.nProfiles = dataOut.nProfiles
1055 1449 if plot == 'pp_power':
1056 1450 buffer = dataOut.dataPP_POWER
1057 1451 self.flagDataAsBlock = dataOut.flagDataAsBlock
1058 1452 self.nProfiles = dataOut.nProfiles
1059 1453 if plot == 'pp_signal':
1060 1454 buffer = dataOut.dataPP_POW
1061 1455 self.flagDataAsBlock = dataOut.flagDataAsBlock
1062 1456 self.nProfiles = dataOut.nProfiles
1063 1457 if plot == 'pp_velocity':
1064 1458 buffer = dataOut.dataPP_DOP
1065 1459 self.flagDataAsBlock = dataOut.flagDataAsBlock
1066 1460 self.nProfiles = dataOut.nProfiles
1067 1461 if plot == 'pp_specwidth':
1068 1462 buffer = dataOut.dataPP_WIDTH
1069 1463 self.flagDataAsBlock = dataOut.flagDataAsBlock
1070 1464 self.nProfiles = dataOut.nProfiles
1071 1465
1072 1466 if plot == 'spc':
1073 1467 self.data['spc'][tm] = buffer
1074 1468 elif plot == 'cspc':
1075 1469 self.data['cspc'][tm] = buffer
1076 1470 elif plot == 'spc_moments':
1077 1471 self.data['spc'][tm] = buffer
1078 1472 self.data['moments'][tm] = dataOut.moments
1473 elif plot == 'spc_oblique':
1474 self.data['spc'][tm] = buffer
1475 self.data['shift1'][tm] = dataOut.Oblique_params[0]
1476 self.data['shift2'][tm] = dataOut.Oblique_params[3]
1079 1477 else:
1080 1478 if self.buffering:
1081 1479 self.data[plot][tm] = buffer
1082 1480 else:
1083 1481 self.data[plot][tm] = buffer
1084 1482
1085 1483 if dataOut.channelList is None:
1086 1484 self.channels = range(buffer.shape[0])
1087 1485 else:
1088 1486 self.channels = dataOut.channelList
1089 1487
1090 1488 if buffer is None:
1091 1489 self.flagNoData = True
1092 1490 raise schainpy.admin.SchainWarning('Attribute data_{} is empty'.format(self.key))
1093 1491
1094 1492 def normalize_heights(self):
1095 1493 '''
1096 1494 Ensure same-dimension of the data for different heighList
1097 1495 '''
1098 1496
1099 1497 H = numpy.array(list(self.__all_heights))
1100 1498 H.sort()
1101 1499 for key in self.data:
1102 1500 shape = self.shape(key)[:-1] + H.shape
1103 1501 for tm, obj in list(self.data[key].items()):
1104 1502 h = self.__heights[self.times.tolist().index(tm)]
1105 1503 if H.size == h.size:
1106 1504 continue
1107 1505 index = numpy.where(numpy.in1d(H, h))[0]
1108 1506 dummy = numpy.zeros(shape) + numpy.nan
1109 1507 if len(shape) == 2:
1110 1508 dummy[:, index] = obj
1111 1509 else:
1112 1510 dummy[index] = obj
1113 1511 self.data[key][tm] = dummy
1114 1512
1115 1513 self.__heights = [H for tm in self.times]
1116 1514
1117 1515 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1118 1516 '''
1119 1517 Convert data to json
1120 1518 '''
1121 1519
1122 1520 dy = int(self.heights.size/self.MAXNUMY) + 1
1123 1521 if self.key in ('spc', 'cspc'):
1124 1522 dx = int(self.data[self.key][tm].shape[1]/self.MAXNUMX) + 1
1125 1523 data = self.roundFloats(
1126 1524 self.data[self.key][tm][::, ::dx, ::dy].tolist())
1127 1525 else:
1128 1526 if self.key is 'noise':
1129 1527 data = [[x] for x in self.roundFloats(self.data[self.key][tm].tolist())]
1130 1528 else:
1131 1529 data = self.roundFloats(self.data[self.key][tm][::, ::dy].tolist())
1132 1530
1133 1531 meta = {}
1134 1532 ret = {
1135 1533 'plot': plot_name,
1136 1534 'code': self.exp_code,
1137 1535 'time': float(tm),
1138 1536 'data': data,
1139 1537 }
1140 1538 meta['type'] = plot_type
1141 1539 meta['interval'] = float(self.interval)
1142 1540 meta['localtime'] = self.localtime
1143 1541 meta['yrange'] = self.roundFloats(self.heights[::dy].tolist())
1542
1144 1543 if 'spc' in self.data or 'cspc' in self.data:
1145 1544 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1146 1545 else:
1147 1546 meta['xrange'] = []
1148 1547
1149 1548 meta.update(self.meta)
1150 1549 ret['metadata'] = meta
1151 1550 return json.dumps(ret)
1152 1551
1153 1552 @property
1154 1553 def times(self):
1155 1554 '''
1156 1555 Return the list of times of the current data
1157 1556 '''
1158 1557
1159 1558 ret = numpy.array([t for t in self.data[self.key]])
1160 1559 if self:
1161 1560 ret.sort()
1162 1561 return ret
1163 1562
1164 1563 @property
1165 1564 def min_time(self):
1166 1565 '''
1167 1566 Return the minimun time value
1168 1567 '''
1169 1568
1170 1569 return self.times[0]
1171 1570
1172 1571 @property
1173 1572 def max_time(self):
1174 1573 '''
1175 1574 Return the maximun time value
1176 1575 '''
1177 1576
1178 1577 return self.times[-1]
1179 1578
1180 1579 @property
1181 1580 def heights(self):
1182 1581 '''
1183 1582 Return the list of heights of the current data
1184 1583 '''
1185 1584
1186 1585 return numpy.array(self.__heights[-1])
1187 1586
1188 1587 @staticmethod
1189 1588 def roundFloats(obj):
1190 1589 if isinstance(obj, list):
1191 1590 return list(map(PlotterData.roundFloats, obj))
1192 1591 elif isinstance(obj, float):
1193 1592 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=None,
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 return DTYPE_WIDTH[index] No newline at end of file
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,665 +1,669
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 multiprocessing import Queue
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('WxAgg')
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
87 87 def popup(message):
88 88 '''
89 89 '''
90 90
91 91 fig = plt.figure(figsize=(12, 8), facecolor='r')
92 92 text = '\n'.join([s.strip() for s in message.split(':')])
93 93 fig.text(0.01, 0.5, text, ha='left', va='center',
94 94 size='20', weight='heavy', color='w')
95 95 fig.show()
96 96 figpause(1000)
97 97
98 98
99 99 class Throttle(object):
100 100 '''
101 101 Decorator that prevents a function from being called more than once every
102 102 time period.
103 103 To create a function that cannot be called more than once a minute, but
104 104 will sleep until it can be called:
105 105 @Throttle(minutes=1)
106 106 def foo():
107 107 pass
108 108
109 109 for i in range(10):
110 110 foo()
111 111 print "This function has run %s times." % i
112 112 '''
113 113
114 114 def __init__(self, seconds=0, minutes=0, hours=0):
115 115 self.throttle_period = datetime.timedelta(
116 116 seconds=seconds, minutes=minutes, hours=hours
117 117 )
118 118
119 119 self.time_of_last_call = datetime.datetime.min
120 120
121 121 def __call__(self, fn):
122 122 @wraps(fn)
123 123 def wrapper(*args, **kwargs):
124 124 coerce = kwargs.pop('coerce', None)
125 125 if coerce:
126 126 self.time_of_last_call = datetime.datetime.now()
127 127 return fn(*args, **kwargs)
128 128 else:
129 129 now = datetime.datetime.now()
130 130 time_since_last_call = now - self.time_of_last_call
131 131 time_left = self.throttle_period - time_since_last_call
132 132
133 133 if time_left > datetime.timedelta(seconds=0):
134 134 return
135 135
136 136 self.time_of_last_call = datetime.datetime.now()
137 137 return fn(*args, **kwargs)
138 138
139 139 return wrapper
140 140
141 141 def apply_throttle(value):
142 142
143 143 @Throttle(seconds=value)
144 144 def fnThrottled(fn):
145 145 fn()
146 146
147 147 return fnThrottled
148 148
149 149
150 150 @MPDecorator
151 151 class Plot(Operation):
152 152 """Base class for Schain plotting operations
153 153
154 154 This class should never be use directtly you must subclass a new operation,
155 155 children classes must be defined as follow:
156 156
157 157 ExamplePlot(Plot):
158 158
159 159 CODE = 'code'
160 160 colormap = 'jet'
161 161 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
162 162
163 163 def setup(self):
164 164 pass
165 165
166 166 def plot(self):
167 167 pass
168 168
169 169 """
170 170
171 171 CODE = 'Figure'
172 172 colormap = 'jet'
173 173 bgcolor = 'white'
174 174 buffering = True
175 175 __missing = 1E30
176 176
177 177 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
178 178 'showprofile']
179 179
180 180 def __init__(self):
181 181
182 182 Operation.__init__(self)
183 183 self.isConfig = False
184 184 self.isPlotConfig = False
185 185 self.save_time = 0
186 186 self.sender_time = 0
187 187 self.data = None
188 188 self.firsttime = True
189 189 self.sender_queue = Queue(maxsize=60)
190 190 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
191 191
192 192 def __fmtTime(self, x, pos):
193 193 '''
194 194 '''
195 195
196 196 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
197 197
198 198 def __setup(self, **kwargs):
199 199 '''
200 200 Initialize variables
201 201 '''
202 202
203 203 self.figures = []
204 204 self.axes = []
205 205 self.cb_axes = []
206 206 self.localtime = kwargs.pop('localtime', True)
207 207 self.show = kwargs.get('show', True)
208 208 self.save = kwargs.get('save', False)
209 209 self.save_period = kwargs.get('save_period', 0)
210 210 self.colormap = kwargs.get('colormap', self.colormap)
211 211 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
212 212 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
213 213 self.colormaps = kwargs.get('colormaps', None)
214 214 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
215 215 self.showprofile = kwargs.get('showprofile', False)
216 216 self.title = kwargs.get('wintitle', self.CODE.upper())
217 217 self.cb_label = kwargs.get('cb_label', None)
218 218 self.cb_labels = kwargs.get('cb_labels', None)
219 219 self.labels = kwargs.get('labels', None)
220 220 self.xaxis = kwargs.get('xaxis', 'frequency')
221 221 self.zmin = kwargs.get('zmin', None)
222 222 self.zmax = kwargs.get('zmax', None)
223 223 self.zlimits = kwargs.get('zlimits', None)
224 self.xlimits = kwargs.get('xlimits', None)
225 self.xstep_given = kwargs.get('xstep_given', None)
226 self.ystep_given = kwargs.get('ystep_given', None)
227 self.autoxticks = kwargs.get('autoxticks', True)
224 228 self.xmin = kwargs.get('xmin', None)
225 229 self.xmax = kwargs.get('xmax', None)
226 230 self.xrange = kwargs.get('xrange', 12)
227 231 self.xscale = kwargs.get('xscale', None)
228 232 self.ymin = kwargs.get('ymin', None)
229 233 self.ymax = kwargs.get('ymax', None)
230 234 self.yscale = kwargs.get('yscale', None)
231 235 self.xlabel = kwargs.get('xlabel', None)
232 236 self.attr_time = kwargs.get('attr_time', 'utctime')
233 237 self.decimation = kwargs.get('decimation', None)
234 238 self.showSNR = kwargs.get('showSNR', False)
235 239 self.oneFigure = kwargs.get('oneFigure', True)
236 240 self.width = kwargs.get('width', None)
237 241 self.height = kwargs.get('height', None)
238 242 self.colorbar = kwargs.get('colorbar', True)
239 243 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
240 244 self.channels = kwargs.get('channels', None)
241 245 self.titles = kwargs.get('titles', [])
242 246 self.polar = False
243 247 self.type = kwargs.get('type', 'iq')
244 248 self.grid = kwargs.get('grid', False)
245 249 self.pause = kwargs.get('pause', False)
246 250 self.save_code = kwargs.get('save_code', self.CODE)
247 251 self.throttle = kwargs.get('throttle', 0)
248 252 self.exp_code = kwargs.get('exp_code', None)
249 253 self.server = kwargs.get('server', False)
250 254 self.sender_period = kwargs.get('sender_period', 60)
251 255 self.tag = kwargs.get('tag', '')
252 256 self.height_index = kwargs.get('height_index', None)
253 257 self.__throttle_plot = apply_throttle(self.throttle)
254 258 self.data = PlotterData(
255 259 self.CODE, self.throttle, self.exp_code, self.localtime, self.buffering, snr=self.showSNR)
256
260
257 261 if self.server:
258 262 if not self.server.startswith('tcp://'):
259 263 self.server = 'tcp://{}'.format(self.server)
260 264 log.success(
261 265 'Sending to server: {}'.format(self.server),
262 266 self.name
263 267 )
264 268
265 269 def __setup_plot(self):
266 270 '''
267 271 Common setup for all figures, here figures and axes are created
268 272 '''
269 273
270 274 self.setup()
271 275
272 self.time_label = 'LT' if self.localtime else 'UTC'
276 self.time_label = 'LT' if self.localtime else 'UTC'
273 277
274 278 if self.width is None:
275 279 self.width = 8
276 280
277 281 self.figures = []
278 282 self.axes = []
279 283 self.cb_axes = []
280 284 self.pf_axes = []
281 285 self.cmaps = []
282 286
283 287 size = '15%' if self.ncols == 1 else '30%'
284 288 pad = '4%' if self.ncols == 1 else '8%'
285 289
286 290 if self.oneFigure:
287 291 if self.height is None:
288 292 self.height = 1.4 * self.nrows + 1
289 293 fig = plt.figure(figsize=(self.width, self.height),
290 294 edgecolor='k',
291 295 facecolor='w')
292 296 self.figures.append(fig)
293 297 for n in range(self.nplots):
294 298 ax = fig.add_subplot(self.nrows, self.ncols,
295 299 n + 1, polar=self.polar)
296 300 ax.tick_params(labelsize=8)
297 301 ax.firsttime = True
298 302 ax.index = 0
299 303 ax.press = None
300 304 self.axes.append(ax)
301 305 if self.showprofile:
302 306 cax = self.__add_axes(ax, size=size, pad=pad)
303 307 cax.tick_params(labelsize=8)
304 308 self.pf_axes.append(cax)
305 309 else:
306 310 if self.height is None:
307 311 self.height = 3
308 312 for n in range(self.nplots):
309 313 fig = plt.figure(figsize=(self.width, self.height),
310 314 edgecolor='k',
311 315 facecolor='w')
312 316 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
313 317 ax.tick_params(labelsize=8)
314 318 ax.firsttime = True
315 319 ax.index = 0
316 320 ax.press = None
317 321 self.figures.append(fig)
318 322 self.axes.append(ax)
319 323 if self.showprofile:
320 324 cax = self.__add_axes(ax, size=size, pad=pad)
321 325 cax.tick_params(labelsize=8)
322 326 self.pf_axes.append(cax)
323 327
324 328 for n in range(self.nrows):
325 329 if self.colormaps is not None:
326 330 cmap = plt.get_cmap(self.colormaps[n])
327 331 else:
328 332 cmap = plt.get_cmap(self.colormap)
329 333 cmap.set_bad(self.bgcolor, 1.)
330 334 self.cmaps.append(cmap)
331 335
332 336 def __add_axes(self, ax, size='30%', pad='8%'):
333 337 '''
334 338 Add new axes to the given figure
335 339 '''
336 340 divider = make_axes_locatable(ax)
337 341 nax = divider.new_horizontal(size=size, pad=pad)
338 342 ax.figure.add_axes(nax)
339 343 return nax
340 344
341 345 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
342 346 '''
343 347 Create a masked array for missing data
344 348 '''
345 349 if x_buffer.shape[0] < 2:
346 350 return x_buffer, y_buffer, z_buffer
347 351
348 352 deltas = x_buffer[1:] - x_buffer[0:-1]
349 353 x_median = numpy.median(deltas)
350 354
351 355 index = numpy.where(deltas > 5 * x_median)
352 356
353 357 if len(index[0]) != 0:
354 358 z_buffer[::, index[0], ::] = self.__missing
355 359 z_buffer = numpy.ma.masked_inside(z_buffer,
356 360 0.99 * self.__missing,
357 361 1.01 * self.__missing)
358 362
359 363 return x_buffer, y_buffer, z_buffer
360 364
361 365 def decimate(self):
362 366
363 367 # dx = int(len(self.x)/self.__MAXNUMX) + 1
364 368 dy = int(len(self.y) / self.decimation) + 1
365 369
366 370 # x = self.x[::dx]
367 371 x = self.x
368 372 y = self.y[::dy]
369 373 z = self.z[::, ::, ::dy]
370 374
371 375 return x, y, z
372 376
373 377 def format(self):
374 378 '''
375 379 Set min and max values, labels, ticks and titles
376 380 '''
377
381
378 382 for n, ax in enumerate(self.axes):
379 383 if ax.firsttime:
380 384 if self.xaxis != 'time':
381 385 xmin = self.xmin
382 386 xmax = self.xmax
383 387 else:
384 388 xmin = self.tmin
385 389 xmax = self.tmin + self.xrange*60*60
386 390 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
387 391 ax.xaxis.set_major_locator(LinearLocator(9))
388 392 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
389 393 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
390 394 ax.set_facecolor(self.bgcolor)
391 395 if self.xscale:
392 396 ax.xaxis.set_major_formatter(FuncFormatter(
393 397 lambda x, pos: '{0:g}'.format(x*self.xscale)))
394 398 if self.yscale:
395 399 ax.yaxis.set_major_formatter(FuncFormatter(
396 400 lambda x, pos: '{0:g}'.format(x*self.yscale)))
397 401 if self.xlabel is not None:
398 402 ax.set_xlabel(self.xlabel)
399 403 if self.ylabel is not None:
400 404 ax.set_ylabel(self.ylabel)
401 405 if self.showprofile:
402 406 self.pf_axes[n].set_ylim(ymin, ymax)
403 407 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
404 408 self.pf_axes[n].set_xlabel('dB')
405 409 self.pf_axes[n].grid(b=True, axis='x')
406 410 [tick.set_visible(False)
407 411 for tick in self.pf_axes[n].get_yticklabels()]
408 412 if self.colorbar:
409 413 ax.cbar = plt.colorbar(
410 414 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
411 415 ax.cbar.ax.tick_params(labelsize=8)
412 416 ax.cbar.ax.press = None
413 417 if self.cb_label:
414 418 ax.cbar.set_label(self.cb_label, size=8)
415 419 elif self.cb_labels:
416 420 ax.cbar.set_label(self.cb_labels[n], size=8)
417 421 else:
418 422 ax.cbar = None
419 423 ax.set_xlim(xmin, xmax)
420 424 ax.set_ylim(ymin, ymax)
421 425 ax.firsttime = False
422 426 if self.grid:
423 427 ax.grid(True)
424 428 if not self.polar:
425 429 ax.set_title('{} {} {}'.format(
426 430 self.titles[n],
427 431 self.getDateTime(self.data.max_time).strftime(
428 432 '%Y-%m-%d %H:%M:%S'),
429 433 self.time_label),
430 434 size=8)
431 435 else:
432 436 ax.set_title('{}'.format(self.titles[n]), size=8)
433 437 ax.set_ylim(0, 90)
434 438 ax.set_yticks(numpy.arange(0, 90, 20))
435 439 ax.yaxis.labelpad = 40
436 440
437 441 if self.firsttime:
438 442 for n, fig in enumerate(self.figures):
439 443 fig.subplots_adjust(**self.plots_adjust)
440 444 self.firsttime = False
441 445
442 446 def clear_figures(self):
443 447 '''
444 448 Reset axes for redraw plots
445 449 '''
446 450
447 451 for ax in self.axes+self.pf_axes+self.cb_axes:
448 452 ax.clear()
449 453 ax.firsttime = True
450 454 if hasattr(ax, 'cbar') and ax.cbar:
451 455 ax.cbar.remove()
452 456
453 457 def __plot(self):
454 458 '''
455 459 Main function to plot, format and save figures
456 460 '''
457 461
458 462 self.plot()
459 463 self.format()
460
464
461 465 for n, fig in enumerate(self.figures):
462 466 if self.nrows == 0 or self.nplots == 0:
463 467 log.warning('No data', self.name)
464 468 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
465 469 fig.canvas.manager.set_window_title(self.CODE)
466 470 continue
467
471
468 472 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
469 473 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
470 474 fig.canvas.draw()
471 475 if self.show:
472 476 fig.show()
473 477 figpause(0.01)
474 478
475 479 if self.save:
476 480 self.save_figure(n)
477
481
478 482 if self.server:
479 483 self.send_to_server()
480 484
481 485 def save_figure(self, n):
482 486 '''
483 487 '''
484 488
485 489 if (self.data.tm - self.save_time) <= self.save_period:
486 490 return
487 491
488 492 self.save_time = self.data.tm
489 493
490 494 fig = self.figures[n]
491 495
492 496 figname = os.path.join(
493 497 self.save,
494 498 self.save_code,
495 '{}_{}.png'.format(
499 '{}_{}.png'.format(
496 500 self.save_code,
497 501 self.getDateTime(self.data.max_time).strftime(
498 502 '%Y%m%d_%H%M%S'
499 503 ),
500 504 )
501 505 )
502 506 log.log('Saving figure: {}'.format(figname), self.name)
503 507 if not os.path.isdir(os.path.dirname(figname)):
504 508 os.makedirs(os.path.dirname(figname))
505 509 fig.savefig(figname)
506 510
507 511 if self.throttle == 0:
508 512 figname = os.path.join(
509 513 self.save,
510 514 '{}_{}.png'.format(
511 515 self.save_code,
512 516 self.getDateTime(self.data.min_time).strftime(
513 517 '%Y%m%d'
514 518 ),
515 519 )
516 520 )
517 521 fig.savefig(figname)
518 522
519 523 def send_to_server(self):
520 524 '''
521 525 '''
522 526
523 527 interval = self.data.tm - self.sender_time
524 528 if interval < self.sender_period:
525 529 return
526 530
527 531 self.sender_time = self.data.tm
528
532
529 533 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
530 534 for attr in attrs:
531 535 value = getattr(self, attr)
532 536 if value:
533 537 if isinstance(value, (numpy.float32, numpy.float64)):
534 538 value = round(float(value), 2)
535 539 self.data.meta[attr] = value
536 540 if self.colormap == 'jet':
537 541 self.data.meta['colormap'] = 'Jet'
538 542 elif 'RdBu' in self.colormap:
539 543 self.data.meta['colormap'] = 'RdBu'
540 544 else:
541 545 self.data.meta['colormap'] = 'Viridis'
542 546 self.data.meta['interval'] = int(interval)
543 547
544 548 try:
545 549 self.sender_queue.put(self.data.tm, block=False)
546 550 except:
547 551 tm = self.sender_queue.get()
548 552 self.sender_queue.put(self.data.tm)
549
553
550 554 while True:
551 555 if self.sender_queue.empty():
552 556 break
553 557 tm = self.sender_queue.get()
554 558 try:
555 559 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
556 560 except:
557 561 continue
558 562 self.socket.send_string(msg)
559 563 socks = dict(self.poll.poll(5000))
560 564 if socks.get(self.socket) == zmq.POLLIN:
561 565 reply = self.socket.recv_string()
562 566 if reply == 'ok':
563 567 log.log("Response from server ok", self.name)
564 568 time.sleep(0.2)
565 569 continue
566 570 else:
567 571 log.warning(
568 572 "Malformed reply from server: {}".format(reply), self.name)
569 573 else:
570 574 log.warning(
571 575 "No response from server, retrying...", self.name)
572 576 self.sender_queue.put(self.data.tm)
573 577 self.socket.setsockopt(zmq.LINGER, 0)
574 578 self.socket.close()
575 579 self.poll.unregister(self.socket)
576 580 time.sleep(0.1)
577 581 self.socket = self.context.socket(zmq.REQ)
578 582 self.socket.connect(self.server)
579 583 self.poll.register(self.socket, zmq.POLLIN)
580 584 break
581 585
582 586 def setup(self):
583 587 '''
584 588 This method should be implemented in the child class, the following
585 589 attributes should be set:
586 590
587 591 self.nrows: number of rows
588 592 self.ncols: number of cols
589 593 self.nplots: number of plots (channels or pairs)
590 594 self.ylabel: label for Y axes
591 self.titles: list of axes title
595 self.titles: list of axes title
592 596
593 597 '''
594 598 raise NotImplementedError
595 599
596 600 def plot(self):
597 601 '''
598 602 Must be defined in the child class
599 603 '''
600 604 raise NotImplementedError
601
605
602 606 def run(self, dataOut, **kwargs):
603 607 '''
604 608 Main plotting routine
605 609 '''
606
610 print("time_inside_plot: ",dataOut.datatime)
611 print(dataOut.flagNoData)
607 612 if self.isConfig is False:
608 613 self.__setup(**kwargs)
609 614
610 615 if self.localtime:
611 616 self.getDateTime = datetime.datetime.fromtimestamp
612 617 else:
613 618 self.getDateTime = datetime.datetime.utcfromtimestamp
614 619
615 620 self.data.setup()
616 621 self.isConfig = True
617 622 if self.server:
618 623 self.context = zmq.Context()
619 624 self.socket = self.context.socket(zmq.REQ)
620 625 self.socket.connect(self.server)
621 626 self.poll = zmq.Poller()
622 627 self.poll.register(self.socket, zmq.POLLIN)
623 628
624 629 tm = getattr(dataOut, self.attr_time)
625
626 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
630
631 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
627 632 self.save_time = tm
628 633 self.__plot()
629 634 self.tmin += self.xrange*60*60
630 635 self.data.setup()
631 636 self.clear_figures()
632 637
633 638 self.data.update(dataOut, tm)
634 639
635 640 if self.isPlotConfig is False:
636 641 self.__setup_plot()
637 642 self.isPlotConfig = True
638 643 if self.xaxis == 'time':
639 644 dt = self.getDateTime(tm)
640 645 if self.xmin is None:
641 646 self.tmin = tm
642 self.xmin = dt.hour
647 self.xmin = dt.hour
643 648 minutes = (self.xmin-int(self.xmin)) * 60
644 649 seconds = (minutes - int(minutes)) * 60
645 650 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
646 651 datetime.datetime(1970, 1, 1)).total_seconds()
647 652 if self.localtime:
648 653 self.tmin += time.timezone
649 654
650 655 if self.xmin is not None and self.xmax is not None:
651 656 self.xrange = self.xmax - self.xmin
652 657
653 658 if self.throttle == 0:
654 659 self.__plot()
655 660 else:
656 661 self.__throttle_plot(self.__plot)#, coerce=coerce)
657 662
658 663 def close(self):
659 664
660 665 if self.data and not self.data.flagNoData:
661 666 self.save_time = self.data.tm
662 667 self.__plot()
663 668 if self.data and not self.data.flagNoData and self.pause:
664 669 figpause(10)
665
@@ -1,339 +1,347
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
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 class SpectralFitObliquePlot(SpectraPlot):
42 '''
43 Plot for Spectral Oblique
44 '''
45 CODE = 'spc_moments'
46 colormap = 'jet'
47 plot_type = 'pcolor'
48
49
41 50
42 51 class SnrPlot(RTIPlot):
43 52 '''
44 53 Plot for SNR Data
45 54 '''
46 55
47 56 CODE = 'snr'
48 57 colormap = 'jet'
49 58
50 59
51 60 class DopplerPlot(RTIPlot):
52 61 '''
53 62 Plot for DOPPLER Data (1st moment)
54 63 '''
55 64
56 65 CODE = 'dop'
57 66 colormap = 'jet'
58 67
59 68
60 69 class PowerPlot(RTIPlot):
61 70 '''
62 71 Plot for Power Data (0 moment)
63 72 '''
64 73
65 74 CODE = 'pow'
66 75 colormap = 'jet'
67 76
68 77
69 78 class SpectralWidthPlot(RTIPlot):
70 79 '''
71 80 Plot for Spectral Width Data (2nd moment)
72 81 '''
73 82
74 83 CODE = 'width'
75 84 colormap = 'jet'
76 85
77 86
78 87 class SkyMapPlot(Plot):
79 88 '''
80 89 Plot for meteors detection data
81 90 '''
82 91
83 92 CODE = 'param'
84 93
85 94 def setup(self):
86 95
87 96 self.ncols = 1
88 97 self.nrows = 1
89 98 self.width = 7.2
90 99 self.height = 7.2
91 100 self.nplots = 1
92 101 self.xlabel = 'Zonal Zenith Angle (deg)'
93 102 self.ylabel = 'Meridional Zenith Angle (deg)'
94 103 self.polar = True
95 104 self.ymin = -180
96 105 self.ymax = 180
97 106 self.colorbar = False
98 107
99 108 def plot(self):
100 109
101 110 arrayParameters = numpy.concatenate(self.data['param'])
102 111 error = arrayParameters[:, -1]
103 112 indValid = numpy.where(error == 0)[0]
104 113 finalMeteor = arrayParameters[indValid, :]
105 114 finalAzimuth = finalMeteor[:, 3]
106 115 finalZenith = finalMeteor[:, 4]
107 116
108 117 x = finalAzimuth * numpy.pi / 180
109 118 y = finalZenith
110 119
111 120 ax = self.axes[0]
112 121
113 122 if ax.firsttime:
114 123 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
115 124 else:
116 125 ax.plot.set_data(x, y)
117 126
118 127 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
119 128 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
120 129 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
121 130 dt2,
122 131 len(x))
123 132 self.titles[0] = title
124 133
125 134
126 135 class ParametersPlot(RTIPlot):
127 136 '''
128 137 Plot for data_param object
129 138 '''
130 139
131 140 CODE = 'param'
132 141 colormap = 'seismic'
133 142
134 143 def setup(self):
135 144 self.xaxis = 'time'
136 145 self.ncols = 1
137 146 self.nrows = self.data.shape(self.CODE)[0]
138 147 self.nplots = self.nrows
139 148 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
140
149
141 150 if not self.xlabel:
142 151 self.xlabel = 'Time'
143
152
144 153 if self.showSNR:
145 154 self.nrows += 1
146 155 self.nplots += 1
147 156
148 157 self.ylabel = 'Height [km]'
149 158 if not self.titles:
150 159 self.titles = self.data.parameters \
151 160 if self.data.parameters else ['Param {}'.format(x) for x in range(self.nrows)]
152 161 if self.showSNR:
153 162 self.titles.append('SNR')
154 163
155 164 def plot(self):
156 165 self.data.normalize_heights()
157 166 self.x = self.data.times
158 167 self.y = self.data.heights
159 168 if self.showSNR:
160 169 self.z = numpy.concatenate(
161 170 (self.data[self.CODE], self.data['snr'])
162 171 )
163 172 else:
164 173 self.z = self.data[self.CODE]
165 174
166 175 self.z = numpy.ma.masked_invalid(self.z)
167 176
168 177 if self.decimation is None:
169 178 x, y, z = self.fill_gaps(self.x, self.y, self.z)
170 179 else:
171 180 x, y, z = self.fill_gaps(*self.decimate())
172 181
173 182 for n, ax in enumerate(self.axes):
174 183
175 184 self.zmax = self.zmax if self.zmax is not None else numpy.max(
176 185 self.z[n])
177 186 self.zmin = self.zmin if self.zmin is not None else numpy.min(
178 187 self.z[n])
179 188
180 189 if ax.firsttime:
181 190 if self.zlimits is not None:
182 191 self.zmin, self.zmax = self.zlimits[n]
183 192
184 193 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
185 194 vmin=self.zmin,
186 195 vmax=self.zmax,
187 196 cmap=self.cmaps[n]
188 197 )
189 198 else:
190 199 if self.zlimits is not None:
191 200 self.zmin, self.zmax = self.zlimits[n]
192 201 ax.collections.remove(ax.collections[0])
193 202 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
194 203 vmin=self.zmin,
195 204 vmax=self.zmax,
196 205 cmap=self.cmaps[n]
197 206 )
198 207
199 208
200 209 class OutputPlot(ParametersPlot):
201 210 '''
202 211 Plot data_output object
203 212 '''
204 213
205 214 CODE = 'output'
206 215 colormap = 'seismic'
207 216
208 217
209 218 class PolarMapPlot(Plot):
210 219 '''
211 220 Plot for weather radar
212 221 '''
213 222
214 223 CODE = 'param'
215 224 colormap = 'seismic'
216 225
217 226 def setup(self):
218 227 self.ncols = 1
219 228 self.nrows = 1
220 229 self.width = 9
221 230 self.height = 8
222 231 self.mode = self.data.meta['mode']
223 232 if self.channels is not None:
224 233 self.nplots = len(self.channels)
225 234 self.nrows = len(self.channels)
226 235 else:
227 236 self.nplots = self.data.shape(self.CODE)[0]
228 237 self.nrows = self.nplots
229 238 self.channels = list(range(self.nplots))
230 239 if self.mode == 'E':
231 240 self.xlabel = 'Longitude'
232 241 self.ylabel = 'Latitude'
233 242 else:
234 243 self.xlabel = 'Range (km)'
235 244 self.ylabel = 'Height (km)'
236 245 self.bgcolor = 'white'
237 246 self.cb_labels = self.data.meta['units']
238 247 self.lat = self.data.meta['latitude']
239 248 self.lon = self.data.meta['longitude']
240 249 self.xmin, self.xmax = float(
241 250 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
242 251 self.ymin, self.ymax = float(
243 252 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
244 253 # self.polar = True
245 254
246 255 def plot(self):
247 256
248 257 for n, ax in enumerate(self.axes):
249 258 data = self.data['param'][self.channels[n]]
250 259
251 260 zeniths = numpy.linspace(
252 261 0, self.data.meta['max_range'], data.shape[1])
253 262 if self.mode == 'E':
254 263 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
255 264 r, theta = numpy.meshgrid(zeniths, azimuths)
256 265 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
257 266 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
258 267 x = km2deg(x) + self.lon
259 268 y = km2deg(y) + self.lat
260 269 else:
261 270 azimuths = numpy.radians(self.data.heights)
262 271 r, theta = numpy.meshgrid(zeniths, azimuths)
263 272 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
264 273 self.y = zeniths
265 274
266 275 if ax.firsttime:
267 276 if self.zlimits is not None:
268 277 self.zmin, self.zmax = self.zlimits[n]
269 278 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
270 279 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
271 280 vmin=self.zmin,
272 281 vmax=self.zmax,
273 282 cmap=self.cmaps[n])
274 283 else:
275 284 if self.zlimits is not None:
276 285 self.zmin, self.zmax = self.zlimits[n]
277 286 ax.collections.remove(ax.collections[0])
278 287 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
279 288 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
280 289 vmin=self.zmin,
281 290 vmax=self.zmax,
282 291 cmap=self.cmaps[n])
283 292
284 293 if self.mode == 'A':
285 294 continue
286 295
287 296 # plot district names
288 297 f = open('/data/workspace/schain_scripts/distrito.csv')
289 298 for line in f:
290 299 label, lon, lat = [s.strip() for s in line.split(',') if s]
291 300 lat = float(lat)
292 301 lon = float(lon)
293 302 # ax.plot(lon, lat, '.b', ms=2)
294 303 ax.text(lon, lat, label.decode('utf8'), ha='center',
295 304 va='bottom', size='8', color='black')
296 305
297 306 # plot limites
298 307 limites = []
299 308 tmp = []
300 309 for line in open('/data/workspace/schain_scripts/lima.csv'):
301 310 if '#' in line:
302 311 if tmp:
303 312 limites.append(tmp)
304 313 tmp = []
305 314 continue
306 315 values = line.strip().split(',')
307 316 tmp.append((float(values[0]), float(values[1])))
308 317 for points in limites:
309 318 ax.add_patch(
310 319 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
311 320
312 321 # plot Cuencas
313 322 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
314 323 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
315 324 values = [line.strip().split(',') for line in f]
316 325 points = [(float(s[0]), float(s[1])) for s in values]
317 326 ax.add_patch(Polygon(points, ec='b', fc='none'))
318 327
319 328 # plot grid
320 329 for r in (15, 30, 45, 60):
321 330 ax.add_artist(plt.Circle((self.lon, self.lat),
322 331 km2deg(r), color='0.6', fill=False, lw=0.2))
323 332 ax.text(
324 333 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
325 334 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
326 335 '{}km'.format(r),
327 336 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
328 337
329 338 if self.mode == 'E':
330 339 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
331 340 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
332 341 else:
333 342 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
334 343 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
335 344
336 345 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
337 346 self.titles = ['{} {}'.format(
338 347 self.data.parameters[x], title) for x in self.channels]
339
This diff has been collapsed as it changes many lines, (572 lines changed) Show them Hide them
@@ -1,641 +1,1171
1 1 '''
2 2 Created on Jul 9, 2014
3 3 Modified on May 10, 2020
4 4
5 5 @author: Juan C. Espinoza
6 6 '''
7 7
8 8 import os
9 9 import datetime
10 10 import numpy
11 11
12 12 from schainpy.model.graphics.jroplot_base import Plot, plt
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
24 24 def setup(self):
25
25 26 self.nplots = len(self.data.channels)
26 27 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
27 28 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
28 29 self.height = 2.6 * self.nrows
29 30 self.cb_label = 'dB'
30 31 if self.showprofile:
31 32 self.width = 4 * self.ncols
32 33 else:
33 34 self.width = 3.5 * self.ncols
34 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
35 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
35 36 self.ylabel = 'Range [km]'
36 37
37 38 def plot(self):
39
40 #print(self.xaxis)
41 #exit(1)
38 42 if self.xaxis == "frequency":
39 43 x = self.data.xrange[0]
40 44 self.xlabel = "Frequency (kHz)"
41 45 elif self.xaxis == "time":
42 46 x = self.data.xrange[1]
43 47 self.xlabel = "Time (ms)"
44 48 else:
45 49 x = self.data.xrange[2]
46 50 self.xlabel = "Velocity (m/s)"
47 51
48 52 if self.CODE == 'spc_moments':
49 53 x = self.data.xrange[2]
50 54 self.xlabel = "Velocity (m/s)"
51 55
52 56 self.titles = []
53 57
58
54 59 y = self.data.heights
55 60 self.y = y
56 61 z = self.data['spc']
57 62
63 self.CODE2 = 'spc_oblique'
64
65
58 66 for n, ax in enumerate(self.axes):
59 67 noise = self.data['noise'][n][-1]
60 68 if self.CODE == 'spc_moments':
61 69 mean = self.data['moments'][n, :, 1, :][-1]
70
62 71 if ax.firsttime:
63 72 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
64 73 self.xmin = self.xmin if self.xmin else -self.xmax
65 74 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
66 75 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
76 #print(numpy.shape(x))
67 77 ax.plt = ax.pcolormesh(x, y, z[n].T,
68 78 vmin=self.zmin,
69 79 vmax=self.zmax,
70 80 cmap=plt.get_cmap(self.colormap)
71 81 )
72 82
73 83 if self.showprofile:
74 84 ax.plt_profile = self.pf_axes[n].plot(
75 85 self.data['rti'][n][-1], y)[0]
76 86 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
77 87 color="k", linestyle="dashed", lw=1)[0]
78 88 if self.CODE == 'spc_moments':
79 89 ax.plt_mean = ax.plot(mean, y, color='k')[0]
90
80 91 else:
92
81 93 ax.plt.set_array(z[n].T.ravel())
82 94 if self.showprofile:
83 95 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
84 96 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
85 97 if self.CODE == 'spc_moments':
86 98 ax.plt_mean.set_data(mean, y)
99
87 100 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
88 101
102 class SpectraObliquePlot(Plot):
103 '''
104 Plot for Spectra data
105 '''
106
107 CODE = 'spc'
108 colormap = 'jet'
109 plot_type = 'pcolor'
110
111 def setup(self):
112 self.xaxis = "oblique"
113 self.nplots = len(self.data.channels)
114 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
115 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
116 self.height = 2.6 * self.nrows
117 self.cb_label = 'dB'
118 if self.showprofile:
119 self.width = 4 * self.ncols
120 else:
121 self.width = 3.5 * self.ncols
122 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
123 self.ylabel = 'Range [km]'
124
125 def plot(self):
126
127 #print(self.xaxis)
128 #exit(1)
129 if self.xaxis == "frequency":
130 x = self.data.xrange[0]
131 self.xlabel = "Frequency (kHz)"
132 elif self.xaxis == "time":
133 x = self.data.xrange[1]
134 self.xlabel = "Time (ms)"
135 else:
136 x = self.data.xrange[2]
137 self.xlabel = "Velocity (m/s)"
138
139 if self.CODE == 'spc_moments':
140 x = self.data.xrange[2]
141 self.xlabel = "Velocity (m/s)"
142
143 self.titles = []
144 #self.xlabel = "Velocidad (m/s)"
145 #self.ylabel = 'Rango (km)'
146
147
148 y = self.data.heights
149 self.y = y
150 z = self.data['spc']
151
152 self.CODE2 = 'spc_oblique'
153
154
155 for n, ax in enumerate(self.axes):
156 noise = self.data['noise'][n][-1]
157 if self.CODE == 'spc_moments':
158 mean = self.data['moments'][n, :, 1, :][-1]
159 if self.CODE2 == 'spc_oblique':
160 shift1 = self.data.shift1
161 shift2 = self.data.shift2
162 if ax.firsttime:
163 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
164 self.xmin = self.xmin if self.xmin else -self.xmax
165 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
166 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
167 #print(numpy.shape(x))
168 ax.plt = ax.pcolormesh(x, y, z[n].T,
169 vmin=self.zmin,
170 vmax=self.zmax,
171 cmap=plt.get_cmap(self.colormap)
172 )
173
174 if self.showprofile:
175 ax.plt_profile = self.pf_axes[n].plot(
176 self.data['rti'][n][-1], y)[0]
177 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
178 color="k", linestyle="dashed", lw=1)[0]
179 if self.CODE == 'spc_moments':
180 ax.plt_mean = ax.plot(mean, y, color='k')[0]
181
182 if self.CODE2 == 'spc_oblique':
183 #ax.plt_shift1 = ax.plot(shift1, y, color='k', marker='x', linestyle='None', markersize=0.5)[0]
184 #ax.plt_shift2 = ax.plot(shift2, y, color='m', marker='x', linestyle='None', markersize=0.5)[0]
185 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)
186 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)
187
188 else:
189 self.ploterr1.remove()
190 self.ploterr2.remove()
191 ax.plt.set_array(z[n].T.ravel())
192 if self.showprofile:
193 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
194 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
195 if self.CODE == 'spc_moments':
196 ax.plt_mean.set_data(mean, y)
197 if self.CODE2 == 'spc_oblique':
198 #ax.plt_shift1.set_data(shift1, y)
199 #ax.plt_shift2.set_data(shift2, y)
200 #ax.clf()
201 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)
202 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)
203
204 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
205 #self.titles.append('{}'.format('Velocidad Doppler'))
89 206
90 207 class CrossSpectraPlot(Plot):
91 208
92 209 CODE = 'cspc'
93 210 colormap = 'jet'
94 211 plot_type = 'pcolor'
95 212 zmin_coh = None
96 213 zmax_coh = None
97 214 zmin_phase = None
98 215 zmax_phase = None
99 216
100 217 def setup(self):
101 218
102 219 self.ncols = 4
103 220 self.nrows = len(self.data.pairs)
104 221 self.nplots = self.nrows * 4
105 222 self.width = 3.1 * self.ncols
106 self.height = 2.6 * self.nrows
223 self.height = 5 * self.nrows
107 224 self.ylabel = 'Range [km]'
108 225 self.showprofile = False
109 226 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
110 227
111 228 def plot(self):
112 229
113 230 if self.xaxis == "frequency":
114 231 x = self.data.xrange[0]
115 232 self.xlabel = "Frequency (kHz)"
116 233 elif self.xaxis == "time":
117 234 x = self.data.xrange[1]
118 235 self.xlabel = "Time (ms)"
119 236 else:
120 237 x = self.data.xrange[2]
121 238 self.xlabel = "Velocity (m/s)"
122
239
123 240 self.titles = []
124 241
242
125 243 y = self.data.heights
126 244 self.y = y
127 245 nspc = self.data['spc']
246 #print(numpy.shape(self.data['spc']))
128 247 spc = self.data['cspc'][0]
248 #print(numpy.shape(spc))
249 #exit()
129 250 cspc = self.data['cspc'][1]
251 #print(numpy.shape(cspc))
252 #exit()
130 253
131 254 for n in range(self.nrows):
132 255 noise = self.data['noise'][:,-1]
133 256 pair = self.data.pairs[n]
257 #print(pair)
258 #exit()
134 259 ax = self.axes[4 * n]
135 if ax.firsttime:
136 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
137 self.xmin = self.xmin if self.xmin else -self.xmax
138 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
139 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
260 if ax.firsttime:
261 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
262 #self.xmin = self.xmin if self.xmin else -self.xmax
263 self.xmin = self.xmin if self.xmin else numpy.nanmin(x)
264 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
265 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
266 #print(numpy.nanmin(x))
267 #print(self.xmax)
268 #print(self.xmin)
269 #exit()
270 #self.xmin=-.1
140 271 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
141 272 vmin=self.zmin,
142 273 vmax=self.zmax,
143 274 cmap=plt.get_cmap(self.colormap)
144 )
145 else:
275 )
276 else:
146 277 ax.plt.set_array(nspc[pair[0]].T.ravel())
147 278 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
148 279
149 280 ax = self.axes[4 * n + 1]
150 281 if ax.firsttime:
151 282 ax.plt = ax.pcolormesh(x , y, nspc[pair[1]].T,
152 283 vmin=self.zmin,
153 284 vmax=self.zmax,
154 285 cmap=plt.get_cmap(self.colormap)
155 286 )
156 else:
287 else:
157 288 ax.plt.set_array(nspc[pair[1]].T.ravel())
158 289 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
159
290
160 291 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
161 292 coh = numpy.abs(out)
162 293 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
163 294
164 295 ax = self.axes[4 * n + 2]
165 296 if ax.firsttime:
166 297 ax.plt = ax.pcolormesh(x, y, coh.T,
167 298 vmin=0,
168 299 vmax=1,
169 300 cmap=plt.get_cmap(self.colormap_coh)
170 301 )
171 302 else:
172 303 ax.plt.set_array(coh.T.ravel())
173 304 self.titles.append(
174 305 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
175
306
176 307 ax = self.axes[4 * n + 3]
177 308 if ax.firsttime:
178 309 ax.plt = ax.pcolormesh(x, y, phase.T,
179 310 vmin=-180,
180 311 vmax=180,
181 cmap=plt.get_cmap(self.colormap_phase)
312 cmap=plt.get_cmap(self.colormap_phase)
182 313 )
183 314 else:
184 315 ax.plt.set_array(phase.T.ravel())
185 316 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
186 317
187 318
319 class CrossSpectra4Plot(Plot):
320
321 CODE = 'cspc'
322 colormap = 'jet'
323 plot_type = 'pcolor'
324 zmin_coh = None
325 zmax_coh = None
326 zmin_phase = None
327 zmax_phase = None
328
329 def setup(self):
330
331 self.ncols = 4
332 self.nrows = len(self.data.pairs)
333 self.nplots = self.nrows * 4
334 self.width = 3.1 * self.ncols
335 self.height = 5 * self.nrows
336 self.ylabel = 'Range [km]'
337 self.showprofile = False
338 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
339
340 def plot(self):
341
342 if self.xaxis == "frequency":
343 x = self.data.xrange[0]
344 self.xlabel = "Frequency (kHz)"
345 elif self.xaxis == "time":
346 x = self.data.xrange[1]
347 self.xlabel = "Time (ms)"
348 else:
349 x = self.data.xrange[2]
350 self.xlabel = "Velocity (m/s)"
351
352 self.titles = []
353
354
355 y = self.data.heights
356 self.y = y
357 nspc = self.data['spc']
358 #print(numpy.shape(self.data['spc']))
359 spc = self.data['cspc'][0]
360 #print(numpy.shape(nspc))
361 #exit()
362 #nspc[1,:,:] = numpy.flip(nspc[1,:,:],axis=0)
363 #print(numpy.shape(spc))
364 #exit()
365 cspc = self.data['cspc'][1]
366
367 #xflip=numpy.flip(x)
368 #print(numpy.shape(cspc))
369 #exit()
370
371 for n in range(self.nrows):
372 noise = self.data['noise'][:,-1]
373 pair = self.data.pairs[n]
374 #print(pair)
375 #exit()
376 ax = self.axes[4 * n]
377 if ax.firsttime:
378 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
379 self.xmin = self.xmin if self.xmin else -self.xmax
380 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
381 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
382 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
383 vmin=self.zmin,
384 vmax=self.zmax,
385 cmap=plt.get_cmap(self.colormap)
386 )
387 else:
388 #print(numpy.shape(nspc[pair[0]].T))
389 #exit()
390 ax.plt.set_array(nspc[pair[0]].T.ravel())
391 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
392
393 ax = self.axes[4 * n + 1]
394
395 if ax.firsttime:
396 ax.plt = ax.pcolormesh(x , y, numpy.flip(nspc[pair[1]],axis=0).T,
397 vmin=self.zmin,
398 vmax=self.zmax,
399 cmap=plt.get_cmap(self.colormap)
400 )
401 else:
402
403 ax.plt.set_array(numpy.flip(nspc[pair[1]],axis=0).T.ravel())
404 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
405
406 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
407 coh = numpy.abs(out)
408 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
409
410 ax = self.axes[4 * n + 2]
411 if ax.firsttime:
412 ax.plt = ax.pcolormesh(x, y, numpy.flip(coh,axis=0).T,
413 vmin=0,
414 vmax=1,
415 cmap=plt.get_cmap(self.colormap_coh)
416 )
417 else:
418 ax.plt.set_array(numpy.flip(coh,axis=0).T.ravel())
419 self.titles.append(
420 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
421
422 ax = self.axes[4 * n + 3]
423 if ax.firsttime:
424 ax.plt = ax.pcolormesh(x, y, numpy.flip(phase,axis=0).T,
425 vmin=-180,
426 vmax=180,
427 cmap=plt.get_cmap(self.colormap_phase)
428 )
429 else:
430 ax.plt.set_array(numpy.flip(phase,axis=0).T.ravel())
431 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
432
433
434 class CrossSpectra2Plot(Plot):
435
436 CODE = 'cspc'
437 colormap = 'jet'
438 plot_type = 'pcolor'
439 zmin_coh = None
440 zmax_coh = None
441 zmin_phase = None
442 zmax_phase = None
443
444 def setup(self):
445
446 self.ncols = 1
447 self.nrows = len(self.data.pairs)
448 self.nplots = self.nrows * 1
449 self.width = 3.1 * self.ncols
450 self.height = 5 * self.nrows
451 self.ylabel = 'Range [km]'
452 self.showprofile = False
453 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
454
455 def plot(self):
456
457 if self.xaxis == "frequency":
458 x = self.data.xrange[0]
459 self.xlabel = "Frequency (kHz)"
460 elif self.xaxis == "time":
461 x = self.data.xrange[1]
462 self.xlabel = "Time (ms)"
463 else:
464 x = self.data.xrange[2]
465 self.xlabel = "Velocity (m/s)"
466
467 self.titles = []
468
469
470 y = self.data.heights
471 self.y = y
472 #nspc = self.data['spc']
473 #print(numpy.shape(self.data['spc']))
474 #spc = self.data['cspc'][0]
475 #print(numpy.shape(spc))
476 #exit()
477 cspc = self.data['cspc'][1]
478 #print(numpy.shape(cspc))
479 #exit()
480
481 for n in range(self.nrows):
482 noise = self.data['noise'][:,-1]
483 pair = self.data.pairs[n]
484 #print(pair) #exit()
485
486
487
488 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
489
490 #print(out[:,53])
491 #exit()
492 cross = numpy.abs(out)
493 z = cross/self.data.nFactor
494 #print("here")
495 #print(dataOut.data_spc[0,0,0])
496 #exit()
497
498 cross = 10*numpy.log10(z)
499 #print(numpy.shape(cross))
500 #print(cross[0,:])
501 #print(self.data.nFactor)
502 #exit()
503 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
504
505 ax = self.axes[1 * n]
506 if ax.firsttime:
507 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
508 self.xmin = self.xmin if self.xmin else -self.xmax
509 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
510 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
511 ax.plt = ax.pcolormesh(x, y, cross.T,
512 vmin=self.zmin,
513 vmax=self.zmax,
514 cmap=plt.get_cmap(self.colormap)
515 )
516 else:
517 ax.plt.set_array(cross.T.ravel())
518 self.titles.append(
519 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
520
521
522 class CrossSpectra3Plot(Plot):
523
524 CODE = 'cspc'
525 colormap = 'jet'
526 plot_type = 'pcolor'
527 zmin_coh = None
528 zmax_coh = None
529 zmin_phase = None
530 zmax_phase = None
531
532 def setup(self):
533
534 self.ncols = 3
535 self.nrows = len(self.data.pairs)
536 self.nplots = self.nrows * 3
537 self.width = 3.1 * self.ncols
538 self.height = 5 * self.nrows
539 self.ylabel = 'Range [km]'
540 self.showprofile = False
541 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
542
543 def plot(self):
544
545 if self.xaxis == "frequency":
546 x = self.data.xrange[0]
547 self.xlabel = "Frequency (kHz)"
548 elif self.xaxis == "time":
549 x = self.data.xrange[1]
550 self.xlabel = "Time (ms)"
551 else:
552 x = self.data.xrange[2]
553 self.xlabel = "Velocity (m/s)"
554
555 self.titles = []
556
557
558 y = self.data.heights
559 self.y = y
560 #nspc = self.data['spc']
561 #print(numpy.shape(self.data['spc']))
562 #spc = self.data['cspc'][0]
563 #print(numpy.shape(spc))
564 #exit()
565 cspc = self.data['cspc'][1]
566 #print(numpy.shape(cspc))
567 #exit()
568
569 for n in range(self.nrows):
570 noise = self.data['noise'][:,-1]
571 pair = self.data.pairs[n]
572 #print(pair) #exit()
573
574
575
576 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
577
578 #print(out[:,53])
579 #exit()
580 cross = numpy.abs(out)
581 z = cross/self.data.nFactor
582 cross = 10*numpy.log10(z)
583
584 out_r= out.real/self.data.nFactor
585 #out_r = 10*numpy.log10(out_r)
586
587 out_i= out.imag/self.data.nFactor
588 #out_i = 10*numpy.log10(out_i)
589 #print(numpy.shape(cross))
590 #print(cross[0,:])
591 #print(self.data.nFactor)
592 #exit()
593 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
594
595 ax = self.axes[3 * n]
596 if ax.firsttime:
597 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
598 self.xmin = self.xmin if self.xmin else -self.xmax
599 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
600 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
601 ax.plt = ax.pcolormesh(x, y, cross.T,
602 vmin=self.zmin,
603 vmax=self.zmax,
604 cmap=plt.get_cmap(self.colormap)
605 )
606 else:
607 ax.plt.set_array(cross.T.ravel())
608 self.titles.append(
609 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
610
611 ax = self.axes[3 * n + 1]
612 if ax.firsttime:
613 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
614 self.xmin = self.xmin if self.xmin else -self.xmax
615 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
616 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
617 ax.plt = ax.pcolormesh(x, y, out_r.T,
618 vmin=-1.e6,
619 vmax=0,
620 cmap=plt.get_cmap(self.colormap)
621 )
622 else:
623 ax.plt.set_array(out_r.T.ravel())
624 self.titles.append(
625 'Cross Spectra Real Ch{} * Ch{}'.format(pair[0], pair[1]))
626
627 ax = self.axes[3 * n + 2]
628
629
630 if ax.firsttime:
631 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
632 self.xmin = self.xmin if self.xmin else -self.xmax
633 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
634 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
635 ax.plt = ax.pcolormesh(x, y, out_i.T,
636 vmin=-1.e6,
637 vmax=1.e6,
638 cmap=plt.get_cmap(self.colormap)
639 )
640 else:
641 ax.plt.set_array(out_i.T.ravel())
642 self.titles.append(
643 'Cross Spectra Imag Ch{} * Ch{}'.format(pair[0], pair[1]))
644
188 645 class RTIPlot(Plot):
189 646 '''
190 647 Plot for RTI data
191 648 '''
192 649
193 650 CODE = 'rti'
194 651 colormap = 'jet'
195 652 plot_type = 'pcolorbuffer'
196 653
197 654 def setup(self):
198 655 self.xaxis = 'time'
199 656 self.ncols = 1
200 657 self.nrows = len(self.data.channels)
201 658 self.nplots = len(self.data.channels)
202 659 self.ylabel = 'Range [km]'
203 660 self.xlabel = 'Time'
204 661 self.cb_label = 'dB'
205 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
662 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
206 663 self.titles = ['{} Channel {}'.format(
207 664 self.CODE.upper(), x) for x in range(self.nrows)]
208 665
209 666 def plot(self):
210 667 self.x = self.data.times
211 668 self.y = self.data.heights
212 669 self.z = self.data[self.CODE]
670
671 self.z = numpy.ma.masked_invalid(self.z)
672
673 if self.decimation is None:
674 x, y, z = self.fill_gaps(self.x, self.y, self.z)
675 else:
676 x, y, z = self.fill_gaps(*self.decimate())
677
678 for n, ax in enumerate(self.axes):
679 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
680 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
681 if ax.firsttime:
682 ax.plt = ax.pcolormesh(x, y, z[n].T,
683 vmin=self.zmin,
684 vmax=self.zmax,
685 cmap=plt.get_cmap(self.colormap)
686 )
687 if self.showprofile:
688 ax.plot_profile = self.pf_axes[n].plot(
689 self.data['rti'][n][-1], self.y)[0]
690 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
691 color="k", linestyle="dashed", lw=1)[0]
692 else:
693 ax.collections.remove(ax.collections[0])
694 ax.plt = ax.pcolormesh(x, y, z[n].T,
695 vmin=self.zmin,
696 vmax=self.zmax,
697 cmap=plt.get_cmap(self.colormap)
698 )
699 if self.showprofile:
700 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
701 ax.plot_noise.set_data(numpy.repeat(
702 self.data['noise'][n][-1], len(self.y)), self.y)
703
704
705 class SpectrogramPlot(Plot):
706 '''
707 Plot for Spectrogram data
708 '''
709
710 CODE = 'spectrogram'
711 colormap = 'binary'
712 plot_type = 'pcolorbuffer'
713
714 def setup(self):
715 self.xaxis = 'time'
716 self.ncols = 1
717 self.nrows = len(self.data.channels)
718 self.nplots = len(self.data.channels)
719 #print(self.dataOut.heightList)
720 #self.ylabel = 'Range [km]'
721 self.xlabel = 'Time'
722 self.cb_label = 'dB'
723 self.plots_adjust.update({'hspace':1.2, 'left': 0.1, 'bottom': 0.12, 'right':0.95})
724 self.titles = ['{} Channel {} \n H = {} km ({} - {})'.format(
725 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)]
726
727 def plot(self):
728 self.x = self.data.times
729 #self.y = self.data.heights
730 self.z = self.data[self.CODE]
731 self.y = self.data.xrange[0]
732 #import time
733 #print(time.ctime(self.x))
734
735 '''
736 print(numpy.shape(self.x))
737 print(numpy.shape(self.y))
738 print(numpy.shape(self.z))
739 '''
740 self.ylabel = "Frequency (kHz)"
741
213 742 self.z = numpy.ma.masked_invalid(self.z)
214 743
215 744 if self.decimation is None:
216 745 x, y, z = self.fill_gaps(self.x, self.y, self.z)
217 746 else:
218 747 x, y, z = self.fill_gaps(*self.decimate())
219 748
220 749 for n, ax in enumerate(self.axes):
221 750 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
222 751 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
223 752 if ax.firsttime:
224 753 ax.plt = ax.pcolormesh(x, y, z[n].T,
225 754 vmin=self.zmin,
226 755 vmax=self.zmax,
227 756 cmap=plt.get_cmap(self.colormap)
228 757 )
229 758 if self.showprofile:
230 759 ax.plot_profile = self.pf_axes[n].plot(
231 760 self.data['rti'][n][-1], self.y)[0]
232 761 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
233 762 color="k", linestyle="dashed", lw=1)[0]
234 763 else:
235 764 ax.collections.remove(ax.collections[0])
236 765 ax.plt = ax.pcolormesh(x, y, z[n].T,
237 766 vmin=self.zmin,
238 767 vmax=self.zmax,
239 768 cmap=plt.get_cmap(self.colormap)
240 769 )
241 770 if self.showprofile:
242 771 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
243 772 ax.plot_noise.set_data(numpy.repeat(
244 773 self.data['noise'][n][-1], len(self.y)), self.y)
245 774
246 775
247 776 class CoherencePlot(RTIPlot):
248 777 '''
249 778 Plot for Coherence data
250 779 '''
251 780
252 781 CODE = 'coh'
253 782
254 783 def setup(self):
255 784 self.xaxis = 'time'
256 785 self.ncols = 1
257 786 self.nrows = len(self.data.pairs)
258 787 self.nplots = len(self.data.pairs)
259 788 self.ylabel = 'Range [km]'
260 789 self.xlabel = 'Time'
261 790 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
262 791 if self.CODE == 'coh':
263 792 self.cb_label = ''
264 793 self.titles = [
265 794 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
266 795 else:
267 796 self.cb_label = 'Degrees'
268 797 self.titles = [
269 798 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
270 799
271 800
272 801 class PhasePlot(CoherencePlot):
273 802 '''
274 803 Plot for Phase map data
275 804 '''
276 805
277 806 CODE = 'phase'
278 807 colormap = 'seismic'
279 808
280 809
281 810 class NoisePlot(Plot):
282 811 '''
283 Plot for noise
812 Plot for noise
284 813 '''
285 814
286 815 CODE = 'noise'
287 816 plot_type = 'scatterbuffer'
288 817
289 818
290 819 def setup(self):
291 820 self.xaxis = 'time'
292 821 self.ncols = 1
293 822 self.nrows = 1
294 823 self.nplots = 1
295 824 self.ylabel = 'Intensity [dB]'
296 825 self.xlabel = 'Time'
297 826 self.titles = ['Noise']
298 827 self.colorbar = False
828 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.17, 'right':0.95})
299 829
300 830 def plot(self):
301 831
302 832 x = self.data.times
303 833 xmin = self.data.min_time
304 834 xmax = xmin + self.xrange * 60 * 60
305 835 Y = self.data[self.CODE]
306 836
307 837 if self.axes[0].firsttime:
308 838 for ch in self.data.channels:
309 839 y = Y[ch]
310 840 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
311 841 plt.legend()
312 842 else:
313 843 for ch in self.data.channels:
314 844 y = Y[ch]
315 845 self.axes[0].lines[ch].set_data(x, y)
316 846
317 847 self.ymin = numpy.nanmin(Y) - 5
318 self.ymax = numpy.nanmax(Y) + 5
848 self.ymax = numpy.nanmax(Y) + 10
319 849
320 850
321 851 class PowerProfilePlot(Plot):
322 852
323 853 CODE = 'spcprofile'
324 854 plot_type = 'scatter'
325 855 buffering = False
326 856
327 857 def setup(self):
328 858
329 859 self.ncols = 1
330 860 self.nrows = 1
331 861 self.nplots = 1
332 862 self.height = 4
333 863 self.width = 3
334 864 self.ylabel = 'Range [km]'
335 865 self.xlabel = 'Intensity [dB]'
336 866 self.titles = ['Power Profile']
337 867 self.colorbar = False
338 868
339 869 def plot(self):
340 870
341 871 y = self.data.heights
342 872 self.y = y
343 873
344 874 x = self.data['spcprofile']
345
875
346 876 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
347 877 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
348
878
349 879 if self.axes[0].firsttime:
350 880 for ch in self.data.channels:
351 881 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
352 882 plt.legend()
353 883 else:
354 884 for ch in self.data.channels:
355 885 self.axes[0].lines[ch].set_data(x[ch], y)
356 886
357 887
358 888 class SpectraCutPlot(Plot):
359 889
360 890 CODE = 'spc_cut'
361 891 plot_type = 'scatter'
362 892 buffering = False
363 893
364 894 def setup(self):
365 895
366 896 self.nplots = len(self.data.channels)
367 897 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
368 898 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
369 899 self.width = 3.4 * self.ncols + 1.5
370 900 self.height = 3 * self.nrows
371 901 self.ylabel = 'Power [dB]'
372 902 self.colorbar = False
373 903 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
374 904
375 905 def plot(self):
376 906 if self.xaxis == "frequency":
377 907 x = self.data.xrange[0][1:]
378 908 self.xlabel = "Frequency (kHz)"
379 909 elif self.xaxis == "time":
380 910 x = self.data.xrange[1]
381 911 self.xlabel = "Time (ms)"
382 912 else:
383 913 x = self.data.xrange[2]
384 914 self.xlabel = "Velocity (m/s)"
385 915
386 916 self.titles = []
387 917
388 918 y = self.data.heights
389 919 #self.y = y
390 920 z = self.data['spc_cut']
391 921
392 922 if self.height_index:
393 923 index = numpy.array(self.height_index)
394 924 else:
395 925 index = numpy.arange(0, len(y), int((len(y))/9))
396 926
397 927 for n, ax in enumerate(self.axes):
398 928 if ax.firsttime:
399 929 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
400 930 self.xmin = self.xmin if self.xmin else -self.xmax
401 931 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
402 932 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
403 933 ax.plt = ax.plot(x, z[n, :, index].T)
404 934 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
405 935 self.figures[0].legend(ax.plt, labels, loc='center right')
406 936 else:
407 937 for i, line in enumerate(ax.plt):
408 938 line.set_data(x, z[n, :, i])
409 939 self.titles.append('CH {}'.format(n))
410 940
411 941
412 942 class BeaconPhase(Plot):
413 943
414 944 __isConfig = None
415 945 __nsubplots = None
416 946
417 947 PREFIX = 'beacon_phase'
418 948
419 949 def __init__(self):
420 950 Plot.__init__(self)
421 951 self.timerange = 24*60*60
422 952 self.isConfig = False
423 953 self.__nsubplots = 1
424 954 self.counter_imagwr = 0
425 955 self.WIDTH = 800
426 956 self.HEIGHT = 400
427 957 self.WIDTHPROF = 120
428 958 self.HEIGHTPROF = 0
429 959 self.xdata = None
430 960 self.ydata = None
431 961
432 962 self.PLOT_CODE = BEACON_CODE
433 963
434 964 self.FTP_WEI = None
435 965 self.EXP_CODE = None
436 966 self.SUB_EXP_CODE = None
437 967 self.PLOT_POS = None
438 968
439 969 self.filename_phase = None
440 970
441 971 self.figfile = None
442 972
443 973 self.xmin = None
444 974 self.xmax = None
445 975
446 976 def getSubplots(self):
447 977
448 978 ncol = 1
449 979 nrow = 1
450 980
451 981 return nrow, ncol
452 982
453 983 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
454 984
455 985 self.__showprofile = showprofile
456 986 self.nplots = nplots
457 987
458 988 ncolspan = 7
459 989 colspan = 6
460 990 self.__nsubplots = 2
461 991
462 992 self.createFigure(id = id,
463 993 wintitle = wintitle,
464 994 widthplot = self.WIDTH+self.WIDTHPROF,
465 995 heightplot = self.HEIGHT+self.HEIGHTPROF,
466 996 show=show)
467 997
468 998 nrow, ncol = self.getSubplots()
469 999
470 1000 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
471 1001
472 1002 def save_phase(self, filename_phase):
473 1003 f = open(filename_phase,'w+')
474 1004 f.write('\n\n')
475 1005 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
476 1006 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
477 1007 f.close()
478 1008
479 1009 def save_data(self, filename_phase, data, data_datetime):
480 1010 f=open(filename_phase,'a')
481 1011 timetuple_data = data_datetime.timetuple()
482 1012 day = str(timetuple_data.tm_mday)
483 1013 month = str(timetuple_data.tm_mon)
484 1014 year = str(timetuple_data.tm_year)
485 1015 hour = str(timetuple_data.tm_hour)
486 1016 minute = str(timetuple_data.tm_min)
487 1017 second = str(timetuple_data.tm_sec)
488 1018 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
489 1019 f.close()
490 1020
491 1021 def plot(self):
492 1022 log.warning('TODO: Not yet implemented...')
493 1023
494 1024 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
495 1025 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
496 1026 timerange=None,
497 1027 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
498 1028 server=None, folder=None, username=None, password=None,
499 1029 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
500 1030
501 if dataOut.flagNoData:
1031 if dataOut.flagNoData:
502 1032 return dataOut
503 1033
504 1034 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
505 1035 return
506 1036
507 1037 if pairsList == None:
508 1038 pairsIndexList = dataOut.pairsIndexList[:10]
509 1039 else:
510 1040 pairsIndexList = []
511 1041 for pair in pairsList:
512 1042 if pair not in dataOut.pairsList:
513 1043 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
514 1044 pairsIndexList.append(dataOut.pairsList.index(pair))
515 1045
516 1046 if pairsIndexList == []:
517 1047 return
518 1048
519 1049 # if len(pairsIndexList) > 4:
520 1050 # pairsIndexList = pairsIndexList[0:4]
521 1051
522 1052 hmin_index = None
523 1053 hmax_index = None
524 1054
525 1055 if hmin != None and hmax != None:
526 1056 indexes = numpy.arange(dataOut.nHeights)
527 1057 hmin_list = indexes[dataOut.heightList >= hmin]
528 1058 hmax_list = indexes[dataOut.heightList <= hmax]
529 1059
530 1060 if hmin_list.any():
531 1061 hmin_index = hmin_list[0]
532 1062
533 1063 if hmax_list.any():
534 1064 hmax_index = hmax_list[-1]+1
535 1065
536 1066 x = dataOut.getTimeRange()
537 1067
538 1068 thisDatetime = dataOut.datatime
539 1069
540 1070 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
541 1071 xlabel = "Local Time"
542 1072 ylabel = "Phase (degrees)"
543 1073
544 1074 update_figfile = False
545 1075
546 1076 nplots = len(pairsIndexList)
547 1077 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
548 1078 phase_beacon = numpy.zeros(len(pairsIndexList))
549 1079 for i in range(nplots):
550 1080 pair = dataOut.pairsList[pairsIndexList[i]]
551 1081 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
552 1082 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
553 1083 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
554 1084 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
555 1085 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
556 1086
557 1087 if dataOut.beacon_heiIndexList:
558 1088 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
559 1089 else:
560 1090 phase_beacon[i] = numpy.average(phase)
561 1091
562 1092 if not self.isConfig:
563 1093
564 1094 nplots = len(pairsIndexList)
565 1095
566 1096 self.setup(id=id,
567 1097 nplots=nplots,
568 1098 wintitle=wintitle,
569 1099 showprofile=showprofile,
570 1100 show=show)
571 1101
572 1102 if timerange != None:
573 1103 self.timerange = timerange
574 1104
575 1105 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
576 1106
577 1107 if ymin == None: ymin = 0
578 1108 if ymax == None: ymax = 360
579 1109
580 1110 self.FTP_WEI = ftp_wei
581 1111 self.EXP_CODE = exp_code
582 1112 self.SUB_EXP_CODE = sub_exp_code
583 1113 self.PLOT_POS = plot_pos
584 1114
585 1115 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
586 1116 self.isConfig = True
587 1117 self.figfile = figfile
588 1118 self.xdata = numpy.array([])
589 1119 self.ydata = numpy.array([])
590 1120
591 1121 update_figfile = True
592 1122
593 1123 #open file beacon phase
594 1124 path = '%s%03d' %(self.PREFIX, self.id)
595 1125 beacon_file = os.path.join(path,'%s.txt'%self.name)
596 1126 self.filename_phase = os.path.join(figpath,beacon_file)
597 1127 #self.save_phase(self.filename_phase)
598 1128
599 1129
600 1130 #store data beacon phase
601 1131 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
602 1132
603 1133 self.setWinTitle(title)
604 1134
605 1135
606 1136 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
607 1137
608 1138 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
609 1139
610 1140 axes = self.axesList[0]
611 1141
612 1142 self.xdata = numpy.hstack((self.xdata, x[0:1]))
613 1143
614 1144 if len(self.ydata)==0:
615 1145 self.ydata = phase_beacon.reshape(-1,1)
616 1146 else:
617 1147 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
618 1148
619 1149
620 1150 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
621 1151 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
622 1152 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
623 1153 XAxisAsTime=True, grid='both'
624 1154 )
625 1155
626 1156 self.draw()
627 1157
628 1158 if dataOut.ltctime >= self.xmax:
629 1159 self.counter_imagwr = wr_period
630 1160 self.isConfig = False
631 1161 update_figfile = True
632 1162
633 1163 self.save(figpath=figpath,
634 1164 figfile=figfile,
635 1165 save=save,
636 1166 ftp=ftp,
637 1167 wr_period=wr_period,
638 1168 thisDatetime=thisDatetime,
639 1169 update_figfile=update_figfile)
640 1170
641 return dataOut No newline at end of file
1171 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 from .jroIO_simulator import * No newline at end of file
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 try:
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 try:
400 try:
399 401 year = int(file[1:5])
400 402 doy = int(file[5:8])
401 set = int(file[8:11])
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 raise NotImplementedError
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 folders = [x for f in path.split(',')
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 for folder in folders:
510 try:
511 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
511 for folder in folders:
512 try:
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
521 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
522
523 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
522 524 expLabel='', last=False):
523
524 for path in folders:
525
526 for path in folders:
525 527 files = glob.glob1(path, '*{}'.format(ext))
526 528 files.sort()
527 529 if last:
528 if files:
530 if files:
529 531 fo = files[-1]
530 try:
532 try:
531 533 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
532 yield os.path.join(path, expLabel, fo)
533 except Exception as e:
534 yield os.path.join(path, expLabel, fo)
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 try:
541 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
542 try:
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 continue
556 continue
549 557
550 558 def searchFilesOffLine(self, path, startDate, endDate,
551 expLabel, ext, walk,
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 folders, ext, filefmt, startDate, endDate, expLabel)
574 folders, ext, filefmt, startDate, endDate, expLabel)
567 575
568 576 def searchFilesOnLine(self, path, startDate, endDate,
569 expLabel, ext, walk,
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 self.fp.close()
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 for nFiles in range(self.nFiles+1):
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 continue
647
669 continue
670
648 671 if fullfilename is not None:
649 672 break
650
651 self.nTries = 1
652 nextFile = True
673
674 #self.nTries = 1
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 self.nTries = 3
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 else:
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 return 0
681
705 return 0
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
787
813
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
820 return None, filename
821
854
855 return None, filename
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 return 0
864
865 if self.flagIsNewFile:
899 return 0
900
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 flag = False
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 self.endDate, self.expLabel, self.ext, self.walk,
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 self.delay, self.path, nTries + 1),
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 'There isn\'t any valid file in {}'.format(self.path))
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 self.set = int(filename[8:11]) - 1
1198 self.set = int(filename[8:11]) - 1
1159 1199 else:
1160 1200 log.log("Searching files in {}".format(self.path), self.name)
1161 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
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 path :
1218 startDate :
1257 path :
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 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1365 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1326 1366 utc = numpy.floor(self.dataOut.utctime)
1327 milisecond = (self.dataOut.utctime - utc) * 1000.0
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 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
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 self.setFile = set - 1
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 self.dataOut = Parameters()
88 self.dataOut = Parameters()
89 89 self.counter_records = 0
90 90 self.nrecords = None
91 91 self.flagNoMoreFiles = 0
92 self.filename = None
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 self.endDate, self.expLabel, self.ext, self.walk,
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 self.delay, self.path, nTries + 1),
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 'There isn\'t any valid file in {}'.format(self.path))
148
147 'There isn\'t any valid file in {}'.format(self.path))
148
149 149 else:
150 150 log.log("Searching files in {}".format(self.path), self.name)
151 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
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
163 return
162
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 self.setNextFile()
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 self.intervals.add((datatime-self.datatime).seconds)
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 self.counter_records += 1
282
281 self.counter_records += 1
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 for param, attr in list(self.oneDDict.items()):
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 dummy = numpy.zeros(self.ranges.shape) + numpy.nan
298 dummy = numpy.zeros(self.ranges.shape) + numpy.nan
299 299 if self.ext == '.txt':
300 300 x = self.parameters.index(param.lower())
301 y = self.parameters.index(self.independentParam.lower())
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 if value not in self.independentParam:
313 if value not in self.independentParam:
314 314 setattr(self.dataOut, value, dummy.reshape(1,-1))
315 elif isinstance(value, list):
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 self.dataOut.utctimeInit = self.dataOut.utctime
324 self.dataOut.utctimeInit = self.dataOut.utctime
325 325 self.dataOut.paramInterval = min(self.intervals)
326 self.dataOut.useLocalTime = False
327 self.dataOut.flagNoData = False
326 self.dataOut.useLocalTime = False
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
403 self.dataOut = dataOut
404 self.putData()
405
406 self.dataOut = dataOut
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 Configure Operation
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 meta = load_json(metadata)
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
430 self.keys = [k.lower() for k in self.twoDDict]
433
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
450 if os.path.isfile(self.fullname) :
456
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 data = getattr(self.dataOut, attr)
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
538 # Setting 1d values
569 #print("rec",rec)
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 for n in index:
576 for n in index:
545 577 for key in out:
546 578 rec.set2D(key, nrec, out[key][n])
547 nrec += 1
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 '''
562
595 '''
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
571 header = madrigal.cedar.CatalogHeaderCreator(self.fullname)
604
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 return 0
580
613 return 0
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 self.counter += 1
591
624 self.counter += 1
625
592 626 def close(self):
593
594 if self.counter > 0:
595 self.setHeader() No newline at end of file
627
628 if self.counter > 0:
629 self.setHeader()
@@ -1,626 +1,627
1 1 import os
2 2 import time
3 3 import datetime
4 4
5 5 import numpy
6 6 import h5py
7 7
8 8 import schainpy.admin
9 9 from schainpy.model.data.jrodata import *
10 10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 11 from schainpy.model.io.jroIO_base import *
12 12 from schainpy.utils import log
13 13
14 14
15 15 class HDFReader(Reader, ProcessingUnit):
16 16 """Processing unit to read HDF5 format files
17 17
18 18 This unit reads HDF5 files created with `HDFWriter` operation contains
19 19 by default two groups Data and Metadata all variables would be saved as `dataOut`
20 attributes.
20 attributes.
21 21 It is possible to read any HDF5 file by given the structure in the `description`
22 22 parameter, also you can add extra values to metadata with the parameter `extras`.
23 23
24 24 Parameters:
25 25 -----------
26 26 path : str
27 27 Path where files are located.
28 28 startDate : date
29 29 Start date of the files
30 30 endDate : list
31 31 End date of the files
32 32 startTime : time
33 33 Start time of the files
34 34 endTime : time
35 35 End time of the files
36 36 description : dict, optional
37 37 Dictionary with the description of the HDF5 file
38 38 extras : dict, optional
39 39 Dictionary with extra metadata to be be added to `dataOut`
40
40
41 41 Examples
42 42 --------
43
43
44 44 desc = {
45 45 'Data': {
46 46 'data_output': ['u', 'v', 'w'],
47 47 'utctime': 'timestamps',
48 48 } ,
49 49 'Metadata': {
50 50 'heightList': 'heights'
51 51 }
52 52 }
53 53
54 54 desc = {
55 55 'Data': {
56 56 'data_output': 'winds',
57 57 'utctime': 'timestamps'
58 58 },
59 59 'Metadata': {
60 60 'heightList': 'heights'
61 61 }
62 62 }
63 63
64 64 extras = {
65 65 'timeZone': 300
66 66 }
67
67
68 68 reader = project.addReadUnit(
69 69 name='HDFReader',
70 70 path='/path/to/files',
71 71 startDate='2019/01/01',
72 72 endDate='2019/01/31',
73 73 startTime='00:00:00',
74 74 endTime='23:59:59',
75 75 # description=json.dumps(desc),
76 76 # extras=json.dumps(extras),
77 77 )
78 78
79 79 """
80 80
81 81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
82 82
83 83 def __init__(self):
84 84 ProcessingUnit.__init__(self)
85 85 self.dataOut = Parameters()
86 86 self.ext = ".hdf5"
87 87 self.optchar = "D"
88 88 self.meta = {}
89 89 self.data = {}
90 90 self.open_file = h5py.File
91 91 self.open_mode = 'r'
92 92 self.description = {}
93 93 self.extras = {}
94 94 self.filefmt = "*%Y%j***"
95 95 self.folderfmt = "*%Y%j"
96 96
97 97 def setup(self, **kwargs):
98 98
99 99 self.set_kwargs(**kwargs)
100 100 if not self.ext.startswith('.'):
101 self.ext = '.{}'.format(self.ext)
101 self.ext = '.{}'.format(self.ext)
102 102
103 103 if self.online:
104 104 log.log("Searching files in online mode...", self.name)
105 105
106 106 for nTries in range(self.nTries):
107 107 fullpath = self.searchFilesOnLine(self.path, self.startDate,
108 self.endDate, self.expLabel, self.ext, self.walk,
108 self.endDate, self.expLabel, self.ext, self.walk,
109 109 self.filefmt, self.folderfmt)
110 110 try:
111 111 fullpath = next(fullpath)
112 112 except:
113 113 fullpath = None
114
114
115 115 if fullpath:
116 116 break
117 117
118 118 log.warning(
119 119 'Waiting {} sec for a valid file in {}: try {} ...'.format(
120 self.delay, self.path, nTries + 1),
120 self.delay, self.path, nTries + 1),
121 121 self.name)
122 122 time.sleep(self.delay)
123 123
124 124 if not(fullpath):
125 125 raise schainpy.admin.SchainError(
126 'There isn\'t any valid file in {}'.format(self.path))
126 'There isn\'t any valid file in {}'.format(self.path))
127 127
128 128 pathname, filename = os.path.split(fullpath)
129 129 self.year = int(filename[1:5])
130 130 self.doy = int(filename[5:8])
131 self.set = int(filename[8:11]) - 1
131 self.set = int(filename[8:11]) - 1
132 132 else:
133 133 log.log("Searching files in {}".format(self.path), self.name)
134 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
134 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
135 135 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
136
136
137 137 self.setNextFile()
138 138
139 139 return
140 140
141 141 def readFirstHeader(self):
142 142 '''Read metadata and data'''
143 143
144 self.__readMetadata()
144 self.__readMetadata()
145 145 self.__readData()
146 146 self.__setBlockList()
147
147
148 148 if 'type' in self.meta:
149 149 self.dataOut = eval(self.meta['type'])()
150
150
151 151 for attr in self.meta:
152 152 setattr(self.dataOut, attr, self.meta[attr])
153
153
154 154 self.blockIndex = 0
155
155
156 156 return
157 157
158 158 def __setBlockList(self):
159 159 '''
160 160 Selects the data within the times defined
161 161
162 162 self.fp
163 163 self.startTime
164 164 self.endTime
165 165 self.blockList
166 166 self.blocksPerFile
167 167
168 168 '''
169 169
170 170 startTime = self.startTime
171 171 endTime = self.endTime
172 172
173 173 thisUtcTime = self.data['utctime']
174 174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
175 175
176 176 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
177 177
178 178 thisDate = thisDatetime.date()
179 179 thisTime = thisDatetime.time()
180 180
181 181 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
182 182 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
183 183
184 184 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
185 185
186 186 self.blockList = ind
187 187 self.blocksPerFile = len(ind)
188 188 return
189 189
190 190 def __readMetadata(self):
191 191 '''
192 192 Reads Metadata
193 193 '''
194 194
195 195 meta = {}
196 196
197 197 if self.description:
198 198 for key, value in self.description['Metadata'].items():
199 199 meta[key] = self.fp[value].value
200 200 else:
201 201 grp = self.fp['Metadata']
202 202 for name in grp:
203 meta[name] = grp[name].value
203 meta[name] = grp[name].value
204 204
205 205 if self.extras:
206 206 for key, value in self.extras.items():
207 207 meta[key] = value
208 208 self.meta = meta
209 209
210 210 return
211 211
212 212 def __readData(self):
213 213
214 214 data = {}
215
215
216 216 if self.description:
217 217 for key, value in self.description['Data'].items():
218 218 if isinstance(value, str):
219 219 if isinstance(self.fp[value], h5py.Dataset):
220 220 data[key] = self.fp[value].value
221 221 elif isinstance(self.fp[value], h5py.Group):
222 222 array = []
223 223 for ch in self.fp[value]:
224 224 array.append(self.fp[value][ch].value)
225 225 data[key] = numpy.array(array)
226 226 elif isinstance(value, list):
227 227 array = []
228 228 for ch in value:
229 229 array.append(self.fp[ch].value)
230 230 data[key] = numpy.array(array)
231 231 else:
232 232 grp = self.fp['Data']
233 233 for name in grp:
234 234 if isinstance(grp[name], h5py.Dataset):
235 235 array = grp[name].value
236 236 elif isinstance(grp[name], h5py.Group):
237 237 array = []
238 238 for ch in grp[name]:
239 239 array.append(grp[name][ch].value)
240 240 array = numpy.array(array)
241 241 else:
242 242 log.warning('Unknown type: {}'.format(name))
243
243
244 244 if name in self.description:
245 245 key = self.description[name]
246 246 else:
247 247 key = name
248 248 data[key] = array
249 249
250 250 self.data = data
251 251 return
252
252
253 253 def getData(self):
254 254
255 255 for attr in self.data:
256 256 if self.data[attr].ndim == 1:
257 257 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
258 258 else:
259 259 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
260 260
261 261 self.dataOut.flagNoData = False
262 262 self.blockIndex += 1
263 263
264 264 log.log("Block No. {}/{} -> {}".format(
265 265 self.blockIndex,
266 266 self.blocksPerFile,
267 267 self.dataOut.datatime.ctime()), self.name)
268 268
269 269 return
270 270
271 271 def run(self, **kwargs):
272 272
273 273 if not(self.isConfig):
274 274 self.setup(**kwargs)
275 275 self.isConfig = True
276 276
277 277 if self.blockIndex == self.blocksPerFile:
278 278 self.setNextFile()
279 279
280 280 self.getData()
281 281
282 282 return
283 283
284 284 @MPDecorator
285 285 class HDFWriter(Operation):
286 286 """Operation to write HDF5 files.
287 287
288 288 The HDF5 file contains by default two groups Data and Metadata where
289 289 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
290 290 parameters, data attributes are normaly time dependent where the metadata
291 are not.
292 It is possible to customize the structure of the HDF5 file with the
291 are not.
292 It is possible to customize the structure of the HDF5 file with the
293 293 optional description parameter see the examples.
294 294
295 295 Parameters:
296 296 -----------
297 297 path : str
298 298 Path where files will be saved.
299 299 blocksPerFile : int
300 300 Number of blocks per file
301 301 metadataList : list
302 302 List of the dataOut attributes that will be saved as metadata
303 303 dataList : int
304 304 List of the dataOut attributes that will be saved as data
305 305 setType : bool
306 306 If True the name of the files corresponds to the timestamp of the data
307 307 description : dict, optional
308 308 Dictionary with the desired description of the HDF5 file
309
309
310 310 Examples
311 311 --------
312
312
313 313 desc = {
314 314 'data_output': {'winds': ['z', 'w', 'v']},
315 315 'utctime': 'timestamps',
316 316 'heightList': 'heights'
317 317 }
318 318 desc = {
319 319 'data_output': ['z', 'w', 'v'],
320 320 'utctime': 'timestamps',
321 321 'heightList': 'heights'
322 322 }
323 323 desc = {
324 324 'Data': {
325 325 'data_output': 'winds',
326 326 'utctime': 'timestamps'
327 327 },
328 328 'Metadata': {
329 329 'heightList': 'heights'
330 330 }
331 331 }
332
332
333 333 writer = proc_unit.addOperation(name='HDFWriter')
334 334 writer.addParameter(name='path', value='/path/to/file')
335 335 writer.addParameter(name='blocksPerFile', value='32')
336 336 writer.addParameter(name='metadataList', value='heightList,timeZone')
337 337 writer.addParameter(name='dataList',value='data_output,utctime')
338 338 # writer.addParameter(name='description',value=json.dumps(desc))
339 339
340 340 """
341 341
342 342 ext = ".hdf5"
343 343 optchar = "D"
344 344 filename = None
345 345 path = None
346 346 setFile = None
347 347 fp = None
348 348 firsttime = True
349 349 #Configurations
350 350 blocksPerFile = None
351 351 blockIndex = None
352 352 dataOut = None
353 353 #Data Arrays
354 354 dataList = None
355 355 metadataList = None
356 356 currentDay = None
357 357 lastTime = None
358 358
359 359 def __init__(self):
360
360
361 361 Operation.__init__(self)
362 362 return
363 363
364 364 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None):
365 365 self.path = path
366 366 self.blocksPerFile = blocksPerFile
367 367 self.metadataList = metadataList
368 368 self.dataList = [s.strip() for s in dataList]
369 369 self.setType = setType
370 370 self.description = description
371 371
372 372 if self.metadataList is None:
373 373 self.metadataList = self.dataOut.metadata_list
374 374
375 375 tableList = []
376 376 dsList = []
377 377
378 378 for i in range(len(self.dataList)):
379 379 dsDict = {}
380 380 if hasattr(self.dataOut, self.dataList[i]):
381 381 dataAux = getattr(self.dataOut, self.dataList[i])
382 382 dsDict['variable'] = self.dataList[i]
383 383 else:
384 384 log.warning('Attribute {} not found in dataOut', self.name)
385 385 continue
386 386
387 387 if dataAux is None:
388 388 continue
389 389 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
390 390 dsDict['nDim'] = 0
391 391 else:
392 392 dsDict['nDim'] = len(dataAux.shape)
393 393 dsDict['shape'] = dataAux.shape
394 394 dsDict['dsNumber'] = dataAux.shape[0]
395 395 dsDict['dtype'] = dataAux.dtype
396
396
397 397 dsList.append(dsDict)
398 398
399 399 self.dsList = dsList
400 400 self.currentDay = self.dataOut.datatime.date()
401 401
402 402 def timeFlag(self):
403 403 currentTime = self.dataOut.utctime
404 404 timeTuple = time.localtime(currentTime)
405 405 dataDay = timeTuple.tm_yday
406 406
407 407 if self.lastTime is None:
408 408 self.lastTime = currentTime
409 409 self.currentDay = dataDay
410 410 return False
411
411
412 412 timeDiff = currentTime - self.lastTime
413 413
414 414 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
415 415 if dataDay != self.currentDay:
416 416 self.currentDay = dataDay
417 417 return True
418 418 elif timeDiff > 3*60*60:
419 419 self.lastTime = currentTime
420 420 return True
421 421 else:
422 422 self.lastTime = currentTime
423 423 return False
424 424
425 425 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
426 426 dataList=[], setType=None, description={}):
427
427 print("hdf",dataOut.flagNoData)
428 print(dataOut.datatime.ctime())
428 429 self.dataOut = dataOut
429 430 if not(self.isConfig):
430 self.setup(path=path, blocksPerFile=blocksPerFile,
431 self.setup(path=path, blocksPerFile=blocksPerFile,
431 432 metadataList=metadataList, dataList=dataList,
432 433 setType=setType, description=description)
433 434
434 435 self.isConfig = True
435 436 self.setNextFile()
436 437
437 438 self.putData()
438 439 return
439
440
440 441 def setNextFile(self):
441
442
442 443 ext = self.ext
443 444 path = self.path
444 445 setFile = self.setFile
445 446
446 447 timeTuple = time.localtime(self.dataOut.utctime)
447 448 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
448 449 fullpath = os.path.join(path, subfolder)
449 450
450 451 if os.path.exists(fullpath):
451 452 filesList = os.listdir(fullpath)
452 453 filesList = [k for k in filesList if k.startswith(self.optchar)]
453 454 if len( filesList ) > 0:
454 455 filesList = sorted(filesList, key=str.lower)
455 456 filen = filesList[-1]
456 457 # el filename debera tener el siguiente formato
457 458 # 0 1234 567 89A BCDE (hex)
458 459 # x YYYY DDD SSS .ext
459 460 if isNumber(filen[8:11]):
460 461 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
461 462 else:
462 463 setFile = -1
463 464 else:
464 465 setFile = -1 #inicializo mi contador de seteo
465 466 else:
466 467 os.makedirs(fullpath)
467 468 setFile = -1 #inicializo mi contador de seteo
468 469
469 470 if self.setType is None:
470 471 setFile += 1
471 472 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
472 473 timeTuple.tm_year,
473 474 timeTuple.tm_yday,
474 475 setFile,
475 476 ext )
476 477 else:
477 478 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
478 479 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
479 480 timeTuple.tm_year,
480 481 timeTuple.tm_yday,
481 482 setFile,
482 483 ext )
483 484
484 485 self.filename = os.path.join( path, subfolder, file )
485 486
486 487 #Setting HDF5 File
487 488 self.fp = h5py.File(self.filename, 'w')
488 489 #write metadata
489 490 self.writeMetadata(self.fp)
490 491 #Write data
491 492 self.writeData(self.fp)
492 493
493 494 def getLabel(self, name, x=None):
494 495
495 496 if x is None:
496 497 if 'Data' in self.description:
497 498 data = self.description['Data']
498 499 if 'Metadata' in self.description:
499 500 data.update(self.description['Metadata'])
500 501 else:
501 502 data = self.description
502 503 if name in data:
503 504 if isinstance(data[name], str):
504 505 return data[name]
505 506 elif isinstance(data[name], list):
506 507 return None
507 508 elif isinstance(data[name], dict):
508 509 for key, value in data[name].items():
509 510 return key
510 511 return name
511 512 else:
512 513 if 'Metadata' in self.description:
513 514 meta = self.description['Metadata']
514 515 else:
515 516 meta = self.description
516 517 if name in meta:
517 518 if isinstance(meta[name], list):
518 519 return meta[name][x]
519 520 elif isinstance(meta[name], dict):
520 521 for key, value in meta[name].items():
521 522 return value[x]
522 523 if 'cspc' in name:
523 524 return 'pair{:02d}'.format(x)
524 525 else:
525 526 return 'channel{:02d}'.format(x)
526
527
527 528 def writeMetadata(self, fp):
528 529
529 530 if self.description:
530 531 if 'Metadata' in self.description:
531 532 grp = fp.create_group('Metadata')
532 533 else:
533 534 grp = fp
534 535 else:
535 536 grp = fp.create_group('Metadata')
536 537
537 538 for i in range(len(self.metadataList)):
538 539 if not hasattr(self.dataOut, self.metadataList[i]):
539 540 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
540 541 continue
541 542 value = getattr(self.dataOut, self.metadataList[i])
542 543 if isinstance(value, bool):
543 544 if value is True:
544 545 value = 1
545 546 else:
546 547 value = 0
547 548 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
548 549 return
549 550
550 551 def writeData(self, fp):
551
552
552 553 if self.description:
553 554 if 'Data' in self.description:
554 555 grp = fp.create_group('Data')
555 556 else:
556 557 grp = fp
557 558 else:
558 559 grp = fp.create_group('Data')
559 560
560 561 dtsets = []
561 562 data = []
562
563
563 564 for dsInfo in self.dsList:
564 565 if dsInfo['nDim'] == 0:
565 566 ds = grp.create_dataset(
566 self.getLabel(dsInfo['variable']),
567 self.getLabel(dsInfo['variable']),
567 568 (self.blocksPerFile, ),
568 chunks=True,
569 chunks=True,
569 570 dtype=numpy.float64)
570 571 dtsets.append(ds)
571 572 data.append((dsInfo['variable'], -1))
572 573 else:
573 574 label = self.getLabel(dsInfo['variable'])
574 575 if label is not None:
575 576 sgrp = grp.create_group(label)
576 577 else:
577 578 sgrp = grp
578 579 for i in range(dsInfo['dsNumber']):
579 580 ds = sgrp.create_dataset(
580 self.getLabel(dsInfo['variable'], i),
581 self.getLabel(dsInfo['variable'], i),
581 582 (self.blocksPerFile, ) + dsInfo['shape'][1:],
582 583 chunks=True,
583 584 dtype=dsInfo['dtype'])
584 585 dtsets.append(ds)
585 586 data.append((dsInfo['variable'], i))
586 587 fp.flush()
587 588
588 589 log.log('Creating file: {}'.format(fp.filename), self.name)
589
590
590 591 self.ds = dtsets
591 592 self.data = data
592 593 self.firsttime = True
593 594 self.blockIndex = 0
594 595 return
595 596
596 597 def putData(self):
597 598
598 599 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
599 600 self.closeFile()
600 601 self.setNextFile()
601 602
602 603 for i, ds in enumerate(self.ds):
603 604 attr, ch = self.data[i]
604 605 if ch == -1:
605 606 ds[self.blockIndex] = getattr(self.dataOut, attr)
606 607 else:
607 608 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
608 609
609 610 self.fp.flush()
610 611 self.blockIndex += 1
611 612 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
612 613
613 614 return
614 615
615 616 def closeFile(self):
616 617
617 618 if self.blockIndex != self.blocksPerFile:
618 619 for ds in self.ds:
619 620 ds.resize(self.blockIndex, axis=0)
620 621
621 622 self.fp.flush()
622 623 self.fp.close()
623 624
624 625 def close(self):
625 626
626 627 self.closeFile()
@@ -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 self.profileIndex = 2**32 - 1
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 Exceptions:
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,203 +1,203
1 1 '''
2 2 Base clases to create Processing units and operations, the MPDecorator
3 3 must be used in plotting and writing operations to allow to run as an
4 4 external process.
5 5 '''
6 6
7 7 import inspect
8 8 import zmq
9 9 import time
10 10 import pickle
11 11 import traceback
12 12 from threading import Thread
13 13 from multiprocessing import Process, Queue
14 14 from schainpy.utils import log
15 15
16 16
17 17 class ProcessingUnit(object):
18 18 '''
19 19 Base class to create Signal Chain Units
20 20 '''
21 21
22 22 proc_type = 'processing'
23 23
24 24 def __init__(self):
25 25
26 26 self.dataIn = None
27 27 self.dataOut = None
28 28 self.isConfig = False
29 29 self.operations = []
30 30
31 31 def setInput(self, unit):
32 32
33 33 self.dataIn = unit.dataOut
34 34
35 35 def getAllowedArgs(self):
36 36 if hasattr(self, '__attrs__'):
37 37 return self.__attrs__
38 38 else:
39 39 return inspect.getargspec(self.run).args
40 40
41 41 def addOperation(self, conf, operation):
42 42 '''
43 43 '''
44 44
45 45 self.operations.append((operation, conf.type, conf.getKwargs()))
46 46
47 47 def getOperationObj(self, objId):
48 48
49 49 if objId not in list(self.operations.keys()):
50 50 return None
51 51
52 52 return self.operations[objId]
53 53
54 54 def call(self, **kwargs):
55 55 '''
56 56 '''
57 57
58 58 try:
59 59 if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error:
60 60 return self.dataIn.isReady()
61 61 elif self.dataIn is None or not self.dataIn.error:
62 62 self.run(**kwargs)
63 63 elif self.dataIn.error:
64 64 self.dataOut.error = self.dataIn.error
65 65 self.dataOut.flagNoData = True
66 66 except:
67 67 err = traceback.format_exc()
68 68 if 'SchainWarning' in err:
69 69 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), self.name)
70 70 elif 'SchainError' in err:
71 71 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), self.name)
72 72 else:
73 73 log.error(err, self.name)
74 74 self.dataOut.error = True
75 75
76 76 for op, optype, opkwargs in self.operations:
77 77 if optype == 'other' and not self.dataOut.flagNoData:
78 78 self.dataOut = op.run(self.dataOut, **opkwargs)
79 79 elif optype == 'external' and not self.dataOut.flagNoData:
80 80 op.queue.put(self.dataOut)
81 81 elif optype == 'external' and self.dataOut.error:
82 82 op.queue.put(self.dataOut)
83 83
84 84 return 'Error' if self.dataOut.error else self.dataOut.isReady()
85 85
86 86 def setup(self):
87 87
88 88 raise NotImplementedError
89 89
90 90 def run(self):
91 91
92 92 raise NotImplementedError
93 93
94 94 def close(self):
95 95
96 96 return
97 97
98 98
99 99 class Operation(object):
100 100
101 101 '''
102 102 '''
103 103
104 104 proc_type = 'operation'
105 105
106 106 def __init__(self):
107 107
108 108 self.id = None
109 109 self.isConfig = False
110 110
111 111 if not hasattr(self, 'name'):
112 112 self.name = self.__class__.__name__
113 113
114 114 def getAllowedArgs(self):
115 115 if hasattr(self, '__attrs__'):
116 116 return self.__attrs__
117 117 else:
118 118 return inspect.getargspec(self.run).args
119 119
120 120 def setup(self):
121 121
122 122 self.isConfig = True
123 123
124 124 raise NotImplementedError
125 125
126 126 def run(self, dataIn, **kwargs):
127 127 """
128 128 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
129 129 atributos del objeto dataIn.
130 130
131 131 Input:
132 132
133 133 dataIn : objeto del tipo JROData
134 134
135 135 Return:
136 136
137 137 None
138 138
139 139 Affected:
140 140 __buffer : buffer de recepcion de datos.
141 141
142 142 """
143 143 if not self.isConfig:
144 144 self.setup(**kwargs)
145 145
146 146 raise NotImplementedError
147 147
148 148 def close(self):
149 149
150 150 return
151 151
152 152
153 153 def MPDecorator(BaseClass):
154 154 """
155 155 Multiprocessing class decorator
156 156
157 157 This function add multiprocessing features to a BaseClass.
158 158 """
159 159
160 160 class MPClass(BaseClass, Process):
161 161
162 162 def __init__(self, *args, **kwargs):
163 163 super(MPClass, self).__init__()
164 164 Process.__init__(self)
165 165
166 166 self.args = args
167 167 self.kwargs = kwargs
168 168 self.t = time.time()
169 169 self.op_type = 'external'
170 170 self.name = BaseClass.__name__
171 171 self.__doc__ = BaseClass.__doc__
172
172
173 173 if 'plot' in self.name.lower() and not self.name.endswith('_'):
174 174 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
175 175
176 176 self.start_time = time.time()
177 177 self.err_queue = args[3]
178 178 self.queue = Queue(maxsize=1)
179 179 self.myrun = BaseClass.run
180 180
181 181 def run(self):
182 182
183 183 while True:
184 184
185 185 dataOut = self.queue.get()
186 186
187 187 if not dataOut.error:
188 188 try:
189 189 BaseClass.run(self, dataOut, **self.kwargs)
190 190 except:
191 191 err = traceback.format_exc()
192 192 log.error(err, self.name)
193 193 else:
194 194 break
195 195
196 196 self.close()
197 197
198 198 def close(self):
199 199
200 200 BaseClass.close(self)
201 201 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
202 202
203 203 return MPClass
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
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
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