##// END OF EJS Templates
Cleaning IO modules (base, voltaje and spectra)
jespinoza -
r1251:6d7191c1eaa6
parent child
Show More
@@ -1,12 +1,6
1 #from schainpy.model.data.jrodata import *
2 # from schainpy.model.io.jrodataIO import *
3 # from schainpy.model.proc.jroprocessing import *
4 # from schainpy.model.graphics.jroplot import *
5 # from schainpy.model.utils.jroutils import *
6 # from schainpy.serializer import *
7 1
8 2 from .graphics import *
9 3 from .data import *
10 4 from .io import *
11 5 from .proc import *
12 6 from .utils import *
@@ -1,810 +1,810
1 1
2 2 import os
3 3 import sys
4 4 import zmq
5 5 import time
6 6 import numpy
7 7 import datetime
8 8 from functools import wraps
9 9 from threading import Thread
10 10 import matplotlib
11 11
12 12 if 'BACKEND' in os.environ:
13 13 matplotlib.use(os.environ['BACKEND'])
14 14 elif 'linux' in sys.platform:
15 15 matplotlib.use("TkAgg")
16 16 elif 'darwin' in sys.platform:
17 17 matplotlib.use('WxAgg')
18 18 else:
19 19 from schainpy.utils import log
20 20 log.warning('Using default Backend="Agg"', 'INFO')
21 21 matplotlib.use('Agg')
22 22
23 23 import matplotlib.pyplot as plt
24 24 from matplotlib.patches import Polygon
25 25 from mpl_toolkits.axes_grid1 import make_axes_locatable
26 26 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
27 27
28 28 from schainpy.model.data.jrodata import PlotterData
29 29 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
30 30 from schainpy.utils import log
31 31
32 32 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
33 33 blu_values = matplotlib.pyplot.get_cmap(
34 34 'seismic_r', 20)(numpy.arange(20))[10:15]
35 35 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
36 36 'jro', numpy.vstack((blu_values, jet_values)))
37 37 matplotlib.pyplot.register_cmap(cmap=ncmap)
38 38
39 39 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
40 40 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
41 41
42 42 EARTH_RADIUS = 6.3710e3
43 43
44 44 def ll2xy(lat1, lon1, lat2, lon2):
45 45
46 46 p = 0.017453292519943295
47 47 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
48 48 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
49 49 r = 12742 * numpy.arcsin(numpy.sqrt(a))
50 50 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
51 51 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
52 52 theta = -theta + numpy.pi/2
53 53 return r*numpy.cos(theta), r*numpy.sin(theta)
54 54
55 55
56 56 def km2deg(km):
57 57 '''
58 58 Convert distance in km to degrees
59 59 '''
60 60
61 61 return numpy.rad2deg(km/EARTH_RADIUS)
62 62
63 63
64 64 def figpause(interval):
65 65 backend = plt.rcParams['backend']
66 66 if backend in matplotlib.rcsetup.interactive_bk:
67 67 figManager = matplotlib._pylab_helpers.Gcf.get_active()
68 68 if figManager is not None:
69 69 canvas = figManager.canvas
70 70 if canvas.figure.stale:
71 71 canvas.draw()
72 72 try:
73 73 canvas.start_event_loop(interval)
74 74 except:
75 75 pass
76 76 return
77 77
78 78
79 79 def popup(message):
80 80 '''
81 81 '''
82 82
83 83 fig = plt.figure(figsize=(12, 8), facecolor='r')
84 84 text = '\n'.join([s.strip() for s in message.split(':')])
85 85 fig.text(0.01, 0.5, text, ha='left', va='center',
86 86 size='20', weight='heavy', color='w')
87 87 fig.show()
88 88 figpause(1000)
89 89
90 90
91 91 class Throttle(object):
92 92 '''
93 93 Decorator that prevents a function from being called more than once every
94 94 time period.
95 95 To create a function that cannot be called more than once a minute, but
96 96 will sleep until it can be called:
97 97 @Throttle(minutes=1)
98 98 def foo():
99 99 pass
100 100
101 101 for i in range(10):
102 102 foo()
103 103 print "This function has run %s times." % i
104 104 '''
105 105
106 106 def __init__(self, seconds=0, minutes=0, hours=0):
107 107 self.throttle_period = datetime.timedelta(
108 108 seconds=seconds, minutes=minutes, hours=hours
109 109 )
110 110
111 111 self.time_of_last_call = datetime.datetime.min
112 112
113 113 def __call__(self, fn):
114 114 @wraps(fn)
115 115 def wrapper(*args, **kwargs):
116 116 coerce = kwargs.pop('coerce', None)
117 117 if coerce:
118 118 self.time_of_last_call = datetime.datetime.now()
119 119 return fn(*args, **kwargs)
120 120 else:
121 121 now = datetime.datetime.now()
122 122 time_since_last_call = now - self.time_of_last_call
123 123 time_left = self.throttle_period - time_since_last_call
124 124
125 125 if time_left > datetime.timedelta(seconds=0):
126 126 return
127 127
128 128 self.time_of_last_call = datetime.datetime.now()
129 129 return fn(*args, **kwargs)
130 130
131 131 return wrapper
132 132
133 133 def apply_throttle(value):
134 134
135 135 @Throttle(seconds=value)
136 136 def fnThrottled(fn):
137 137 fn()
138 138
139 139 return fnThrottled
140 140
141 141
142 142 @MPDecorator
143 143 class Plot(Operation):
144 144 '''
145 145 Base class for Schain plotting operations
146 146 '''
147 147
148 148 CODE = 'Figure'
149 149 colormap = 'jet'
150 150 bgcolor = 'white'
151 151 __missing = 1E30
152 152
153 153 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
154 154 'zlimits', 'xlabel', 'ylabel', 'xaxis', 'cb_label', 'title',
155 155 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
156 156 'showprofile', 'decimation', 'pause']
157 157
158 158 def __init__(self):
159 159
160 160 Operation.__init__(self)
161 161 self.isConfig = False
162 162 self.isPlotConfig = False
163 163 self.save_counter = 1
164 164 self.sender_counter = 1
165 165 self.data = None
166 166
167 167 def __fmtTime(self, x, pos):
168 168 '''
169 169 '''
170 170
171 171 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
172 172
173 173 def __setup(self, **kwargs):
174 174 '''
175 175 Initialize variables
176 176 '''
177 177
178 178 self.figures = []
179 179 self.axes = []
180 180 self.cb_axes = []
181 181 self.localtime = kwargs.pop('localtime', True)
182 182 self.show = kwargs.get('show', True)
183 183 self.save = kwargs.get('save', False)
184 self.save_period = kwargs.get('save_period', 2)
184 self.save_period = kwargs.get('save_period', 1)
185 185 self.ftp = kwargs.get('ftp', False)
186 186 self.colormap = kwargs.get('colormap', self.colormap)
187 187 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
188 188 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
189 189 self.colormaps = kwargs.get('colormaps', None)
190 190 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
191 191 self.showprofile = kwargs.get('showprofile', False)
192 192 self.title = kwargs.get('wintitle', self.CODE.upper())
193 193 self.cb_label = kwargs.get('cb_label', None)
194 194 self.cb_labels = kwargs.get('cb_labels', None)
195 195 self.labels = kwargs.get('labels', None)
196 196 self.xaxis = kwargs.get('xaxis', 'frequency')
197 197 self.zmin = kwargs.get('zmin', None)
198 198 self.zmax = kwargs.get('zmax', None)
199 199 self.zlimits = kwargs.get('zlimits', None)
200 200 self.xmin = kwargs.get('xmin', None)
201 201 self.xmax = kwargs.get('xmax', None)
202 202 self.xrange = kwargs.get('xrange', 24)
203 203 self.xscale = kwargs.get('xscale', None)
204 204 self.ymin = kwargs.get('ymin', None)
205 205 self.ymax = kwargs.get('ymax', None)
206 206 self.yscale = kwargs.get('yscale', None)
207 207 self.xlabel = kwargs.get('xlabel', None)
208 208 self.decimation = kwargs.get('decimation', None)
209 209 self.showSNR = kwargs.get('showSNR', False)
210 210 self.oneFigure = kwargs.get('oneFigure', True)
211 211 self.width = kwargs.get('width', None)
212 212 self.height = kwargs.get('height', None)
213 213 self.colorbar = kwargs.get('colorbar', True)
214 214 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
215 215 self.channels = kwargs.get('channels', None)
216 216 self.titles = kwargs.get('titles', [])
217 217 self.polar = False
218 218 self.type = kwargs.get('type', 'iq')
219 219 self.grid = kwargs.get('grid', False)
220 220 self.pause = kwargs.get('pause', False)
221 221 self.save_labels = kwargs.get('save_labels', None)
222 222 self.realtime = kwargs.get('realtime', True)
223 223 self.buffering = kwargs.get('buffering', True)
224 224 self.throttle = kwargs.get('throttle', 2)
225 225 self.exp_code = kwargs.get('exp_code', None)
226 226 self.plot_server = kwargs.get('plot_server', False)
227 227 self.sender_period = kwargs.get('sender_period', 1)
228 228 self.__throttle_plot = apply_throttle(self.throttle)
229 229 self.data = PlotterData(
230 230 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
231 231
232 232 if self.plot_server:
233 233 if not self.plot_server.startswith('tcp://'):
234 234 self.plot_server = 'tcp://{}'.format(self.plot_server)
235 235 log.success(
236 236 'Sending to server: {}'.format(self.plot_server),
237 237 self.name
238 238 )
239 239 if 'plot_name' in kwargs:
240 240 self.plot_name = kwargs['plot_name']
241 241
242 242 def __setup_plot(self):
243 243 '''
244 244 Common setup for all figures, here figures and axes are created
245 245 '''
246 246
247 247 self.setup()
248 248
249 249 self.time_label = 'LT' if self.localtime else 'UTC'
250 250
251 251 if self.width is None:
252 252 self.width = 8
253 253
254 254 self.figures = []
255 255 self.axes = []
256 256 self.cb_axes = []
257 257 self.pf_axes = []
258 258 self.cmaps = []
259 259
260 260 size = '15%' if self.ncols == 1 else '30%'
261 261 pad = '4%' if self.ncols == 1 else '8%'
262 262
263 263 if self.oneFigure:
264 264 if self.height is None:
265 265 self.height = 1.4 * self.nrows + 1
266 266 fig = plt.figure(figsize=(self.width, self.height),
267 267 edgecolor='k',
268 268 facecolor='w')
269 269 self.figures.append(fig)
270 270 for n in range(self.nplots):
271 271 ax = fig.add_subplot(self.nrows, self.ncols,
272 272 n + 1, polar=self.polar)
273 273 ax.tick_params(labelsize=8)
274 274 ax.firsttime = True
275 275 ax.index = 0
276 276 ax.press = None
277 277 self.axes.append(ax)
278 278 if self.showprofile:
279 279 cax = self.__add_axes(ax, size=size, pad=pad)
280 280 cax.tick_params(labelsize=8)
281 281 self.pf_axes.append(cax)
282 282 else:
283 283 if self.height is None:
284 284 self.height = 3
285 285 for n in range(self.nplots):
286 286 fig = plt.figure(figsize=(self.width, self.height),
287 287 edgecolor='k',
288 288 facecolor='w')
289 289 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
290 290 ax.tick_params(labelsize=8)
291 291 ax.firsttime = True
292 292 ax.index = 0
293 293 ax.press = None
294 294 self.figures.append(fig)
295 295 self.axes.append(ax)
296 296 if self.showprofile:
297 297 cax = self.__add_axes(ax, size=size, pad=pad)
298 298 cax.tick_params(labelsize=8)
299 299 self.pf_axes.append(cax)
300 300
301 301 for n in range(self.nrows):
302 302 if self.colormaps is not None:
303 303 cmap = plt.get_cmap(self.colormaps[n])
304 304 else:
305 305 cmap = plt.get_cmap(self.colormap)
306 306 cmap.set_bad(self.bgcolor, 1.)
307 307 self.cmaps.append(cmap)
308 308
309 309 for fig in self.figures:
310 310 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
311 311 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
312 312 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
313 313 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
314 314 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
315 315
316 316 def OnKeyPress(self, event):
317 317 '''
318 318 Event for pressing keys (up, down) change colormap
319 319 '''
320 320 ax = event.inaxes
321 321 if ax in self.axes:
322 322 if event.key == 'down':
323 323 ax.index += 1
324 324 elif event.key == 'up':
325 325 ax.index -= 1
326 326 if ax.index < 0:
327 327 ax.index = len(CMAPS) - 1
328 328 elif ax.index == len(CMAPS):
329 329 ax.index = 0
330 330 cmap = CMAPS[ax.index]
331 331 ax.cbar.set_cmap(cmap)
332 332 ax.cbar.draw_all()
333 333 ax.plt.set_cmap(cmap)
334 334 ax.cbar.patch.figure.canvas.draw()
335 335 self.colormap = cmap.name
336 336
337 337 def OnBtnScroll(self, event):
338 338 '''
339 339 Event for scrolling, scale figure
340 340 '''
341 341 cb_ax = event.inaxes
342 342 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
343 343 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
344 344 pt = ax.cbar.ax.bbox.get_points()[:, 1]
345 345 nrm = ax.cbar.norm
346 346 vmin, vmax, p0, p1, pS = (
347 347 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
348 348 scale = 2 if event.step == 1 else 0.5
349 349 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
350 350 ax.cbar.norm.vmin = point - scale * (point - vmin)
351 351 ax.cbar.norm.vmax = point - scale * (point - vmax)
352 352 ax.plt.set_norm(ax.cbar.norm)
353 353 ax.cbar.draw_all()
354 354 ax.cbar.patch.figure.canvas.draw()
355 355
356 356 def onBtnPress(self, event):
357 357 '''
358 358 Event for mouse button press
359 359 '''
360 360 cb_ax = event.inaxes
361 361 if cb_ax is None:
362 362 return
363 363
364 364 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
365 365 cb_ax.press = event.x, event.y
366 366 else:
367 367 cb_ax.press = None
368 368
369 369 def onMotion(self, event):
370 370 '''
371 371 Event for move inside colorbar
372 372 '''
373 373 cb_ax = event.inaxes
374 374 if cb_ax is None:
375 375 return
376 376 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
377 377 return
378 378 if cb_ax.press is None:
379 379 return
380 380
381 381 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
382 382 xprev, yprev = cb_ax.press
383 383 dx = event.x - xprev
384 384 dy = event.y - yprev
385 385 cb_ax.press = event.x, event.y
386 386 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
387 387 perc = 0.03
388 388
389 389 if event.button == 1:
390 390 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
391 391 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
392 392 elif event.button == 3:
393 393 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
394 394 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
395 395
396 396 ax.cbar.draw_all()
397 397 ax.plt.set_norm(ax.cbar.norm)
398 398 ax.cbar.patch.figure.canvas.draw()
399 399
400 400 def onBtnRelease(self, event):
401 401 '''
402 402 Event for mouse button release
403 403 '''
404 404 cb_ax = event.inaxes
405 405 if cb_ax is not None:
406 406 cb_ax.press = None
407 407
408 408 def __add_axes(self, ax, size='30%', pad='8%'):
409 409 '''
410 410 Add new axes to the given figure
411 411 '''
412 412 divider = make_axes_locatable(ax)
413 413 nax = divider.new_horizontal(size=size, pad=pad)
414 414 ax.figure.add_axes(nax)
415 415 return nax
416 416
417 417 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
418 418 '''
419 419 Create a masked array for missing data
420 420 '''
421 421 if x_buffer.shape[0] < 2:
422 422 return x_buffer, y_buffer, z_buffer
423 423
424 424 deltas = x_buffer[1:] - x_buffer[0:-1]
425 425 x_median = numpy.median(deltas)
426 426
427 427 index = numpy.where(deltas > 5 * x_median)
428 428
429 429 if len(index[0]) != 0:
430 430 z_buffer[::, index[0], ::] = self.__missing
431 431 z_buffer = numpy.ma.masked_inside(z_buffer,
432 432 0.99 * self.__missing,
433 433 1.01 * self.__missing)
434 434
435 435 return x_buffer, y_buffer, z_buffer
436 436
437 437 def decimate(self):
438 438
439 439 # dx = int(len(self.x)/self.__MAXNUMX) + 1
440 440 dy = int(len(self.y) / self.decimation) + 1
441 441
442 442 # x = self.x[::dx]
443 443 x = self.x
444 444 y = self.y[::dy]
445 445 z = self.z[::, ::, ::dy]
446 446
447 447 return x, y, z
448 448
449 449 def format(self):
450 450 '''
451 451 Set min and max values, labels, ticks and titles
452 452 '''
453 453
454 454 if self.xmin is None:
455 455 xmin = self.data.min_time
456 456 else:
457 457 if self.xaxis is 'time':
458 458 dt = self.getDateTime(self.data.min_time)
459 459 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
460 460 datetime.datetime(1970, 1, 1)).total_seconds()
461 461 if self.data.localtime:
462 462 xmin += time.timezone
463 463 else:
464 464 xmin = self.xmin
465 465
466 466 if self.xmax is None:
467 467 xmax = xmin + self.xrange * 60 * 60
468 468 else:
469 469 if self.xaxis is 'time':
470 470 dt = self.getDateTime(self.data.max_time)
471 471 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
472 472 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
473 473 if self.data.localtime:
474 474 xmax += time.timezone
475 475 else:
476 476 xmax = self.xmax
477 477
478 478 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
479 479 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
480 480 #Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000])
481 481
482 482 #i = 1 if numpy.where(
483 483 # abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
484 484 #ystep = Y[i] / 10.
485 485 dig = int(numpy.log10(ymax))
486 486 if dig == 0:
487 487 digD = len(str(ymax)) - 2
488 488 ydec = ymax*(10**digD)
489 489
490 490 dig = int(numpy.log10(ydec))
491 491 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
492 492 ystep = ystep/5
493 493 ystep = ystep/(10**digD)
494 494
495 495 else:
496 496 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
497 497 ystep = ystep/5
498 498
499 499 if self.xaxis is not 'time':
500 500
501 501 dig = int(numpy.log10(xmax))
502 502
503 503 if dig <= 0:
504 504 digD = len(str(xmax)) - 2
505 505 xdec = xmax*(10**digD)
506 506
507 507 dig = int(numpy.log10(xdec))
508 508 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
509 509 xstep = xstep*0.5
510 510 xstep = xstep/(10**digD)
511 511
512 512 else:
513 513 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
514 514 xstep = xstep/5
515 515
516 516 for n, ax in enumerate(self.axes):
517 517 if ax.firsttime:
518 518 ax.set_facecolor(self.bgcolor)
519 519 ax.yaxis.set_major_locator(MultipleLocator(ystep))
520 520 if self.xscale:
521 521 ax.xaxis.set_major_formatter(FuncFormatter(
522 522 lambda x, pos: '{0:g}'.format(x*self.xscale)))
523 523 if self.xscale:
524 524 ax.yaxis.set_major_formatter(FuncFormatter(
525 525 lambda x, pos: '{0:g}'.format(x*self.yscale)))
526 526 if self.xaxis is 'time':
527 527 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
528 528 ax.xaxis.set_major_locator(LinearLocator(9))
529 529 else:
530 530 ax.xaxis.set_major_locator(MultipleLocator(xstep))
531 531 if self.xlabel is not None:
532 532 ax.set_xlabel(self.xlabel)
533 533 ax.set_ylabel(self.ylabel)
534 534 ax.firsttime = False
535 535 if self.showprofile:
536 536 self.pf_axes[n].set_ylim(ymin, ymax)
537 537 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
538 538 self.pf_axes[n].set_xlabel('dB')
539 539 self.pf_axes[n].grid(b=True, axis='x')
540 540 [tick.set_visible(False)
541 541 for tick in self.pf_axes[n].get_yticklabels()]
542 542 if self.colorbar:
543 543 ax.cbar = plt.colorbar(
544 544 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
545 545 ax.cbar.ax.tick_params(labelsize=8)
546 546 ax.cbar.ax.press = None
547 547 if self.cb_label:
548 548 ax.cbar.set_label(self.cb_label, size=8)
549 549 elif self.cb_labels:
550 550 ax.cbar.set_label(self.cb_labels[n], size=8)
551 551 else:
552 552 ax.cbar = None
553 553 if self.grid:
554 554 ax.grid(True)
555 555
556 556 if not self.polar:
557 557 ax.set_xlim(xmin, xmax)
558 558 ax.set_ylim(ymin, ymax)
559 559 ax.set_title('{} {} {}'.format(
560 560 self.titles[n],
561 561 self.getDateTime(self.data.max_time).strftime(
562 562 '%Y-%m-%d %H:%M:%S'),
563 563 self.time_label),
564 564 size=8)
565 565 else:
566 566 ax.set_title('{}'.format(self.titles[n]), size=8)
567 567 ax.set_ylim(0, 90)
568 568 ax.set_yticks(numpy.arange(0, 90, 20))
569 569 ax.yaxis.labelpad = 40
570 570
571 571 def clear_figures(self):
572 572 '''
573 573 Reset axes for redraw plots
574 574 '''
575 575
576 576 for ax in self.axes:
577 577 ax.clear()
578 578 ax.firsttime = True
579 579 if ax.cbar:
580 580 ax.cbar.remove()
581 581
582 582 def __plot(self):
583 583 '''
584 584 Main function to plot, format and save figures
585 585 '''
586 586
587 587 try:
588 588 self.plot()
589 589 self.format()
590 590 except Exception as e:
591 591 log.warning('{} Plot could not be updated... check data'.format(
592 592 self.CODE), self.name)
593 593 log.error(str(e), '')
594 594 return
595 595
596 596 for n, fig in enumerate(self.figures):
597 597 if self.nrows == 0 or self.nplots == 0:
598 598 log.warning('No data', self.name)
599 599 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
600 600 fig.canvas.manager.set_window_title(self.CODE)
601 601 continue
602 602
603 603 fig.tight_layout()
604 604 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
605 605 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
606 606 fig.canvas.draw()
607 607 if self.show:
608 608 fig.show()
609 609 figpause(0.1)
610 610
611 611 if self.save:
612 612 self.save_figure(n)
613 613
614 614 if self.plot_server:
615 615 self.send_to_server()
616 616 # t = Thread(target=self.send_to_server)
617 617 # t.start()
618 618
619 619 def save_figure(self, n):
620 620 '''
621 621 '''
622 622
623 623 if self.save_counter < self.save_period:
624 624 self.save_counter += 1
625 625 return
626 626
627 627 self.save_counter = 1
628 628
629 629 fig = self.figures[n]
630 630
631 631 if self.save_labels:
632 632 labels = self.save_labels
633 633 else:
634 634 labels = list(range(self.nrows))
635 635
636 636 if self.oneFigure:
637 637 label = ''
638 638 else:
639 639 label = '-{}'.format(labels[n])
640 640 figname = os.path.join(
641 641 self.save,
642 642 self.CODE,
643 643 '{}{}_{}.png'.format(
644 644 self.CODE,
645 645 label,
646 646 self.getDateTime(self.data.max_time).strftime(
647 647 '%Y%m%d_%H%M%S'
648 648 ),
649 649 )
650 650 )
651 651 log.log('Saving figure: {}'.format(figname), self.name)
652 652 if not os.path.isdir(os.path.dirname(figname)):
653 653 os.makedirs(os.path.dirname(figname))
654 654 fig.savefig(figname)
655 655
656 656 if self.realtime:
657 657 figname = os.path.join(
658 658 self.save,
659 659 '{}{}_{}.png'.format(
660 660 self.CODE,
661 661 label,
662 662 self.getDateTime(self.data.min_time).strftime(
663 663 '%Y%m%d'
664 664 ),
665 665 )
666 666 )
667 667 fig.savefig(figname)
668 668
669 669 def send_to_server(self):
670 670 '''
671 671 '''
672 672
673 673 if self.sender_counter < self.sender_period:
674 674 self.sender_counter += 1
675 675 return
676 676
677 677 self.sender_counter = 1
678 678 self.data.meta['titles'] = self.titles
679 679 retries = 2
680 680 while True:
681 681 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
682 682 socks = dict(self.poll.poll(5000))
683 683 if socks.get(self.socket) == zmq.POLLIN:
684 684 reply = self.socket.recv_string()
685 685 if reply == 'ok':
686 686 log.log("Response from server ok", self.name)
687 687 break
688 688 else:
689 689 log.warning(
690 690 "Malformed reply from server: {}".format(reply), self.name)
691 691
692 692 else:
693 693 log.warning(
694 694 "No response from server, retrying...", self.name)
695 695 self.socket.setsockopt(zmq.LINGER, 0)
696 696 self.socket.close()
697 697 self.poll.unregister(self.socket)
698 698 retries -= 1
699 699 if retries == 0:
700 700 log.error(
701 701 "Server seems to be offline, abandoning", self.name)
702 702 self.socket = self.context.socket(zmq.REQ)
703 703 self.socket.connect(self.plot_server)
704 704 self.poll.register(self.socket, zmq.POLLIN)
705 705 time.sleep(1)
706 706 break
707 707 self.socket = self.context.socket(zmq.REQ)
708 708 self.socket.connect(self.plot_server)
709 709 self.poll.register(self.socket, zmq.POLLIN)
710 710 time.sleep(0.5)
711 711
712 712 def setup(self):
713 713 '''
714 714 This method should be implemented in the child class, the following
715 715 attributes should be set:
716 716
717 717 self.nrows: number of rows
718 718 self.ncols: number of cols
719 719 self.nplots: number of plots (channels or pairs)
720 720 self.ylabel: label for Y axes
721 721 self.titles: list of axes title
722 722
723 723 '''
724 724 raise NotImplementedError
725 725
726 726 def plot(self):
727 727 '''
728 728 Must be defined in the child class
729 729 '''
730 730 raise NotImplementedError
731 731
732 732 def run(self, dataOut, **kwargs):
733 733 '''
734 734 Main plotting routine
735 735 '''
736 736
737 737 if self.isConfig is False:
738 738 self.__setup(**kwargs)
739 739 if dataOut.type == 'Parameters':
740 740 t = dataOut.utctimeInit
741 741 else:
742 742 t = dataOut.utctime
743 743
744 744 if dataOut.useLocalTime:
745 745 self.getDateTime = datetime.datetime.fromtimestamp
746 746 if not self.localtime:
747 747 t += time.timezone
748 748 else:
749 749 self.getDateTime = datetime.datetime.utcfromtimestamp
750 750 if self.localtime:
751 751 t -= time.timezone
752 752
753 753 if 'buffer' in self.plot_type:
754 754 if self.xmin is None:
755 755 self.tmin = t
756 756 else:
757 757 self.tmin = (
758 758 self.getDateTime(t).replace(
759 759 hour=self.xmin,
760 760 minute=0,
761 761 second=0) - self.getDateTime(0)).total_seconds()
762 762
763 763 self.data.setup()
764 764 self.isConfig = True
765 765 if self.plot_server:
766 766 self.context = zmq.Context()
767 767 self.socket = self.context.socket(zmq.REQ)
768 768 self.socket.connect(self.plot_server)
769 769 self.poll = zmq.Poller()
770 770 self.poll.register(self.socket, zmq.POLLIN)
771 771
772 772 if dataOut.type == 'Parameters':
773 773 tm = dataOut.utctimeInit
774 774 else:
775 775 tm = dataOut.utctime
776 776
777 777 if not dataOut.useLocalTime and self.localtime:
778 778 tm -= time.timezone
779 779 if dataOut.useLocalTime and not self.localtime:
780 780 tm += time.timezone
781 781
782 782 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
783 783 self.save_counter = self.save_period
784 784 self.__plot()
785 785 self.xmin += self.xrange
786 786 if self.xmin >= 24:
787 787 self.xmin -= 24
788 788 self.tmin += self.xrange*60*60
789 789 self.data.setup()
790 790 self.clear_figures()
791 791
792 792 self.data.update(dataOut, tm)
793 793
794 794 if self.isPlotConfig is False:
795 795 self.__setup_plot()
796 796 self.isPlotConfig = True
797 797
798 798 if self.realtime:
799 799 self.__plot()
800 800 else:
801 801 self.__throttle_plot(self.__plot)#, coerce=coerce)
802 802
803 803 def close(self):
804 804
805 805 if self.data:
806 806 self.save_counter = self.save_period
807 807 self.__plot()
808 808 if self.data and self.pause:
809 809 figpause(10)
810 810
This diff has been collapsed as it changes many lines, (1038 lines changed) Show them Hide them
@@ -1,1831 +1,1565
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 import traceback
16 15 import zmq
17 16
18 17 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
19 18 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
20 19 from schainpy.utils import log
21 20 import schainpy.admin
22 21
23 22 LOCALTIME = True
23 DT_DIRECTIVES = {
24 '%Y': 4,
25 '%y': 2,
26 '%m': 2,
27 '%d': 2,
28 '%j': 3,
29 '%H': 2,
30 '%M': 2,
31 '%S': 2,
32 '%f': 6
33 }
24 34
25 35
26 36 def isNumber(cad):
27 37 """
28 38 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
29 39
30 40 Excepciones:
31 41 Si un determinado string no puede ser convertido a numero
32 42 Input:
33 43 str, string al cual se le analiza para determinar si convertible a un numero o no
34 44
35 45 Return:
36 46 True : si el string es uno numerico
37 47 False : no es un string numerico
38 48 """
39 49 try:
40 50 float(cad)
41 51 return True
42 52 except:
43 53 return False
44 54
45 55
46 56 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
47 57 """
48 58 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
49 59
50 60 Inputs:
51 61 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
52 62
53 63 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
54 64 segundos contados desde 01/01/1970.
55 65 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
56 66 segundos contados desde 01/01/1970.
57 67
58 68 Return:
59 69 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
60 70 fecha especificado, de lo contrario retorna False.
61 71
62 72 Excepciones:
63 73 Si el archivo no existe o no puede ser abierto
64 74 Si la cabecera no puede ser leida.
65 75
66 76 """
67 77 basicHeaderObj = BasicHeader(LOCALTIME)
68 78
69 79 try:
70 80 fp = open(filename, 'rb')
71 81 except IOError:
72 82 print("The file %s can't be opened" % (filename))
73 83 return 0
74 84
75 85 sts = basicHeaderObj.read(fp)
76 86 fp.close()
77 87
78 88 if not(sts):
79 89 print("Skipping the file %s because it has not a valid header" % (filename))
80 90 return 0
81 91
82 92 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
83 93 return 0
84 94
85 95 return 1
86 96
87 97
88 98 def isTimeInRange(thisTime, startTime, endTime):
89 99 if endTime >= startTime:
90 100 if (thisTime < startTime) or (thisTime > endTime):
91 101 return 0
92 102 return 1
93 103 else:
94 104 if (thisTime < startTime) and (thisTime > endTime):
95 105 return 0
96 106 return 1
97 107
98 108
99 109 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
100 110 """
101 111 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
102 112
103 113 Inputs:
104 114 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
105 115
106 116 startDate : fecha inicial del rango seleccionado en formato datetime.date
107 117
108 118 endDate : fecha final del rango seleccionado en formato datetime.date
109 119
110 120 startTime : tiempo inicial del rango seleccionado en formato datetime.time
111 121
112 122 endTime : tiempo final del rango seleccionado en formato datetime.time
113 123
114 124 Return:
115 125 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
116 126 fecha especificado, de lo contrario retorna False.
117 127
118 128 Excepciones:
119 129 Si el archivo no existe o no puede ser abierto
120 130 Si la cabecera no puede ser leida.
121 131
122 132 """
123 133
124 134 try:
125 135 fp = open(filename, 'rb')
126 136 except IOError:
127 137 print("The file %s can't be opened" % (filename))
128 138 return None
129 139
130 140 firstBasicHeaderObj = BasicHeader(LOCALTIME)
131 141 systemHeaderObj = SystemHeader()
132 142 radarControllerHeaderObj = RadarControllerHeader()
133 143 processingHeaderObj = ProcessingHeader()
134 144
135 145 lastBasicHeaderObj = BasicHeader(LOCALTIME)
136 146
137 147 sts = firstBasicHeaderObj.read(fp)
138 148
139 149 if not(sts):
140 150 print("[Reading] Skipping the file %s because it has not a valid header" % (filename))
141 151 return None
142 152
143 153 if not systemHeaderObj.read(fp):
144 154 return None
145 155
146 156 if not radarControllerHeaderObj.read(fp):
147 157 return None
148 158
149 159 if not processingHeaderObj.read(fp):
150 160 return None
151 161
152 162 filesize = os.path.getsize(filename)
153 163
154 164 offset = processingHeaderObj.blockSize + 24 # header size
155 165
156 166 if filesize <= offset:
157 167 print("[Reading] %s: This file has not enough data" % filename)
158 168 return None
159 169
160 170 fp.seek(-offset, 2)
161 171
162 172 sts = lastBasicHeaderObj.read(fp)
163 173
164 174 fp.close()
165 175
166 176 thisDatetime = lastBasicHeaderObj.datatime
167 177 thisTime_last_block = thisDatetime.time()
168 178
169 179 thisDatetime = firstBasicHeaderObj.datatime
170 180 thisDate = thisDatetime.date()
171 181 thisTime_first_block = thisDatetime.time()
172 182
173 183 # General case
174 184 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
175 185 #-----------o----------------------------o-----------
176 186 # startTime endTime
177 187
178 188 if endTime >= startTime:
179 189 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
180 190 return None
181 191
182 192 return thisDatetime
183 193
184 194 # If endTime < startTime then endTime belongs to the next day
185 195
186 196 #<<<<<<<<<<<o o>>>>>>>>>>>
187 197 #-----------o----------------------------o-----------
188 198 # endTime startTime
189 199
190 200 if (thisDate == startDate) and (thisTime_last_block < startTime):
191 201 return None
192 202
193 203 if (thisDate == endDate) and (thisTime_first_block > endTime):
194 204 return None
195 205
196 206 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
197 207 return None
198 208
199 209 return thisDatetime
200 210
201 211
202 212 def isFolderInDateRange(folder, startDate=None, endDate=None):
203 213 """
204 214 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
205 215
206 216 Inputs:
207 217 folder : nombre completo del directorio.
208 218 Su formato deberia ser "/path_root/?YYYYDDD"
209 219
210 220 siendo:
211 221 YYYY : Anio (ejemplo 2015)
212 222 DDD : Dia del anio (ejemplo 305)
213 223
214 224 startDate : fecha inicial del rango seleccionado en formato datetime.date
215 225
216 226 endDate : fecha final del rango seleccionado en formato datetime.date
217 227
218 228 Return:
219 229 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
220 230 fecha especificado, de lo contrario retorna False.
221 231 Excepciones:
222 232 Si el directorio no tiene el formato adecuado
223 233 """
224 234
225 235 basename = os.path.basename(folder)
226 236
227 237 if not isRadarFolder(basename):
228 238 print("The folder %s has not the rigth format" % folder)
229 239 return 0
230 240
231 241 if startDate and endDate:
232 242 thisDate = getDateFromRadarFolder(basename)
233 243
234 244 if thisDate < startDate:
235 245 return 0
236 246
237 247 if thisDate > endDate:
238 248 return 0
239 249
240 250 return 1
241 251
242 252
243 253 def isFileInDateRange(filename, startDate=None, endDate=None):
244 254 """
245 255 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
246 256
247 257 Inputs:
248 258 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
249 259
250 260 Su formato deberia ser "?YYYYDDDsss"
251 261
252 262 siendo:
253 263 YYYY : Anio (ejemplo 2015)
254 264 DDD : Dia del anio (ejemplo 305)
255 265 sss : set
256 266
257 267 startDate : fecha inicial del rango seleccionado en formato datetime.date
258 268
259 269 endDate : fecha final del rango seleccionado en formato datetime.date
260 270
261 271 Return:
262 272 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
263 273 fecha especificado, de lo contrario retorna False.
264 274 Excepciones:
265 275 Si el archivo no tiene el formato adecuado
266 276 """
267 277
268 278 basename = os.path.basename(filename)
269 279
270 280 if not isRadarFile(basename):
271 281 print("The filename %s has not the rigth format" % filename)
272 282 return 0
273 283
274 284 if startDate and endDate:
275 285 thisDate = getDateFromRadarFile(basename)
276 286
277 287 if thisDate < startDate:
278 288 return 0
279 289
280 290 if thisDate > endDate:
281 291 return 0
282 292
283 293 return 1
284 294
285 295
286 296 def getFileFromSet(path, ext, set):
287 297 validFilelist = []
288 298 fileList = os.listdir(path)
289 299
290 300 # 0 1234 567 89A BCDE
291 301 # H YYYY DDD SSS .ext
292 302
293 303 for thisFile in fileList:
294 304 try:
295 305 year = int(thisFile[1:5])
296 306 doy = int(thisFile[5:8])
297 307 except:
298 308 continue
299 309
300 310 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
301 311 continue
302 312
303 313 validFilelist.append(thisFile)
304 314
305 315 myfile = fnmatch.filter(
306 316 validFilelist, '*%4.4d%3.3d%3.3d*' % (year, doy, set))
307 317
308 318 if len(myfile) != 0:
309 319 return myfile[0]
310 320 else:
311 321 filename = '*%4.4d%3.3d%3.3d%s' % (year, doy, set, ext.lower())
312 322 print('the filename %s does not exist' % filename)
313 323 print('...going to the last file: ')
314 324
315 325 if validFilelist:
316 326 validFilelist = sorted(validFilelist, key=str.lower)
317 327 return validFilelist[-1]
318 328
319 329 return None
320 330
321 331
322 332 def getlastFileFromPath(path, ext):
323 333 """
324 334 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
325 335 al final de la depuracion devuelve el ultimo file de la lista que quedo.
326 336
327 337 Input:
328 338 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
329 339 ext : extension de los files contenidos en una carpeta
330 340
331 341 Return:
332 342 El ultimo file de una determinada carpeta, no se considera el path.
333 343 """
334 344 validFilelist = []
335 345 fileList = os.listdir(path)
336 346
337 347 # 0 1234 567 89A BCDE
338 348 # H YYYY DDD SSS .ext
339 349
340 350 for thisFile in fileList:
341 351
342 352 year = thisFile[1:5]
343 353 if not isNumber(year):
344 354 continue
345 355
346 356 doy = thisFile[5:8]
347 357 if not isNumber(doy):
348 358 continue
349 359
350 360 year = int(year)
351 361 doy = int(doy)
352 362
353 363 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
354 364 continue
355 365
356 366 validFilelist.append(thisFile)
357 367
358 368 if validFilelist:
359 369 validFilelist = sorted(validFilelist, key=str.lower)
360 370 return validFilelist[-1]
361 371
362 372 return None
363 373
364 374
365 def checkForRealPath(path, foldercounter, year, doy, set, ext):
366 """
367 Por ser Linux Case Sensitive entonces checkForRealPath encuentra el nombre correcto de un path,
368 Prueba por varias combinaciones de nombres entre mayusculas y minusculas para determinar
369 el path exacto de un determinado file.
370
371 Example :
372 nombre correcto del file es .../.../D2009307/P2009307367.ext
373
374 Entonces la funcion prueba con las siguientes combinaciones
375 .../.../y2009307367.ext
376 .../.../Y2009307367.ext
377 .../.../x2009307/y2009307367.ext
378 .../.../x2009307/Y2009307367.ext
379 .../.../X2009307/y2009307367.ext
380 .../.../X2009307/Y2009307367.ext
381 siendo para este caso, la ultima combinacion de letras, identica al file buscado
382
383 Return:
384 Si encuentra la cobinacion adecuada devuelve el path completo y el nombre del file
385 caso contrario devuelve None como path y el la ultima combinacion de nombre en mayusculas
386 para el filename
387 """
388 fullfilename = None
389 find_flag = False
390 filename = None
391
392 prefixDirList = [None, 'd', 'D']
393 if ext.lower() == ".r": # voltage
394 prefixFileList = ['d', 'D']
395 elif ext.lower() == ".pdata": # spectra
396 prefixFileList = ['p', 'P']
397 else:
398 return None, filename
399
400 # barrido por las combinaciones posibles
401 for prefixDir in prefixDirList:
402 thispath = path
403 if prefixDir != None:
404 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
405 if foldercounter == 0:
406 thispath = os.path.join(path, "%s%04d%03d" %
407 (prefixDir, year, doy))
408 else:
409 thispath = os.path.join(path, "%s%04d%03d_%02d" % (
410 prefixDir, year, doy, foldercounter))
411 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
412 # formo el nombre del file xYYYYDDDSSS.ext
413 filename = "%s%04d%03d%03d%s" % (prefixFile, year, doy, set, ext)
414 fullfilename = os.path.join(
415 thispath, filename) # formo el path completo
416
417 if os.path.exists(fullfilename): # verifico que exista
418 find_flag = True
419 break
420 if find_flag:
421 break
422
423 if not(find_flag):
424 return None, filename
425
426 return fullfilename, filename
427
428
429 375 def isRadarFolder(folder):
430 376 try:
431 377 year = int(folder[1:5])
432 378 doy = int(folder[5:8])
433 379 except:
434 380 return 0
435 381
436 382 return 1
437 383
438 384
439 385 def isRadarFile(file):
440 386 try:
441 387 year = int(file[1:5])
442 388 doy = int(file[5:8])
443 389 set = int(file[8:11])
444 390 except:
445 391 return 0
446 392
447 393 return 1
448 394
449 395
450 396 def getDateFromRadarFile(file):
451 397 try:
452 398 year = int(file[1:5])
453 399 doy = int(file[5:8])
454 400 set = int(file[8:11])
455 401 except:
456 402 return None
457 403
458 404 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
459 405 return thisDate
460 406
461 407
462 408 def getDateFromRadarFolder(folder):
463 409 try:
464 410 year = int(folder[1:5])
465 411 doy = int(folder[5:8])
466 412 except:
467 413 return None
468 414
469 415 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
470 416 return thisDate
471 417
418 def parse_format(s, fmt):
419
420 for i in range(fmt.count('%')):
421 x = fmt.index('%')
422 d = DT_DIRECTIVES[fmt[x:x+2]]
423 fmt = fmt.replace(fmt[x:x+2], s[x:x+d])
424 return fmt
472 425
473 class JRODataIO:
426 class Reader(object):
474 427
475 428 c = 3E8
476
477 429 isConfig = False
478
479 basicHeaderObj = None
480
481 systemHeaderObj = None
482
483 radarControllerHeaderObj = None
484
485 processingHeaderObj = None
486
487 430 dtype = None
488
489 431 pathList = []
490
491 432 filenameList = []
492
433 datetimeList = []
493 434 filename = None
494
495 435 ext = None
496
497 436 flagIsNewFile = 1
498
499 437 flagDiscontinuousBlock = 0
500
501 438 flagIsNewBlock = 0
502
439 flagNoMoreFiles = 0
503 440 fp = None
504
505 441 firstHeaderSize = 0
506
507 442 basicHeaderSize = 24
508
509 443 versionFile = 1103
510
511 444 fileSize = None
512
513 # ippSeconds = None
514
515 445 fileSizeByHeader = None
516
517 fileIndex = None
518
446 fileIndex = -1
519 447 profileIndex = None
520
521 blockIndex = None
522
523 nTotalBlocks = None
524
448 blockIndex = 0
449 nTotalBlocks = 0
525 450 maxTimeStep = 30
526
527 451 lastUTTime = None
528
529 452 datablock = None
530
531 453 dataOut = None
532
533 blocksize = None
534
535 454 getByBlock = False
536
537 def __init__(self):
538
539 raise NotImplementedError
455 path = None
456 startDate = None
457 endDate = None
458 startTime = datetime.time(0, 0, 0)
459 endTime = datetime.time(23, 59, 59)
460 set = None
461 expLabel = ""
462 online = False
463 delay = 60
464 nTries = 3 # quantity tries
465 nFiles = 3 # number of files for searching
466 walk = True
467 getblock = False
468 nTxs = 1
469 realtime = False
470 blocksize = 0
471 blocktime = None
472 warnings = True
473 verbose = True
474 server = None
475 format = None
476 oneDDict = None
477 twoDDict = None
478 independentParam = None
479 filefmt = None
480 folderfmt = None
540 481
541 482 def run(self):
542 483
543 raise NotImplementedError
544
545 def getDtypeWidth(self):
546
547 dtype_index = get_dtype_index(self.dtype)
548 dtype_width = get_dtype_width(dtype_index)
549
550 return dtype_width
484 raise NotImplementedError
551 485
552 486 def getAllowedArgs(self):
553 487 if hasattr(self, '__attrs__'):
554 488 return self.__attrs__
555 489 else:
556 490 return inspect.getargspec(self.run).args
557 491
492 def set_kwargs(self, **kwargs):
558 493
559 class JRODataReader(JRODataIO):
560
561 online = 0
562
563 realtime = 0
564
565 nReadBlocks = 0
566
567 delay = 10 # number of seconds waiting a new file
568
569 nTries = 3 # quantity tries
570
571 nFiles = 3 # number of files for searching
572
573 path = None
574
575 foldercounter = 0
576
577 flagNoMoreFiles = 0
578
579 datetimeList = []
580
581 __isFirstTimeOnline = 1
582
583 __printInfo = True
494 for key, value in kwargs.items():
495 setattr(self, key, value)
496
497 def find_folders(self, path, startDate, endDate, folderfmt, last=False):
584 498
585 profileIndex = None
586
587 nTxs = 1
499 folders = [x for f in path.split(',')
500 for x in os.listdir(f) if os.path.isdir(os.path.join(f, x))]
501 folders.sort()
588 502
589 txIndex = None
503 if last:
504 folders = [folders[-1]]
590 505
591 # Added--------------------
592
593 selBlocksize = None
594
595 selBlocktime = None
596
597 def __init__(self):
598 """
599 This class is used to find data files
600
601 Example:
602 reader = JRODataReader()
603 fileList = reader.findDataFiles()
506 for folder in folders:
507 try:
508 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
509 if dt >= startDate and dt <= endDate:
510 yield os.path.join(path, folder)
511 else:
512 log.log('Skiping folder {}'.format(folder), self.name)
513 except Exception as e:
514 log.log('Skiping folder {}'.format(folder), self.name)
515 continue
516 return
517
518 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
519 expLabel='', last=False):
520
521 for path in folders:
522 files = glob.glob1(path, '*{}'.format(ext))
523 files.sort()
524 if last:
525 if files:
526 fo = files[-1]
527 try:
528 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
529 yield os.path.join(path, expLabel, fo)
530 except Exception as e:
531 pass
532 return None
533 else:
534 return None
604 535
605 """
606 pass
536 for fo in files:
537 try:
538 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
539 if dt >= startDate and dt <= endDate:
540 yield os.path.join(path, expLabel, fo)
541 else:
542 log.log('Skiping file {}'.format(fo), self.name)
543 except Exception as e:
544 log.log('Skiping file {}'.format(fo), self.name)
545 continue
607 546
608 def createObjByDefault(self):
609 """
547 def searchFilesOffLine(self, path, startDate, endDate,
548 expLabel, ext, walk,
549 filefmt, folderfmt):
550 """Search files in offline mode for the given arguments
610 551
552 Return:
553 Generator of files
611 554 """
612 raise NotImplementedError
613
614 def getBlockDimension(self):
615
616 raise NotImplementedError
617 555
618 def searchFilesOffLine(self,
619 path,
620 startDate=None,
621 endDate=None,
622 startTime=datetime.time(0, 0, 0),
623 endTime=datetime.time(23, 59, 59),
624 set=None,
625 expLabel='',
626 ext='.r',
627 cursor=None,
628 skip=None,
629 walk=True):
630
631 self.filenameList = []
632 self.datetimeList = []
633
634 pathList = []
635
636 dateList, pathList = self.findDatafiles(
637 path, startDate, endDate, expLabel, ext, walk, include_path=True)
638
639 if dateList == []:
640 return [], []
641
642 if len(dateList) > 1:
643 print("[Reading] Data found for date range [%s - %s]: total days = %d" % (startDate, endDate, len(dateList)))
556 if walk:
557 folders = self.find_folders(
558 path, startDate, endDate, folderfmt)
644 559 else:
645 print("[Reading] Data found for date range [%s - %s]: date = %s" % (startDate, endDate, dateList[0]))
646
647 filenameList = []
648 datetimeList = []
560 folders = path.split(',')
649 561
650 for thisPath in pathList:
651
652 fileList = glob.glob1(thisPath, "*%s" % ext)
653 fileList.sort()
654
655 for file in fileList:
656
657 filename = os.path.join(thisPath, file)
658
659 if not isFileInDateRange(filename, startDate, endDate):
660 continue
661
662 thisDatetime = isFileInTimeRange(
663 filename, startDate, endDate, startTime, endTime)
664
665 if not(thisDatetime):
666 continue
667
668 filenameList.append(filename)
669 datetimeList.append(thisDatetime)
670
671 if cursor is not None and skip is not None:
672 filenameList = filenameList[cursor * skip:cursor * skip + skip]
673 datetimeList = datetimeList[cursor * skip:cursor * skip + skip]
674
675 if not(filenameList):
676 print("[Reading] Time range selected invalid [%s - %s]: No *%s files in %s)" % (startTime, endTime, ext, path))
677 return [], []
678
679 print("[Reading] %d file(s) was(were) found in time range: %s - %s" % (len(filenameList), startTime, endTime))
680
681 # for i in range(len(filenameList)):
682 # print "[Reading] %s -> [%s]" %(filenameList[i], datetimeList[i].ctime())
683
684 self.filenameList = filenameList
685 self.datetimeList = datetimeList
686
687 return pathList, filenameList
688
689 def __searchFilesOnLine(self, path, expLabel="", ext=None, walk=True, set=None):
690 """
691 Busca el ultimo archivo de la ultima carpeta (determinada o no por startDateTime) y
692 devuelve el archivo encontrado ademas de otros datos.
693
694 Input:
695 path : carpeta donde estan contenidos los files que contiene data
696
697 expLabel : Nombre del subexperimento (subfolder)
698
699 ext : extension de los files
700
562 return self.find_files(
563 folders, ext, filefmt, startDate, endDate, expLabel)
564
565 def searchFilesOnLine(self, path, startDate, endDate,
566 expLabel, ext, walk,
567 filefmt, folderfmt):
568 """Search for the last file of the last folder
569
570 Arguments:
571 path : carpeta donde estan contenidos los files que contiene data
572 expLabel : Nombre del subexperimento (subfolder)
573 ext : extension de los files
701 574 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
702 575
703 576 Return:
704 directory : eL directorio donde esta el file encontrado
705 filename : el ultimo file de una determinada carpeta
706 year : el anho
707 doy : el numero de dia del anho
708 set : el set del archivo
709
710
577 generator with the full path of last filename
711 578 """
712 if not os.path.isdir(path):
713 return None, None, None, None, None, None
714
715 dirList = []
716
717 if not walk:
718 fullpath = path
719 foldercounter = 0
579
580 if walk:
581 folders = self.find_folders(
582 path, startDate, endDate, folderfmt, last=True)
720 583 else:
721 # Filtra solo los directorios
722 for thisPath in os.listdir(path):
723 if not os.path.isdir(os.path.join(path, thisPath)):
724 continue
725 if not isRadarFolder(thisPath):
726 continue
727
728 dirList.append(thisPath)
729
730 if not(dirList):
731 return None, None, None, None, None, None
732
733 dirList = sorted(dirList, key=str.lower)
584 folders = path.split(',')
585
586 return self.find_files(
587 folders, ext, filefmt, startDate, endDate, expLabel, last=True)
734 588
735 doypath = dirList[-1]
736 foldercounter = int(doypath.split('_')[1]) if len(
737 doypath.split('_')) > 1 else 0
738 fullpath = os.path.join(path, doypath, expLabel)
589 def setNextFile(self):
590 """Set the next file to be readed open it and parse de file header"""
739 591
740 print("[Reading] %s folder was found: " % (fullpath))
592 if self.fp != None:
593 self.fp.close()
741 594
742 if set == None:
743 filename = getlastFileFromPath(fullpath, ext)
595 if self.online:
596 newFile = self.setNextFileOnline()
744 597 else:
745 filename = getFileFromSet(fullpath, ext, set)
746
747 if not(filename):
748 return None, None, None, None, None, None
749
750 print("[Reading] %s file was found" % (filename))
751
752 if not(self.__verifyFile(os.path.join(fullpath, filename))):
753 return None, None, None, None, None, None
754
755 year = int(filename[1:5])
756 doy = int(filename[5:8])
757 set = int(filename[8:11])
758
759 return fullpath, foldercounter, filename, year, doy, set
760
761 def __setNextFileOffline(self):
762
763 idFile = self.fileIndex
764
765 while (True):
766 idFile += 1
767 if not(idFile < len(self.filenameList)):
768 self.flagNoMoreFiles = 1
769 return 0
770
771 filename = self.filenameList[idFile]
772
773 if not(self.__verifyFile(filename)):
774 continue
775
776 fileSize = os.path.getsize(filename)
777 fp = open(filename, 'rb')
778 break
779
780 self.flagIsNewFile = 1
781 self.fileIndex = idFile
782 self.filename = filename
783 self.fileSize = fileSize
784 self.fp = fp
785
786 # print "[Reading] Setting the file: %s"%self.filename
598 newFile = self.setNextFileOffline()
599
600 if not(newFile):
601 if self.online:
602 raise schainpy.admin.SchainError('Time to wait for new files reach')
603 else:
604 if self.fileIndex == -1:
605 raise schainpy.admin.SchainWarning('No files found in the given path')
606 else:
607 raise schainpy.admin.SchainWarning('No more files to read')
608
609 if not(self.verifyFile(self.filename)):
610 self.setNextFile()
611
612 log.log('Opening file: %s' % self.filename, self.name)
787 613
788 return 1
614 self.readFirstHeader()
615 self.nReadBlocks = 0
789 616
790 def __setNextFileOnline(self):
791 """
792 Busca el siguiente file que tenga suficiente data para ser leida, dentro de un folder especifico, si
793 no encuentra un file valido espera un tiempo determinado y luego busca en los posibles n files
794 siguientes.
617 def setNextFileOnline(self):
618 """Check for the next file to be readed in online mode.
795 619
796 Affected:
797 self.flagIsNewFile
620 Set:
798 621 self.filename
799 self.fileSize
800 622 self.fp
801 self.set
802 self.flagNoMoreFiles
803
623 self.filesize
624
804 625 Return:
805 0 : si luego de una busqueda del siguiente file valido este no pudo ser encontrado
806 1 : si el file fue abierto con exito y esta listo a ser leido
626 boolean
807 627
808 Excepciones:
809 Si un determinado file no puede ser abierto
810 628 """
811 nFiles = 0
812 fileOk_flag = False
813 firstTime_flag = True
814
815 self.set += 1
629 nextFile = True
630 nextDay = False
816 631
817 if self.set > 999:
818 self.set = 0
819 self.foldercounter += 1
820
821 # busca el 1er file disponible
822 fullfilename, filename = checkForRealPath(
823 self.path, self.foldercounter, self.year, self.doy, self.set, self.ext)
824 if fullfilename:
825 if self.__verifyFile(fullfilename, False):
826 fileOk_flag = True
827
828 # si no encuentra un file entonces espera y vuelve a buscar
829 if not(fileOk_flag):
830 # busco en los siguientes self.nFiles+1 files posibles
831 for nFiles in range(self.nFiles + 1):
832
833 if firstTime_flag: # si es la 1era vez entonces hace el for self.nTries veces
834 tries = self.nTries
835 else:
836 tries = 1 # si no es la 1era vez entonces solo lo hace una vez
837
838 for nTries in range(tries):
839 if firstTime_flag:
840 log.warning(
841 "Waiting %0.2f sec for the next file: \"%s\" , try %03d ..." % (self.delay, filename, nTries + 1),
842 self.name)
843 time.sleep(self.delay)
844 else:
845 log.warning(
846 "Searching the next \"%s%04d%03d%03d%s\" file ..." % (self.optchar, self.year, self.doy, self.set, self.ext),
847 self.name)
848
849 fullfilename, filename = checkForRealPath(
850 self.path, self.foldercounter, self.year, self.doy, self.set, self.ext)
851 if fullfilename:
852 if self.__verifyFile(fullfilename):
853 fileOk_flag = True
854 break
855
856 if fileOk_flag:
632 for nFiles in range(self.nFiles+1):
633 for nTries in range(self.nTries):
634 fullfilename, filename = self.checkForRealPath(nextFile, nextDay)
635 if fullfilename is not None:
857 636 break
858
859 firstTime_flag = False
860
861 637 log.warning(
862 'Skipping the file {} due to this file doesn\'t exist'.format(filename),
638 "Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, filename, nTries + 1),
863 639 self.name)
864 self.set += 1
640 time.sleep(self.delay)
641 nextFile = False
642 continue
643
644 if fullfilename:
645 break
646
647 self.nTries = 1
648 nextFile = True
865 649
866 # si no encuentro el file buscado cambio de carpeta y busco en la siguiente carpeta
867 if nFiles == (self.nFiles - 1):
868 self.set = 0
869 self.doy += 1
870 self.foldercounter = 0
650 if nFiles == (self.nFiles - 1):
651 log.log('Trying with next day...', self.name)
652 nextDay = True
871 653
872 if fileOk_flag:
654 if fullfilename:
873 655 self.fileSize = os.path.getsize(fullfilename)
874 656 self.filename = fullfilename
875 657 self.flagIsNewFile = 1
876 658 if self.fp != None:
877 659 self.fp.close()
878 660 self.fp = open(fullfilename, 'rb')
879 661 self.flagNoMoreFiles = 0
880 else:
881 raise schainpy.admin.SchainError('Time for waiting new files reach')
882 self.fileSize = 0
883 self.filename = None
884 self.flagIsNewFile = 0
885 self.fp = None
662 self.fileIndex += 1
663 return 1
664 else:
665 return 0
666
667 def setNextFileOffline(self):
668 """Open the next file to be readed in offline mode"""
669
670 try:
671 filename = next(self.filenameList)
672 self.fileIndex +=1
673 except StopIteration:
886 674 self.flagNoMoreFiles = 1
675 return 0
887 676
888 return fileOk_flag
677 self.filename = filename
678 self.fileSize = os.path.getsize(filename)
679 self.fp = open(filename, 'rb')
680 self.flagIsNewFile = 1
889 681
890 def setNextFile(self):
891 if self.fp != None:
892 self.fp.close()
682 return 1
683
684 def verifyFile(self, filename):
685 """Check for a valid file
686
687 Arguments:
688 filename -- full path filename
689
690 Return:
691 boolean
692 """
893 693
894 if self.online:
895 newFile = self.__setNextFileOnline()
896 else:
897 newFile = self.__setNextFileOffline()
694 return True
898 695
899 if not(newFile):
900 raise schainpy.admin.SchainWarning('No more files to read')
901
696 def checkForRealPath(self, nextFile, nextDay):
697 """Check if the next file to be readed exists"""
902 698
903 if self.verbose:
904 print('[Reading] Setting the file: %s' % self.filename)
699 raise NotImplementedError
700
701 def readFirstHeader(self):
702 """Parse the file header"""
905 703
906 self.__readFirstHeader()
907 self.nReadBlocks = 0
908 return 1
704 pass
705
706 class JRODataReader(Reader):
707
708 utc = 0
709 nReadBlocks = 0
710 foldercounter = 0
711 firstHeaderSize = 0
712 basicHeaderSize = 24
713 __isFirstTimeOnline = 1
714 __printInfo = True
715 filefmt = "*%Y%j***"
716 folderfmt = "*%Y%j"
909 717
718 def getDtypeWidth(self):
719
720 dtype_index = get_dtype_index(self.dtype)
721 dtype_width = get_dtype_width(dtype_index)
722
723 return dtype_width
724
725 def checkForRealPath(self, nextFile, nextDay):
726 """Check if the next file to be readed exists.
727
728 Example :
729 nombre correcto del file es .../.../D2009307/P2009307367.ext
730
731 Entonces la funcion prueba con las siguientes combinaciones
732 .../.../y2009307367.ext
733 .../.../Y2009307367.ext
734 .../.../x2009307/y2009307367.ext
735 .../.../x2009307/Y2009307367.ext
736 .../.../X2009307/y2009307367.ext
737 .../.../X2009307/Y2009307367.ext
738 siendo para este caso, la ultima combinacion de letras, identica al file buscado
739
740 Return:
741 str -- fullpath of the file
742 """
743
744
745 if nextFile:
746 self.set += 1
747 if nextDay:
748 self.set = 0
749 self.doy += 1
750 foldercounter = 0
751 prefixDirList = [None, 'd', 'D']
752 if self.ext.lower() == ".r": # voltage
753 prefixFileList = ['d', 'D']
754 elif self.ext.lower() == ".pdata": # spectra
755 prefixFileList = ['p', 'P']
756
757 # barrido por las combinaciones posibles
758 for prefixDir in prefixDirList:
759 thispath = self.path
760 if prefixDir != None:
761 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
762 if foldercounter == 0:
763 thispath = os.path.join(self.path, "%s%04d%03d" %
764 (prefixDir, self.year, self.doy))
765 else:
766 thispath = os.path.join(self.path, "%s%04d%03d_%02d" % (
767 prefixDir, self.year, self.doy, foldercounter))
768 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
769 # formo el nombre del file xYYYYDDDSSS.ext
770 filename = "%s%04d%03d%03d%s" % (prefixFile, self.year, self.doy, self.set, self.ext)
771 fullfilename = os.path.join(
772 thispath, filename)
773
774 if os.path.exists(fullfilename):
775 return fullfilename, filename
776
777 return None, filename
778
910 779 def __waitNewBlock(self):
911 780 """
912 781 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
913 782
914 783 Si el modo de lectura es OffLine siempre retorn 0
915 784 """
916 785 if not self.online:
917 786 return 0
918 787
919 788 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
920 789 return 0
921 790
922 791 currentPointer = self.fp.tell()
923 792
924 793 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
925 794
926 795 for nTries in range(self.nTries):
927 796
928 797 self.fp.close()
929 798 self.fp = open(self.filename, 'rb')
930 799 self.fp.seek(currentPointer)
931 800
932 801 self.fileSize = os.path.getsize(self.filename)
933 802 currentSize = self.fileSize - currentPointer
934 803
935 804 if (currentSize >= neededSize):
936 805 self.basicHeaderObj.read(self.fp)
937 806 return 1
938 807
939 808 if self.fileSize == self.fileSizeByHeader:
940 809 # self.flagEoF = True
941 810 return 0
942 811
943 812 print("[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1))
944 813 time.sleep(self.delay)
945 814
946 815 return 0
947 816
948 817 def waitDataBlock(self, pointer_location, blocksize=None):
949 818
950 819 currentPointer = pointer_location
951 820 if blocksize is None:
952 821 neededSize = self.processingHeaderObj.blockSize # + self.basicHeaderSize
953 822 else:
954 823 neededSize = blocksize
955 824
956 825 for nTries in range(self.nTries):
957 826 self.fp.close()
958 827 self.fp = open(self.filename, 'rb')
959 828 self.fp.seek(currentPointer)
960 829
961 830 self.fileSize = os.path.getsize(self.filename)
962 831 currentSize = self.fileSize - currentPointer
963 832
964 833 if (currentSize >= neededSize):
965 834 return 1
966 835
967 836 log.warning(
968 837 "Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1),
969 838 self.name
970 839 )
971 840 time.sleep(self.delay)
972 841
973 842 return 0
974 843
975 def __jumpToLastBlock(self):
976
977 if not(self.__isFirstTimeOnline):
978 return
979
980 csize = self.fileSize - self.fp.tell()
981 blocksize = self.processingHeaderObj.blockSize
982
983 # salta el primer bloque de datos
984 if csize > self.processingHeaderObj.blockSize:
985 self.fp.seek(self.fp.tell() + blocksize)
986 else:
987 return
988
989 csize = self.fileSize - self.fp.tell()
990 neededsize = self.processingHeaderObj.blockSize + self.basicHeaderSize
991 while True:
992
993 if self.fp.tell() < self.fileSize:
994 self.fp.seek(self.fp.tell() + neededsize)
995 else:
996 self.fp.seek(self.fp.tell() - neededsize)
997 break
998
999 # csize = self.fileSize - self.fp.tell()
1000 # neededsize = self.processingHeaderObj.blockSize + self.basicHeaderSize
1001 # factor = int(csize/neededsize)
1002 # if factor > 0:
1003 # self.fp.seek(self.fp.tell() + factor*neededsize)
1004
1005 self.flagIsNewFile = 0
1006 self.__isFirstTimeOnline = 0
1007
1008 844 def __setNewBlock(self):
1009 # if self.server is None:
1010 if self.fp == None:
1011 return 0
1012 845
1013 # if self.online:
1014 # self.__jumpToLastBlock()
846 if self.fp == None:
847 return 0
1015 848
1016 if self.flagIsNewFile:
849 if self.flagIsNewFile:
1017 850 self.lastUTTime = self.basicHeaderObj.utc
1018 851 return 1
1019 852
1020 853 if self.realtime:
1021 854 self.flagDiscontinuousBlock = 1
1022 855 if not(self.setNextFile()):
1023 856 return 0
1024 857 else:
1025 858 return 1
1026 # if self.server is None:
859
1027 860 currentSize = self.fileSize - self.fp.tell()
1028 861 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
862
1029 863 if (currentSize >= neededSize):
1030 864 self.basicHeaderObj.read(self.fp)
1031 865 self.lastUTTime = self.basicHeaderObj.utc
1032 866 return 1
1033 # else:
1034 # self.basicHeaderObj.read(self.zHeader)
1035 # self.lastUTTime = self.basicHeaderObj.utc
1036 # return 1
867
1037 868 if self.__waitNewBlock():
1038 869 self.lastUTTime = self.basicHeaderObj.utc
1039 870 return 1
1040 # if self.server is None:
871
1041 872 if not(self.setNextFile()):
1042 873 return 0
1043 874
1044 875 deltaTime = self.basicHeaderObj.utc - self.lastUTTime
1045 876 self.lastUTTime = self.basicHeaderObj.utc
1046 877
1047 878 self.flagDiscontinuousBlock = 0
1048 879
1049 880 if deltaTime > self.maxTimeStep:
1050 881 self.flagDiscontinuousBlock = 1
1051 882
1052 883 return 1
1053 884
1054 885 def readNextBlock(self):
1055 886
1056 # Skip block out of startTime and endTime
1057 887 while True:
1058 if not(self.__setNewBlock()):
1059 raise schainpy.admin.SchainWarning('No more files to read')
888 self.__setNewBlock()
1060 889
1061 890 if not(self.readBlock()):
1062 891 return 0
1063 892
1064 893 self.getBasicHeader()
1065 894 if (self.dataOut.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or (self.dataOut.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
1066 895 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.nReadBlocks,
1067 896 self.processingHeaderObj.dataBlocksPerFile,
1068 897 self.dataOut.datatime.ctime()))
1069 898 continue
1070 899
1071 900 break
1072 901
1073 902 if self.verbose:
1074 903 print("[Reading] Block No. %d/%d -> %s" % (self.nReadBlocks,
1075 904 self.processingHeaderObj.dataBlocksPerFile,
1076 905 self.dataOut.datatime.ctime()))
1077 906 return 1
1078 907
1079 def __readFirstHeader(self):
908 def readFirstHeader(self):
1080 909
1081 910 self.basicHeaderObj.read(self.fp)
1082 911 self.systemHeaderObj.read(self.fp)
1083 912 self.radarControllerHeaderObj.read(self.fp)
1084 913 self.processingHeaderObj.read(self.fp)
1085
1086 914 self.firstHeaderSize = self.basicHeaderObj.size
1087 915
1088 916 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
1089 917 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
1090 918 if datatype == 0:
1091 919 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
1092 920 elif datatype == 1:
1093 921 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
1094 922 elif datatype == 2:
1095 923 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
1096 924 elif datatype == 3:
1097 925 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
1098 926 elif datatype == 4:
1099 927 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
1100 928 elif datatype == 5:
1101 929 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
1102 930 else:
1103 931 raise ValueError('Data type was not defined')
1104 932
1105 933 self.dtype = datatype_str
1106 934 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
1107 935 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
1108 936 self.firstHeaderSize + self.basicHeaderSize * \
1109 937 (self.processingHeaderObj.dataBlocksPerFile - 1)
1110 938 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
1111 939 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
1112 940 self.getBlockDimension()
1113 941
1114 def __verifyFile(self, filename, msgFlag=True):
942 def verifyFile(self, filename, msgFlag=True):
1115 943
1116 944 msg = None
1117 945
1118 946 try:
1119 947 fp = open(filename, 'rb')
1120 948 except IOError:
1121 949
1122 950 if msgFlag:
1123 951 print("[Reading] File %s can't be opened" % (filename))
1124 952
1125 953 return False
1126 954
1127 955 currentPosition = fp.tell()
1128 956 neededSize = self.processingHeaderObj.blockSize + self.firstHeaderSize
1129 957
1130 958 if neededSize == 0:
1131 959 basicHeaderObj = BasicHeader(LOCALTIME)
1132 960 systemHeaderObj = SystemHeader()
1133 961 radarControllerHeaderObj = RadarControllerHeader()
1134 962 processingHeaderObj = ProcessingHeader()
1135 963
1136 964 if not(basicHeaderObj.read(fp)):
1137 965 fp.close()
1138 966 return False
1139 967
1140 968 if not(systemHeaderObj.read(fp)):
1141 969 fp.close()
1142 970 return False
1143 971
1144 972 if not(radarControllerHeaderObj.read(fp)):
1145 973 fp.close()
1146 974 return False
1147 975
1148 976 if not(processingHeaderObj.read(fp)):
1149 977 fp.close()
1150 978 return False
1151 979
1152 980 neededSize = processingHeaderObj.blockSize + basicHeaderObj.size
1153 981 else:
1154 982 msg = "[Reading] Skipping the file %s due to it hasn't enough data" % filename
1155 983
1156 984 fp.close()
1157 985
1158 986 fileSize = os.path.getsize(filename)
1159 987 currentSize = fileSize - currentPosition
1160 988
1161 989 if currentSize < neededSize:
1162 990 if msgFlag and (msg != None):
1163 991 print(msg)
1164 992 return False
1165 993
1166 994 return True
1167 995
1168 996 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1169 997
1170 998 path_empty = True
1171 999
1172 1000 dateList = []
1173 1001 pathList = []
1174 1002
1175 1003 multi_path = path.split(',')
1176 1004
1177 1005 if not walk:
1178 1006
1179 1007 for single_path in multi_path:
1180 1008
1181 1009 if not os.path.isdir(single_path):
1182 1010 continue
1183 1011
1184 1012 fileList = glob.glob1(single_path, "*" + ext)
1185 1013
1186 1014 if not fileList:
1187 1015 continue
1188 1016
1189 1017 path_empty = False
1190 1018
1191 1019 fileList.sort()
1192 1020
1193 1021 for thisFile in fileList:
1194 1022
1195 1023 if not os.path.isfile(os.path.join(single_path, thisFile)):
1196 1024 continue
1197 1025
1198 1026 if not isRadarFile(thisFile):
1199 1027 continue
1200 1028
1201 1029 if not isFileInDateRange(thisFile, startDate, endDate):
1202 1030 continue
1203 1031
1204 1032 thisDate = getDateFromRadarFile(thisFile)
1205 1033
1206 1034 if thisDate in dateList or single_path in pathList:
1207 1035 continue
1208 1036
1209 1037 dateList.append(thisDate)
1210 1038 pathList.append(single_path)
1211 1039
1212 1040 else:
1213 1041 for single_path in multi_path:
1214 1042
1215 1043 if not os.path.isdir(single_path):
1216 1044 continue
1217 1045
1218 1046 dirList = []
1219 1047
1220 1048 for thisPath in os.listdir(single_path):
1221 1049
1222 1050 if not os.path.isdir(os.path.join(single_path, thisPath)):
1223 1051 continue
1224 1052
1225 1053 if not isRadarFolder(thisPath):
1226 1054 continue
1227 1055
1228 1056 if not isFolderInDateRange(thisPath, startDate, endDate):
1229 1057 continue
1230 1058
1231 1059 dirList.append(thisPath)
1232 1060
1233 1061 if not dirList:
1234 1062 continue
1235 1063
1236 1064 dirList.sort()
1237 1065
1238 1066 for thisDir in dirList:
1239 1067
1240 1068 datapath = os.path.join(single_path, thisDir, expLabel)
1241 1069 fileList = glob.glob1(datapath, "*" + ext)
1242 1070
1243 1071 if not fileList:
1244 1072 continue
1245 1073
1246 1074 path_empty = False
1247 1075
1248 1076 thisDate = getDateFromRadarFolder(thisDir)
1249 1077
1250 1078 pathList.append(datapath)
1251 1079 dateList.append(thisDate)
1252 1080
1253 1081 dateList.sort()
1254 1082
1255 1083 if walk:
1256 1084 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1257 1085 else:
1258 1086 pattern_path = multi_path[0]
1259 1087
1260 1088 if path_empty:
1261 1089 raise schainpy.admin.SchainError("[Reading] No *%s files in %s for %s to %s" % (ext, pattern_path, startDate, endDate))
1262 1090 else:
1263 1091 if not dateList:
1264 1092 raise schainpy.admin.SchainError("[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" % (startDate, endDate, ext, path))
1265 1093
1266 1094 if include_path:
1267 1095 return dateList, pathList
1268 1096
1269 1097 return dateList
1270 1098
1271 def setup(self,
1272 path=None,
1273 startDate=None,
1274 endDate=None,
1275 startTime=datetime.time(0, 0, 0),
1276 endTime=datetime.time(23, 59, 59),
1277 set=None,
1278 expLabel="",
1279 ext=None,
1280 online=False,
1281 delay=60,
1282 walk=True,
1283 getblock=False,
1284 nTxs=1,
1285 realtime=False,
1286 blocksize=None,
1287 blocktime=None,
1288 skip=None,
1289 cursor=None,
1290 warnings=True,
1291 verbose=True,
1292 server=None,
1293 format=None,
1294 oneDDict=None,
1295 twoDDict=None,
1296 independentParam=None):
1099 def setup(self, **kwargs):
1100
1101 self.set_kwargs(**kwargs)
1102 if not self.ext.startswith('.'):
1103 self.ext = '.{}'.format(self.ext)
1297 1104
1298 self.online = online
1299 self.realtime = realtime
1300 self.delay = delay
1301 self.getByBlock = getblock
1302 self.nTxs = nTxs
1303 self.startTime = startTime
1304 self.endTime = endTime
1305 self.endDate = endDate
1306 self.startDate = startDate
1307
1308 if server is not None:
1309 if 'tcp://' in server:
1105 if self.server is not None:
1106 if 'tcp://' in self.server:
1310 1107 address = server
1311 1108 else:
1312 address = 'ipc:///tmp/%s' % server
1109 address = 'ipc:///tmp/%s' % self.server
1313 1110 self.server = address
1314 1111 self.context = zmq.Context()
1315 1112 self.receiver = self.context.socket(zmq.PULL)
1316 1113 self.receiver.connect(self.server)
1317 1114 time.sleep(0.5)
1318 1115 print('[Starting] ReceiverData from {}'.format(self.server))
1319 1116 else:
1320 1117 self.server = None
1321 if path == None:
1118 if self.path == None:
1322 1119 raise ValueError("[Reading] The path is not valid")
1323 1120
1324 if ext == None:
1325 ext = self.ext
1326
1327 if online:
1328 print("[Reading] Searching files in online mode...")
1121 if self.online:
1122 log.log("[Reading] Searching files in online mode...", self.name)
1329 1123
1330 1124 for nTries in range(self.nTries):
1331 fullpath, foldercounter, file, year, doy, set = self.__searchFilesOnLine(
1332 path=path, expLabel=expLabel, ext=ext, walk=walk, set=set)
1333
1125 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1126 self.endDate, self.expLabel, self.ext, self.walk,
1127 self.filefmt, self.folderfmt)
1128
1129 try:
1130 fullpath = next(fullpath)
1131 except:
1132 fullpath = None
1133
1334 1134 if fullpath:
1335 1135 break
1336 1136
1337 print('[Reading] Waiting %0.2f sec for an valid file in %s: try %02d ...' % (self.delay, path, nTries + 1))
1137 log.warning(
1138 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1139 self.delay, self.path, nTries + 1),
1140 self.name)
1338 1141 time.sleep(self.delay)
1339 1142
1340 1143 if not(fullpath):
1341 raise schainpy.admin.SchainError('There isn\'t any valid file in {}'.format(path))
1342 return
1343
1344 self.year = year
1345 self.doy = doy
1346 self.set = set - 1
1347 self.path = path
1348 self.foldercounter = foldercounter
1349 last_set = None
1350 else:
1351 print("[Reading] Searching files in offline mode ...")
1352 pathList, filenameList = self.searchFilesOffLine(path, startDate=startDate, endDate=endDate,
1353 startTime=startTime, endTime=endTime,
1354 set=set, expLabel=expLabel, ext=ext,
1355 walk=walk, cursor=cursor,
1356 skip=skip)
1357
1358 if not(pathList):
1359 self.fileIndex = -1
1360 self.pathList = []
1361 self.filenameList = []
1362 return
1363
1364 self.fileIndex = -1
1365 self.pathList = pathList
1366 self.filenameList = filenameList
1367 file_name = os.path.basename(filenameList[-1])
1368 basename, ext = os.path.splitext(file_name)
1369 last_set = int(basename[-3:])
1144 raise schainpy.admin.SchainError(
1145 'There isn\'t any valid file in {}'.format(self.path))
1370 1146
1147 pathname, filename = os.path.split(fullpath)
1148 self.year = int(filename[1:5])
1149 self.doy = int(filename[5:8])
1150 self.set = int(filename[8:11]) - 1
1151 else:
1152 log.log("Searching files in {}".format(self.path), self.name)
1153 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1154 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1371 1155
1372 ext = ext.lower()
1373 self.ext = ext
1374
1375 # Added-----------------
1376 self.selBlocksize = blocksize
1377 self.selBlocktime = blocktime
1378
1379 # Verbose-----------
1380 self.verbose = verbose
1381 self.warnings = warnings
1382
1383 if not(self.setNextFile()):
1384 if (startDate != None) and (endDate != None):
1385 print("[Reading] No files in range: %s - %s" % (datetime.datetime.combine(startDate, startTime).ctime(), datetime.datetime.combine(endDate, endTime).ctime()))
1386 elif startDate != None:
1387 print("[Reading] No files in range: %s" % (datetime.datetime.combine(startDate, startTime).ctime()))
1388 else:
1389 print("[Reading] No files")
1390
1391 self.fileIndex = -1
1392 self.pathList = []
1393 self.filenameList = []
1394 return
1156 self.setNextFile()
1395 1157
1396 if last_set != None:
1397 self.dataOut.last_block = last_set * \
1398 self.processingHeaderObj.dataBlocksPerFile + self.basicHeaderObj.dataBlock
1399 1158 return
1400 1159
1401 1160 def getBasicHeader(self):
1402 1161
1403 1162 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond / \
1404 1163 1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1405 1164
1406 1165 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1407 1166
1408 1167 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1409 1168
1410 1169 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1411 1170
1412 1171 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1413 1172
1414 1173 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1415 1174
1416 1175 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
1417 1176
1418 # self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock*self.nTxs
1177 # self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock*self.nTxs
1419 1178
1420 1179 def getFirstHeader(self):
1421 1180
1422 1181 raise NotImplementedError
1423 1182
1424 1183 def getData(self):
1425 1184
1426 1185 raise NotImplementedError
1427 1186
1428 1187 def hasNotDataInBuffer(self):
1429 1188
1430 1189 raise NotImplementedError
1431 1190
1432 1191 def readBlock(self):
1433 1192
1434 1193 raise NotImplementedError
1435 1194
1436 1195 def isEndProcess(self):
1437 1196
1438 1197 return self.flagNoMoreFiles
1439 1198
1440 1199 def printReadBlocks(self):
1441 1200
1442 1201 print("[Reading] Number of read blocks per file %04d" % self.nReadBlocks)
1443 1202
1444 1203 def printTotalBlocks(self):
1445 1204
1446 1205 print("[Reading] Number of read blocks %04d" % self.nTotalBlocks)
1447 1206
1448 1207 def printNumberOfBlock(self):
1449 1208 'SPAM!'
1450 1209
1451 # if self.flagIsNewBlock:
1452 # print "[Reading] Block No. %d/%d -> %s" %(self.nReadBlocks,
1453 # self.processingHeaderObj.dataBlocksPerFile,
1454 # self.dataOut.datatime.ctime())
1210 # if self.flagIsNewBlock:
1211 # print "[Reading] Block No. %d/%d -> %s" %(self.nReadBlocks,
1212 # self.processingHeaderObj.dataBlocksPerFile,
1213 # self.dataOut.datatime.ctime())
1455 1214
1456 1215 def printInfo(self):
1457 1216
1458 1217 if self.__printInfo == False:
1459 1218 return
1460 1219
1461 1220 self.basicHeaderObj.printInfo()
1462 1221 self.systemHeaderObj.printInfo()
1463 1222 self.radarControllerHeaderObj.printInfo()
1464 1223 self.processingHeaderObj.printInfo()
1465 1224
1466 1225 self.__printInfo = False
1467 1226
1468 def run(self,
1469 path=None,
1470 startDate=None,
1471 endDate=None,
1472 startTime=datetime.time(0, 0, 0),
1473 endTime=datetime.time(23, 59, 59),
1474 set=None,
1475 expLabel="",
1476 ext=None,
1477 online=False,
1478 delay=60,
1479 walk=True,
1480 getblock=False,
1481 nTxs=1,
1482 realtime=False,
1483 blocksize=None,
1484 blocktime=None,
1485 skip=None,
1486 cursor=None,
1487 warnings=True,
1488 server=None,
1489 verbose=True,
1490 format=None,
1491 oneDDict=None,
1492 twoDDict=None,
1493 independentParam=None, **kwargs):
1227 def run(self, **kwargs):
1228 """
1229
1230 Arguments:
1231 path :
1232 startDate :
1233 endDate :
1234 startTime :
1235 endTime :
1236 set :
1237 expLabel :
1238 ext :
1239 online :
1240 delay :
1241 walk :
1242 getblock :
1243 nTxs :
1244 realtime :
1245 blocksize :
1246 blocktime :
1247 skip :
1248 cursor :
1249 warnings :
1250 server :
1251 verbose :
1252 format :
1253 oneDDict :
1254 twoDDict :
1255 independentParam :
1256 """
1494 1257
1495 1258 if not(self.isConfig):
1496 self.setup(path=path,
1497 startDate=startDate,
1498 endDate=endDate,
1499 startTime=startTime,
1500 endTime=endTime,
1501 set=set,
1502 expLabel=expLabel,
1503 ext=ext,
1504 online=online,
1505 delay=delay,
1506 walk=walk,
1507 getblock=getblock,
1508 nTxs=nTxs,
1509 realtime=realtime,
1510 blocksize=blocksize,
1511 blocktime=blocktime,
1512 skip=skip,
1513 cursor=cursor,
1514 warnings=warnings,
1515 server=server,
1516 verbose=verbose,
1517 format=format,
1518 oneDDict=oneDDict,
1519 twoDDict=twoDDict,
1520 independentParam=independentParam)
1259 self.setup(**kwargs)
1521 1260 self.isConfig = True
1522 if server is None:
1261 if self.server is None:
1523 1262 self.getData()
1524 1263 else:
1525 1264 self.getFromServer()
1526 1265
1527 1266
1528 class JRODataWriter(JRODataIO):
1267 class JRODataWriter(Reader):
1529 1268
1530 1269 """
1531 1270 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1532 1271 de los datos siempre se realiza por bloques.
1533 1272 """
1534 1273
1535 blockIndex = 0
1536
1537 path = None
1538
1539 1274 setFile = None
1540
1541 1275 profilesPerBlock = None
1542
1543 1276 blocksPerFile = None
1544
1545 1277 nWriteBlocks = 0
1546
1547 1278 fileDate = None
1548 1279
1549 1280 def __init__(self, dataOut=None):
1550 1281 raise NotImplementedError
1551 1282
1552 1283 def hasAllDataInBuffer(self):
1553 1284 raise NotImplementedError
1554 1285
1555 1286 def setBlockDimension(self):
1556 1287 raise NotImplementedError
1557 1288
1558 1289 def writeBlock(self):
1559 1290 raise NotImplementedError
1560 1291
1561 1292 def putData(self):
1562 1293 raise NotImplementedError
1563 1294
1295 def getDtypeWidth(self):
1296
1297 dtype_index = get_dtype_index(self.dtype)
1298 dtype_width = get_dtype_width(dtype_index)
1299
1300 return dtype_width
1301
1564 1302 def getProcessFlags(self):
1565 1303
1566 1304 processFlags = 0
1567 1305
1568 1306 dtype_index = get_dtype_index(self.dtype)
1569 1307 procflag_dtype = get_procflag_dtype(dtype_index)
1570 1308
1571 1309 processFlags += procflag_dtype
1572 1310
1573 1311 if self.dataOut.flagDecodeData:
1574 1312 processFlags += PROCFLAG.DECODE_DATA
1575 1313
1576 1314 if self.dataOut.flagDeflipData:
1577 1315 processFlags += PROCFLAG.DEFLIP_DATA
1578 1316
1579 1317 if self.dataOut.code is not None:
1580 1318 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1581 1319
1582 1320 if self.dataOut.nCohInt > 1:
1583 1321 processFlags += PROCFLAG.COHERENT_INTEGRATION
1584 1322
1585 1323 if self.dataOut.type == "Spectra":
1586 1324 if self.dataOut.nIncohInt > 1:
1587 1325 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1588 1326
1589 1327 if self.dataOut.data_dc is not None:
1590 1328 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1591 1329
1592 1330 if self.dataOut.flagShiftFFT:
1593 1331 processFlags += PROCFLAG.SHIFT_FFT_DATA
1594 1332
1595 1333 return processFlags
1596 1334
1597 1335 def setBasicHeader(self):
1598 1336
1599 1337 self.basicHeaderObj.size = self.basicHeaderSize # bytes
1600 1338 self.basicHeaderObj.version = self.versionFile
1601 1339 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1602 1340 utc = numpy.floor(self.dataOut.utctime)
1603 1341 milisecond = (self.dataOut.utctime - utc) * 1000.0
1604 1342 self.basicHeaderObj.utc = utc
1605 1343 self.basicHeaderObj.miliSecond = milisecond
1606 1344 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1607 1345 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1608 1346 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1609 1347
1610 1348 def setFirstHeader(self):
1611 1349 """
1612 1350 Obtiene una copia del First Header
1613 1351
1614 1352 Affected:
1615 1353
1616 1354 self.basicHeaderObj
1617 1355 self.systemHeaderObj
1618 1356 self.radarControllerHeaderObj
1619 1357 self.processingHeaderObj self.
1620 1358
1621 1359 Return:
1622 1360 None
1623 1361 """
1624 1362
1625 1363 raise NotImplementedError
1626 1364
1627 1365 def __writeFirstHeader(self):
1628 1366 """
1629 1367 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1630 1368
1631 1369 Affected:
1632 1370 __dataType
1633 1371
1634 1372 Return:
1635 1373 None
1636 1374 """
1637 1375
1638 1376 # CALCULAR PARAMETROS
1639 1377
1640 1378 sizeLongHeader = self.systemHeaderObj.size + \
1641 1379 self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1642 1380 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1643 1381
1644 1382 self.basicHeaderObj.write(self.fp)
1645 1383 self.systemHeaderObj.write(self.fp)
1646 1384 self.radarControllerHeaderObj.write(self.fp)
1647 1385 self.processingHeaderObj.write(self.fp)
1648 1386
1649 1387 def __setNewBlock(self):
1650 1388 """
1651 1389 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1652 1390
1653 1391 Return:
1654 1392 0 : si no pudo escribir nada
1655 1393 1 : Si escribio el Basic el First Header
1656 1394 """
1657 1395 if self.fp == None:
1658 1396 self.setNextFile()
1659 1397
1660 1398 if self.flagIsNewFile:
1661 1399 return 1
1662 1400
1663 1401 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1664 1402 self.basicHeaderObj.write(self.fp)
1665 1403 return 1
1666 1404
1667 1405 if not(self.setNextFile()):
1668 1406 return 0
1669 1407
1670 1408 return 1
1671 1409
1672 1410 def writeNextBlock(self):
1673 1411 """
1674 1412 Selecciona el bloque siguiente de datos y los escribe en un file
1675 1413
1676 1414 Return:
1677 1415 0 : Si no hizo pudo escribir el bloque de datos
1678 1416 1 : Si no pudo escribir el bloque de datos
1679 1417 """
1680 1418 if not(self.__setNewBlock()):
1681 1419 return 0
1682 1420
1683 1421 self.writeBlock()
1684 1422
1685 1423 print("[Writing] Block No. %d/%d" % (self.blockIndex,
1686 1424 self.processingHeaderObj.dataBlocksPerFile))
1687 1425
1688 1426 return 1
1689 1427
1690 1428 def setNextFile(self):
1691 """
1692 Determina el siguiente file que sera escrito
1429 """Determina el siguiente file que sera escrito
1693 1430
1694 1431 Affected:
1695 1432 self.filename
1696 1433 self.subfolder
1697 1434 self.fp
1698 1435 self.setFile
1699 1436 self.flagIsNewFile
1700 1437
1701 1438 Return:
1702 1439 0 : Si el archivo no puede ser escrito
1703 1440 1 : Si el archivo esta listo para ser escrito
1704 1441 """
1705 1442 ext = self.ext
1706 1443 path = self.path
1707 1444
1708 1445 if self.fp != None:
1709 1446 self.fp.close()
1710 1447
1448 if not os.path.exists(path):
1449 os.mkdir(path)
1450
1711 1451 timeTuple = time.localtime(self.dataOut.utctime)
1712 1452 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
1713 1453
1714 1454 fullpath = os.path.join(path, subfolder)
1715 1455 setFile = self.setFile
1716 1456
1717 1457 if not(os.path.exists(fullpath)):
1718 1458 os.mkdir(fullpath)
1719 1459 setFile = -1 # inicializo mi contador de seteo
1720 1460 else:
1721 1461 filesList = os.listdir(fullpath)
1722 1462 if len(filesList) > 0:
1723 1463 filesList = sorted(filesList, key=str.lower)
1724 1464 filen = filesList[-1]
1725 1465 # el filename debera tener el siguiente formato
1726 1466 # 0 1234 567 89A BCDE (hex)
1727 1467 # x YYYY DDD SSS .ext
1728 1468 if isNumber(filen[8:11]):
1729 1469 # inicializo mi contador de seteo al seteo del ultimo file
1730 1470 setFile = int(filen[8:11])
1731 1471 else:
1732 1472 setFile = -1
1733 1473 else:
1734 1474 setFile = -1 # inicializo mi contador de seteo
1735 1475
1736 1476 setFile += 1
1737 1477
1738 1478 # If this is a new day it resets some values
1739 1479 if self.dataOut.datatime.date() > self.fileDate:
1740 1480 setFile = 0
1741 1481 self.nTotalBlocks = 0
1742 1482
1743 1483 filen = '{}{:04d}{:03d}{:03d}{}'.format(
1744 1484 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
1745 1485
1746 1486 filename = os.path.join(path, subfolder, filen)
1747 1487
1748 1488 fp = open(filename, 'wb')
1749 1489
1750 1490 self.blockIndex = 0
1751
1752 # guardando atributos
1753 1491 self.filename = filename
1754 1492 self.subfolder = subfolder
1755 1493 self.fp = fp
1756 1494 self.setFile = setFile
1757 1495 self.flagIsNewFile = 1
1758 1496 self.fileDate = self.dataOut.datatime.date()
1759
1760 1497 self.setFirstHeader()
1761 1498
1762 1499 print('[Writing] Opening file: %s' % self.filename)
1763 1500
1764 1501 self.__writeFirstHeader()
1765 1502
1766 1503 return 1
1767 1504
1768 1505 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1769 1506 """
1770 1507 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1771 1508
1772 1509 Inputs:
1773 1510 path : directory where data will be saved
1774 1511 profilesPerBlock : number of profiles per block
1775 1512 set : initial file set
1776 1513 datatype : An integer number that defines data type:
1777 1514 0 : int8 (1 byte)
1778 1515 1 : int16 (2 bytes)
1779 1516 2 : int32 (4 bytes)
1780 1517 3 : int64 (8 bytes)
1781 1518 4 : float32 (4 bytes)
1782 1519 5 : double64 (8 bytes)
1783 1520
1784 1521 Return:
1785 1522 0 : Si no realizo un buen seteo
1786 1523 1 : Si realizo un buen seteo
1787 1524 """
1788 1525
1789 1526 if ext == None:
1790 1527 ext = self.ext
1791 1528
1792 1529 self.ext = ext.lower()
1793 1530
1794 1531 self.path = path
1795 1532
1796 1533 if set is None:
1797 1534 self.setFile = -1
1798 1535 else:
1799 1536 self.setFile = set - 1
1800 1537
1801 1538 self.blocksPerFile = blocksPerFile
1802
1803 1539 self.profilesPerBlock = profilesPerBlock
1804
1805 1540 self.dataOut = dataOut
1806 1541 self.fileDate = self.dataOut.datatime.date()
1807 # By default
1808 1542 self.dtype = self.dataOut.dtype
1809 1543
1810 1544 if datatype is not None:
1811 1545 self.dtype = get_numpy_dtype(datatype)
1812 1546
1813 1547 if not(self.setNextFile()):
1814 1548 print("[Writing] There isn't a next file")
1815 1549 return 0
1816 1550
1817 1551 self.setBlockDimension()
1818 1552
1819 1553 return 1
1820 1554
1821 1555 def run(self, dataOut, path, blocksPerFile=100, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1822 1556
1823 1557 if not(self.isConfig):
1824 1558
1825 1559 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock,
1826 1560 set=set, ext=ext, datatype=datatype, **kwargs)
1827 1561 self.isConfig = True
1828 1562
1829 1563 self.dataOut = dataOut
1830 1564 self.putData()
1831 return self.dataOut No newline at end of file
1565 return self.dataOut
@@ -1,675 +1,527
1 1 '''
2 2 Created on Jul 2, 2014
3 3
4 4 @author: roj-idl71
5 5 '''
6 6 import numpy
7 7
8 8 from schainpy.model.io.jroIO_base import LOCALTIME, JRODataReader, JRODataWriter
9 9 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
10 10 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
11 11 from schainpy.model.data.jrodata import Spectra
12 12 from schainpy.utils import log
13 13
14 14 @MPDecorator
15 15 class SpectraReader(JRODataReader, ProcessingUnit):
16 16 """
17 17 Esta clase permite leer datos de espectros desde archivos procesados (.pdata). La lectura
18 18 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones)
19 19 son almacenados en tres buffer's para el Self Spectra, el Cross Spectra y el DC Channel.
20 20
21 21 paresCanalesIguales * alturas * perfiles (Self Spectra)
22 22 paresCanalesDiferentes * alturas * perfiles (Cross Spectra)
23 23 canales * alturas (DC Channels)
24 24
25 25 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
26 26 RadarControllerHeader y Spectra. Los tres primeros se usan para almacenar informacion de la
27 27 cabecera de datos (metadata), y el cuarto (Spectra) para obtener y almacenar un bloque de
28 28 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
29 29
30 30 Example:
31 31 dpath = "/home/myuser/data"
32 32
33 33 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
34 34
35 35 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
36 36
37 37 readerObj = SpectraReader()
38 38
39 39 readerObj.setup(dpath, startTime, endTime)
40 40
41 41 while(True):
42 42
43 43 readerObj.getData()
44 44
45 45 print readerObj.data_spc
46 46
47 47 print readerObj.data_cspc
48 48
49 49 print readerObj.data_dc
50 50
51 51 if readerObj.flagNoMoreFiles:
52 52 break
53 53
54 54 """
55 55
56 pts2read_SelfSpectra = 0
57
58 pts2read_CrossSpectra = 0
59
60 pts2read_DCchannels = 0
61
62 ext = ".pdata"
63
64 optchar = "P"
65
66 dataOut = None
67
68 nRdChannels = None
69
70 nRdPairs = None
71
72 rdPairList = []
73
74 56 def __init__(self):#, **kwargs):
75 57 """
76 58 Inicializador de la clase SpectraReader para la lectura de datos de espectros.
77 59
78 60 Inputs:
79 61 dataOut : Objeto de la clase Spectra. Este objeto sera utilizado para
80 62 almacenar un perfil de datos cada vez que se haga un requerimiento
81 63 (getData). El perfil sera obtenido a partir del buffer de datos,
82 64 si el buffer esta vacio se hara un nuevo proceso de lectura de un
83 65 bloque de datos.
84 66 Si este parametro no es pasado se creara uno internamente.
85 67
86 68 Affected:
87 69 self.dataOut
88 70
89 71 Return : None
90 72 """
91 73
92 #Eliminar de la base la herencia
93 ProcessingUnit.__init__(self)#, **kwargs)
94
74 ProcessingUnit.__init__(self)
95 75
96 76 self.pts2read_SelfSpectra = 0
97
98 77 self.pts2read_CrossSpectra = 0
99
100 self.pts2read_DCchannels = 0
101
102 self.datablock = None
103
104 self.utc = None
105
78 self.pts2read_DCchannels = 0
106 79 self.ext = ".pdata"
107
108 80 self.optchar = "P"
109
110 81 self.basicHeaderObj = BasicHeader(LOCALTIME)
111
112 82 self.systemHeaderObj = SystemHeader()
113
114 83 self.radarControllerHeaderObj = RadarControllerHeader()
115
116 84 self.processingHeaderObj = ProcessingHeader()
117
118 self.online = 0
119
120 self.fp = None
121
122 self.idFile = None
123
124 self.dtype = None
125
126 self.fileSizeByHeader = None
127
128 self.filenameList = []
129
130 self.filename = None
131
132 self.fileSize = None
133
134 self.firstHeaderSize = 0
135
136 self.basicHeaderSize = 24
137
138 self.pathList = []
139
140 85 self.lastUTTime = 0
141
142 86 self.maxTimeStep = 30
143
144 self.flagNoMoreFiles = 0
145
146 self.set = 0
147
148 self.path = None
149
150 self.delay = 60 #seconds
151
152 self.nTries = 3 #quantity tries
153
154 self.nFiles = 3 #number of files for searching
155
156 self.nReadBlocks = 0
157
158 self.flagIsNewFile = 1
159
160 self.__isFirstTimeOnline = 1
161
162
163 self.flagDiscontinuousBlock = 0
164
165 self.flagIsNewBlock = 0
166
167 self.nTotalBlocks = 0
168
169 self.blocksize = 0
170
171 self.dataOut = self.createObjByDefault()
172
173 self.profileIndex = 1 #Always
174
87 self.dataOut = Spectra()
88 self.profileIndex = 1
89 self.nRdChannels = None
90 self.nRdPairs = None
91 self.rdPairList = []
175 92
176 93 def createObjByDefault(self):
177 94
178 95 dataObj = Spectra()
179 96
180 97 return dataObj
181 98
182 99 def __hasNotDataInBuffer(self):
183 100 return 1
184 101
185 102
186 103 def getBlockDimension(self):
187 104 """
188 105 Obtiene la cantidad de puntos a leer por cada bloque de datos
189 106
190 107 Affected:
191 108 self.nRdChannels
192 109 self.nRdPairs
193 110 self.pts2read_SelfSpectra
194 111 self.pts2read_CrossSpectra
195 112 self.pts2read_DCchannels
196 113 self.blocksize
197 114 self.dataOut.nChannels
198 115 self.dataOut.nPairs
199 116
200 117 Return:
201 118 None
202 119 """
203 120 self.nRdChannels = 0
204 121 self.nRdPairs = 0
205 122 self.rdPairList = []
206 123
207 124 for i in range(0, self.processingHeaderObj.totalSpectra*2, 2):
208 125 if self.processingHeaderObj.spectraComb[i] == self.processingHeaderObj.spectraComb[i+1]:
209 126 self.nRdChannels = self.nRdChannels + 1 #par de canales iguales
210 127 else:
211 128 self.nRdPairs = self.nRdPairs + 1 #par de canales diferentes
212 129 self.rdPairList.append((self.processingHeaderObj.spectraComb[i], self.processingHeaderObj.spectraComb[i+1]))
213 130
214 131 pts2read = self.processingHeaderObj.nHeights * self.processingHeaderObj.profilesPerBlock
215 132
216 133 self.pts2read_SelfSpectra = int(self.nRdChannels * pts2read)
217 134 self.blocksize = self.pts2read_SelfSpectra
218 135
219 136 if self.processingHeaderObj.flag_cspc:
220 137 self.pts2read_CrossSpectra = int(self.nRdPairs * pts2read)
221 138 self.blocksize += self.pts2read_CrossSpectra
222 139
223 140 if self.processingHeaderObj.flag_dc:
224 141 self.pts2read_DCchannels = int(self.systemHeaderObj.nChannels * self.processingHeaderObj.nHeights)
225 142 self.blocksize += self.pts2read_DCchannels
226 143
227 # self.blocksize = self.pts2read_SelfSpectra + self.pts2read_CrossSpectra + self.pts2read_DCchannels
228
229
230 144 def readBlock(self):
231 145 """
232 146 Lee el bloque de datos desde la posicion actual del puntero del archivo
233 147 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
234 148 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
235 149 es seteado a 0
236 150
237 151 Return: None
238 152
239 153 Variables afectadas:
240 154
241 155 self.flagIsNewFile
242 156 self.flagIsNewBlock
243 157 self.nTotalBlocks
244 158 self.data_spc
245 159 self.data_cspc
246 160 self.data_dc
247 161
248 162 Exceptions:
249 163 Si un bloque leido no es un bloque valido
250 164 """
251 blockOk_flag = False
165
252 166 fpointer = self.fp.tell()
253 167
254 168 spc = numpy.fromfile( self.fp, self.dtype[0], self.pts2read_SelfSpectra )
255 169 spc = spc.reshape( (self.nRdChannels, self.processingHeaderObj.nHeights, self.processingHeaderObj.profilesPerBlock) ) #transforma a un arreglo 3D
256 170
257 171 if self.processingHeaderObj.flag_cspc:
258 172 cspc = numpy.fromfile( self.fp, self.dtype, self.pts2read_CrossSpectra )
259 173 cspc = cspc.reshape( (self.nRdPairs, self.processingHeaderObj.nHeights, self.processingHeaderObj.profilesPerBlock) ) #transforma a un arreglo 3D
260 174
261 175 if self.processingHeaderObj.flag_dc:
262 176 dc = numpy.fromfile( self.fp, self.dtype, self.pts2read_DCchannels ) #int(self.processingHeaderObj.nHeights*self.systemHeaderObj.nChannels) )
263 177 dc = dc.reshape( (self.systemHeaderObj.nChannels, self.processingHeaderObj.nHeights) ) #transforma a un arreglo 2D
264 178
265
266 179 if not self.processingHeaderObj.shif_fft:
267 180 #desplaza a la derecha en el eje 2 determinadas posiciones
268 181 shift = int(self.processingHeaderObj.profilesPerBlock/2)
269 182 spc = numpy.roll( spc, shift , axis=2 )
270 183
271 184 if self.processingHeaderObj.flag_cspc:
272 185 #desplaza a la derecha en el eje 2 determinadas posiciones
273 186 cspc = numpy.roll( cspc, shift, axis=2 )
274 187
275 188 #Dimensions : nChannels, nProfiles, nSamples
276 189 spc = numpy.transpose( spc, (0,2,1) )
277 190 self.data_spc = spc
278 191
279 192 if self.processingHeaderObj.flag_cspc:
280 193 cspc = numpy.transpose( cspc, (0,2,1) )
281 194 self.data_cspc = cspc['real'] + cspc['imag']*1j
282 195 else:
283 196 self.data_cspc = None
284 197
285 198 if self.processingHeaderObj.flag_dc:
286 199 self.data_dc = dc['real'] + dc['imag']*1j
287 200 else:
288 201 self.data_dc = None
289 202
290 203 self.flagIsNewFile = 0
291 204 self.flagIsNewBlock = 1
292 205
293 206 self.nTotalBlocks += 1
294 207 self.nReadBlocks += 1
295 208
296 209 return 1
297 210
298 211 def getFirstHeader(self):
299 212
300 213 self.getBasicHeader()
301
302 214 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
303
304 215 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
305
306 # self.dataOut.ippSeconds = self.ippSeconds
307
308 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt * self.processingHeaderObj.nIncohInt * self.processingHeaderObj.profilesPerBlock
309
310 216 self.dataOut.dtype = self.dtype
311
312 # self.dataOut.nPairs = self.nPairs
313
314 217 self.dataOut.pairsList = self.rdPairList
315
316 218 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
317
318 219 self.dataOut.nFFTPoints = self.processingHeaderObj.profilesPerBlock
319
320 220 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
321
322 221 self.dataOut.nIncohInt = self.processingHeaderObj.nIncohInt
323
324 222 xf = self.processingHeaderObj.firstHeight + self.processingHeaderObj.nHeights*self.processingHeaderObj.deltaHeight
325
326 223 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.firstHeight, xf, self.processingHeaderObj.deltaHeight)
327
328 224 self.dataOut.channelList = list(range(self.systemHeaderObj.nChannels))
329
330 225 self.dataOut.flagShiftFFT = True #Data is always shifted
331
332 226 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode #asumo q la data no esta decodificada
333
334 227 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip #asumo q la data esta sin flip
335 228
336 229 def getData(self):
337 230 """
338 231 First method to execute before "RUN" is called.
339 232
340 233 Copia el buffer de lectura a la clase "Spectra",
341 234 con todos los parametros asociados a este (metadata). cuando no hay datos en el buffer de
342 235 lectura es necesario hacer una nueva lectura de los bloques de datos usando "readNextBlock"
343 236
344 237 Return:
345 238 0 : Si no hay mas archivos disponibles
346 239 1 : Si hizo una buena copia del buffer
347 240
348 241 Affected:
349 242 self.dataOut
350
351 243 self.flagDiscontinuousBlock
352 244 self.flagIsNewBlock
353 245 """
354 246
355 247 if self.flagNoMoreFiles:
356 248 self.dataOut.flagNoData = True
357 249 return 0
358 250
359 251 self.flagDiscontinuousBlock = 0
360 252 self.flagIsNewBlock = 0
361 253
362 254 if self.__hasNotDataInBuffer():
363 255
364 256 if not( self.readNextBlock() ):
365 257 self.dataOut.flagNoData = True
366 258 return 0
367 259
368 260 #data es un numpy array de 3 dmensiones (perfiles, alturas y canales)
369 261
370 262 if self.data_spc is None:
371 263 self.dataOut.flagNoData = True
372 264 return 0
373 265
374 266 self.getBasicHeader()
375
376 267 self.getFirstHeader()
377
378 268 self.dataOut.data_spc = self.data_spc
379
380 269 self.dataOut.data_cspc = self.data_cspc
381
382 270 self.dataOut.data_dc = self.data_dc
383
384 271 self.dataOut.flagNoData = False
385
386 272 self.dataOut.realtime = self.online
387 273
388 274 return self.dataOut.data_spc
275
276
389 277 @MPDecorator
390 278 class SpectraWriter(JRODataWriter, Operation):
391 279
392 280 """
393 281 Esta clase permite escribir datos de espectros a archivos procesados (.pdata). La escritura
394 282 de los datos siempre se realiza por bloques.
395 283 """
396 284
397 ext = ".pdata"
398
399 optchar = "P"
400
401 shape_spc_Buffer = None
402
403 shape_cspc_Buffer = None
404
405 shape_dc_Buffer = None
406
407 data_spc = None
408
409 data_cspc = None
410
411 data_dc = None
412
413 285 def __init__(self):
414 286 """
415 287 Inicializador de la clase SpectraWriter para la escritura de datos de espectros.
416 288
417 289 Affected:
418 290 self.dataOut
419 291 self.basicHeaderObj
420 292 self.systemHeaderObj
421 293 self.radarControllerHeaderObj
422 294 self.processingHeaderObj
423 295
424 296 Return: None
425 297 """
426 298
427 299 Operation.__init__(self)
428 300
429 self.nTotalBlocks = 0
430
301 self.ext = ".pdata"
302 self.optchar = "P"
303 self.shape_spc_Buffer = None
304 self.shape_cspc_Buffer = None
305 self.shape_dc_Buffer = None
431 306 self.data_spc = None
432
433 307 self.data_cspc = None
434
435 308 self.data_dc = None
436
437 self.fp = None
438
439 self.flagIsNewFile = 1
440
441 self.nTotalBlocks = 0
442
443 self.flagIsNewBlock = 0
444
445 309 self.setFile = None
446
447 self.dtype = None
448
449 self.path = None
450
451 310 self.noMoreFiles = 0
452
453 self.filename = None
454
455 311 self.basicHeaderObj = BasicHeader(LOCALTIME)
456
457 312 self.systemHeaderObj = SystemHeader()
458
459 313 self.radarControllerHeaderObj = RadarControllerHeader()
460
461 314 self.processingHeaderObj = ProcessingHeader()
462 315
463
464 316 def hasAllDataInBuffer(self):
465 317 return 1
466 318
467 319
468 320 def setBlockDimension(self):
469 321 """
470 322 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
471 323
472 324 Affected:
473 325 self.shape_spc_Buffer
474 326 self.shape_cspc_Buffer
475 327 self.shape_dc_Buffer
476 328
477 329 Return: None
478 330 """
479 331 self.shape_spc_Buffer = (self.dataOut.nChannels,
480 332 self.processingHeaderObj.nHeights,
481 333 self.processingHeaderObj.profilesPerBlock)
482 334
483 335 self.shape_cspc_Buffer = (self.dataOut.nPairs,
484 336 self.processingHeaderObj.nHeights,
485 337 self.processingHeaderObj.profilesPerBlock)
486 338
487 339 self.shape_dc_Buffer = (self.dataOut.nChannels,
488 340 self.processingHeaderObj.nHeights)
489 341
490 342
491 343 def writeBlock(self):
492 344 """processingHeaderObj
493 345 Escribe el buffer en el file designado
494 346
495 347 Affected:
496 348 self.data_spc
497 349 self.data_cspc
498 350 self.data_dc
499 351 self.flagIsNewFile
500 352 self.flagIsNewBlock
501 353 self.nTotalBlocks
502 354 self.nWriteBlocks
503 355
504 356 Return: None
505 357 """
506 358
507 359 spc = numpy.transpose( self.data_spc, (0,2,1) )
508 360 if not self.processingHeaderObj.shif_fft:
509 361 spc = numpy.roll( spc, self.processingHeaderObj.profilesPerBlock/2, axis=2 ) #desplaza a la derecha en el eje 2 determinadas posiciones
510 362 data = spc.reshape((-1))
511 363 data = data.astype(self.dtype[0])
512 364 data.tofile(self.fp)
513 365
514 366 if self.data_cspc is not None:
515 367
516 368 cspc = numpy.transpose( self.data_cspc, (0,2,1) )
517 369 data = numpy.zeros( numpy.shape(cspc), self.dtype )
518 370 #print 'data.shape', self.shape_cspc_Buffer
519 371 if not self.processingHeaderObj.shif_fft:
520 372 cspc = numpy.roll( cspc, self.processingHeaderObj.profilesPerBlock/2, axis=2 ) #desplaza a la derecha en el eje 2 determinadas posiciones
521 373 data['real'] = cspc.real
522 374 data['imag'] = cspc.imag
523 375 data = data.reshape((-1))
524 376 data.tofile(self.fp)
525 377
526 378 if self.data_dc is not None:
527 379
528 380 dc = self.data_dc
529 381 data = numpy.zeros( numpy.shape(dc), self.dtype )
530 382 data['real'] = dc.real
531 383 data['imag'] = dc.imag
532 384 data = data.reshape((-1))
533 385 data.tofile(self.fp)
534 386
535 387 # self.data_spc.fill(0)
536 388 #
537 389 # if self.data_dc is not None:
538 390 # self.data_dc.fill(0)
539 391 #
540 392 # if self.data_cspc is not None:
541 393 # self.data_cspc.fill(0)
542 394
543 395 self.flagIsNewFile = 0
544 396 self.flagIsNewBlock = 1
545 397 self.nTotalBlocks += 1
546 398 self.nWriteBlocks += 1
547 399 self.blockIndex += 1
548 400
549 401 # print "[Writing] Block = %d04" %self.blockIndex
550 402
551 403 def putData(self):
552 404 """
553 405 Setea un bloque de datos y luego los escribe en un file
554 406
555 407 Affected:
556 408 self.data_spc
557 409 self.data_cspc
558 410 self.data_dc
559 411
560 412 Return:
561 413 0 : Si no hay data o no hay mas files que puedan escribirse
562 414 1 : Si se escribio la data de un bloque en un file
563 415 """
564 416
565 417 if self.dataOut.flagNoData:
566 418 return 0
567 419
568 420 self.flagIsNewBlock = 0
569 421
570 422 if self.dataOut.flagDiscontinuousBlock:
571 423 self.data_spc.fill(0)
572 424 if self.dataOut.data_cspc is not None:
573 425 self.data_cspc.fill(0)
574 426 if self.dataOut.data_dc is not None:
575 427 self.data_dc.fill(0)
576 428 self.setNextFile()
577 429
578 430 if self.flagIsNewFile == 0:
579 431 self.setBasicHeader()
580 432
581 433 self.data_spc = self.dataOut.data_spc.copy()
582 434
583 435 if self.dataOut.data_cspc is not None:
584 436 self.data_cspc = self.dataOut.data_cspc.copy()
585 437
586 438 if self.dataOut.data_dc is not None:
587 439 self.data_dc = self.dataOut.data_dc.copy()
588 440
589 441 # #self.processingHeaderObj.dataBlocksPerFile)
590 442 if self.hasAllDataInBuffer():
591 443 # self.setFirstHeader()
592 444 self.writeNextBlock()
593 445
594 446 def __getBlockSize(self):
595 447 '''
596 448 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Spectra
597 449 '''
598 450
599 451 dtype_width = self.getDtypeWidth()
600 452
601 453 pts2write = self.dataOut.nHeights * self.dataOut.nFFTPoints
602 454
603 455 pts2write_SelfSpectra = int(self.dataOut.nChannels * pts2write)
604 456 blocksize = (pts2write_SelfSpectra*dtype_width)
605 457
606 458 if self.dataOut.data_cspc is not None:
607 459 pts2write_CrossSpectra = int(self.dataOut.nPairs * pts2write)
608 460 blocksize += (pts2write_CrossSpectra*dtype_width*2)
609 461
610 462 if self.dataOut.data_dc is not None:
611 463 pts2write_DCchannels = int(self.dataOut.nChannels * self.dataOut.nHeights)
612 464 blocksize += (pts2write_DCchannels*dtype_width*2)
613 465
614 466 # blocksize = blocksize #* datatypeValue * 2 #CORREGIR ESTO
615 467
616 468 return blocksize
617 469
618 470 def setFirstHeader(self):
619 471
620 472 """
621 473 Obtiene una copia del First Header
622 474
623 475 Affected:
624 476 self.systemHeaderObj
625 477 self.radarControllerHeaderObj
626 478 self.dtype
627 479
628 480 Return:
629 481 None
630 482 """
631 483
632 484 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
633 485 self.systemHeaderObj.nChannels = self.dataOut.nChannels
634 486 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
635 487
636 488 self.processingHeaderObj.dtype = 1 # Spectra
637 489 self.processingHeaderObj.blockSize = self.__getBlockSize()
638 490 self.processingHeaderObj.profilesPerBlock = self.dataOut.nFFTPoints
639 491 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
640 492 self.processingHeaderObj.nWindows = 1 #podria ser 1 o self.dataOut.processingHeaderObj.nWindows
641 493 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt# Se requiere para determinar el valor de timeInterval
642 494 self.processingHeaderObj.nIncohInt = self.dataOut.nIncohInt
643 495 self.processingHeaderObj.totalSpectra = self.dataOut.nPairs + self.dataOut.nChannels
644 496 self.processingHeaderObj.shif_fft = self.dataOut.flagShiftFFT
645 497
646 498 if self.processingHeaderObj.totalSpectra > 0:
647 499 channelList = []
648 500 for channel in range(self.dataOut.nChannels):
649 501 channelList.append(channel)
650 502 channelList.append(channel)
651 503
652 504 pairsList = []
653 505 if self.dataOut.nPairs > 0:
654 506 for pair in self.dataOut.pairsList:
655 507 pairsList.append(pair[0])
656 508 pairsList.append(pair[1])
657 509
658 510 spectraComb = channelList + pairsList
659 511 spectraComb = numpy.array(spectraComb, dtype="u1")
660 512 self.processingHeaderObj.spectraComb = spectraComb
661 513
662 514 if self.dataOut.code is not None:
663 515 self.processingHeaderObj.code = self.dataOut.code
664 516 self.processingHeaderObj.nCode = self.dataOut.nCode
665 517 self.processingHeaderObj.nBaud = self.dataOut.nBaud
666 518
667 519 if self.processingHeaderObj.nWindows != 0:
668 520 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
669 521 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
670 522 self.processingHeaderObj.nHeights = self.dataOut.nHeights
671 523 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
672 524
673 525 self.processingHeaderObj.processFlags = self.getProcessFlags()
674 526
675 527 self.setBasicHeader() No newline at end of file
@@ -1,754 +1,680
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 import zmq
14 14 import tempfile
15 15 from io import StringIO
16 16 # from _sha import blocksize
17 17
18 18 @MPDecorator
19 19 class VoltageReader(JRODataReader, ProcessingUnit):
20 20 """
21 21 Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura
22 22 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones:
23 23 perfiles*alturas*canales) son almacenados en la variable "buffer".
24 24
25 25 perfiles * alturas * canales
26 26
27 27 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
28 28 RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la
29 29 cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de
30 30 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
31 31
32 32 Example:
33 33
34 34 dpath = "/home/myuser/data"
35 35
36 36 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
37 37
38 38 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
39 39
40 40 readerObj = VoltageReader()
41 41
42 42 readerObj.setup(dpath, startTime, endTime)
43 43
44 44 while(True):
45 45
46 46 #to get one profile
47 47 profile = readerObj.getData()
48 48
49 49 #print the profile
50 50 print profile
51 51
52 52 #If you want to see all datablock
53 53 print readerObj.datablock
54 54
55 55 if readerObj.flagNoMoreFiles:
56 56 break
57 57
58 58 """
59 59
60 ext = ".r"
61
62 optchar = "D"
63 dataOut = None
64
65 def __init__(self):#, **kwargs):
60 def __init__(self):
66 61 """
67 62 Inicializador de la clase VoltageReader para la lectura de datos de voltage.
68 63
69 64 Input:
70 65 dataOut : Objeto de la clase Voltage. Este objeto sera utilizado para
71 66 almacenar un perfil de datos cada vez que se haga un requerimiento
72 67 (getData). El perfil sera obtenido a partir del buffer de datos,
73 68 si el buffer esta vacio se hara un nuevo proceso de lectura de un
74 69 bloque de datos.
75 70 Si este parametro no es pasado se creara uno internamente.
76 71
77 72 Variables afectadas:
78 73 self.dataOut
79 74
80 75 Return:
81 76 None
82 77 """
83 78
84 ProcessingUnit.__init__(self)#, **kwargs)
85
86 self.isConfig = False
87
88 self.datablock = None
89
90 self.utc = 0
91
79 ProcessingUnit.__init__(self)
80
92 81 self.ext = ".r"
93
94 82 self.optchar = "D"
95
96 83 self.basicHeaderObj = BasicHeader(LOCALTIME)
97
98 84 self.systemHeaderObj = SystemHeader()
99
100 85 self.radarControllerHeaderObj = RadarControllerHeader()
101
102 86 self.processingHeaderObj = ProcessingHeader()
103
104 self.online = 0
105
106 self.fp = None
107
108 self.idFile = None
109
110 self.dtype = None
111
112 self.fileSizeByHeader = None
113
114 self.filenameList = []
115
116 self.filename = None
117
118 self.fileSize = None
119
120 self.firstHeaderSize = 0
121
122 self.basicHeaderSize = 24
123
124 self.pathList = []
125
126 self.filenameList = []
127
128 87 self.lastUTTime = 0
129
130 self.maxTimeStep = 30
131
132 self.flagNoMoreFiles = 0
133
134 self.set = 0
135
136 self.path = None
137
138 self.profileIndex = 2**32 - 1
139
140 self.delay = 3 # seconds
141
142 self.nTries = 3 # quantity tries
143
144 self.nFiles = 3 # number of files for searching
145
146 self.nReadBlocks = 0
147
148 self.flagIsNewFile = 1
149
150 self.__isFirstTimeOnline = 1
151
152 # self.ippSeconds = 0
153
154 self.flagDiscontinuousBlock = 0
155
156 self.flagIsNewBlock = 0
157
158 self.nTotalBlocks = 0
159
160 self.blocksize = 0
161
162 self.dataOut = self.createObjByDefault()
163
164 self.nTxs = 1
165
166 self.txIndex = 0
88 self.profileIndex = 2**32 - 1
89 self.dataOut = Voltage()
90 self.selBlocksize = None
91 self.selBlocktime = None
167 92
168 93 def createObjByDefault(self):
169 94
170 95 dataObj = Voltage()
171 96
172 97 return dataObj
173 98
174 99 def __hasNotDataInBuffer(self):
175 100
176 101 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock * self.nTxs:
177 102 return 1
178 103
179 104 return 0
180 105
181 106 def getBlockDimension(self):
182 107 """
183 108 Obtiene la cantidad de puntos a leer por cada bloque de datos
184 109
185 110 Affected:
186 111 self.blocksize
187 112
188 113 Return:
189 114 None
190 115 """
191 116 pts2read = self.processingHeaderObj.profilesPerBlock * \
192 117 self.processingHeaderObj.nHeights * self.systemHeaderObj.nChannels
193 118 self.blocksize = pts2read
194 119
195 120 def readBlock(self):
196 121 """
197 122 readBlock lee el bloque de datos desde la posicion actual del puntero del archivo
198 123 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
199 124 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
200 125 es seteado a 0
201 126
202 127 Inputs:
203 128 None
204 129
205 130 Return:
206 131 None
207 132
208 133 Affected:
209 134 self.profileIndex
210 135 self.datablock
211 136 self.flagIsNewFile
212 137 self.flagIsNewBlock
213 138 self.nTotalBlocks
214 139
215 140 Exceptions:
216 141 Si un bloque leido no es un bloque valido
217 142 """
218 143
219 144 # if self.server is not None:
220 145 # self.zBlock = self.receiver.recv()
221 146 # self.zHeader = self.zBlock[:24]
222 147 # self.zDataBlock = self.zBlock[24:]
223 148 # junk = numpy.fromstring(self.zDataBlock, numpy.dtype([('real','<i4'),('imag','<i4')]))
224 149 # self.processingHeaderObj.profilesPerBlock = 240
225 150 # self.processingHeaderObj.nHeights = 248
226 151 # self.systemHeaderObj.nChannels
227 152 # else:
228 153 current_pointer_location = self.fp.tell()
229 154 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
230 155
231 156 try:
232 157 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
233 158 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
234 159 except:
235 160 # print "The read block (%3d) has not enough data" %self.nReadBlocks
236 161
237 162 if self.waitDataBlock(pointer_location=current_pointer_location):
238 163 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
239 164 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
240 165 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
241 166 # return 0
242 167
243 168 # Dimensions : nChannels, nProfiles, nSamples
244 169
245 170 junk = numpy.transpose(junk, (2, 0, 1))
246 171 self.datablock = junk['real'] + junk['imag'] * 1j
247 172
248 173 self.profileIndex = 0
249 174
250 175 self.flagIsNewFile = 0
251 176 self.flagIsNewBlock = 1
252 177
253 178 self.nTotalBlocks += 1
254 179 self.nReadBlocks += 1
255 180
256 181 return 1
257 182
258 183 def getFirstHeader(self):
259 184
260 185 self.getBasicHeader()
261 186
262 187 self.dataOut.processingHeaderObj = self.processingHeaderObj.copy()
263 188
264 189 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
265 190
266 191 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
267 192
268 193 if self.nTxs > 1:
269 194 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
270 195 # Time interval and code are propierties of dataOut. Its value depends of radarControllerHeaderObj.
271 196
272 197 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt
273 198 #
274 199 # if self.radarControllerHeaderObj.code is not None:
275 200 #
276 201 # self.dataOut.nCode = self.radarControllerHeaderObj.nCode
277 202 #
278 203 # self.dataOut.nBaud = self.radarControllerHeaderObj.nBaud
279 204 #
280 205 # self.dataOut.code = self.radarControllerHeaderObj.code
281 206
282 207 self.dataOut.dtype = self.dtype
283 208
284 209 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
285 210
286 211 self.dataOut.heightList = numpy.arange(
287 212 self.processingHeaderObj.nHeights) * self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
288 213
289 214 self.dataOut.channelList = list(range(self.systemHeaderObj.nChannels))
290 215
291 216 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
292 217
293 218 # asumo q la data no esta decodificada
294 219 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode
295 220
296 221 # asumo q la data no esta sin flip
297 222 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip
298 223
299 224 self.dataOut.flagShiftFFT = self.processingHeaderObj.shif_fft
300 225
301 226 def reshapeData(self):
302 227
303 228 if self.nTxs < 0:
304 229 return
305 230
306 231 if self.nTxs == 1:
307 232 return
308 233
309 234 if self.nTxs < 1 and self.processingHeaderObj.profilesPerBlock % (1. / self.nTxs) != 0:
310 235 raise ValueError("1./nTxs (=%f), should be a multiple of nProfiles (=%d)" % (
311 236 1. / self.nTxs, self.processingHeaderObj.profilesPerBlock))
312 237
313 238 if self.nTxs > 1 and self.processingHeaderObj.nHeights % self.nTxs != 0:
314 239 raise ValueError("nTxs (=%d), should be a multiple of nHeights (=%d)" % (
315 240 self.nTxs, self.processingHeaderObj.nHeights))
316 241
317 242 self.datablock = self.datablock.reshape(
318 243 (self.systemHeaderObj.nChannels, self.processingHeaderObj.profilesPerBlock * self.nTxs, int(self.processingHeaderObj.nHeights / self.nTxs)))
319 244
320 245 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock * self.nTxs
321 246 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights / self.nTxs) * \
322 247 self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
323 248 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
324 249
325 250 return
326 251
327 252 def readFirstHeaderFromServer(self):
328 253
329 254 self.getFirstHeader()
330 255
331 256 self.firstHeaderSize = self.basicHeaderObj.size
332 257
333 258 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
334 259 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
335 260 if datatype == 0:
336 261 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
337 262 elif datatype == 1:
338 263 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
339 264 elif datatype == 2:
340 265 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
341 266 elif datatype == 3:
342 267 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
343 268 elif datatype == 4:
344 269 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
345 270 elif datatype == 5:
346 271 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
347 272 else:
348 273 raise ValueError('Data type was not defined')
349 274
350 275 self.dtype = datatype_str
351 276 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
352 277 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
353 278 self.firstHeaderSize + self.basicHeaderSize * \
354 279 (self.processingHeaderObj.dataBlocksPerFile - 1)
355 280 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
356 281 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
357 282 self.getBlockDimension()
358 283
359 284 def getFromServer(self):
360 285 self.flagDiscontinuousBlock = 0
361 286 self.profileIndex = 0
362 287 self.flagIsNewBlock = 1
363 288 self.dataOut.flagNoData = False
364 289 self.nTotalBlocks += 1
365 290 self.nReadBlocks += 1
366 291 self.blockPointer = 0
367 292
368 293 block = self.receiver.recv()
369 294
370 295 self.basicHeaderObj.read(block[self.blockPointer:])
371 296 self.blockPointer += self.basicHeaderObj.length
372 297 self.systemHeaderObj.read(block[self.blockPointer:])
373 298 self.blockPointer += self.systemHeaderObj.length
374 299 self.radarControllerHeaderObj.read(block[self.blockPointer:])
375 300 self.blockPointer += self.radarControllerHeaderObj.length
376 301 self.processingHeaderObj.read(block[self.blockPointer:])
377 302 self.blockPointer += self.processingHeaderObj.length
378 303 self.readFirstHeaderFromServer()
379 304
380 305 timestamp = self.basicHeaderObj.get_datatime()
381 306 print('[Reading] - Block {} - {}'.format(self.nTotalBlocks, timestamp))
382 307 current_pointer_location = self.blockPointer
383 308 junk = numpy.fromstring(
384 309 block[self.blockPointer:], self.dtype, self.blocksize)
385 310
386 311 try:
387 312 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
388 313 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
389 314 except:
390 315 # print "The read block (%3d) has not enough data" %self.nReadBlocks
391 316 if self.waitDataBlock(pointer_location=current_pointer_location):
392 317 junk = numpy.fromstring(
393 318 block[self.blockPointer:], self.dtype, self.blocksize)
394 319 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
395 320 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
396 321 # return 0
397 322
398 323 # Dimensions : nChannels, nProfiles, nSamples
399 324
400 325 junk = numpy.transpose(junk, (2, 0, 1))
401 326 self.datablock = junk['real'] + junk['imag'] * 1j
402 327 self.profileIndex = 0
403 328 if self.selBlocksize == None:
404 329 self.selBlocksize = self.dataOut.nProfiles
405 330 if self.selBlocktime != None:
406 331 if self.dataOut.nCohInt is not None:
407 332 nCohInt = self.dataOut.nCohInt
408 333 else:
409 334 nCohInt = 1
410 335 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
411 336 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
412 337 self.dataOut.data = self.datablock[:,
413 338 self.profileIndex:self.profileIndex + self.selBlocksize, :]
414 339 datasize = self.dataOut.data.shape[1]
415 340 if datasize < self.selBlocksize:
416 341 buffer = numpy.zeros(
417 342 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
418 343 buffer[:, :datasize, :] = self.dataOut.data
419 344 self.dataOut.data = buffer
420 345 self.profileIndex = blockIndex
421 346
422 347 self.dataOut.flagDataAsBlock = True
423 348 self.flagIsNewBlock = 1
424 349 self.dataOut.realtime = self.online
425 350
426 351 return self.dataOut.data
427 352
428 353 def getData(self):
429 354 """
430 355 getData obtiene una unidad de datos del buffer de lectura, un perfil, y la copia al objeto self.dataOut
431 356 del tipo "Voltage" con todos los parametros asociados a este (metadata). cuando no hay datos
432 357 en el buffer de lectura es necesario hacer una nueva lectura de los bloques de datos usando
433 358 "readNextBlock"
434 359
435 360 Ademas incrementa el contador del buffer "self.profileIndex" en 1.
436 361
437 362 Return:
438 363
439 364 Si el flag self.getByBlock ha sido seteado el bloque completo es copiado a self.dataOut y el self.profileIndex
440 365 es igual al total de perfiles leidos desde el archivo.
441 366
442 367 Si self.getByBlock == False:
443 368
444 369 self.dataOut.data = buffer[:, thisProfile, :]
445 370
446 371 shape = [nChannels, nHeis]
447 372
448 373 Si self.getByBlock == True:
449 374
450 375 self.dataOut.data = buffer[:, :, :]
451 376
452 377 shape = [nChannels, nProfiles, nHeis]
453 378
454 379 Variables afectadas:
455 380 self.dataOut
456 381 self.profileIndex
457 382
458 383 Affected:
459 384 self.dataOut
460 385 self.profileIndex
461 386 self.flagDiscontinuousBlock
462 387 self.flagIsNewBlock
463 388 """
464 389 if self.flagNoMoreFiles:
465 390 self.dataOut.flagNoData = True
466 391 return 0
467 392 self.flagDiscontinuousBlock = 0
468 393 self.flagIsNewBlock = 0
469 394 if self.__hasNotDataInBuffer():
470 395 if not(self.readNextBlock()):
471 396 return 0
472 397
473 398 self.getFirstHeader()
474 399
475 400 self.reshapeData()
476 401 if self.datablock is None:
477 402 self.dataOut.flagNoData = True
478 403 return 0
479 404
480 405 if not self.getByBlock:
481 406
482 407 """
483 408 Return profile by profile
484 409
485 410 If nTxs > 1 then one profile is divided by nTxs and number of total
486 411 blocks is increased by nTxs (nProfiles *= nTxs)
487 412 """
488 413 self.dataOut.flagDataAsBlock = False
489 414 self.dataOut.data = self.datablock[:, self.profileIndex, :]
490 415 self.dataOut.profileIndex = self.profileIndex
491 416
492 417 self.profileIndex += 1
493 418
494 419 else:
495 420 """
496 421 Return a block
497 422 """
498 423 if self.selBlocksize == None:
499 424 self.selBlocksize = self.dataOut.nProfiles
500 425 if self.selBlocktime != None:
501 426 if self.dataOut.nCohInt is not None:
502 427 nCohInt = self.dataOut.nCohInt
503 428 else:
504 429 nCohInt = 1
505 430 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
506 431 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
507 432
508 433 self.dataOut.data = self.datablock[:,
509 434 self.profileIndex:self.profileIndex + self.selBlocksize, :]
510 435 self.profileIndex += self.selBlocksize
511 436 datasize = self.dataOut.data.shape[1]
512 437
513 438 if datasize < self.selBlocksize:
514 439 buffer = numpy.zeros(
515 440 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
516 441 buffer[:, :datasize, :] = self.dataOut.data
517 442
518 443 while datasize < self.selBlocksize: # Not enough profiles to fill the block
519 444 if not(self.readNextBlock()):
520 445 return 0
521 446 self.getFirstHeader()
522 447 self.reshapeData()
523 448 if self.datablock is None:
524 449 self.dataOut.flagNoData = True
525 450 return 0
526 451 # stack data
527 452 blockIndex = self.selBlocksize - datasize
528 453 datablock1 = self.datablock[:, :blockIndex, :]
529 454
530 455 buffer[:, datasize:datasize +
531 456 datablock1.shape[1], :] = datablock1
532 457 datasize += datablock1.shape[1]
533 458
534 459 self.dataOut.data = buffer
535 460 self.profileIndex = blockIndex
536 461
537 462 self.dataOut.flagDataAsBlock = True
538 463 self.dataOut.nProfiles = self.dataOut.data.shape[1]
539 464
540 465 self.dataOut.flagNoData = False
541 466
542 467 self.getBasicHeader()
543 468
544 469 self.dataOut.realtime = self.online
545 470
546 471 return self.dataOut.data
547 472
473
548 474 @MPDecorator
549 475 class VoltageWriter(JRODataWriter, Operation):
550 476 """
551 477 Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura
552 478 de los datos siempre se realiza por bloques.
553 479 """
554 480
555 481 ext = ".r"
556 482
557 483 optchar = "D"
558 484
559 485 shapeBuffer = None
560 486
561 487 def __init__(self):#, **kwargs):
562 488 """
563 489 Inicializador de la clase VoltageWriter para la escritura de datos de espectros.
564 490
565 491 Affected:
566 492 self.dataOut
567 493
568 494 Return: None
569 495 """
570 496 Operation.__init__(self)#, **kwargs)
571 497
572 498 self.nTotalBlocks = 0
573 499
574 500 self.profileIndex = 0
575 501
576 502 self.isConfig = False
577 503
578 504 self.fp = None
579 505
580 506 self.flagIsNewFile = 1
581 507
582 508 self.blockIndex = 0
583 509
584 510 self.flagIsNewBlock = 0
585 511
586 512 self.setFile = None
587 513
588 514 self.dtype = None
589 515
590 516 self.path = None
591 517
592 518 self.filename = None
593 519
594 520 self.basicHeaderObj = BasicHeader(LOCALTIME)
595 521
596 522 self.systemHeaderObj = SystemHeader()
597 523
598 524 self.radarControllerHeaderObj = RadarControllerHeader()
599 525
600 526 self.processingHeaderObj = ProcessingHeader()
601 527
602 528 def hasAllDataInBuffer(self):
603 529 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock:
604 530 return 1
605 531 return 0
606 532
607 533 def setBlockDimension(self):
608 534 """
609 535 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
610 536
611 537 Affected:
612 538 self.shape_spc_Buffer
613 539 self.shape_cspc_Buffer
614 540 self.shape_dc_Buffer
615 541
616 542 Return: None
617 543 """
618 544 self.shapeBuffer = (self.processingHeaderObj.profilesPerBlock,
619 545 self.processingHeaderObj.nHeights,
620 546 self.systemHeaderObj.nChannels)
621 547
622 548 self.datablock = numpy.zeros((self.systemHeaderObj.nChannels,
623 549 self.processingHeaderObj.profilesPerBlock,
624 550 self.processingHeaderObj.nHeights),
625 551 dtype=numpy.dtype('complex64'))
626 552
627 553 def writeBlock(self):
628 554 """
629 555 Escribe el buffer en el file designado
630 556
631 557 Affected:
632 558 self.profileIndex
633 559 self.flagIsNewFile
634 560 self.flagIsNewBlock
635 561 self.nTotalBlocks
636 562 self.blockIndex
637 563
638 564 Return: None
639 565 """
640 566 data = numpy.zeros(self.shapeBuffer, self.dtype)
641 567
642 568 junk = numpy.transpose(self.datablock, (1, 2, 0))
643 569
644 570 data['real'] = junk.real
645 571 data['imag'] = junk.imag
646 572
647 573 data = data.reshape((-1))
648 574
649 575 data.tofile(self.fp)
650 576
651 577 self.datablock.fill(0)
652 578
653 579 self.profileIndex = 0
654 580 self.flagIsNewFile = 0
655 581 self.flagIsNewBlock = 1
656 582
657 583 self.blockIndex += 1
658 584 self.nTotalBlocks += 1
659 585
660 586 # print "[Writing] Block = %04d" %self.blockIndex
661 587
662 588 def putData(self):
663 589 """
664 590 Setea un bloque de datos y luego los escribe en un file
665 591
666 592 Affected:
667 593 self.flagIsNewBlock
668 594 self.profileIndex
669 595
670 596 Return:
671 597 0 : Si no hay data o no hay mas files que puedan escribirse
672 598 1 : Si se escribio la data de un bloque en un file
673 599 """
674 600 if self.dataOut.flagNoData:
675 601 return 0
676 602
677 603 self.flagIsNewBlock = 0
678 604
679 605 if self.dataOut.flagDiscontinuousBlock:
680 606 self.datablock.fill(0)
681 607 self.profileIndex = 0
682 608 self.setNextFile()
683 609
684 610 if self.profileIndex == 0:
685 611 self.setBasicHeader()
686 612
687 613 self.datablock[:, self.profileIndex, :] = self.dataOut.data
688 614
689 615 self.profileIndex += 1
690 616
691 617 if self.hasAllDataInBuffer():
692 618 # if self.flagIsNewFile:
693 619 self.writeNextBlock()
694 620 # self.setFirstHeader()
695 621
696 622 return 1
697 623
698 624 def __getBlockSize(self):
699 625 '''
700 626 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Voltage
701 627 '''
702 628
703 629 dtype_width = self.getDtypeWidth()
704 630
705 631 blocksize = int(self.dataOut.nHeights * self.dataOut.nChannels *
706 632 self.profilesPerBlock * dtype_width * 2)
707 633
708 634 return blocksize
709 635
710 636 def setFirstHeader(self):
711 637 """
712 638 Obtiene una copia del First Header
713 639
714 640 Affected:
715 641 self.systemHeaderObj
716 642 self.radarControllerHeaderObj
717 643 self.dtype
718 644
719 645 Return:
720 646 None
721 647 """
722 648
723 649 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
724 650 self.systemHeaderObj.nChannels = self.dataOut.nChannels
725 651 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
726 652
727 653 self.processingHeaderObj.dtype = 0 # Voltage
728 654 self.processingHeaderObj.blockSize = self.__getBlockSize()
729 655 self.processingHeaderObj.profilesPerBlock = self.profilesPerBlock
730 656 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
731 657 # podria ser 1 o self.dataOut.processingHeaderObj.nWindows
732 658 self.processingHeaderObj.nWindows = 1
733 659 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt
734 660 # Cuando la data de origen es de tipo Voltage
735 661 self.processingHeaderObj.nIncohInt = 1
736 662 # Cuando la data de origen es de tipo Voltage
737 663 self.processingHeaderObj.totalSpectra = 0
738 664
739 665 if self.dataOut.code is not None:
740 666 self.processingHeaderObj.code = self.dataOut.code
741 667 self.processingHeaderObj.nCode = self.dataOut.nCode
742 668 self.processingHeaderObj.nBaud = self.dataOut.nBaud
743 669
744 670 if self.processingHeaderObj.nWindows != 0:
745 671 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
746 672 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - \
747 673 self.dataOut.heightList[0]
748 674 self.processingHeaderObj.nHeights = self.dataOut.nHeights
749 675 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
750 676
751 677 self.processingHeaderObj.processFlags = self.getProcessFlags()
752 678
753 679 self.setBasicHeader()
754 680 No newline at end of file
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now