##// END OF EJS Templates
Fix support for ZMQ in VoltageReader
Juan C. Espinoza -
r1564:d1f6bedb3696
parent child
Show More
@@ -1,659 +1,661
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """API to create signal chain projects
5 """API to create signal chain projects
6
6
7 The API is provide through class: Project
7 The API is provide through class: Project
8 """
8 """
9
9
10 import re
10 import re
11 import sys
11 import sys
12 import ast
12 import ast
13 import datetime
13 import datetime
14 import traceback
14 import traceback
15 import time
15 import time
16 import multiprocessing
16 import multiprocessing
17 from multiprocessing import Process, Queue
17 from multiprocessing import Process, Queue
18 from threading import Thread
18 from threading import Thread
19 from xml.etree.ElementTree import ElementTree, Element, SubElement
19 from xml.etree.ElementTree import ElementTree, Element, SubElement
20
20
21 from schainpy.admin import Alarm, SchainWarning
21 from schainpy.admin import Alarm, SchainWarning
22 from schainpy.model import *
22 from schainpy.model import *
23 from schainpy.utils import log
23 from schainpy.utils import log
24
24
25 if 'darwin' in sys.platform and sys.version_info[0] == 3 and sys.version_info[1] > 7:
25 if 'darwin' in sys.platform and sys.version_info[0] == 3 and sys.version_info[1] > 7:
26 multiprocessing.set_start_method('fork')
26 multiprocessing.set_start_method('fork')
27
27
28 class ConfBase():
28 class ConfBase():
29
29
30 def __init__(self):
30 def __init__(self):
31
31
32 self.id = '0'
32 self.id = '0'
33 self.name = None
33 self.name = None
34 self.priority = None
34 self.priority = None
35 self.parameters = {}
35 self.parameters = {}
36 self.object = None
36 self.object = None
37 self.operations = []
37 self.operations = []
38
38
39 def getId(self):
39 def getId(self):
40
40
41 return self.id
41 return self.id
42
42
43 def getNewId(self):
43 def getNewId(self):
44
44
45 return int(self.id) * 10 + len(self.operations) + 1
45 return int(self.id) * 10 + len(self.operations) + 1
46
46
47 def updateId(self, new_id):
47 def updateId(self, new_id):
48
48
49 self.id = str(new_id)
49 self.id = str(new_id)
50
50
51 n = 1
51 n = 1
52 for conf in self.operations:
52 for conf in self.operations:
53 conf_id = str(int(new_id) * 10 + n)
53 conf_id = str(int(new_id) * 10 + n)
54 conf.updateId(conf_id)
54 conf.updateId(conf_id)
55 n += 1
55 n += 1
56
56
57 def getKwargs(self):
57 def getKwargs(self):
58
58
59 params = {}
59 params = {}
60
60
61 for key, value in self.parameters.items():
61 for key, value in self.parameters.items():
62 if value not in (None, '', ' '):
62 if value not in (None, '', ' '):
63 params[key] = value
63 params[key] = value
64
64
65 return params
65 return params
66
66
67 def update(self, **kwargs):
67 def update(self, **kwargs):
68
68
69 for key, value in kwargs.items():
69 for key, value in kwargs.items():
70 self.addParameter(name=key, value=value)
70 self.addParameter(name=key, value=value)
71
71
72 def addParameter(self, name, value, format=None):
72 def addParameter(self, name, value, format=None):
73 '''
73 '''
74 '''
74 '''
75
75
76 if isinstance(value, str) and re.search(r'(\d+/\d+/\d+)', value):
76 if isinstance(value, str) and re.search(r'(\d+/\d+/\d+)', value):
77 self.parameters[name] = datetime.date(*[int(x) for x in value.split('/')])
77 self.parameters[name] = datetime.date(*[int(x) for x in value.split('/')])
78 elif isinstance(value, str) and re.search(r'(\d+:\d+:\d+)', value):
78 elif isinstance(value, str) and re.search(r'(\d+:\d+:\d+)', value):
79 self.parameters[name] = datetime.time(*[int(x) for x in value.split(':')])
79 self.parameters[name] = datetime.time(*[int(x) for x in value.split(':')])
80 else:
80 else:
81 try:
81 try:
82 self.parameters[name] = ast.literal_eval(value)
82 self.parameters[name] = ast.literal_eval(value)
83 except:
83 except:
84 if isinstance(value, str) and ',' in value:
84 if isinstance(value, str) and ',' in value:
85 self.parameters[name] = value.split(',')
85 self.parameters[name] = value.split(',')
86 else:
86 else:
87 self.parameters[name] = value
87 self.parameters[name] = value
88
88
89 def getParameters(self):
89 def getParameters(self):
90
90
91 params = {}
91 params = {}
92 for key, value in self.parameters.items():
92 for key, value in self.parameters.items():
93 s = type(value).__name__
93 s = type(value).__name__
94 if s == 'date':
94 if s == 'date':
95 params[key] = value.strftime('%Y/%m/%d')
95 params[key] = value.strftime('%Y/%m/%d')
96 elif s == 'time':
96 elif s == 'time':
97 params[key] = value.strftime('%H:%M:%S')
97 params[key] = value.strftime('%H:%M:%S')
98 else:
98 else:
99 params[key] = str(value)
99 params[key] = str(value)
100
100
101 return params
101 return params
102
102
103 def makeXml(self, element):
103 def makeXml(self, element):
104
104
105 xml = SubElement(element, self.ELEMENTNAME)
105 xml = SubElement(element, self.ELEMENTNAME)
106 for label in self.xml_labels:
106 for label in self.xml_labels:
107 xml.set(label, str(getattr(self, label)))
107 xml.set(label, str(getattr(self, label)))
108
108
109 for key, value in self.getParameters().items():
109 for key, value in self.getParameters().items():
110 xml_param = SubElement(xml, 'Parameter')
110 xml_param = SubElement(xml, 'Parameter')
111 xml_param.set('name', key)
111 xml_param.set('name', key)
112 xml_param.set('value', value)
112 xml_param.set('value', value)
113
113
114 for conf in self.operations:
114 for conf in self.operations:
115 conf.makeXml(xml)
115 conf.makeXml(xml)
116
116
117 def __str__(self):
117 def __str__(self):
118
118
119 if self.ELEMENTNAME == 'Operation':
119 if self.ELEMENTNAME == 'Operation':
120 s = ' {}[id={}]\n'.format(self.name, self.id)
120 s = ' {}[id={}]\n'.format(self.name, self.id)
121 else:
121 else:
122 s = '{}[id={}, inputId={}]\n'.format(self.name, self.id, self.inputId)
122 s = '{}[id={}, inputId={}]\n'.format(self.name, self.id, self.inputId)
123
123
124 for key, value in self.parameters.items():
124 for key, value in self.parameters.items():
125 if self.ELEMENTNAME == 'Operation':
125 if self.ELEMENTNAME == 'Operation':
126 s += ' {}: {}\n'.format(key, value)
126 s += ' {}: {}\n'.format(key, value)
127 else:
127 else:
128 s += ' {}: {}\n'.format(key, value)
128 s += ' {}: {}\n'.format(key, value)
129
129
130 for conf in self.operations:
130 for conf in self.operations:
131 s += str(conf)
131 s += str(conf)
132
132
133 return s
133 return s
134
134
135 class OperationConf(ConfBase):
135 class OperationConf(ConfBase):
136
136
137 ELEMENTNAME = 'Operation'
137 ELEMENTNAME = 'Operation'
138 xml_labels = ['id', 'name']
138 xml_labels = ['id', 'name']
139
139
140 def setup(self, id, name, priority, project_id, err_queue):
140 def setup(self, id, name, priority, project_id, err_queue):
141
141
142 self.id = str(id)
142 self.id = str(id)
143 self.project_id = project_id
143 self.project_id = project_id
144 self.name = name
144 self.name = name
145 self.type = 'other'
145 self.type = 'other'
146 self.err_queue = err_queue
146 self.err_queue = err_queue
147
147
148 def readXml(self, element, project_id, err_queue):
148 def readXml(self, element, project_id, err_queue):
149
149
150 self.id = element.get('id')
150 self.id = element.get('id')
151 self.name = element.get('name')
151 self.name = element.get('name')
152 self.type = 'other'
152 self.type = 'other'
153 self.project_id = str(project_id)
153 self.project_id = str(project_id)
154 self.err_queue = err_queue
154 self.err_queue = err_queue
155
155
156 for elm in element.iter('Parameter'):
156 for elm in element.iter('Parameter'):
157 self.addParameter(elm.get('name'), elm.get('value'))
157 self.addParameter(elm.get('name'), elm.get('value'))
158
158
159 def createObject(self):
159 def createObject(self):
160
160
161 className = eval(self.name)
161 className = eval(self.name)
162
162
163 if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name or 'print' in self.name:
163 if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name or 'print' in self.name:
164 kwargs = self.getKwargs()
164 kwargs = self.getKwargs()
165 opObj = className(self.id, self.id, self.project_id, self.err_queue, **kwargs)
165 opObj = className(self.id, self.id, self.project_id, self.err_queue, **kwargs)
166 opObj.start()
166 opObj.start()
167 self.type = 'external'
167 self.type = 'external'
168 else:
168 else:
169 opObj = className()
169 opObj = className()
170
170
171 self.object = opObj
171 self.object = opObj
172 return opObj
172 return opObj
173
173
174 class ProcUnitConf(ConfBase):
174 class ProcUnitConf(ConfBase):
175
175
176 ELEMENTNAME = 'ProcUnit'
176 ELEMENTNAME = 'ProcUnit'
177 xml_labels = ['id', 'inputId', 'name']
177 xml_labels = ['id', 'inputId', 'name']
178
178
179 def setup(self, project_id, id, name, datatype, inputId, err_queue):
179 def setup(self, project_id, id, name, datatype, inputId, err_queue):
180 '''
180 '''
181 '''
181 '''
182
182
183 if datatype == None and name == None:
183 if datatype == None and name == None:
184 raise ValueError('datatype or name should be defined')
184 raise ValueError('datatype or name should be defined')
185
185
186 if name == None:
186 if name == None:
187 if 'Proc' in datatype:
187 if 'Proc' in datatype:
188 name = datatype
188 name = datatype
189 else:
189 else:
190 name = '%sProc' % (datatype)
190 name = '%sProc' % (datatype)
191
191
192 if datatype == None:
192 if datatype == None:
193 datatype = name.replace('Proc', '')
193 datatype = name.replace('Proc', '')
194
194
195 self.id = str(id)
195 self.id = str(id)
196 self.project_id = project_id
196 self.project_id = project_id
197 self.name = name
197 self.name = name
198 self.datatype = datatype
198 self.datatype = datatype
199 self.inputId = inputId
199 self.inputId = inputId
200 self.err_queue = err_queue
200 self.err_queue = err_queue
201 self.operations = []
201 self.operations = []
202 self.parameters = {}
202 self.parameters = {}
203
203
204 def removeOperation(self, id):
204 def removeOperation(self, id):
205
205
206 i = [1 if x.id == id else 0 for x in self.operations]
206 i = [1 if x.id == id else 0 for x in self.operations]
207 self.operations.pop(i.index(1))
207 self.operations.pop(i.index(1))
208
208
209 def getOperation(self, id):
209 def getOperation(self, id):
210
210
211 for conf in self.operations:
211 for conf in self.operations:
212 if conf.id == id:
212 if conf.id == id:
213 return conf
213 return conf
214
214
215 def addOperation(self, name, optype='self'):
215 def addOperation(self, name, optype='self'):
216 '''
216 '''
217 '''
217 '''
218
218
219 id = self.getNewId()
219 id = self.getNewId()
220 conf = OperationConf()
220 conf = OperationConf()
221 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
221 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
222 self.operations.append(conf)
222 self.operations.append(conf)
223
223
224 return conf
224 return conf
225
225
226 def readXml(self, element, project_id, err_queue):
226 def readXml(self, element, project_id, err_queue):
227
227
228 self.id = element.get('id')
228 self.id = element.get('id')
229 self.name = element.get('name')
229 self.name = element.get('name')
230 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
230 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
231 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
231 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
232 self.project_id = str(project_id)
232 self.project_id = str(project_id)
233 self.err_queue = err_queue
233 self.err_queue = err_queue
234 self.operations = []
234 self.operations = []
235 self.parameters = {}
235 self.parameters = {}
236
236
237 for elm in element:
237 for elm in element:
238 if elm.tag == 'Parameter':
238 if elm.tag == 'Parameter':
239 self.addParameter(elm.get('name'), elm.get('value'))
239 self.addParameter(elm.get('name'), elm.get('value'))
240 elif elm.tag == 'Operation':
240 elif elm.tag == 'Operation':
241 conf = OperationConf()
241 conf = OperationConf()
242 conf.readXml(elm, project_id, err_queue)
242 conf.readXml(elm, project_id, err_queue)
243 self.operations.append(conf)
243 self.operations.append(conf)
244
244
245 def createObjects(self):
245 def createObjects(self):
246 '''
246 '''
247 Instancia de unidades de procesamiento.
247 Instancia de unidades de procesamiento.
248 '''
248 '''
249
249
250 className = eval(self.name)
250 className = eval(self.name)
251 kwargs = self.getKwargs()
251 kwargs = self.getKwargs()
252 procUnitObj = className()
252 procUnitObj = className()
253 procUnitObj.name = self.name
253 procUnitObj.name = self.name
254 log.success('creating process...', self.name)
254 log.success('creating process...', self.name)
255
255
256 for conf in self.operations:
256 for conf in self.operations:
257
257
258 opObj = conf.createObject()
258 opObj = conf.createObject()
259
259
260 log.success('adding operation: {}, type:{}'.format(
260 log.success('adding operation: {}, type:{}'.format(
261 conf.name,
261 conf.name,
262 conf.type), self.name)
262 conf.type), self.name)
263
263
264 procUnitObj.addOperation(conf, opObj)
264 procUnitObj.addOperation(conf, opObj)
265
265
266 self.object = procUnitObj
266 self.object = procUnitObj
267
267
268 def run(self):
268 def run(self):
269 '''
269 '''
270 '''
270 '''
271
271
272 return self.object.call(**self.getKwargs())
272 return self.object.call(**self.getKwargs())
273
273
274
274
275 class ReadUnitConf(ProcUnitConf):
275 class ReadUnitConf(ProcUnitConf):
276
276
277 ELEMENTNAME = 'ReadUnit'
277 ELEMENTNAME = 'ReadUnit'
278
278
279 def __init__(self):
279 def __init__(self):
280
280
281 self.id = None
281 self.id = None
282 self.datatype = None
282 self.datatype = None
283 self.name = None
283 self.name = None
284 self.inputId = None
284 self.inputId = None
285 self.operations = []
285 self.operations = []
286 self.parameters = {}
286 self.parameters = {}
287
287
288 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
288 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
289 startTime='', endTime='', server=None, **kwargs):
289 startTime='', endTime='', server=None, topic='', **kwargs):
290
290
291 if datatype == None and name == None:
291 if datatype == None and name == None:
292 raise ValueError('datatype or name should be defined')
292 raise ValueError('datatype or name should be defined')
293 if name == None:
293 if name == None:
294 if 'Reader' in datatype:
294 if 'Reader' in datatype:
295 name = datatype
295 name = datatype
296 datatype = name.replace('Reader', '')
296 datatype = name.replace('Reader', '')
297 else:
297 else:
298 name = '{}Reader'.format(datatype)
298 name = '{}Reader'.format(datatype)
299 if datatype == None:
299 if datatype == None:
300 if 'Reader' in name:
300 if 'Reader' in name:
301 datatype = name.replace('Reader', '')
301 datatype = name.replace('Reader', '')
302 else:
302 else:
303 datatype = name
303 datatype = name
304 name = '{}Reader'.format(name)
304 name = '{}Reader'.format(name)
305
305
306 self.id = id
306 self.id = id
307 self.project_id = project_id
307 self.project_id = project_id
308 self.name = name
308 self.name = name
309 self.datatype = datatype
309 self.datatype = datatype
310 self.err_queue = err_queue
310 self.err_queue = err_queue
311
311
312 self.addParameter(name='path', value=path)
312 self.addParameter(name='path', value=path)
313 self.addParameter(name='startDate', value=startDate)
313 self.addParameter(name='startDate', value=startDate)
314 self.addParameter(name='endDate', value=endDate)
314 self.addParameter(name='endDate', value=endDate)
315 self.addParameter(name='startTime', value=startTime)
315 self.addParameter(name='startTime', value=startTime)
316 self.addParameter(name='endTime', value=endTime)
316 self.addParameter(name='endTime', value=endTime)
317 self.addParameter(name='server', value=server)
318 self.addParameter(name='topic', value=topic)
317
319
318 for key, value in kwargs.items():
320 for key, value in kwargs.items():
319 self.addParameter(name=key, value=value)
321 self.addParameter(name=key, value=value)
320
322
321
323
322 class Project(Process):
324 class Project(Process):
323 """API to create signal chain projects"""
325 """API to create signal chain projects"""
324
326
325 ELEMENTNAME = 'Project'
327 ELEMENTNAME = 'Project'
326
328
327 def __init__(self, name=''):
329 def __init__(self, name=''):
328
330
329 Process.__init__(self)
331 Process.__init__(self)
330 self.id = '1'
332 self.id = '1'
331 if name:
333 if name:
332 self.name = '{} ({})'.format(Process.__name__, name)
334 self.name = '{} ({})'.format(Process.__name__, name)
333 self.filename = None
335 self.filename = None
334 self.description = None
336 self.description = None
335 self.email = None
337 self.email = None
336 self.alarm = []
338 self.alarm = []
337 self.configurations = {}
339 self.configurations = {}
338 # self.err_queue = Queue()
340 # self.err_queue = Queue()
339 self.err_queue = None
341 self.err_queue = None
340 self.started = False
342 self.started = False
341
343
342 def getNewId(self):
344 def getNewId(self):
343
345
344 idList = list(self.configurations.keys())
346 idList = list(self.configurations.keys())
345 id = int(self.id) * 10
347 id = int(self.id) * 10
346
348
347 while True:
349 while True:
348 id += 1
350 id += 1
349
351
350 if str(id) in idList:
352 if str(id) in idList:
351 continue
353 continue
352
354
353 break
355 break
354
356
355 return str(id)
357 return str(id)
356
358
357 def updateId(self, new_id):
359 def updateId(self, new_id):
358
360
359 self.id = str(new_id)
361 self.id = str(new_id)
360
362
361 keyList = list(self.configurations.keys())
363 keyList = list(self.configurations.keys())
362 keyList.sort()
364 keyList.sort()
363
365
364 n = 1
366 n = 1
365 new_confs = {}
367 new_confs = {}
366
368
367 for procKey in keyList:
369 for procKey in keyList:
368
370
369 conf = self.configurations[procKey]
371 conf = self.configurations[procKey]
370 idProcUnit = str(int(self.id) * 10 + n)
372 idProcUnit = str(int(self.id) * 10 + n)
371 conf.updateId(idProcUnit)
373 conf.updateId(idProcUnit)
372 new_confs[idProcUnit] = conf
374 new_confs[idProcUnit] = conf
373 n += 1
375 n += 1
374
376
375 self.configurations = new_confs
377 self.configurations = new_confs
376
378
377 def setup(self, id=1, name='', description='', email=None, alarm=[]):
379 def setup(self, id=1, name='', description='', email=None, alarm=[]):
378
380
379 self.id = str(id)
381 self.id = str(id)
380 self.description = description
382 self.description = description
381 self.email = email
383 self.email = email
382 self.alarm = alarm
384 self.alarm = alarm
383 if name:
385 if name:
384 self.name = '{} ({})'.format(Process.__name__, name)
386 self.name = '{} ({})'.format(Process.__name__, name)
385
387
386 def update(self, **kwargs):
388 def update(self, **kwargs):
387
389
388 for key, value in kwargs.items():
390 for key, value in kwargs.items():
389 setattr(self, key, value)
391 setattr(self, key, value)
390
392
391 def clone(self):
393 def clone(self):
392
394
393 p = Project()
395 p = Project()
394 p.id = self.id
396 p.id = self.id
395 p.name = self.name
397 p.name = self.name
396 p.description = self.description
398 p.description = self.description
397 p.configurations = self.configurations.copy()
399 p.configurations = self.configurations.copy()
398
400
399 return p
401 return p
400
402
401 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
403 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
402
404
403 '''
405 '''
404 '''
406 '''
405
407
406 if id is None:
408 if id is None:
407 idReadUnit = self.getNewId()
409 idReadUnit = self.getNewId()
408 else:
410 else:
409 idReadUnit = str(id)
411 idReadUnit = str(id)
410
412
411 conf = ReadUnitConf()
413 conf = ReadUnitConf()
412 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
414 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
413 self.configurations[conf.id] = conf
415 self.configurations[conf.id] = conf
414
416
415 return conf
417 return conf
416
418
417 def addProcUnit(self, id=None, inputId='0', datatype=None, name=None):
419 def addProcUnit(self, id=None, inputId='0', datatype=None, name=None):
418
420
419 '''
421 '''
420 '''
422 '''
421
423
422 if id is None:
424 if id is None:
423 idProcUnit = self.getNewId()
425 idProcUnit = self.getNewId()
424 else:
426 else:
425 idProcUnit = id
427 idProcUnit = id
426
428
427 conf = ProcUnitConf()
429 conf = ProcUnitConf()
428 conf.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue)
430 conf.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue)
429 self.configurations[conf.id] = conf
431 self.configurations[conf.id] = conf
430
432
431 return conf
433 return conf
432
434
433 def removeProcUnit(self, id):
435 def removeProcUnit(self, id):
434
436
435 if id in self.configurations:
437 if id in self.configurations:
436 self.configurations.pop(id)
438 self.configurations.pop(id)
437
439
438 def getReadUnit(self):
440 def getReadUnit(self):
439
441
440 for obj in list(self.configurations.values()):
442 for obj in list(self.configurations.values()):
441 if obj.ELEMENTNAME == 'ReadUnit':
443 if obj.ELEMENTNAME == 'ReadUnit':
442 return obj
444 return obj
443
445
444 return None
446 return None
445
447
446 def getProcUnit(self, id):
448 def getProcUnit(self, id):
447
449
448 return self.configurations[id]
450 return self.configurations[id]
449
451
450 def getUnits(self):
452 def getUnits(self):
451
453
452 keys = list(self.configurations)
454 keys = list(self.configurations)
453 keys.sort()
455 keys.sort()
454
456
455 for key in keys:
457 for key in keys:
456 yield self.configurations[key]
458 yield self.configurations[key]
457
459
458 def updateUnit(self, id, **kwargs):
460 def updateUnit(self, id, **kwargs):
459
461
460 conf = self.configurations[id].update(**kwargs)
462 conf = self.configurations[id].update(**kwargs)
461
463
462 def makeXml(self):
464 def makeXml(self):
463
465
464 xml = Element('Project')
466 xml = Element('Project')
465 xml.set('id', str(self.id))
467 xml.set('id', str(self.id))
466 xml.set('name', self.name)
468 xml.set('name', self.name)
467 xml.set('description', self.description)
469 xml.set('description', self.description)
468
470
469 for conf in self.configurations.values():
471 for conf in self.configurations.values():
470 conf.makeXml(xml)
472 conf.makeXml(xml)
471
473
472 self.xml = xml
474 self.xml = xml
473
475
474 def writeXml(self, filename=None):
476 def writeXml(self, filename=None):
475
477
476 if filename == None:
478 if filename == None:
477 if self.filename:
479 if self.filename:
478 filename = self.filename
480 filename = self.filename
479 else:
481 else:
480 filename = 'schain.xml'
482 filename = 'schain.xml'
481
483
482 if not filename:
484 if not filename:
483 print('filename has not been defined. Use setFilename(filename) for do it.')
485 print('filename has not been defined. Use setFilename(filename) for do it.')
484 return 0
486 return 0
485
487
486 abs_file = os.path.abspath(filename)
488 abs_file = os.path.abspath(filename)
487
489
488 if not os.access(os.path.dirname(abs_file), os.W_OK):
490 if not os.access(os.path.dirname(abs_file), os.W_OK):
489 print('No write permission on %s' % os.path.dirname(abs_file))
491 print('No write permission on %s' % os.path.dirname(abs_file))
490 return 0
492 return 0
491
493
492 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
494 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
493 print('File %s already exists and it could not be overwriten' % abs_file)
495 print('File %s already exists and it could not be overwriten' % abs_file)
494 return 0
496 return 0
495
497
496 self.makeXml()
498 self.makeXml()
497
499
498 ElementTree(self.xml).write(abs_file, method='xml')
500 ElementTree(self.xml).write(abs_file, method='xml')
499
501
500 self.filename = abs_file
502 self.filename = abs_file
501
503
502 return 1
504 return 1
503
505
504 def readXml(self, filename):
506 def readXml(self, filename):
505
507
506 abs_file = os.path.abspath(filename)
508 abs_file = os.path.abspath(filename)
507
509
508 self.configurations = {}
510 self.configurations = {}
509
511
510 try:
512 try:
511 self.xml = ElementTree().parse(abs_file)
513 self.xml = ElementTree().parse(abs_file)
512 except:
514 except:
513 log.error('Error reading %s, verify file format' % filename)
515 log.error('Error reading %s, verify file format' % filename)
514 return 0
516 return 0
515
517
516 self.id = self.xml.get('id')
518 self.id = self.xml.get('id')
517 self.name = self.xml.get('name')
519 self.name = self.xml.get('name')
518 self.description = self.xml.get('description')
520 self.description = self.xml.get('description')
519
521
520 for element in self.xml:
522 for element in self.xml:
521 if element.tag == 'ReadUnit':
523 if element.tag == 'ReadUnit':
522 conf = ReadUnitConf()
524 conf = ReadUnitConf()
523 conf.readXml(element, self.id, self.err_queue)
525 conf.readXml(element, self.id, self.err_queue)
524 self.configurations[conf.id] = conf
526 self.configurations[conf.id] = conf
525 elif element.tag == 'ProcUnit':
527 elif element.tag == 'ProcUnit':
526 conf = ProcUnitConf()
528 conf = ProcUnitConf()
527 input_proc = self.configurations[element.get('inputId')]
529 input_proc = self.configurations[element.get('inputId')]
528 conf.readXml(element, self.id, self.err_queue)
530 conf.readXml(element, self.id, self.err_queue)
529 self.configurations[conf.id] = conf
531 self.configurations[conf.id] = conf
530
532
531 self.filename = abs_file
533 self.filename = abs_file
532
534
533 return 1
535 return 1
534
536
535 def __str__(self):
537 def __str__(self):
536
538
537 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
539 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
538 self.id,
540 self.id,
539 self.name,
541 self.name,
540 self.description,
542 self.description,
541 )
543 )
542
544
543 for conf in self.configurations.values():
545 for conf in self.configurations.values():
544 text += '{}'.format(conf)
546 text += '{}'.format(conf)
545
547
546 return text
548 return text
547
549
548 def createObjects(self):
550 def createObjects(self):
549
551
550 keys = list(self.configurations.keys())
552 keys = list(self.configurations.keys())
551 keys.sort()
553 keys.sort()
552 for key in keys:
554 for key in keys:
553 conf = self.configurations[key]
555 conf = self.configurations[key]
554 conf.createObjects()
556 conf.createObjects()
555 if conf.inputId is not None:
557 if conf.inputId is not None:
556 conf.object.setInput(self.configurations[conf.inputId].object)
558 conf.object.setInput(self.configurations[conf.inputId].object)
557
559
558 def monitor(self):
560 def monitor(self):
559
561
560 t = Thread(target=self._monitor, args=(self.err_queue, self.ctx))
562 t = Thread(target=self._monitor, args=(self.err_queue, self.ctx))
561 t.start()
563 t.start()
562
564
563 def _monitor(self, queue, ctx):
565 def _monitor(self, queue, ctx):
564
566
565 import socket
567 import socket
566
568
567 procs = 0
569 procs = 0
568 err_msg = ''
570 err_msg = ''
569
571
570 while True:
572 while True:
571 msg = queue.get()
573 msg = queue.get()
572 if '#_start_#' in msg:
574 if '#_start_#' in msg:
573 procs += 1
575 procs += 1
574 elif '#_end_#' in msg:
576 elif '#_end_#' in msg:
575 procs -= 1
577 procs -= 1
576 else:
578 else:
577 err_msg = msg
579 err_msg = msg
578
580
579 if procs == 0 or 'Traceback' in err_msg:
581 if procs == 0 or 'Traceback' in err_msg:
580 break
582 break
581 time.sleep(0.1)
583 time.sleep(0.1)
582
584
583 if '|' in err_msg:
585 if '|' in err_msg:
584 name, err = err_msg.split('|')
586 name, err = err_msg.split('|')
585 if 'SchainWarning' in err:
587 if 'SchainWarning' in err:
586 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
588 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
587 elif 'SchainError' in err:
589 elif 'SchainError' in err:
588 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
590 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
589 else:
591 else:
590 log.error(err, name)
592 log.error(err, name)
591 else:
593 else:
592 name, err = self.name, err_msg
594 name, err = self.name, err_msg
593
595
594 time.sleep(1)
596 time.sleep(1)
595
597
596 ctx.term()
598 ctx.term()
597
599
598 message = ''.join(err)
600 message = ''.join(err)
599
601
600 if err_msg:
602 if err_msg:
601 subject = 'SChain v%s: Error running %s\n' % (
603 subject = 'SChain v%s: Error running %s\n' % (
602 schainpy.__version__, self.name)
604 schainpy.__version__, self.name)
603
605
604 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
606 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
605 socket.gethostname())
607 socket.gethostname())
606 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
608 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
607 subtitle += 'Configuration file: %s\n' % self.filename
609 subtitle += 'Configuration file: %s\n' % self.filename
608 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
610 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
609
611
610 readUnitConfObj = self.getReadUnit()
612 readUnitConfObj = self.getReadUnit()
611 if readUnitConfObj:
613 if readUnitConfObj:
612 subtitle += '\nInput parameters:\n'
614 subtitle += '\nInput parameters:\n'
613 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
615 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
614 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
616 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
615 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
617 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
616 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
618 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
617 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
619 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
618
620
619 a = Alarm(
621 a = Alarm(
620 modes=self.alarm,
622 modes=self.alarm,
621 email=self.email,
623 email=self.email,
622 message=message,
624 message=message,
623 subject=subject,
625 subject=subject,
624 subtitle=subtitle,
626 subtitle=subtitle,
625 filename=self.filename
627 filename=self.filename
626 )
628 )
627
629
628 a.start()
630 a.start()
629
631
630 def setFilename(self, filename):
632 def setFilename(self, filename):
631
633
632 self.filename = filename
634 self.filename = filename
633
635
634 def runProcs(self):
636 def runProcs(self):
635
637
636 err = False
638 err = False
637 n = len(self.configurations)
639 n = len(self.configurations)
638
640
639 while not err:
641 while not err:
640 for conf in self.getUnits():
642 for conf in self.getUnits():
641 ok = conf.run()
643 ok = conf.run()
642 if ok == 'Error':
644 if ok == 'Error':
643 n -= 1
645 n -= 1
644 continue
646 continue
645 elif not ok:
647 elif not ok:
646 break
648 break
647 if n == 0:
649 if n == 0:
648 err = True
650 err = True
649
651
650 def run(self):
652 def run(self):
651
653
652 log.success('\nStarting Project {} [id={}]'.format(self.name, self.id), tag='')
654 log.success('\nStarting Project {} [id={}]'.format(self.name, self.id), tag='')
653 self.started = True
655 self.started = True
654 self.start_time = time.time()
656 self.start_time = time.time()
655 self.createObjects()
657 self.createObjects()
656 self.runProcs()
658 self.runProcs()
657 log.success('{} Done (Time: {:4.2f}s)'.format(
659 log.success('{} Done (Time: {:4.2f}s)'.format(
658 self.name,
660 self.name,
659 time.time() - self.start_time), '')
661 time.time() - self.start_time), '')
@@ -1,697 +1,697
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Base class to create plot operations
5 """Base class to create plot operations
6
6
7 """
7 """
8
8
9 import os
9 import os
10 import sys
10 import sys
11 import zmq
11 import zmq
12 import time
12 import time
13 import numpy
13 import numpy
14 import datetime
14 import datetime
15 from collections import deque
15 from collections import deque
16 from functools import wraps
16 from functools import wraps
17 from threading import Thread
17 from threading import Thread
18 import matplotlib
18 import matplotlib
19
19
20 if 'BACKEND' in os.environ:
20 if 'BACKEND' in os.environ:
21 matplotlib.use(os.environ['BACKEND'])
21 matplotlib.use(os.environ['BACKEND'])
22 elif 'linux' in sys.platform:
22 elif 'linux' in sys.platform:
23 matplotlib.use("TkAgg")
23 matplotlib.use("TkAgg")
24 elif 'darwin' in sys.platform:
24 elif 'darwin' in sys.platform:
25 matplotlib.use('MacOSX')
25 matplotlib.use('MacOSX')
26 else:
26 else:
27 from schainpy.utils import log
27 from schainpy.utils import log
28 log.warning('Using default Backend="Agg"', 'INFO')
28 log.warning('Using default Backend="Agg"', 'INFO')
29 matplotlib.use('Agg')
29 matplotlib.use('Agg')
30
30
31 import matplotlib.pyplot as plt
31 import matplotlib.pyplot as plt
32 from matplotlib.patches import Polygon
32 from matplotlib.patches import Polygon
33 from mpl_toolkits.axes_grid1 import make_axes_locatable
33 from mpl_toolkits.axes_grid1 import make_axes_locatable
34 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
34 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
35
35
36 from schainpy.model.data.jrodata import PlotterData
36 from schainpy.model.data.jrodata import PlotterData
37 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
37 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
38 from schainpy.utils import log
38 from schainpy.utils import log
39
39
40 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
40 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
41 blu_values = matplotlib.pyplot.get_cmap(
41 blu_values = matplotlib.pyplot.get_cmap(
42 'seismic_r', 20)(numpy.arange(20))[10:15]
42 'seismic_r', 20)(numpy.arange(20))[10:15]
43 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
43 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
44 'jro', numpy.vstack((blu_values, jet_values)))
44 'jro', numpy.vstack((blu_values, jet_values)))
45 matplotlib.pyplot.register_cmap(cmap=ncmap)
45 matplotlib.pyplot.register_cmap(cmap=ncmap)
46
46
47 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
47 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
48 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
48 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
49
49
50 EARTH_RADIUS = 6.3710e3
50 EARTH_RADIUS = 6.3710e3
51
51
52 def ll2xy(lat1, lon1, lat2, lon2):
52 def ll2xy(lat1, lon1, lat2, lon2):
53
53
54 p = 0.017453292519943295
54 p = 0.017453292519943295
55 a = 0.5 - numpy.cos((lat2 - lat1) * p) / 2 + numpy.cos(lat1 * p) * \
55 a = 0.5 - numpy.cos((lat2 - lat1) * p) / 2 + numpy.cos(lat1 * p) * \
56 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
56 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
57 r = 12742 * numpy.arcsin(numpy.sqrt(a))
57 r = 12742 * numpy.arcsin(numpy.sqrt(a))
58 theta = numpy.arctan2(numpy.sin((lon2 - lon1) * p) * numpy.cos(lat2 * p), numpy.cos(lat1 * p)
58 theta = numpy.arctan2(numpy.sin((lon2 - lon1) * p) * numpy.cos(lat2 * p), numpy.cos(lat1 * p)
59 * numpy.sin(lat2 * p) - numpy.sin(lat1 * p) * numpy.cos(lat2 * p) * numpy.cos((lon2 - lon1) * p))
59 * numpy.sin(lat2 * p) - numpy.sin(lat1 * p) * numpy.cos(lat2 * p) * numpy.cos((lon2 - lon1) * p))
60 theta = -theta + numpy.pi / 2
60 theta = -theta + numpy.pi / 2
61 return r * numpy.cos(theta), r * numpy.sin(theta)
61 return r * numpy.cos(theta), r * numpy.sin(theta)
62
62
63
63
64 def km2deg(km):
64 def km2deg(km):
65 '''
65 '''
66 Convert distance in km to degrees
66 Convert distance in km to degrees
67 '''
67 '''
68
68
69 return numpy.rad2deg(km / EARTH_RADIUS)
69 return numpy.rad2deg(km / EARTH_RADIUS)
70
70
71
71
72 def figpause(interval):
72 def figpause(interval):
73 backend = plt.rcParams['backend']
73 backend = plt.rcParams['backend']
74 if backend in matplotlib.rcsetup.interactive_bk:
74 if backend in matplotlib.rcsetup.interactive_bk:
75 figManager = matplotlib._pylab_helpers.Gcf.get_active()
75 figManager = matplotlib._pylab_helpers.Gcf.get_active()
76 if figManager is not None:
76 if figManager is not None:
77 canvas = figManager.canvas
77 canvas = figManager.canvas
78 if canvas.figure.stale:
78 if canvas.figure.stale:
79 canvas.draw()
79 canvas.draw()
80 try:
80 try:
81 canvas.start_event_loop(interval)
81 canvas.start_event_loop(interval)
82 except:
82 except:
83 pass
83 pass
84 return
84 return
85
85
86 def popup(message):
86 def popup(message):
87 '''
87 '''
88 '''
88 '''
89
89
90 fig = plt.figure(figsize=(12, 8), facecolor='r')
90 fig = plt.figure(figsize=(12, 8), facecolor='r')
91 text = '\n'.join([s.strip() for s in message.split(':')])
91 text = '\n'.join([s.strip() for s in message.split(':')])
92 fig.text(0.01, 0.5, text, ha='left', va='center',
92 fig.text(0.01, 0.5, text, ha='left', va='center',
93 size='20', weight='heavy', color='w')
93 size='20', weight='heavy', color='w')
94 fig.show()
94 fig.show()
95 figpause(1000)
95 figpause(1000)
96
96
97
97
98 class Throttle(object):
98 class Throttle(object):
99 '''
99 '''
100 Decorator that prevents a function from being called more than once every
100 Decorator that prevents a function from being called more than once every
101 time period.
101 time period.
102 To create a function that cannot be called more than once a minute, but
102 To create a function that cannot be called more than once a minute, but
103 will sleep until it can be called:
103 will sleep until it can be called:
104 @Throttle(minutes=1)
104 @Throttle(minutes=1)
105 def foo():
105 def foo():
106 pass
106 pass
107
107
108 for i in range(10):
108 for i in range(10):
109 foo()
109 foo()
110 print "This function has run %s times." % i
110 print "This function has run %s times." % i
111 '''
111 '''
112
112
113 def __init__(self, seconds=0, minutes=0, hours=0):
113 def __init__(self, seconds=0, minutes=0, hours=0):
114 self.throttle_period = datetime.timedelta(
114 self.throttle_period = datetime.timedelta(
115 seconds=seconds, minutes=minutes, hours=hours
115 seconds=seconds, minutes=minutes, hours=hours
116 )
116 )
117
117
118 self.time_of_last_call = datetime.datetime.min
118 self.time_of_last_call = datetime.datetime.min
119
119
120 def __call__(self, fn):
120 def __call__(self, fn):
121 @wraps(fn)
121 @wraps(fn)
122 def wrapper(*args, **kwargs):
122 def wrapper(*args, **kwargs):
123 coerce = kwargs.pop('coerce', None)
123 coerce = kwargs.pop('coerce', None)
124 if coerce:
124 if coerce:
125 self.time_of_last_call = datetime.datetime.now()
125 self.time_of_last_call = datetime.datetime.now()
126 return fn(*args, **kwargs)
126 return fn(*args, **kwargs)
127 else:
127 else:
128 now = datetime.datetime.now()
128 now = datetime.datetime.now()
129 time_since_last_call = now - self.time_of_last_call
129 time_since_last_call = now - self.time_of_last_call
130 time_left = self.throttle_period - time_since_last_call
130 time_left = self.throttle_period - time_since_last_call
131
131
132 if time_left > datetime.timedelta(seconds=0):
132 if time_left > datetime.timedelta(seconds=0):
133 return
133 return
134
134
135 self.time_of_last_call = datetime.datetime.now()
135 self.time_of_last_call = datetime.datetime.now()
136 return fn(*args, **kwargs)
136 return fn(*args, **kwargs)
137
137
138 return wrapper
138 return wrapper
139
139
140 def apply_throttle(value):
140 def apply_throttle(value):
141
141
142 @Throttle(seconds=value)
142 @Throttle(seconds=value)
143 def fnThrottled(fn):
143 def fnThrottled(fn):
144 fn()
144 fn()
145
145
146 return fnThrottled
146 return fnThrottled
147
147
148
148
149 @MPDecorator
149 @MPDecorator
150 class Plot(Operation):
150 class Plot(Operation):
151 """Base class for Schain plotting operations
151 """Base class for Schain plotting operations
152
152
153 This class should never be use directtly you must subclass a new operation,
153 This class should never be use directtly you must subclass a new operation,
154 children classes must be defined as follow:
154 children classes must be defined as follow:
155
155
156 ExamplePlot(Plot):
156 ExamplePlot(Plot):
157
157
158 CODE = 'code'
158 CODE = 'code'
159 colormap = 'jet'
159 colormap = 'jet'
160 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
160 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
161
161
162 def setup(self):
162 def setup(self):
163 pass
163 pass
164
164
165 def plot(self):
165 def plot(self):
166 pass
166 pass
167
167
168 """
168 """
169
169
170 CODE = 'Figure'
170 CODE = 'Figure'
171 colormap = 'jet'
171 colormap = 'jet'
172 bgcolor = 'white'
172 bgcolor = 'white'
173 buffering = True
173 buffering = True
174 __missing = 1E30
174 __missing = 1E30
175
175
176 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
176 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
177 'showprofile']
177 'showprofile']
178
178
179 def __init__(self):
179 def __init__(self):
180
180
181 Operation.__init__(self)
181 Operation.__init__(self)
182 self.isConfig = False
182 self.isConfig = False
183 self.isPlotConfig = False
183 self.isPlotConfig = False
184 self.save_time = 0
184 self.save_time = 0
185 self.sender_time = 0
185 self.sender_time = 0
186 self.data = None
186 self.data = None
187 self.firsttime = True
187 self.firsttime = True
188 self.sender_queue = deque(maxlen=10)
188 self.sender_queue = deque(maxlen=10)
189 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
189 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
190
190
191 def __fmtTime(self, x, pos):
191 def __fmtTime(self, x, pos):
192 '''
192 '''
193 '''
193 '''
194
194
195 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
195 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
196
196
197 def __setup(self, **kwargs):
197 def __setup(self, **kwargs):
198 '''
198 '''
199 Initialize variables
199 Initialize variables
200 '''
200 '''
201
201
202 self.figures = []
202 self.figures = []
203 self.axes = []
203 self.axes = []
204 self.cb_axes = []
204 self.cb_axes = []
205 self.localtime = kwargs.pop('localtime', True)
205 self.localtime = kwargs.pop('localtime', True)
206 self.show = kwargs.get('show', True)
206 self.show = kwargs.get('show', True)
207 self.save = kwargs.get('save', False)
207 self.save = kwargs.get('save', False)
208 self.save_period = kwargs.get('save_period', 0)
208 self.save_period = kwargs.get('save_period', 0)
209 self.colormap = kwargs.get('colormap', self.colormap)
209 self.colormap = kwargs.get('colormap', self.colormap)
210 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
210 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
211 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
211 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
212 self.colormaps = kwargs.get('colormaps', None)
212 self.colormaps = kwargs.get('colormaps', None)
213 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
213 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
214 self.showprofile = kwargs.get('showprofile', False)
214 self.showprofile = kwargs.get('showprofile', False)
215 self.title = kwargs.get('wintitle', self.CODE.upper())
215 self.title = kwargs.get('wintitle', self.CODE.upper())
216 self.cb_label = kwargs.get('cb_label', None)
216 self.cb_label = kwargs.get('cb_label', None)
217 self.cb_labels = kwargs.get('cb_labels', None)
217 self.cb_labels = kwargs.get('cb_labels', None)
218 self.labels = kwargs.get('labels', None)
218 self.labels = kwargs.get('labels', None)
219 self.xaxis = kwargs.get('xaxis', 'frequency')
219 self.xaxis = kwargs.get('xaxis', 'frequency')
220 self.zmin = kwargs.get('zmin', None)
220 self.zmin = kwargs.get('zmin', None)
221 self.zmax = kwargs.get('zmax', None)
221 self.zmax = kwargs.get('zmax', None)
222 self.zlimits = kwargs.get('zlimits', None)
222 self.zlimits = kwargs.get('zlimits', None)
223 self.xlimits = kwargs.get('xlimits', None)
223 self.xlimits = kwargs.get('xlimits', None)
224 self.xstep_given = kwargs.get('xstep_given', None)
224 self.xstep_given = kwargs.get('xstep_given', None)
225 self.ystep_given = kwargs.get('ystep_given', None)
225 self.ystep_given = kwargs.get('ystep_given', None)
226 self.autoxticks = kwargs.get('autoxticks', True)
226 self.autoxticks = kwargs.get('autoxticks', True)
227 self.xmin = kwargs.get('xmin', None)
227 self.xmin = kwargs.get('xmin', None)
228 self.xmax = kwargs.get('xmax', None)
228 self.xmax = kwargs.get('xmax', None)
229 self.xrange = kwargs.get('xrange', 12)
229 self.xrange = kwargs.get('xrange', 12)
230 self.xscale = kwargs.get('xscale', None)
230 self.xscale = kwargs.get('xscale', None)
231 self.ymin = kwargs.get('ymin', None)
231 self.ymin = kwargs.get('ymin', None)
232 self.ymax = kwargs.get('ymax', None)
232 self.ymax = kwargs.get('ymax', None)
233 self.yscale = kwargs.get('yscale', None)
233 self.yscale = kwargs.get('yscale', None)
234 self.xlabel = kwargs.get('xlabel', None)
234 self.xlabel = kwargs.get('xlabel', None)
235 self.attr_time = kwargs.get('attr_time', 'utctime')
235 self.attr_time = kwargs.get('attr_time', 'utctime')
236 self.attr_data = kwargs.get('attr_data', 'data_param')
236 self.attr_data = kwargs.get('attr_data', 'data_param')
237 self.decimation = kwargs.get('decimation', None)
237 self.decimation = kwargs.get('decimation', None)
238 self.oneFigure = kwargs.get('oneFigure', True)
238 self.oneFigure = kwargs.get('oneFigure', True)
239 self.width = kwargs.get('width', None)
239 self.width = kwargs.get('width', None)
240 self.height = kwargs.get('height', None)
240 self.height = kwargs.get('height', None)
241 self.colorbar = kwargs.get('colorbar', True)
241 self.colorbar = kwargs.get('colorbar', True)
242 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
242 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
243 self.channels = kwargs.get('channels', None)
243 self.channels = kwargs.get('channels', None)
244 self.titles = kwargs.get('titles', [])
244 self.titles = kwargs.get('titles', [])
245 self.polar = False
245 self.polar = False
246 self.type = kwargs.get('type', 'iq')
246 self.type = kwargs.get('type', 'iq')
247 self.grid = kwargs.get('grid', False)
247 self.grid = kwargs.get('grid', False)
248 self.pause = kwargs.get('pause', False)
248 self.pause = kwargs.get('pause', False)
249 self.save_code = kwargs.get('save_code', self.CODE)
249 self.save_code = kwargs.get('save_code', self.CODE)
250 self.throttle = kwargs.get('throttle', 0)
250 self.throttle = kwargs.get('throttle', 0)
251 self.exp_code = kwargs.get('exp_code', None)
251 self.exp_code = kwargs.get('exp_code', None)
252 self.server = kwargs.get('server', False)
252 self.server = kwargs.get('server', False)
253 self.sender_period = kwargs.get('sender_period', 60)
253 self.sender_period = kwargs.get('sender_period', 60)
254 self.tag = kwargs.get('tag', '')
254 self.tag = kwargs.get('tag', '')
255 self.height_index = kwargs.get('height_index', None)
255 self.height_index = kwargs.get('height_index', None)
256 self.__throttle_plot = apply_throttle(self.throttle)
256 self.__throttle_plot = apply_throttle(self.throttle)
257 code = self.attr_data if self.attr_data else self.CODE
257 code = self.attr_data if self.attr_data else self.CODE
258 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
258 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
259
259
260 if self.server:
260 if self.server:
261 if not self.server.startswith('tcp://'):
261 if not self.server.startswith('tcp://'):
262 self.server = 'tcp://{}'.format(self.server)
262 self.server = 'tcp://{}'.format(self.server)
263 log.success(
263 log.success(
264 'Sending to server: {}'.format(self.server),
264 'Sending to server: {}'.format(self.server),
265 self.name
265 self.name
266 )
266 )
267
267
268 if isinstance(self.attr_data, str):
268 if isinstance(self.attr_data, str):
269 self.attr_data = [self.attr_data]
269 self.attr_data = [self.attr_data]
270
270
271 def __setup_plot(self):
271 def __setup_plot(self):
272 '''
272 '''
273 Common setup for all figures, here figures and axes are created
273 Common setup for all figures, here figures and axes are created
274 '''
274 '''
275
275
276 self.setup()
276 self.setup()
277
277
278 self.time_label = 'LT' if self.localtime else 'UTC'
278 self.time_label = 'LT' if self.localtime else 'UTC'
279
279
280 if self.width is None:
280 if self.width is None:
281 self.width = 8
281 self.width = 8
282
282
283 self.figures = []
283 self.figures = []
284 self.axes = []
284 self.axes = []
285 self.cb_axes = []
285 self.cb_axes = []
286 self.pf_axes = []
286 self.pf_axes = []
287 self.cmaps = []
287 self.cmaps = []
288
288
289 size = '15%' if self.ncols == 1 else '30%'
289 size = '15%' if self.ncols == 1 else '30%'
290 pad = '4%' if self.ncols == 1 else '8%'
290 pad = '4%' if self.ncols == 1 else '8%'
291
291
292 if self.oneFigure:
292 if self.oneFigure:
293 if self.height is None:
293 if self.height is None:
294 self.height = 1.4 * self.nrows + 1
294 self.height = 1.4 * self.nrows + 1
295 fig = plt.figure(figsize=(self.width, self.height),
295 fig = plt.figure(figsize=(self.width, self.height),
296 edgecolor='k',
296 edgecolor='k',
297 facecolor='w')
297 facecolor='w')
298 self.figures.append(fig)
298 self.figures.append(fig)
299 for n in range(self.nplots):
299 for n in range(self.nplots):
300 ax = fig.add_subplot(self.nrows, self.ncols,
300 ax = fig.add_subplot(self.nrows, self.ncols,
301 n + 1, polar=self.polar)
301 n + 1, polar=self.polar)
302 ax.tick_params(labelsize=8)
302 ax.tick_params(labelsize=8)
303 ax.firsttime = True
303 ax.firsttime = True
304 ax.index = 0
304 ax.index = 0
305 ax.press = None
305 ax.press = None
306 self.axes.append(ax)
306 self.axes.append(ax)
307 if self.showprofile:
307 if self.showprofile:
308 cax = self.__add_axes(ax, size=size, pad=pad)
308 cax = self.__add_axes(ax, size=size, pad=pad)
309 cax.tick_params(labelsize=8)
309 cax.tick_params(labelsize=8)
310 self.pf_axes.append(cax)
310 self.pf_axes.append(cax)
311 else:
311 else:
312 if self.height is None:
312 if self.height is None:
313 self.height = 3
313 self.height = 3
314 for n in range(self.nplots):
314 for n in range(self.nplots):
315 fig = plt.figure(figsize=(self.width, self.height),
315 fig = plt.figure(figsize=(self.width, self.height),
316 edgecolor='k',
316 edgecolor='k',
317 facecolor='w')
317 facecolor='w')
318 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
318 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
319 ax.tick_params(labelsize=8)
319 ax.tick_params(labelsize=8)
320 ax.firsttime = True
320 ax.firsttime = True
321 ax.index = 0
321 ax.index = 0
322 ax.press = None
322 ax.press = None
323 self.figures.append(fig)
323 self.figures.append(fig)
324 self.axes.append(ax)
324 self.axes.append(ax)
325 if self.showprofile:
325 if self.showprofile:
326 cax = self.__add_axes(ax, size=size, pad=pad)
326 cax = self.__add_axes(ax, size=size, pad=pad)
327 cax.tick_params(labelsize=8)
327 cax.tick_params(labelsize=8)
328 self.pf_axes.append(cax)
328 self.pf_axes.append(cax)
329
329
330 for n in range(self.nrows):
330 for n in range(self.nrows):
331 if self.colormaps is not None:
331 if self.colormaps is not None:
332 cmap = plt.get_cmap(self.colormaps[n])
332 cmap = plt.get_cmap(self.colormaps[n])
333 else:
333 else:
334 cmap = plt.get_cmap(self.colormap)
334 cmap = plt.get_cmap(self.colormap)
335 cmap.set_bad(self.bgcolor, 1.)
335 cmap.set_bad(self.bgcolor, 1.)
336 self.cmaps.append(cmap)
336 self.cmaps.append(cmap)
337
337
338 def __add_axes(self, ax, size='30%', pad='8%'):
338 def __add_axes(self, ax, size='30%', pad='8%'):
339 '''
339 '''
340 Add new axes to the given figure
340 Add new axes to the given figure
341 '''
341 '''
342 divider = make_axes_locatable(ax)
342 divider = make_axes_locatable(ax)
343 nax = divider.new_horizontal(size=size, pad=pad)
343 nax = divider.new_horizontal(size=size, pad=pad)
344 ax.figure.add_axes(nax)
344 ax.figure.add_axes(nax)
345 return nax
345 return nax
346
346
347 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
347 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
348 '''
348 '''
349 Create a masked array for missing data
349 Create a masked array for missing data
350 '''
350 '''
351 if x_buffer.shape[0] < 2:
351 if x_buffer.shape[0] < 2:
352 return x_buffer, y_buffer, z_buffer
352 return x_buffer, y_buffer, z_buffer
353
353
354 deltas = x_buffer[1:] - x_buffer[0:-1]
354 deltas = x_buffer[1:] - x_buffer[0:-1]
355 x_median = numpy.median(deltas)
355 x_median = numpy.median(deltas)
356
356
357 index = numpy.where(deltas > 5 * x_median)
357 index = numpy.where(deltas > 5 * x_median)
358
358
359 if len(index[0]) != 0:
359 if len(index[0]) != 0:
360 z_buffer[::, index[0], ::] = self.__missing
360 z_buffer[::, index[0], ::] = self.__missing
361 z_buffer = numpy.ma.masked_inside(z_buffer,
361 z_buffer = numpy.ma.masked_inside(z_buffer,
362 0.99 * self.__missing,
362 0.99 * self.__missing,
363 1.01 * self.__missing)
363 1.01 * self.__missing)
364
364
365 return x_buffer, y_buffer, z_buffer
365 return x_buffer, y_buffer, z_buffer
366
366
367 def decimate(self):
367 def decimate(self):
368
368
369 # dx = int(len(self.x)/self.__MAXNUMX) + 1
369 # dx = int(len(self.x)/self.__MAXNUMX) + 1
370 dy = int(len(self.y) / self.decimation) + 1
370 dy = int(len(self.y) / self.decimation) + 1
371
371
372 # x = self.x[::dx]
372 # x = self.x[::dx]
373 x = self.x
373 x = self.x
374 y = self.y[::dy]
374 y = self.y[::dy]
375 z = self.z[::, ::, ::dy]
375 z = self.z[::, ::, ::dy]
376
376
377 return x, y, z
377 return x, y, z
378
378
379 def format(self):
379 def format(self):
380 '''
380 '''
381 Set min and max values, labels, ticks and titles
381 Set min and max values, labels, ticks and titles
382 '''
382 '''
383
383
384 for n, ax in enumerate(self.axes):
384 for n, ax in enumerate(self.axes):
385 if ax.firsttime:
385 if ax.firsttime:
386 if self.xaxis != 'time':
386 if self.xaxis != 'time':
387 xmin = self.xmin
387 xmin = self.xmin
388 xmax = self.xmax
388 xmax = self.xmax
389 else:
389 else:
390 xmin = self.tmin
390 xmin = self.tmin
391 xmax = self.tmin + self.xrange * 60 * 60
391 xmax = self.tmin + self.xrange * 60 * 60
392 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
392 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
393 ax.xaxis.set_major_locator(LinearLocator(9))
393 ax.xaxis.set_major_locator(LinearLocator(9))
394 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
394 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
395 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
395 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
396 ax.set_facecolor(self.bgcolor)
396 ax.set_facecolor(self.bgcolor)
397 if self.xscale:
397 if self.xscale:
398 ax.xaxis.set_major_formatter(FuncFormatter(
398 ax.xaxis.set_major_formatter(FuncFormatter(
399 lambda x, pos: '{0:g}'.format(x * self.xscale)))
399 lambda x, pos: '{0:g}'.format(x * self.xscale)))
400 if self.yscale:
400 if self.yscale:
401 ax.yaxis.set_major_formatter(FuncFormatter(
401 ax.yaxis.set_major_formatter(FuncFormatter(
402 lambda x, pos: '{0:g}'.format(x * self.yscale)))
402 lambda x, pos: '{0:g}'.format(x * self.yscale)))
403 if self.xlabel is not None:
403 if self.xlabel is not None:
404 ax.set_xlabel(self.xlabel)
404 ax.set_xlabel(self.xlabel)
405 if self.ylabel is not None:
405 if self.ylabel is not None:
406 ax.set_ylabel(self.ylabel)
406 ax.set_ylabel(self.ylabel)
407 if self.showprofile:
407 if self.showprofile:
408 self.pf_axes[n].set_ylim(ymin, ymax)
408 self.pf_axes[n].set_ylim(ymin, ymax)
409 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
409 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
410 self.pf_axes[n].set_xlabel('dB')
410 self.pf_axes[n].set_xlabel('dB')
411 self.pf_axes[n].grid(b=True, axis='x')
411 self.pf_axes[n].grid(b=True, axis='x')
412 [tick.set_visible(False)
412 [tick.set_visible(False)
413 for tick in self.pf_axes[n].get_yticklabels()]
413 for tick in self.pf_axes[n].get_yticklabels()]
414 if self.colorbar:
414 if self.colorbar:
415 ax.cbar = plt.colorbar(
415 ax.cbar = plt.colorbar(
416 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
416 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
417 ax.cbar.ax.tick_params(labelsize=8)
417 ax.cbar.ax.tick_params(labelsize=8)
418 ax.cbar.ax.press = None
418 ax.cbar.ax.press = None
419 if self.cb_label:
419 if self.cb_label:
420 ax.cbar.set_label(self.cb_label, size=8)
420 ax.cbar.set_label(self.cb_label, size=8)
421 elif self.cb_labels:
421 elif self.cb_labels:
422 ax.cbar.set_label(self.cb_labels[n], size=8)
422 ax.cbar.set_label(self.cb_labels[n], size=8)
423 else:
423 else:
424 ax.cbar = None
424 ax.cbar = None
425 ax.set_xlim(xmin, xmax)
425 ax.set_xlim(xmin, xmax)
426 ax.set_ylim(ymin, ymax)
426 ax.set_ylim(ymin, ymax)
427 ax.firsttime = False
427 ax.firsttime = False
428 if self.grid:
428 if self.grid:
429 ax.grid(True)
429 ax.grid(True)
430 if not self.polar:
430 if not self.polar:
431 ax.set_title('{} {} {}'.format(
431 ax.set_title('{} {} {}'.format(
432 self.titles[n],
432 self.titles[n],
433 self.getDateTime(self.data.max_time).strftime(
433 self.getDateTime(self.data.max_time).strftime(
434 '%Y-%m-%d %H:%M:%S'),
434 '%Y-%m-%d %H:%M:%S'),
435 self.time_label),
435 self.time_label),
436 size=8)
436 size=8)
437 else:
437 else:
438 ax.set_title('{}'.format(self.titles[n]), size=8)
438 ax.set_title('{}'.format(self.titles[n]), size=8)
439 ax.set_ylim(0, 90)
439 ax.set_ylim(0, 90)
440 ax.set_yticks(numpy.arange(0, 90, 20))
440 ax.set_yticks(numpy.arange(0, 90, 20))
441 ax.yaxis.labelpad = 40
441 ax.yaxis.labelpad = 40
442
442
443 if self.firsttime:
443 if self.firsttime:
444 for n, fig in enumerate(self.figures):
444 for n, fig in enumerate(self.figures):
445 fig.subplots_adjust(**self.plots_adjust)
445 fig.subplots_adjust(**self.plots_adjust)
446 self.firsttime = False
446 self.firsttime = False
447
447
448 def clear_figures(self):
448 def clear_figures(self):
449 '''
449 '''
450 Reset axes for redraw plots
450 Reset axes for redraw plots
451 '''
451 '''
452
452
453 for ax in self.axes + self.pf_axes + self.cb_axes:
453 for ax in self.axes + self.pf_axes + self.cb_axes:
454 ax.clear()
454 ax.clear()
455 ax.firsttime = True
455 ax.firsttime = True
456 if hasattr(ax, 'cbar') and ax.cbar:
456 if hasattr(ax, 'cbar') and ax.cbar:
457 ax.cbar.remove()
457 ax.cbar.remove()
458
458
459 def __plot(self):
459 def __plot(self):
460 '''
460 '''
461 Main function to plot, format and save figures
461 Main function to plot, format and save figures
462 '''
462 '''
463
463
464 self.plot()
464 self.plot()
465 self.format()
465 self.format()
466
466
467 for n, fig in enumerate(self.figures):
467 for n, fig in enumerate(self.figures):
468 if self.nrows == 0 or self.nplots == 0:
468 if self.nrows == 0 or self.nplots == 0:
469 log.warning('No data', self.name)
469 log.warning('No data', self.name)
470 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
470 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
471 fig.canvas.manager.set_window_title(self.CODE)
471 fig.canvas.manager.set_window_title(self.CODE)
472 continue
472 continue
473
473
474 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
474 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
475 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
475 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
476 fig.canvas.draw()
476 fig.canvas.draw()
477 if self.show:
477 if self.show:
478 fig.show()
478 fig.show()
479 figpause(0.01)
479 figpause(0.01)
480
480
481 if self.save:
481 if self.save:
482 self.save_figure(n)
482 self.save_figure(n)
483
483
484 if self.server:
484 if self.server:
485 self.send_to_server()
485 self.send_to_server()
486
486
487 def __update(self, dataOut, timestamp):
487 def __update(self, dataOut, timestamp):
488 '''
488 '''
489 '''
489 '''
490
490
491 metadata = {
491 metadata = {
492 'yrange': dataOut.heightList,
492 'yrange': dataOut.heightList,
493 'interval': dataOut.timeInterval,
493 'interval': dataOut.timeInterval,
494 'channels': dataOut.channelList
494 'channels': dataOut.channelList
495 }
495 }
496
496
497 data, meta = self.update(dataOut)
497 data, meta = self.update(dataOut)
498 metadata.update(meta)
498 metadata.update(meta)
499 self.data.update(data, timestamp, metadata)
499 self.data.update(data, timestamp, metadata)
500
500
501 def save_figure(self, n):
501 def save_figure(self, n):
502 '''
502 '''
503 '''
503 '''
504
504
505 if (self.data.max_time - self.save_time) <= self.save_period:
505 if (self.data.max_time - self.save_time) <= self.save_period:
506 return
506 return
507
507
508 self.save_time = self.data.max_time
508 self.save_time = self.data.max_time
509
509
510 fig = self.figures[n]
510 fig = self.figures[n]
511
511
512 if self.throttle == 0:
512 if self.throttle == 0:
513 figname = os.path.join(
513 figname = os.path.join(
514 self.save,
514 self.save,
515 self.save_code,
515 self.save_code,
516 '{}_{}.png'.format(
516 '{}_{}.png'.format(
517 self.save_code,
517 self.save_code,
518 self.getDateTime(self.data.max_time).strftime(
518 self.getDateTime(self.data.max_time).strftime(
519 '%Y%m%d_%H%M%S'
519 '%Y%m%d_%H%M%S'
520 ),
520 ),
521 )
521 )
522 )
522 )
523 log.log('Saving figure: {}'.format(figname), self.name)
523 log.log('Saving figure: {}'.format(figname), self.name)
524 if not os.path.isdir(os.path.dirname(figname)):
524 if not os.path.isdir(os.path.dirname(figname)):
525 os.makedirs(os.path.dirname(figname))
525 os.makedirs(os.path.dirname(figname))
526 fig.savefig(figname)
526 fig.savefig(figname)
527
527
528 figname = os.path.join(
528 figname = os.path.join(
529 self.save,
529 self.save,
530 self.save_code,
530 self.save_code,
531 '{}_{}.png'.format(
531 '{}_{}.png'.format(
532 self.save_code,
532 self.save_code,
533 self.getDateTime(self.data.min_time).strftime(
533 self.getDateTime(self.data.min_time).strftime(
534 '%Y%m%d'
534 '%Y%m%d'
535 ),
535 ),
536 )
536 )
537 )
537 )
538 log.log('Saving figure: {}'.format(figname), self.name)
538 log.log('Saving figure: {}'.format(figname), self.name)
539 if not os.path.isdir(os.path.dirname(figname)):
539 if not os.path.isdir(os.path.dirname(figname)):
540 os.makedirs(os.path.dirname(figname))
540 os.makedirs(os.path.dirname(figname))
541 fig.savefig(figname)
541 fig.savefig(figname)
542
542
543 def send_to_server(self):
543 def send_to_server(self):
544 '''
544 '''
545 '''
545 '''
546
546
547 if self.exp_code == None:
547 if self.exp_code == None:
548 log.warning('Missing `exp_code` skipping sending to server...')
548 log.warning('Missing `exp_code` skipping sending to server...')
549
549
550 last_time = self.data.max_time
550 last_time = self.data.max_time
551 interval = last_time - self.sender_time
551 interval = last_time - self.sender_time
552 if interval < self.sender_period:
552 if interval < self.sender_period:
553 return
553 return
554
554
555 self.sender_time = last_time
555 self.sender_time = last_time
556
556
557 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
557 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax', 'zlimits']
558 for attr in attrs:
558 for attr in attrs:
559 value = getattr(self, attr)
559 value = getattr(self, attr)
560 if value:
560 if value:
561 if isinstance(value, (numpy.float32, numpy.float64)):
561 if isinstance(value, (numpy.float32, numpy.float64)):
562 value = round(float(value), 2)
562 value = round(float(value), 2)
563 self.data.meta[attr] = value
563 self.data.meta[attr] = value
564 if self.colormap == 'jet':
564 if self.colormap == 'jet':
565 self.data.meta['colormap'] = 'Jet'
565 self.data.meta['colormap'] = 'Jet'
566 elif 'RdBu' in self.colormap:
566 elif 'RdBu' in self.colormap:
567 self.data.meta['colormap'] = 'RdBu'
567 self.data.meta['colormap'] = 'RdBu'
568 else:
568 else:
569 self.data.meta['colormap'] = 'Viridis'
569 self.data.meta['colormap'] = 'Viridis'
570 self.data.meta['interval'] = int(interval)
570 self.data.meta['interval'] = int(interval)
571
571
572 self.sender_queue.append(last_time)
572 self.sender_queue.append(last_time)
573
573
574 while True:
574 while True:
575 try:
575 try:
576 tm = self.sender_queue.popleft()
576 tm = self.sender_queue.popleft()
577 except IndexError:
577 except IndexError:
578 break
578 break
579 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
579 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
580 self.socket.send_string(msg)
580 self.socket.send_string(msg)
581 socks = dict(self.poll.poll(2000))
581 socks = dict(self.poll.poll(2000))
582 if socks.get(self.socket) == zmq.POLLIN:
582 if socks.get(self.socket) == zmq.POLLIN:
583 reply = self.socket.recv_string()
583 reply = self.socket.recv_string()
584 if reply == 'ok':
584 if reply == 'ok':
585 log.log("Response from server ok", self.name)
585 log.log("Response from server ok", self.name)
586 time.sleep(0.1)
586 time.sleep(0.1)
587 continue
587 continue
588 else:
588 else:
589 log.warning(
589 log.warning(
590 "Malformed reply from server: {}".format(reply), self.name)
590 "Malformed reply from server: {}".format(reply), self.name)
591 else:
591 else:
592 log.warning(
592 log.warning(
593 "No response from server, retrying...", self.name)
593 "No response from server, retrying...", self.name)
594 self.sender_queue.appendleft(tm)
594 self.sender_queue.appendleft(tm)
595 self.socket.setsockopt(zmq.LINGER, 0)
595 self.socket.setsockopt(zmq.LINGER, 0)
596 self.socket.close()
596 self.socket.close()
597 self.poll.unregister(self.socket)
597 self.poll.unregister(self.socket)
598 self.socket = self.context.socket(zmq.REQ)
598 self.socket = self.context.socket(zmq.REQ)
599 self.socket.connect(self.server)
599 self.socket.connect(self.server)
600 self.poll.register(self.socket, zmq.POLLIN)
600 self.poll.register(self.socket, zmq.POLLIN)
601 break
601 break
602
602
603 def setup(self):
603 def setup(self):
604 '''
604 '''
605 This method should be implemented in the child class, the following
605 This method should be implemented in the child class, the following
606 attributes should be set:
606 attributes should be set:
607
607
608 self.nrows: number of rows
608 self.nrows: number of rows
609 self.ncols: number of cols
609 self.ncols: number of cols
610 self.nplots: number of plots (channels or pairs)
610 self.nplots: number of plots (channels or pairs)
611 self.ylabel: label for Y axes
611 self.ylabel: label for Y axes
612 self.titles: list of axes title
612 self.titles: list of axes title
613
613
614 '''
614 '''
615 raise NotImplementedError
615 raise NotImplementedError
616
616
617 def plot(self):
617 def plot(self):
618 '''
618 '''
619 Must be defined in the child class, the actual plotting method
619 Must be defined in the child class, the actual plotting method
620 '''
620 '''
621 raise NotImplementedError
621 raise NotImplementedError
622
622
623 def update(self, dataOut):
623 def update(self, dataOut):
624 '''
624 '''
625 Must be defined in the child class, update self.data with new data
625 Must be defined in the child class, update self.data with new data
626 '''
626 '''
627
627
628 data = {
628 data = {
629 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
629 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
630 }
630 }
631 meta = {}
631 meta = {}
632
632
633 return data, meta
633 return data, meta
634
634
635 def run(self, dataOut, **kwargs):
635 def run(self, dataOut, **kwargs):
636 '''
636 '''
637 Main plotting routine
637 Main plotting routine
638 '''
638 '''
639
639
640 if self.isConfig is False:
640 if self.isConfig is False:
641 self.__setup(**kwargs)
641 self.__setup(**kwargs)
642
642
643 if self.localtime:
643 if self.localtime:
644 self.getDateTime = datetime.datetime.fromtimestamp
644 self.getDateTime = datetime.datetime.fromtimestamp
645 else:
645 else:
646 self.getDateTime = datetime.datetime.utcfromtimestamp
646 self.getDateTime = datetime.datetime.utcfromtimestamp
647
647
648 self.data.setup()
648 self.data.setup()
649 self.isConfig = True
649 self.isConfig = True
650 if self.server:
650 if self.server:
651 self.context = zmq.Context()
651 self.context = zmq.Context()
652 self.socket = self.context.socket(zmq.REQ)
652 self.socket = self.context.socket(zmq.REQ)
653 self.socket.connect(self.server)
653 self.socket.connect(self.server)
654 self.poll = zmq.Poller()
654 self.poll = zmq.Poller()
655 self.poll.register(self.socket, zmq.POLLIN)
655 self.poll.register(self.socket, zmq.POLLIN)
656
656
657 tm = getattr(dataOut, self.attr_time)
657 tm = getattr(dataOut, self.attr_time)
658
658
659 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange * 60 * 60:
659 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange * 60 * 60:
660 self.save_time = tm
660 self.save_time = tm
661 self.__plot()
661 self.__plot()
662 self.tmin += self.xrange * 60 * 60
662 self.tmin += self.xrange * 60 * 60
663 self.data.setup()
663 self.data.setup()
664 self.clear_figures()
664 self.clear_figures()
665
665
666 self.__update(dataOut, tm)
666 self.__update(dataOut, tm)
667
667
668 if self.isPlotConfig is False:
668 if self.isPlotConfig is False:
669 self.__setup_plot()
669 self.__setup_plot()
670 self.isPlotConfig = True
670 self.isPlotConfig = True
671 if self.xaxis == 'time':
671 if self.xaxis == 'time':
672 dt = self.getDateTime(tm)
672 dt = self.getDateTime(tm)
673 if self.xmin is None:
673 if self.xmin is None:
674 self.tmin = tm
674 self.tmin = tm
675 self.xmin = dt.hour
675 self.xmin = dt.hour
676 minutes = (self.xmin - int(self.xmin)) * 60
676 minutes = (self.xmin - int(self.xmin)) * 60
677 seconds = (minutes - int(minutes)) * 60
677 seconds = (minutes - int(minutes)) * 60
678 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
678 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
679 datetime.datetime(1970, 1, 1)).total_seconds()
679 datetime.datetime(1970, 1, 1)).total_seconds()
680 if self.localtime:
680 if self.localtime:
681 self.tmin += time.timezone
681 self.tmin += time.timezone
682
682
683 if self.xmin is not None and self.xmax is not None:
683 if self.xmin is not None and self.xmax is not None:
684 self.xrange = self.xmax - self.xmin
684 self.xrange = self.xmax - self.xmin
685
685
686 if self.throttle == 0:
686 if self.throttle == 0:
687 self.__plot()
687 self.__plot()
688 else:
688 else:
689 self.__throttle_plot(self.__plot) # , coerce=coerce)
689 self.__throttle_plot(self.__plot) # , coerce=coerce)
690
690
691 def close(self):
691 def close(self):
692
692
693 if self.data and not self.data.flagNoData:
693 if self.data and not self.data.flagNoData:
694 self.save_time = 0
694 self.save_time = 0
695 self.__plot()
695 self.__plot()
696 if self.data and not self.data.flagNoData and self.pause:
696 if self.data and not self.data.flagNoData and self.pause:
697 figpause(10)
697 figpause(10)
@@ -1,1615 +1,1621
1 """
1 """
2 Created on Jul 2, 2014
2 Created on Jul 2, 2014
3
3
4 @author: roj-idl71
4 @author: roj-idl71
5 """
5 """
6 import os
6 import os
7 import sys
7 import sys
8 import glob
8 import glob
9 import time
9 import time
10 import numpy
10 import numpy
11 import fnmatch
11 import fnmatch
12 import inspect
12 import inspect
13 import time
13 import time
14 import datetime
14 import datetime
15 import zmq
15 import zmq
16
16
17 from schainpy.model.proc.jroproc_base import Operation, MPDecorator
17 from schainpy.model.proc.jroproc_base import Operation, MPDecorator
18 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
18 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
19 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
19 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
20 from schainpy.utils import log
20 from schainpy.utils import log
21 import schainpy.admin
21 import schainpy.admin
22
22
23 LOCALTIME = True
23 LOCALTIME = True
24 DT_DIRECTIVES = {
24 DT_DIRECTIVES = {
25 '%Y': 4,
25 '%Y': 4,
26 '%y': 2,
26 '%y': 2,
27 '%m': 2,
27 '%m': 2,
28 '%d': 2,
28 '%d': 2,
29 '%j': 3,
29 '%j': 3,
30 '%H': 2,
30 '%H': 2,
31 '%M': 2,
31 '%M': 2,
32 '%S': 2,
32 '%S': 2,
33 '%f': 6
33 '%f': 6
34 }
34 }
35
35
36
36
37 def isNumber(cad):
37 def isNumber(cad):
38 """
38 """
39 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
39 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
40
40
41 Excepciones:
41 Excepciones:
42 Si un determinado string no puede ser convertido a numero
42 Si un determinado string no puede ser convertido a numero
43 Input:
43 Input:
44 str, string al cual se le analiza para determinar si convertible a un numero o no
44 str, string al cual se le analiza para determinar si convertible a un numero o no
45
45
46 Return:
46 Return:
47 True : si el string es uno numerico
47 True : si el string es uno numerico
48 False : no es un string numerico
48 False : no es un string numerico
49 """
49 """
50 try:
50 try:
51 float(cad)
51 float(cad)
52 return True
52 return True
53 except:
53 except:
54 return False
54 return False
55
55
56
56
57 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
57 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
58 """
58 """
59 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
59 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
60
60
61 Inputs:
61 Inputs:
62 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
62 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
63
63
64 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
64 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
65 segundos contados desde 01/01/1970.
65 segundos contados desde 01/01/1970.
66 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
66 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
67 segundos contados desde 01/01/1970.
67 segundos contados desde 01/01/1970.
68
68
69 Return:
69 Return:
70 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
70 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
71 fecha especificado, de lo contrario retorna False.
71 fecha especificado, de lo contrario retorna False.
72
72
73 Excepciones:
73 Excepciones:
74 Si el archivo no existe o no puede ser abierto
74 Si el archivo no existe o no puede ser abierto
75 Si la cabecera no puede ser leida.
75 Si la cabecera no puede ser leida.
76
76
77 """
77 """
78 basicHeaderObj = BasicHeader(LOCALTIME)
78 basicHeaderObj = BasicHeader(LOCALTIME)
79
79
80 try:
80 try:
81
81
82 fp = open(filename, 'rb')
82 fp = open(filename, 'rb')
83 except IOError:
83 except IOError:
84 print("The file %s can't be opened" % (filename))
84 print("The file %s can't be opened" % (filename))
85 return 0
85 return 0
86
86
87 sts = basicHeaderObj.read(fp)
87 sts = basicHeaderObj.read(fp)
88 fp.close()
88 fp.close()
89
89
90 if not(sts):
90 if not(sts):
91 print("Skipping the file %s because it has not a valid header" % (filename))
91 print("Skipping the file %s because it has not a valid header" % (filename))
92 return 0
92 return 0
93
93
94 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
94 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
95 return 0
95 return 0
96
96
97 return 1
97 return 1
98
98
99
99
100 def isTimeInRange(thisTime, startTime, endTime):
100 def isTimeInRange(thisTime, startTime, endTime):
101 if endTime >= startTime:
101 if endTime >= startTime:
102 if (thisTime < startTime) or (thisTime > endTime):
102 if (thisTime < startTime) or (thisTime > endTime):
103 return 0
103 return 0
104 return 1
104 return 1
105 else:
105 else:
106 if (thisTime < startTime) and (thisTime > endTime):
106 if (thisTime < startTime) and (thisTime > endTime):
107 return 0
107 return 0
108 return 1
108 return 1
109
109
110
110
111 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
111 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
112 """
112 """
113 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
113 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
114
114
115 Inputs:
115 Inputs:
116 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
116 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
117
117
118 startDate : fecha inicial del rango seleccionado en formato datetime.date
118 startDate : fecha inicial del rango seleccionado en formato datetime.date
119
119
120 endDate : fecha final del rango seleccionado en formato datetime.date
120 endDate : fecha final del rango seleccionado en formato datetime.date
121
121
122 startTime : tiempo inicial del rango seleccionado en formato datetime.time
122 startTime : tiempo inicial del rango seleccionado en formato datetime.time
123
123
124 endTime : tiempo final del rango seleccionado en formato datetime.time
124 endTime : tiempo final del rango seleccionado en formato datetime.time
125
125
126 Return:
126 Return:
127 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
127 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
128 fecha especificado, de lo contrario retorna False.
128 fecha especificado, de lo contrario retorna False.
129
129
130 Excepciones:
130 Excepciones:
131 Si el archivo no existe o no puede ser abierto
131 Si el archivo no existe o no puede ser abierto
132 Si la cabecera no puede ser leida.
132 Si la cabecera no puede ser leida.
133
133
134 """
134 """
135
135
136 try:
136 try:
137 fp = open(filename, 'rb')
137 fp = open(filename, 'rb')
138 except IOError:
138 except IOError:
139 print("The file %s can't be opened" % (filename))
139 print("The file %s can't be opened" % (filename))
140 return None
140 return None
141
141
142 firstBasicHeaderObj = BasicHeader(LOCALTIME)
142 firstBasicHeaderObj = BasicHeader(LOCALTIME)
143 systemHeaderObj = SystemHeader()
143 systemHeaderObj = SystemHeader()
144
144
145 radarControllerHeaderObj = RadarControllerHeader()
145 radarControllerHeaderObj = RadarControllerHeader()
146 processingHeaderObj = ProcessingHeader()
146 processingHeaderObj = ProcessingHeader()
147
147
148 lastBasicHeaderObj = BasicHeader(LOCALTIME)
148 lastBasicHeaderObj = BasicHeader(LOCALTIME)
149
149
150 sts = firstBasicHeaderObj.read(fp)
150 sts = firstBasicHeaderObj.read(fp)
151
151
152 if not(sts):
152 if not(sts):
153 print("[Reading] Skipping the file %s because it has not a valid header" % (filename))
153 print("[Reading] Skipping the file %s because it has not a valid header" % (filename))
154 return None
154 return None
155
155
156 if not systemHeaderObj.read(fp):
156 if not systemHeaderObj.read(fp):
157 return None
157 return None
158
158
159 if not radarControllerHeaderObj.read(fp):
159 if not radarControllerHeaderObj.read(fp):
160 return None
160 return None
161
161
162 if not processingHeaderObj.read(fp):
162 if not processingHeaderObj.read(fp):
163 return None
163 return None
164
164
165 filesize = os.path.getsize(filename)
165 filesize = os.path.getsize(filename)
166
166
167 offset = processingHeaderObj.blockSize + 24 # header size
167 offset = processingHeaderObj.blockSize + 24 # header size
168
168
169 if filesize <= offset:
169 if filesize <= offset:
170 print("[Reading] %s: This file has not enough data" % filename)
170 print("[Reading] %s: This file has not enough data" % filename)
171 return None
171 return None
172
172
173 fp.seek(-offset, 2)
173 fp.seek(-offset, 2)
174
174
175 sts = lastBasicHeaderObj.read(fp)
175 sts = lastBasicHeaderObj.read(fp)
176
176
177 fp.close()
177 fp.close()
178
178
179 thisDatetime = lastBasicHeaderObj.datatime
179 thisDatetime = lastBasicHeaderObj.datatime
180 thisTime_last_block = thisDatetime.time()
180 thisTime_last_block = thisDatetime.time()
181
181
182 thisDatetime = firstBasicHeaderObj.datatime
182 thisDatetime = firstBasicHeaderObj.datatime
183 thisDate = thisDatetime.date()
183 thisDate = thisDatetime.date()
184 thisTime_first_block = thisDatetime.time()
184 thisTime_first_block = thisDatetime.time()
185
185
186 # General case
186 # General case
187 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
187 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
188 #-----------o----------------------------o-----------
188 #-----------o----------------------------o-----------
189 # startTime endTime
189 # startTime endTime
190
190
191 if endTime >= startTime:
191 if endTime >= startTime:
192 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
192 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
193 return None
193 return None
194
194
195 return thisDatetime
195 return thisDatetime
196
196
197 # If endTime < startTime then endTime belongs to the next day
197 # If endTime < startTime then endTime belongs to the next day
198
198
199 # <<<<<<<<<<<o o>>>>>>>>>>>
199 # <<<<<<<<<<<o o>>>>>>>>>>>
200 #-----------o----------------------------o-----------
200 #-----------o----------------------------o-----------
201 # endTime startTime
201 # endTime startTime
202
202
203 if (thisDate == startDate) and (thisTime_last_block < startTime):
203 if (thisDate == startDate) and (thisTime_last_block < startTime):
204 return None
204 return None
205
205
206 if (thisDate == endDate) and (thisTime_first_block > endTime):
206 if (thisDate == endDate) and (thisTime_first_block > endTime):
207 return None
207 return None
208
208
209 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
209 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
210 return None
210 return None
211
211
212 return thisDatetime
212 return thisDatetime
213
213
214
214
215 def isFolderInDateRange(folder, startDate=None, endDate=None):
215 def isFolderInDateRange(folder, startDate=None, endDate=None):
216 """
216 """
217 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
217 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
218
218
219 Inputs:
219 Inputs:
220 folder : nombre completo del directorio.
220 folder : nombre completo del directorio.
221 Su formato deberia ser "/path_root/?YYYYDDD"
221 Su formato deberia ser "/path_root/?YYYYDDD"
222
222
223 siendo:
223 siendo:
224 YYYY : Anio (ejemplo 2015)
224 YYYY : Anio (ejemplo 2015)
225 DDD : Dia del anio (ejemplo 305)
225 DDD : Dia del anio (ejemplo 305)
226
226
227 startDate : fecha inicial del rango seleccionado en formato datetime.date
227 startDate : fecha inicial del rango seleccionado en formato datetime.date
228
228
229 endDate : fecha final del rango seleccionado en formato datetime.date
229 endDate : fecha final del rango seleccionado en formato datetime.date
230
230
231 Return:
231 Return:
232 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
232 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
233 fecha especificado, de lo contrario retorna False.
233 fecha especificado, de lo contrario retorna False.
234 Excepciones:
234 Excepciones:
235 Si el directorio no tiene el formato adecuado
235 Si el directorio no tiene el formato adecuado
236 """
236 """
237
237
238 basename = os.path.basename(folder)
238 basename = os.path.basename(folder)
239
239
240 if not isRadarFolder(basename):
240 if not isRadarFolder(basename):
241 print("The folder %s has not the rigth format" % folder)
241 print("The folder %s has not the rigth format" % folder)
242 return 0
242 return 0
243
243
244 if startDate and endDate:
244 if startDate and endDate:
245 thisDate = getDateFromRadarFolder(basename)
245 thisDate = getDateFromRadarFolder(basename)
246
246
247 if thisDate < startDate:
247 if thisDate < startDate:
248 return 0
248 return 0
249
249
250 if thisDate > endDate:
250 if thisDate > endDate:
251 return 0
251 return 0
252
252
253 return 1
253 return 1
254
254
255
255
256 def isFileInDateRange(filename, startDate=None, endDate=None):
256 def isFileInDateRange(filename, startDate=None, endDate=None):
257 """
257 """
258 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
258 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
259
259
260 Inputs:
260 Inputs:
261 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
261 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
262
262
263 Su formato deberia ser "?YYYYDDDsss"
263 Su formato deberia ser "?YYYYDDDsss"
264
264
265 siendo:
265 siendo:
266 YYYY : Anio (ejemplo 2015)
266 YYYY : Anio (ejemplo 2015)
267 DDD : Dia del anio (ejemplo 305)
267 DDD : Dia del anio (ejemplo 305)
268 sss : set
268 sss : set
269
269
270 startDate : fecha inicial del rango seleccionado en formato datetime.date
270 startDate : fecha inicial del rango seleccionado en formato datetime.date
271
271
272 endDate : fecha final del rango seleccionado en formato datetime.date
272 endDate : fecha final del rango seleccionado en formato datetime.date
273
273
274 Return:
274 Return:
275 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
275 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
276 fecha especificado, de lo contrario retorna False.
276 fecha especificado, de lo contrario retorna False.
277 Excepciones:
277 Excepciones:
278 Si el archivo no tiene el formato adecuado
278 Si el archivo no tiene el formato adecuado
279 """
279 """
280
280
281 basename = os.path.basename(filename)
281 basename = os.path.basename(filename)
282
282
283 if not isRadarFile(basename):
283 if not isRadarFile(basename):
284 print("The filename %s has not the rigth format" % filename)
284 print("The filename %s has not the rigth format" % filename)
285 return 0
285 return 0
286
286
287 if startDate and endDate:
287 if startDate and endDate:
288 thisDate = getDateFromRadarFile(basename)
288 thisDate = getDateFromRadarFile(basename)
289
289
290 if thisDate < startDate:
290 if thisDate < startDate:
291 return 0
291 return 0
292
292
293 if thisDate > endDate:
293 if thisDate > endDate:
294 return 0
294 return 0
295
295
296 return 1
296 return 1
297
297
298
298
299 def getFileFromSet(path, ext, set):
299 def getFileFromSet(path, ext, set):
300 validFilelist = []
300 validFilelist = []
301 fileList = os.listdir(path)
301 fileList = os.listdir(path)
302
302
303 # 0 1234 567 89A BCDE
303 # 0 1234 567 89A BCDE
304 # H YYYY DDD SSS .ext
304 # H YYYY DDD SSS .ext
305
305
306 for thisFile in fileList:
306 for thisFile in fileList:
307 try:
307 try:
308 year = int(thisFile[1:5])
308 year = int(thisFile[1:5])
309 doy = int(thisFile[5:8])
309 doy = int(thisFile[5:8])
310 except:
310 except:
311 continue
311 continue
312
312
313 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
313 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
314 continue
314 continue
315
315
316 validFilelist.append(thisFile)
316 validFilelist.append(thisFile)
317
317
318 myfile = fnmatch.filter(
318 myfile = fnmatch.filter(
319 validFilelist, '*%4.4d%3.3d%3.3d*' % (year, doy, set))
319 validFilelist, '*%4.4d%3.3d%3.3d*' % (year, doy, set))
320
320
321 if len(myfile) != 0:
321 if len(myfile) != 0:
322 return myfile[0]
322 return myfile[0]
323 else:
323 else:
324 filename = '*%4.4d%3.3d%3.3d%s' % (year, doy, set, ext.lower())
324 filename = '*%4.4d%3.3d%3.3d%s' % (year, doy, set, ext.lower())
325 print('the filename %s does not exist' % filename)
325 print('the filename %s does not exist' % filename)
326 print('...going to the last file: ')
326 print('...going to the last file: ')
327
327
328 if validFilelist:
328 if validFilelist:
329 validFilelist = sorted(validFilelist, key=str.lower)
329 validFilelist = sorted(validFilelist, key=str.lower)
330 return validFilelist[-1]
330 return validFilelist[-1]
331
331
332 return None
332 return None
333
333
334
334
335 def getlastFileFromPath(path, ext):
335 def getlastFileFromPath(path, ext):
336 """
336 """
337 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
337 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
338 al final de la depuracion devuelve el ultimo file de la lista que quedo.
338 al final de la depuracion devuelve el ultimo file de la lista que quedo.
339
339
340 Input:
340 Input:
341 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
341 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
342 ext : extension de los files contenidos en una carpeta
342 ext : extension de los files contenidos en una carpeta
343
343
344 Return:
344 Return:
345 El ultimo file de una determinada carpeta, no se considera el path.
345 El ultimo file de una determinada carpeta, no se considera el path.
346 """
346 """
347 validFilelist = []
347 validFilelist = []
348 fileList = os.listdir(path)
348 fileList = os.listdir(path)
349
349
350 # 0 1234 567 89A BCDE
350 # 0 1234 567 89A BCDE
351 # H YYYY DDD SSS .ext
351 # H YYYY DDD SSS .ext
352
352
353 for thisFile in fileList:
353 for thisFile in fileList:
354
354
355 year = thisFile[1:5]
355 year = thisFile[1:5]
356 if not isNumber(year):
356 if not isNumber(year):
357 continue
357 continue
358
358
359 doy = thisFile[5:8]
359 doy = thisFile[5:8]
360 if not isNumber(doy):
360 if not isNumber(doy):
361 continue
361 continue
362
362
363 year = int(year)
363 year = int(year)
364 doy = int(doy)
364 doy = int(doy)
365
365
366 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
366 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
367 continue
367 continue
368
368
369 validFilelist.append(thisFile)
369 validFilelist.append(thisFile)
370
370
371 if validFilelist:
371 if validFilelist:
372 validFilelist = sorted(validFilelist, key=str.lower)
372 validFilelist = sorted(validFilelist, key=str.lower)
373 return validFilelist[-1]
373 return validFilelist[-1]
374
374
375 return None
375 return None
376
376
377
377
378 def isRadarFolder(folder):
378 def isRadarFolder(folder):
379 try:
379 try:
380 year = int(folder[1:5])
380 year = int(folder[1:5])
381 doy = int(folder[5:8])
381 doy = int(folder[5:8])
382 except:
382 except:
383 return 0
383 return 0
384
384
385 return 1
385 return 1
386
386
387
387
388 def isRadarFile(file):
388 def isRadarFile(file):
389 try:
389 try:
390 year = int(file[1:5])
390 year = int(file[1:5])
391 doy = int(file[5:8])
391 doy = int(file[5:8])
392 set = int(file[8:11])
392 set = int(file[8:11])
393 except:
393 except:
394 return 0
394 return 0
395
395
396 return 1
396 return 1
397
397
398
398
399 def getDateFromRadarFile(file):
399 def getDateFromRadarFile(file):
400 try:
400 try:
401 year = int(file[1:5])
401 year = int(file[1:5])
402 doy = int(file[5:8])
402 doy = int(file[5:8])
403 set = int(file[8:11])
403 set = int(file[8:11])
404 except:
404 except:
405 return None
405 return None
406
406
407 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
407 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
408 return thisDate
408 return thisDate
409
409
410
410
411 def getDateFromRadarFolder(folder):
411 def getDateFromRadarFolder(folder):
412 try:
412 try:
413 year = int(folder[1:5])
413 year = int(folder[1:5])
414 doy = int(folder[5:8])
414 doy = int(folder[5:8])
415 except:
415 except:
416 return None
416 return None
417
417
418 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
418 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
419 return thisDate
419 return thisDate
420
420
421 def parse_format(s, fmt):
421 def parse_format(s, fmt):
422
422
423 for i in range(fmt.count('%')):
423 for i in range(fmt.count('%')):
424 x = fmt.index('%')
424 x = fmt.index('%')
425 d = DT_DIRECTIVES[fmt[x:x + 2]]
425 d = DT_DIRECTIVES[fmt[x:x + 2]]
426 fmt = fmt.replace(fmt[x:x + 2], s[x:x + d])
426 fmt = fmt.replace(fmt[x:x + 2], s[x:x + d])
427 return fmt
427 return fmt
428
428
429 class Reader(object):
429 class Reader(object):
430
430
431 c = 3E8
431 c = 3E8
432 isConfig = False
432 isConfig = False
433 dtype = None
433 dtype = None
434 pathList = []
434 pathList = []
435 filenameList = []
435 filenameList = []
436 datetimeList = []
436 datetimeList = []
437 filename = None
437 filename = None
438 ext = None
438 ext = None
439 flagIsNewFile = 1
439 flagIsNewFile = 1
440 flagDiscontinuousBlock = 0
440 flagDiscontinuousBlock = 0
441 flagIsNewBlock = 0
441 flagIsNewBlock = 0
442 flagNoMoreFiles = 0
442 flagNoMoreFiles = 0
443 fp = None
443 fp = None
444 firstHeaderSize = 0
444 firstHeaderSize = 0
445 basicHeaderSize = 24
445 basicHeaderSize = 24
446 versionFile = 1103
446 versionFile = 1103
447 fileSize = None
447 fileSize = None
448 fileSizeByHeader = None
448 fileSizeByHeader = None
449 fileIndex = -1
449 fileIndex = -1
450 profileIndex = None
450 profileIndex = None
451 blockIndex = 0
451 blockIndex = 0
452 nTotalBlocks = 0
452 nTotalBlocks = 0
453 maxTimeStep = 30
453 maxTimeStep = 30
454 lastUTTime = None
454 lastUTTime = None
455 datablock = None
455 datablock = None
456 dataOut = None
456 dataOut = None
457 getByBlock = False
457 getByBlock = False
458 path = None
458 path = None
459 startDate = None
459 startDate = None
460 endDate = None
460 endDate = None
461 startTime = datetime.time(0, 0, 0)
461 startTime = datetime.time(0, 0, 0)
462 endTime = datetime.time(23, 59, 59)
462 endTime = datetime.time(23, 59, 59)
463 set = None
463 set = None
464 expLabel = ""
464 expLabel = ""
465 online = False
465 online = False
466 delay = 60
466 delay = 60
467 nTries = 3 # quantity tries
467 nTries = 3 # quantity tries
468 nFiles = 3 # number of files for searching
468 nFiles = 3 # number of files for searching
469 walk = True
469 walk = True
470 getblock = False
470 getblock = False
471 nTxs = 1
471 nTxs = 1
472 realtime = False
472 realtime = False
473 blocksize = 0
473 blocksize = 0
474 blocktime = None
474 blocktime = None
475 warnings = True
475 warnings = True
476 verbose = True
476 verbose = True
477 server = None
477 server = None
478 format = None
478 format = None
479 oneDDict = None
479 oneDDict = None
480 twoDDict = None
480 twoDDict = None
481 independentParam = None
481 independentParam = None
482 filefmt = None
482 filefmt = None
483 folderfmt = None
483 folderfmt = None
484 open_file = open
484 open_file = open
485 open_mode = 'rb'
485 open_mode = 'rb'
486
486
487 def run(self):
487 def run(self):
488
488
489 raise NotImplementedError
489 raise NotImplementedError
490
490
491 def getAllowedArgs(self):
491 def getAllowedArgs(self):
492 if hasattr(self, '__attrs__'):
492 if hasattr(self, '__attrs__'):
493 return self.__attrs__
493 return self.__attrs__
494 else:
494 else:
495 return inspect.getargspec(self.run).args
495 return inspect.getargspec(self.run).args
496
496
497 def set_kwargs(self, **kwargs):
497 def set_kwargs(self, **kwargs):
498
498
499 for key, value in kwargs.items():
499 for key, value in kwargs.items():
500 setattr(self, key, value)
500 setattr(self, key, value)
501
501
502 def find_folders(self, path, startDate, endDate, folderfmt, last=False):
502 def find_folders(self, path, startDate, endDate, folderfmt, last=False):
503
503
504 folders = [x for f in path.split(',')
504 folders = [x for f in path.split(',')
505 for x in os.listdir(f) if os.path.isdir(os.path.join(f, x))]
505 for x in os.listdir(f) if os.path.isdir(os.path.join(f, x))]
506 folders.sort()
506 folders.sort()
507
507
508 if last:
508 if last:
509 folders = [folders[-1]]
509 folders = [folders[-1]]
510
510
511 for folder in folders:
511 for folder in folders:
512 try:
512 try:
513 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
513 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
514 if dt >= startDate and dt <= endDate:
514 if dt >= startDate and dt <= endDate:
515 yield os.path.join(path, folder)
515 yield os.path.join(path, folder)
516 else:
516 else:
517 log.log('Skiping folder {}'.format(folder), self.name)
517 log.log('Skiping folder {}'.format(folder), self.name)
518 except Exception as e:
518 except Exception as e:
519 log.log('Skiping folder {}'.format(folder), self.name)
519 log.log('Skiping folder {}'.format(folder), self.name)
520 continue
520 continue
521 return
521 return
522
522
523 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
523 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
524 expLabel='', last=False):
524 expLabel='', last=False):
525
525
526 for path in folders:
526 for path in folders:
527 files = glob.glob1(path, '*{}'.format(ext))
527 files = glob.glob1(path, '*{}'.format(ext))
528 files.sort()
528 files.sort()
529 if last:
529 if last:
530 if files:
530 if files:
531 fo = files[-1]
531 fo = files[-1]
532 try:
532 try:
533 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
533 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
534 yield os.path.join(path, expLabel, fo)
534 yield os.path.join(path, expLabel, fo)
535 except Exception as e:
535 except Exception as e:
536 pass
536 pass
537 return
537 return
538 else:
538 else:
539 return
539 return
540
540
541 for fo in files:
541 for fo in files:
542 try:
542 try:
543 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
543 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
544 #print(dt)
544 #print(dt)
545 #print(startDate)
545 #print(startDate)
546 #print(endDate)
546 #print(endDate)
547 if dt >= startDate and dt <= endDate:
547 if dt >= startDate and dt <= endDate:
548
548
549 yield os.path.join(path, expLabel, fo)
549 yield os.path.join(path, expLabel, fo)
550
550
551 else:
551 else:
552
552
553 log.log('Skiping file {}'.format(fo), self.name)
553 log.log('Skiping file {}'.format(fo), self.name)
554 except Exception as e:
554 except Exception as e:
555 log.log('Skiping file {}'.format(fo), self.name)
555 log.log('Skiping file {}'.format(fo), self.name)
556 continue
556 continue
557
557
558 def searchFilesOffLine(self, path, startDate, endDate,
558 def searchFilesOffLine(self, path, startDate, endDate,
559 expLabel, ext, walk,
559 expLabel, ext, walk,
560 filefmt, folderfmt):
560 filefmt, folderfmt):
561 """Search files in offline mode for the given arguments
561 """Search files in offline mode for the given arguments
562
562
563 Return:
563 Return:
564 Generator of files
564 Generator of files
565 """
565 """
566
566
567 if walk:
567 if walk:
568 folders = self.find_folders(
568 folders = self.find_folders(
569 path, startDate, endDate, folderfmt)
569 path, startDate, endDate, folderfmt)
570 else:
570 else:
571 folders = path.split(',')
571 folders = path.split(',')
572
572
573 return self.find_files(
573 return self.find_files(
574 folders, ext, filefmt, startDate, endDate, expLabel)
574 folders, ext, filefmt, startDate, endDate, expLabel)
575
575
576 def searchFilesOnLine(self, path, startDate, endDate,
576 def searchFilesOnLine(self, path, startDate, endDate,
577 expLabel, ext, walk,
577 expLabel, ext, walk,
578 filefmt, folderfmt):
578 filefmt, folderfmt):
579 """Search for the last file of the last folder
579 """Search for the last file of the last folder
580
580
581 Arguments:
581 Arguments:
582 path : carpeta donde estan contenidos los files que contiene data
582 path : carpeta donde estan contenidos los files que contiene data
583 expLabel : Nombre del subexperimento (subfolder)
583 expLabel : Nombre del subexperimento (subfolder)
584 ext : extension de los files
584 ext : extension de los files
585 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
585 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
586
586
587 Return:
587 Return:
588 generator with the full path of last filename
588 generator with the full path of last filename
589 """
589 """
590
590
591 if walk:
591 if walk:
592 folders = self.find_folders(
592 folders = self.find_folders(
593 path, startDate, endDate, folderfmt, last=True)
593 path, startDate, endDate, folderfmt, last=True)
594 else:
594 else:
595 folders = path.split(',')
595 folders = path.split(',')
596
596
597 return self.find_files(
597 return self.find_files(
598 folders, ext, filefmt, startDate, endDate, expLabel, last=True)
598 folders, ext, filefmt, startDate, endDate, expLabel, last=True)
599
599
600 def setNextFile(self):
600 def setNextFile(self):
601 """Set the next file to be readed open it and parse de file header"""
601 """Set the next file to be readed open it and parse de file header"""
602
602
603 #print("fp: ",self.fp)
603 #print("fp: ",self.fp)
604 while True:
604 while True:
605
605
606 #print(self.fp)
606 #print(self.fp)
607 if self.fp != None:
607 if self.fp != None:
608 self.fp.close()
608 self.fp.close()
609
609
610 #print("setNextFile")
610 #print("setNextFile")
611 #print("BEFORE OPENING",self.filename)
611 #print("BEFORE OPENING",self.filename)
612 if self.online:
612 if self.online:
613 newFile = self.setNextFileOnline()
613 newFile = self.setNextFileOnline()
614
614
615 else:
615 else:
616
616
617 newFile = self.setNextFileOffline()
617 newFile = self.setNextFileOffline()
618
618
619 #print("newFile: ",newFile)
619 #print("newFile: ",newFile)
620 if not(newFile):
620 if not(newFile):
621
621
622 if self.online:
622 if self.online:
623 raise schainpy.admin.SchainError('Time to wait for new files reach')
623 raise schainpy.admin.SchainError('Time to wait for new files reach')
624 else:
624 else:
625 if self.fileIndex == -1:
625 if self.fileIndex == -1:
626 #print("OKK")
626 #print("OKK")
627 raise schainpy.admin.SchainWarning('No files found in the given path')
627 raise schainpy.admin.SchainWarning('No files found in the given path')
628 else:
628 else:
629
629
630 raise schainpy.admin.SchainWarning('No more files to read')
630 raise schainpy.admin.SchainWarning('No more files to read')
631
631
632 if self.verifyFile(self.filename):
632 if self.verifyFile(self.filename):
633
633
634 break
634 break
635
635
636 ##print("BEFORE OPENING",self.filename)
636 ##print("BEFORE OPENING",self.filename)
637
637
638 log.log('Opening file: %s' % self.filename, self.name)
638 log.log('Opening file: %s' % self.filename, self.name)
639
639
640 self.readFirstHeader()
640 self.readFirstHeader()
641 self.nReadBlocks = 0
641 self.nReadBlocks = 0
642
642
643 def setNextFileOnline(self):
643 def setNextFileOnline(self):
644 """Check for the next file to be readed in online mode.
644 """Check for the next file to be readed in online mode.
645
645
646 Set:
646 Set:
647 self.filename
647 self.filename
648 self.fp
648 self.fp
649 self.filesize
649 self.filesize
650
650
651 Return:
651 Return:
652 boolean
652 boolean
653
653
654 """
654 """
655
655
656 nextFile = True
656 nextFile = True
657 nextDay = False
657 nextDay = False
658
658
659 for nFiles in range(self.nFiles + 1):
659 for nFiles in range(self.nFiles + 1):
660 for nTries in range(self.nTries):
660 for nTries in range(self.nTries):
661 fullfilename, filename = self.checkForRealPath(nextFile, nextDay)
661 fullfilename, filename = self.checkForRealPath(nextFile, nextDay)
662 if fullfilename is not None:
662 if fullfilename is not None:
663 break
663 break
664 log.warning(
664 log.warning(
665 "Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, filename, nTries + 1),
665 "Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, filename, nTries + 1),
666 self.name)
666 self.name)
667 time.sleep(self.delay)
667 time.sleep(self.delay)
668 nextFile = False
668 nextFile = False
669 continue
669 continue
670
670
671 if fullfilename is not None:
671 if fullfilename is not None:
672 break
672 break
673
673
674 #self.nTries = 1
674 #self.nTries = 1
675 nextFile = True
675 nextFile = True
676
676
677 if nFiles == (self.nFiles - 1):
677 if nFiles == (self.nFiles - 1):
678 log.log('Trying with next day...', self.name)
678 log.log('Trying with next day...', self.name)
679 nextDay = True
679 nextDay = True
680 self.nTries = 3
680 self.nTries = 3
681
681
682 if fullfilename:
682 if fullfilename:
683 self.fileSize = os.path.getsize(fullfilename)
683 self.fileSize = os.path.getsize(fullfilename)
684 self.filename = fullfilename
684 self.filename = fullfilename
685 self.flagIsNewFile = 1
685 self.flagIsNewFile = 1
686 if self.fp != None:
686 if self.fp != None:
687 self.fp.close()
687 self.fp.close()
688 #print(fullfilename)
688 #print(fullfilename)
689 self.fp = self.open_file(fullfilename, self.open_mode)
689 self.fp = self.open_file(fullfilename, self.open_mode)
690
690
691 self.flagNoMoreFiles = 0
691 self.flagNoMoreFiles = 0
692 self.fileIndex += 1
692 self.fileIndex += 1
693 return 1
693 return 1
694 else:
694 else:
695 return 0
695 return 0
696
696
697 def setNextFileOffline(self):
697 def setNextFileOffline(self):
698 """Open the next file to be readed in offline mode"""
698 """Open the next file to be readed in offline mode"""
699
699
700 try:
700 try:
701 filename = next(self.filenameList)
701 filename = next(self.filenameList)
702 self.fileIndex += 1
702 self.fileIndex += 1
703 except StopIteration:
703 except StopIteration:
704 self.flagNoMoreFiles = 1
704 self.flagNoMoreFiles = 1
705 return 0
705 return 0
706 #print(self.fileIndex)
706 #print(self.fileIndex)
707 #print(filename)
707 #print(filename)
708 self.filename = filename
708 self.filename = filename
709 self.fileSize = os.path.getsize(filename)
709 self.fileSize = os.path.getsize(filename)
710 self.fp = self.open_file(filename, self.open_mode)
710 self.fp = self.open_file(filename, self.open_mode)
711 self.flagIsNewFile = 1
711 self.flagIsNewFile = 1
712
712
713 return 1
713 return 1
714
714
715 @staticmethod
715 @staticmethod
716 def isDateTimeInRange(dt, startDate, endDate, startTime, endTime):
716 def isDateTimeInRange(dt, startDate, endDate, startTime, endTime):
717 """Check if the given datetime is in range"""
717 """Check if the given datetime is in range"""
718
718
719 if startDate <= dt.date() <= endDate:
719 if startDate <= dt.date() <= endDate:
720 if startTime <= dt.time() <= endTime:
720 if startTime <= dt.time() <= endTime:
721 return True
721 return True
722 return False
722 return False
723
723
724 def verifyFile(self, filename):
724 def verifyFile(self, filename):
725 """Check for a valid file
725 """Check for a valid file
726
726
727 Arguments:
727 Arguments:
728 filename -- full path filename
728 filename -- full path filename
729
729
730 Return:
730 Return:
731 boolean
731 boolean
732 """
732 """
733
733
734 return True
734 return True
735
735
736 def checkForRealPath(self, nextFile, nextDay):
736 def checkForRealPath(self, nextFile, nextDay):
737 """Check if the next file to be readed exists"""
737 """Check if the next file to be readed exists"""
738
738
739 raise NotImplementedError
739 raise NotImplementedError
740
740
741 def readFirstHeader(self):
741 def readFirstHeader(self):
742 """Parse the file header"""
742 """Parse the file header"""
743
743
744
744
745 pass
745 pass
746
746
747 def waitDataBlock(self, pointer_location, blocksize=None):
747 def waitDataBlock(self, pointer_location, blocksize=None):
748 """
748 """
749 """
749 """
750
750
751 currentPointer = pointer_location
751 currentPointer = pointer_location
752 if blocksize is None:
752 if blocksize is None:
753 neededSize = self.processingHeaderObj.blockSize # + self.basicHeaderSize
753 neededSize = self.processingHeaderObj.blockSize # + self.basicHeaderSize
754 else:
754 else:
755 neededSize = blocksize
755 neededSize = blocksize
756
756
757 for nTries in range(self.nTries):
757 for nTries in range(self.nTries):
758 self.fp.close()
758 self.fp.close()
759 self.fp = open(self.filename, 'rb')
759 self.fp = open(self.filename, 'rb')
760 self.fp.seek(currentPointer)
760 self.fp.seek(currentPointer)
761
761
762 self.fileSize = os.path.getsize(self.filename)
762 self.fileSize = os.path.getsize(self.filename)
763 currentSize = self.fileSize - currentPointer
763 currentSize = self.fileSize - currentPointer
764
764
765 if (currentSize >= neededSize):
765 if (currentSize >= neededSize):
766 return 1
766 return 1
767
767
768 log.warning(
768 log.warning(
769 "Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1),
769 "Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1),
770 self.name
770 self.name
771 )
771 )
772 time.sleep(self.delay)
772 time.sleep(self.delay)
773
773
774 return 0
774 return 0
775
775
776 class JRODataReader(Reader):
776 class JRODataReader(Reader):
777
777
778 utc = 0
778 utc = 0
779 nReadBlocks = 0
779 nReadBlocks = 0
780 foldercounter = 0
780 foldercounter = 0
781 firstHeaderSize = 0
781 firstHeaderSize = 0
782 basicHeaderSize = 24
782 basicHeaderSize = 24
783 __isFirstTimeOnline = 1
783 __isFirstTimeOnline = 1
784 topic = ''
784 filefmt = "*%Y%j***"
785 filefmt = "*%Y%j***"
785 folderfmt = "*%Y%j"
786 folderfmt = "*%Y%j"
786 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'online', 'delay', 'walk']
787 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'online', 'delay', 'walk']
787
788
788 def getDtypeWidth(self):
789 def getDtypeWidth(self):
789
790
790 dtype_index = get_dtype_index(self.dtype)
791 dtype_index = get_dtype_index(self.dtype)
791 dtype_width = get_dtype_width(dtype_index)
792 dtype_width = get_dtype_width(dtype_index)
792
793
793 return dtype_width
794 return dtype_width
794
795
795 def checkForRealPath(self, nextFile, nextDay):
796 def checkForRealPath(self, nextFile, nextDay):
796 """Check if the next file to be readed exists.
797 """Check if the next file to be readed exists.
797
798
798 Example :
799 Example :
799 nombre correcto del file es .../.../D2009307/P2009307367.ext
800 nombre correcto del file es .../.../D2009307/P2009307367.ext
800
801
801 Entonces la funcion prueba con las siguientes combinaciones
802 Entonces la funcion prueba con las siguientes combinaciones
802 .../.../y2009307367.ext
803 .../.../y2009307367.ext
803 .../.../Y2009307367.ext
804 .../.../Y2009307367.ext
804 .../.../x2009307/y2009307367.ext
805 .../.../x2009307/y2009307367.ext
805 .../.../x2009307/Y2009307367.ext
806 .../.../x2009307/Y2009307367.ext
806 .../.../X2009307/y2009307367.ext
807 .../.../X2009307/y2009307367.ext
807 .../.../X2009307/Y2009307367.ext
808 .../.../X2009307/Y2009307367.ext
808 siendo para este caso, la ultima combinacion de letras, identica al file buscado
809 siendo para este caso, la ultima combinacion de letras, identica al file buscado
809
810
810 Return:
811 Return:
811 str -- fullpath of the file
812 str -- fullpath of the file
812 """
813 """
813
814
814
815
815 if nextFile:
816 if nextFile:
816 self.set += 1
817 self.set += 1
817 if nextDay:
818 if nextDay:
818 self.set = 0
819 self.set = 0
819 self.doy += 1
820 self.doy += 1
820 foldercounter = 0
821 foldercounter = 0
821 prefixDirList = [None, 'd', 'D']
822 prefixDirList = [None, 'd', 'D']
822 if self.ext.lower() == ".r": # voltage
823 if self.ext.lower() == ".r": # voltage
823 prefixFileList = ['d', 'D']
824 prefixFileList = ['d', 'D']
824 elif self.ext.lower() == ".pdata": # spectra
825 elif self.ext.lower() == ".pdata": # spectra
825 prefixFileList = ['p', 'P']
826 prefixFileList = ['p', 'P']
826
827
827 ##############DP##############
828 ##############DP##############
828
829
829 elif self.ext.lower() == ".dat": # dat
830 elif self.ext.lower() == ".dat": # dat
830 prefixFileList = ['z', 'Z']
831 prefixFileList = ['z', 'Z']
831
832
832
833
833
834
834 ##############DP##############
835 ##############DP##############
835 # barrido por las combinaciones posibles
836 # barrido por las combinaciones posibles
836 for prefixDir in prefixDirList:
837 for prefixDir in prefixDirList:
837 thispath = self.path
838 thispath = self.path
838 if prefixDir != None:
839 if prefixDir != None:
839 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
840 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
840 if foldercounter == 0:
841 if foldercounter == 0:
841 thispath = os.path.join(self.path, "%s%04d%03d" %
842 thispath = os.path.join(self.path, "%s%04d%03d" %
842 (prefixDir, self.year, self.doy))
843 (prefixDir, self.year, self.doy))
843 else:
844 else:
844 thispath = os.path.join(self.path, "%s%04d%03d_%02d" % (
845 thispath = os.path.join(self.path, "%s%04d%03d_%02d" % (
845 prefixDir, self.year, self.doy, foldercounter))
846 prefixDir, self.year, self.doy, foldercounter))
846 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
847 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
847 # formo el nombre del file xYYYYDDDSSS.ext
848 # formo el nombre del file xYYYYDDDSSS.ext
848 filename = "%s%04d%03d%03d%s" % (prefixFile, self.year, self.doy, self.set, self.ext)
849 filename = "%s%04d%03d%03d%s" % (prefixFile, self.year, self.doy, self.set, self.ext)
849 fullfilename = os.path.join(
850 fullfilename = os.path.join(
850 thispath, filename)
851 thispath, filename)
851
852
852 if os.path.exists(fullfilename):
853 if os.path.exists(fullfilename):
853 return fullfilename, filename
854 return fullfilename, filename
854
855
855 return None, filename
856 return None, filename
856
857
857 def __waitNewBlock(self):
858 def __waitNewBlock(self):
858 """
859 """
859 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
860 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
860
861
861 Si el modo de lectura es OffLine siempre retorn 0
862 Si el modo de lectura es OffLine siempre retorn 0
862 """
863 """
863 if not self.online:
864 if not self.online:
864 return 0
865 return 0
865
866
866 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
867 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
867 return 0
868 return 0
868
869
869 currentPointer = self.fp.tell()
870 currentPointer = self.fp.tell()
870
871
871 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
872 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
872
873
873 for nTries in range(self.nTries):
874 for nTries in range(self.nTries):
874
875
875 self.fp.close()
876 self.fp.close()
876 self.fp = open(self.filename, 'rb')
877 self.fp = open(self.filename, 'rb')
877 self.fp.seek(currentPointer)
878 self.fp.seek(currentPointer)
878
879
879 self.fileSize = os.path.getsize(self.filename)
880 self.fileSize = os.path.getsize(self.filename)
880 currentSize = self.fileSize - currentPointer
881 currentSize = self.fileSize - currentPointer
881
882
882 if (currentSize >= neededSize):
883 if (currentSize >= neededSize):
883 self.basicHeaderObj.read(self.fp)
884 self.basicHeaderObj.read(self.fp)
884 return 1
885 return 1
885
886
886 if self.fileSize == self.fileSizeByHeader:
887 if self.fileSize == self.fileSizeByHeader:
887 # self.flagEoF = True
888 # self.flagEoF = True
888 return 0
889 return 0
889
890
890 print("[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1))
891 print("[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1))
891 #print(self.filename)
892 #print(self.filename)
892 time.sleep(self.delay)
893 time.sleep(self.delay)
893
894
894 return 0
895 return 0
895
896
896 def __setNewBlock(self):
897 def __setNewBlock(self):
897
898
898 if self.fp == None:
899 if self.fp == None:
899 return 0
900 return 0
900
901
901 if self.flagIsNewFile:
902 if self.flagIsNewFile:
902 self.lastUTTime = self.basicHeaderObj.utc
903 self.lastUTTime = self.basicHeaderObj.utc
903 return 1
904 return 1
904
905
905 if self.realtime:
906 if self.realtime:
906 self.flagDiscontinuousBlock = 1
907 self.flagDiscontinuousBlock = 1
907 if not(self.setNextFile()):
908 if not(self.setNextFile()):
908 return 0
909 return 0
909 else:
910 else:
910 return 1
911 return 1
911
912
912 currentSize = self.fileSize - self.fp.tell()
913 currentSize = self.fileSize - self.fp.tell()
913 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
914 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
914
915
915 if (currentSize >= neededSize):
916 if (currentSize >= neededSize):
916 self.basicHeaderObj.read(self.fp)
917 self.basicHeaderObj.read(self.fp)
917 self.lastUTTime = self.basicHeaderObj.utc
918 self.lastUTTime = self.basicHeaderObj.utc
918 return 1
919 return 1
919
920
920 if self.__waitNewBlock():
921 if self.__waitNewBlock():
921 self.lastUTTime = self.basicHeaderObj.utc
922 self.lastUTTime = self.basicHeaderObj.utc
922 return 1
923 return 1
923
924
924 if not(self.setNextFile()):
925 if not(self.setNextFile()):
925 return 0
926 return 0
926
927
927 deltaTime = self.basicHeaderObj.utc - self.lastUTTime
928 deltaTime = self.basicHeaderObj.utc - self.lastUTTime
928 self.lastUTTime = self.basicHeaderObj.utc
929 self.lastUTTime = self.basicHeaderObj.utc
929
930
930 self.flagDiscontinuousBlock = 0
931 self.flagDiscontinuousBlock = 0
931
932
932 if deltaTime > self.maxTimeStep:
933 if deltaTime > self.maxTimeStep:
933 self.flagDiscontinuousBlock = 1
934 self.flagDiscontinuousBlock = 1
934
935
935 return 1
936 return 1
936
937
937 def readNextBlock(self):
938 def readNextBlock(self):
938
939
939 while True:
940 while True:
940 if not(self.__setNewBlock()):
941 if not(self.__setNewBlock()):
941 continue
942 continue
942
943
943 if not(self.readBlock()):
944 if not(self.readBlock()):
944 return 0
945 return 0
945
946
946 self.getBasicHeader()
947 self.getBasicHeader()
947
948
948 if not self.isDateTimeInRange(self.dataOut.datatime, self.startDate, self.endDate, self.startTime, self.endTime):
949 if not self.isDateTimeInRange(self.dataOut.datatime, self.startDate, self.endDate, self.startTime, self.endTime):
949 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.nReadBlocks,
950 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.nReadBlocks,
950 self.processingHeaderObj.dataBlocksPerFile,
951 self.processingHeaderObj.dataBlocksPerFile,
951 self.dataOut.datatime.ctime()))
952 self.dataOut.datatime.ctime()))
952 continue
953 continue
953
954
954 break
955 break
955
956
956 if self.verbose:
957 if self.verbose:
957 print("[Reading] Block No. %d/%d -> %s" % (self.nReadBlocks,
958 print("[Reading] Block No. %d/%d -> %s" % (self.nReadBlocks,
958 self.processingHeaderObj.dataBlocksPerFile,
959 self.processingHeaderObj.dataBlocksPerFile,
959 self.dataOut.datatime.ctime()))
960 self.dataOut.datatime.ctime()))
960 #################DP#################
961 #################DP#################
961 self.dataOut.TimeBlockDate=self.dataOut.datatime.ctime()
962 self.dataOut.TimeBlockDate=self.dataOut.datatime.ctime()
962 self.dataOut.TimeBlockSeconds=time.mktime(time.strptime(self.dataOut.datatime.ctime()))
963 self.dataOut.TimeBlockSeconds=time.mktime(time.strptime(self.dataOut.datatime.ctime()))
963 #################DP#################
964 #################DP#################
964 return 1
965 return 1
965
966
966 def readFirstHeader(self):
967 def readFirstHeader(self):
967
968
968 self.basicHeaderObj.read(self.fp)
969 self.basicHeaderObj.read(self.fp)
969 self.systemHeaderObj.read(self.fp)
970 self.systemHeaderObj.read(self.fp)
970 self.radarControllerHeaderObj.read(self.fp)
971 self.radarControllerHeaderObj.read(self.fp)
971 self.processingHeaderObj.read(self.fp)
972 self.processingHeaderObj.read(self.fp)
972 self.firstHeaderSize = self.basicHeaderObj.size
973 self.firstHeaderSize = self.basicHeaderObj.size
973
974
974 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
975 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
975 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
976 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
976 if datatype == 0:
977 if datatype == 0:
977 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
978 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
978 elif datatype == 1:
979 elif datatype == 1:
979 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
980 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
980 elif datatype == 2:
981 elif datatype == 2:
981 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
982 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
982 elif datatype == 3:
983 elif datatype == 3:
983 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
984 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
984 elif datatype == 4:
985 elif datatype == 4:
985 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
986 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
986 elif datatype == 5:
987 elif datatype == 5:
987 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
988 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
988 else:
989 else:
989 raise ValueError('Data type was not defined')
990 raise ValueError('Data type was not defined')
990
991
991 self.dtype = datatype_str
992 self.dtype = datatype_str
992 # self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
993 # self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
993 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
994 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
994 self.firstHeaderSize + self.basicHeaderSize * \
995 self.firstHeaderSize + self.basicHeaderSize * \
995 (self.processingHeaderObj.dataBlocksPerFile - 1)
996 (self.processingHeaderObj.dataBlocksPerFile - 1)
996 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
997 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
997 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
998 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
998 self.getBlockDimension()
999 self.getBlockDimension()
999
1000
1000 def verifyFile(self, filename):
1001 def verifyFile(self, filename):
1001
1002
1002 flag = True
1003 flag = True
1003
1004
1004 try:
1005 try:
1005 fp = open(filename, 'rb')
1006 fp = open(filename, 'rb')
1006 except IOError:
1007 except IOError:
1007 log.error("File {} can't be opened".format(filename), self.name)
1008 log.error("File {} can't be opened".format(filename), self.name)
1008 return False
1009 return False
1009
1010
1010 if self.online and self.waitDataBlock(0):
1011 if self.online and self.waitDataBlock(0):
1011 pass
1012 pass
1012
1013
1013 basicHeaderObj = BasicHeader(LOCALTIME)
1014 basicHeaderObj = BasicHeader(LOCALTIME)
1014 systemHeaderObj = SystemHeader()
1015 systemHeaderObj = SystemHeader()
1015 radarControllerHeaderObj = RadarControllerHeader()
1016 radarControllerHeaderObj = RadarControllerHeader()
1016 processingHeaderObj = ProcessingHeader()
1017 processingHeaderObj = ProcessingHeader()
1017
1018
1018 if not(basicHeaderObj.read(fp)):
1019 if not(basicHeaderObj.read(fp)):
1019 flag = False
1020 flag = False
1020 if not(systemHeaderObj.read(fp)):
1021 if not(systemHeaderObj.read(fp)):
1021 flag = False
1022 flag = False
1022 if not(radarControllerHeaderObj.read(fp)):
1023 if not(radarControllerHeaderObj.read(fp)):
1023 flag = False
1024 flag = False
1024 if not(processingHeaderObj.read(fp)):
1025 if not(processingHeaderObj.read(fp)):
1025 flag = False
1026 flag = False
1026 if not self.online:
1027 if not self.online:
1027 dt1 = basicHeaderObj.datatime
1028 dt1 = basicHeaderObj.datatime
1028 pos = self.fileSize - processingHeaderObj.blockSize - 24
1029 pos = self.fileSize - processingHeaderObj.blockSize - 24
1029 if pos < 0:
1030 if pos < 0:
1030 flag = False
1031 flag = False
1031 log.error('Invalid size for file: {}'.format(self.filename), self.name)
1032 log.error('Invalid size for file: {}'.format(self.filename), self.name)
1032 else:
1033 else:
1033 fp.seek(pos)
1034 fp.seek(pos)
1034 if not(basicHeaderObj.read(fp)):
1035 if not(basicHeaderObj.read(fp)):
1035 flag = False
1036 flag = False
1036 dt2 = basicHeaderObj.datatime
1037 dt2 = basicHeaderObj.datatime
1037 if not self.isDateTimeInRange(dt1, self.startDate, self.endDate, self.startTime, self.endTime) and not \
1038 if not self.isDateTimeInRange(dt1, self.startDate, self.endDate, self.startTime, self.endTime) and not \
1038 self.isDateTimeInRange(dt2, self.startDate, self.endDate, self.startTime, self.endTime):
1039 self.isDateTimeInRange(dt2, self.startDate, self.endDate, self.startTime, self.endTime):
1039 flag = False
1040 flag = False
1040
1041
1041 fp.close()
1042 fp.close()
1042 return flag
1043 return flag
1043
1044
1044 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1045 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1045
1046
1046 path_empty = True
1047 path_empty = True
1047
1048
1048 dateList = []
1049 dateList = []
1049 pathList = []
1050 pathList = []
1050
1051
1051 multi_path = path.split(',')
1052 multi_path = path.split(',')
1052
1053
1053 if not walk:
1054 if not walk:
1054
1055
1055 for single_path in multi_path:
1056 for single_path in multi_path:
1056
1057
1057 if not os.path.isdir(single_path):
1058 if not os.path.isdir(single_path):
1058 continue
1059 continue
1059
1060
1060 fileList = glob.glob1(single_path, "*" + ext)
1061 fileList = glob.glob1(single_path, "*" + ext)
1061
1062
1062 if not fileList:
1063 if not fileList:
1063 continue
1064 continue
1064
1065
1065 path_empty = False
1066 path_empty = False
1066
1067
1067 fileList.sort()
1068 fileList.sort()
1068
1069
1069 for thisFile in fileList:
1070 for thisFile in fileList:
1070
1071
1071 if not os.path.isfile(os.path.join(single_path, thisFile)):
1072 if not os.path.isfile(os.path.join(single_path, thisFile)):
1072 continue
1073 continue
1073
1074
1074 if not isRadarFile(thisFile):
1075 if not isRadarFile(thisFile):
1075 continue
1076 continue
1076
1077
1077 if not isFileInDateRange(thisFile, startDate, endDate):
1078 if not isFileInDateRange(thisFile, startDate, endDate):
1078 continue
1079 continue
1079
1080
1080 thisDate = getDateFromRadarFile(thisFile)
1081 thisDate = getDateFromRadarFile(thisFile)
1081
1082
1082 if thisDate in dateList or single_path in pathList:
1083 if thisDate in dateList or single_path in pathList:
1083 continue
1084 continue
1084
1085
1085 dateList.append(thisDate)
1086 dateList.append(thisDate)
1086 pathList.append(single_path)
1087 pathList.append(single_path)
1087
1088
1088 else:
1089 else:
1089 for single_path in multi_path:
1090 for single_path in multi_path:
1090
1091
1091 if not os.path.isdir(single_path):
1092 if not os.path.isdir(single_path):
1092 continue
1093 continue
1093
1094
1094 dirList = []
1095 dirList = []
1095
1096
1096 for thisPath in os.listdir(single_path):
1097 for thisPath in os.listdir(single_path):
1097
1098
1098 if not os.path.isdir(os.path.join(single_path, thisPath)):
1099 if not os.path.isdir(os.path.join(single_path, thisPath)):
1099 continue
1100 continue
1100
1101
1101 if not isRadarFolder(thisPath):
1102 if not isRadarFolder(thisPath):
1102 continue
1103 continue
1103
1104
1104 if not isFolderInDateRange(thisPath, startDate, endDate):
1105 if not isFolderInDateRange(thisPath, startDate, endDate):
1105 continue
1106 continue
1106
1107
1107 dirList.append(thisPath)
1108 dirList.append(thisPath)
1108
1109
1109 if not dirList:
1110 if not dirList:
1110 continue
1111 continue
1111
1112
1112 dirList.sort()
1113 dirList.sort()
1113
1114
1114 for thisDir in dirList:
1115 for thisDir in dirList:
1115
1116
1116 datapath = os.path.join(single_path, thisDir, expLabel)
1117 datapath = os.path.join(single_path, thisDir, expLabel)
1117 fileList = glob.glob1(datapath, "*" + ext)
1118 fileList = glob.glob1(datapath, "*" + ext)
1118
1119
1119 if not fileList:
1120 if not fileList:
1120 continue
1121 continue
1121
1122
1122 path_empty = False
1123 path_empty = False
1123
1124
1124 thisDate = getDateFromRadarFolder(thisDir)
1125 thisDate = getDateFromRadarFolder(thisDir)
1125
1126
1126 pathList.append(datapath)
1127 pathList.append(datapath)
1127 dateList.append(thisDate)
1128 dateList.append(thisDate)
1128
1129
1129 dateList.sort()
1130 dateList.sort()
1130
1131
1131 if walk:
1132 if walk:
1132 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1133 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1133 else:
1134 else:
1134 pattern_path = multi_path[0]
1135 pattern_path = multi_path[0]
1135
1136
1136 if path_empty:
1137 if path_empty:
1137 raise schainpy.admin.SchainError("[Reading] No *%s files in %s for %s to %s" % (ext, pattern_path, startDate, endDate))
1138 raise schainpy.admin.SchainError("[Reading] No *%s files in %s for %s to %s" % (ext, pattern_path, startDate, endDate))
1138 else:
1139 else:
1139 if not dateList:
1140 if not dateList:
1140 raise schainpy.admin.SchainError("[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" % (startDate, endDate, ext, path))
1141 raise schainpy.admin.SchainError("[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" % (startDate, endDate, ext, path))
1141
1142
1142 if include_path:
1143 if include_path:
1143 return dateList, pathList
1144 return dateList, pathList
1144
1145
1145 return dateList
1146 return dateList
1146
1147
1147 def setup(self, **kwargs):
1148 def setup(self, **kwargs):
1148
1149
1149 self.set_kwargs(**kwargs)
1150 self.set_kwargs(**kwargs)
1150 if not self.ext.startswith('.'):
1151 if not self.ext.startswith('.'):
1151 self.ext = '.{}'.format(self.ext)
1152 self.ext = '.{}'.format(self.ext)
1152
1153
1153 if self.server is not None:
1154 if self.server is not None:
1154 if 'tcp://' in self.server:
1155 if 'tcp://' in self.server:
1155 address = server
1156 address = self.server
1156 else:
1157 else:
1157 address = 'ipc:///tmp/%s' % self.server
1158 address = 'ipc:///tmp/%s' % self.server
1158 self.server = address
1159 self.server = address
1159 self.context = zmq.Context()
1160 self.context = zmq.Context()
1160 self.receiver = self.context.socket(zmq.PULL)
1161 self.receiver = self.context.socket(zmq.SUB)
1161 self.receiver.connect(self.server)
1162 self.receiver.connect(self.server)
1163 self.receiver.setsockopt(zmq.SUBSCRIBE, str.encode(str(self.topic)))
1162 time.sleep(0.5)
1164 time.sleep(0.5)
1163 print('[Starting] ReceiverData from {}'.format(self.server))
1165 print('[Starting] ReceiverData from {}'.format(self.server))
1164 else:
1166 else:
1165 self.server = None
1167 self.server = None
1166 if self.path == None:
1168 if self.path == None:
1167 raise ValueError("[Reading] The path is not valid")
1169 raise ValueError("[Reading] The path is not valid")
1168
1170
1169 if self.online:
1171 if self.online:
1170 log.log("[Reading] Searching files in online mode...", self.name)
1172 log.log("[Reading] Searching files in online mode...", self.name)
1171
1173
1172 for nTries in range(self.nTries):
1174 for nTries in range(self.nTries):
1173 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1175 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1174 self.endDate, self.expLabel, self.ext, self.walk,
1176 self.endDate, self.expLabel, self.ext, self.walk,
1175 self.filefmt, self.folderfmt)
1177 self.filefmt, self.folderfmt)
1176
1178
1177 try:
1179 try:
1178 fullpath = next(fullpath)
1180 fullpath = next(fullpath)
1179 except:
1181 except:
1180 fullpath = None
1182 fullpath = None
1181
1183
1182 if fullpath:
1184 if fullpath:
1183 break
1185 break
1184
1186
1185 log.warning(
1187 log.warning(
1186 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1188 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1187 self.delay, self.path, nTries + 1),
1189 self.delay, self.path, nTries + 1),
1188 self.name)
1190 self.name)
1189 time.sleep(self.delay)
1191 time.sleep(self.delay)
1190
1192
1191 if not(fullpath):
1193 if not(fullpath):
1192 raise schainpy.admin.SchainError(
1194 raise schainpy.admin.SchainError(
1193 'There isn\'t any valid file in {}'.format(self.path))
1195 'There isn\'t any valid file in {}'.format(self.path))
1194
1196
1195 pathname, filename = os.path.split(fullpath)
1197 pathname, filename = os.path.split(fullpath)
1196 self.year = int(filename[1:5])
1198 self.year = int(filename[1:5])
1197 self.doy = int(filename[5:8])
1199 self.doy = int(filename[5:8])
1198 self.set = int(filename[8:11]) - 1
1200 self.set = int(filename[8:11]) - 1
1199 else:
1201 else:
1200 log.log("Searching files in {}".format(self.path), self.name)
1202 log.log("Searching files in {}".format(self.path), self.name)
1201 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1203 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1202 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1204 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1203
1205
1204 self.setNextFile()
1206 self.setNextFile()
1205
1207
1206 return
1208 return
1207
1209
1208 def getBasicHeader(self):
1210 def getBasicHeader(self):
1209
1211
1210 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond / \
1212 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond / \
1211 1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1213 1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1212
1214
1213 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1215 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1214
1216
1215 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1217 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1216
1218
1217 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1219 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1218
1220
1219 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1221 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1220
1222
1221 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1223 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1222
1224
1223 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
1225 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
1224
1226
1225 def getFirstHeader(self):
1227 def getFirstHeader(self):
1226
1228
1227 raise NotImplementedError
1229 raise NotImplementedError
1228
1230
1229 def getData(self):
1231 def getData(self):
1230
1232
1231 raise NotImplementedError
1233 raise NotImplementedError
1232
1234
1233 def hasNotDataInBuffer(self):
1235 def hasNotDataInBuffer(self):
1234
1236
1235 raise NotImplementedError
1237 raise NotImplementedError
1236
1238
1237 def readBlock(self):
1239 def readBlock(self):
1238
1240
1239 raise NotImplementedError
1241 raise NotImplementedError
1240
1242
1241 def isEndProcess(self):
1243 def isEndProcess(self):
1242
1244
1243 return self.flagNoMoreFiles
1245 return self.flagNoMoreFiles
1244
1246
1245 def printReadBlocks(self):
1247 def printReadBlocks(self):
1246
1248
1247 print("[Reading] Number of read blocks per file %04d" % self.nReadBlocks)
1249 print("[Reading] Number of read blocks per file %04d" % self.nReadBlocks)
1248
1250
1249 def printTotalBlocks(self):
1251 def printTotalBlocks(self):
1250
1252
1251 print("[Reading] Number of read blocks %04d" % self.nTotalBlocks)
1253 print("[Reading] Number of read blocks %04d" % self.nTotalBlocks)
1252
1254
1253 def run(self, **kwargs):
1255 def run(self, **kwargs):
1254 """
1256 """
1255
1257
1256 Arguments:
1258 Arguments:
1257 path :
1259 path :
1258 startDate :
1260 startDate :
1259 endDate :
1261 endDate :
1260 startTime :
1262 startTime :
1261 endTime :
1263 endTime :
1262 set :
1264 set :
1263 expLabel :
1265 expLabel :
1264 ext :
1266 ext :
1265 online :
1267 online :
1266 delay :
1268 delay :
1267 walk :
1269 walk :
1268 getblock :
1270 getblock :
1269 nTxs :
1271 nTxs :
1270 realtime :
1272 realtime :
1271 blocksize :
1273 blocksize :
1272 blocktime :
1274 blocktime :
1273 skip :
1275 skip :
1274 cursor :
1276 cursor :
1275 warnings :
1277 warnings :
1276 server :
1278 server :
1277 verbose :
1279 verbose :
1278 format :
1280 format :
1279 oneDDict :
1281 oneDDict :
1280 twoDDict :
1282 twoDDict :
1281 independentParam :
1283 independentParam :
1282 """
1284 """
1283
1285
1284 if not(self.isConfig):
1286 if not(self.isConfig):
1285 self.setup(**kwargs)
1287 self.setup(**kwargs)
1286 self.isConfig = True
1288 self.isConfig = True
1287 if self.server is None:
1289 if self.server is None:
1288 self.getData()
1290 self.getData()
1289 else:
1291 else:
1290 self.getFromServer()
1292 try:
1293 self.getFromServer()
1294 except Exception as e:
1295 log.warning('Invalid block...')
1296 self.dataOut.flagNoData = True
1291
1297
1292
1298
1293 class JRODataWriter(Reader):
1299 class JRODataWriter(Reader):
1294
1300
1295 """
1301 """
1296 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1302 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1297 de los datos siempre se realiza por bloques.
1303 de los datos siempre se realiza por bloques.
1298 """
1304 """
1299
1305
1300 setFile = None
1306 setFile = None
1301 profilesPerBlock = None
1307 profilesPerBlock = None
1302 blocksPerFile = None
1308 blocksPerFile = None
1303 nWriteBlocks = 0
1309 nWriteBlocks = 0
1304 fileDate = None
1310 fileDate = None
1305
1311
1306 def __init__(self, dataOut=None):
1312 def __init__(self, dataOut=None):
1307 raise NotImplementedError
1313 raise NotImplementedError
1308
1314
1309 def hasAllDataInBuffer(self):
1315 def hasAllDataInBuffer(self):
1310 raise NotImplementedError
1316 raise NotImplementedError
1311
1317
1312 def setBlockDimension(self):
1318 def setBlockDimension(self):
1313 raise NotImplementedError
1319 raise NotImplementedError
1314
1320
1315 def writeBlock(self):
1321 def writeBlock(self):
1316 raise NotImplementedError
1322 raise NotImplementedError
1317
1323
1318 def putData(self):
1324 def putData(self):
1319 raise NotImplementedError
1325 raise NotImplementedError
1320
1326
1321 def getDtypeWidth(self):
1327 def getDtypeWidth(self):
1322
1328
1323 dtype_index = get_dtype_index(self.dtype)
1329 dtype_index = get_dtype_index(self.dtype)
1324 dtype_width = get_dtype_width(dtype_index)
1330 dtype_width = get_dtype_width(dtype_index)
1325
1331
1326 return dtype_width
1332 return dtype_width
1327
1333
1328 def getProcessFlags(self):
1334 def getProcessFlags(self):
1329
1335
1330 processFlags = 0
1336 processFlags = 0
1331
1337
1332 dtype_index = get_dtype_index(self.dtype)
1338 dtype_index = get_dtype_index(self.dtype)
1333 procflag_dtype = get_procflag_dtype(dtype_index)
1339 procflag_dtype = get_procflag_dtype(dtype_index)
1334
1340
1335 processFlags += procflag_dtype
1341 processFlags += procflag_dtype
1336
1342
1337 if self.dataOut.flagDecodeData:
1343 if self.dataOut.flagDecodeData:
1338 processFlags += PROCFLAG.DECODE_DATA
1344 processFlags += PROCFLAG.DECODE_DATA
1339
1345
1340 if self.dataOut.flagDeflipData:
1346 if self.dataOut.flagDeflipData:
1341 processFlags += PROCFLAG.DEFLIP_DATA
1347 processFlags += PROCFLAG.DEFLIP_DATA
1342
1348
1343 if self.dataOut.code is not None:
1349 if self.dataOut.code is not None:
1344 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1350 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1345
1351
1346 if self.dataOut.nCohInt > 1:
1352 if self.dataOut.nCohInt > 1:
1347 processFlags += PROCFLAG.COHERENT_INTEGRATION
1353 processFlags += PROCFLAG.COHERENT_INTEGRATION
1348
1354
1349 if self.dataOut.type == "Spectra":
1355 if self.dataOut.type == "Spectra":
1350 if self.dataOut.nIncohInt > 1:
1356 if self.dataOut.nIncohInt > 1:
1351 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1357 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1352
1358
1353 if self.dataOut.data_dc is not None:
1359 if self.dataOut.data_dc is not None:
1354 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1360 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1355
1361
1356 if self.dataOut.flagShiftFFT:
1362 if self.dataOut.flagShiftFFT:
1357 processFlags += PROCFLAG.SHIFT_FFT_DATA
1363 processFlags += PROCFLAG.SHIFT_FFT_DATA
1358
1364
1359 return processFlags
1365 return processFlags
1360
1366
1361 def setBasicHeader(self):
1367 def setBasicHeader(self):
1362
1368
1363 self.basicHeaderObj.size = self.basicHeaderSize # bytes
1369 self.basicHeaderObj.size = self.basicHeaderSize # bytes
1364 self.basicHeaderObj.version = self.versionFile
1370 self.basicHeaderObj.version = self.versionFile
1365 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1371 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1366 utc = numpy.floor(self.dataOut.utctime)
1372 utc = numpy.floor(self.dataOut.utctime)
1367 milisecond = (self.dataOut.utctime - utc) * 1000.0
1373 milisecond = (self.dataOut.utctime - utc) * 1000.0
1368 self.basicHeaderObj.utc = utc
1374 self.basicHeaderObj.utc = utc
1369 self.basicHeaderObj.miliSecond = milisecond
1375 self.basicHeaderObj.miliSecond = milisecond
1370 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1376 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1371 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1377 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1372 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1378 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1373
1379
1374 def setFirstHeader(self):
1380 def setFirstHeader(self):
1375 """
1381 """
1376 Obtiene una copia del First Header
1382 Obtiene una copia del First Header
1377
1383
1378 Affected:
1384 Affected:
1379
1385
1380 self.basicHeaderObj
1386 self.basicHeaderObj
1381 self.systemHeaderObj
1387 self.systemHeaderObj
1382 self.radarControllerHeaderObj
1388 self.radarControllerHeaderObj
1383 self.processingHeaderObj self.
1389 self.processingHeaderObj self.
1384
1390
1385 Return:
1391 Return:
1386 None
1392 None
1387 """
1393 """
1388
1394
1389 raise NotImplementedError
1395 raise NotImplementedError
1390
1396
1391 def __writeFirstHeader(self):
1397 def __writeFirstHeader(self):
1392 """
1398 """
1393 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1399 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1394
1400
1395 Affected:
1401 Affected:
1396 __dataType
1402 __dataType
1397
1403
1398 Return:
1404 Return:
1399 None
1405 None
1400 """
1406 """
1401
1407
1402 # CALCULAR PARAMETROS
1408 # CALCULAR PARAMETROS
1403
1409
1404 sizeLongHeader = self.systemHeaderObj.size + \
1410 sizeLongHeader = self.systemHeaderObj.size + \
1405 self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1411 self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1406 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1412 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1407
1413
1408 self.basicHeaderObj.write(self.fp)
1414 self.basicHeaderObj.write(self.fp)
1409 self.systemHeaderObj.write(self.fp)
1415 self.systemHeaderObj.write(self.fp)
1410 self.radarControllerHeaderObj.write(self.fp)
1416 self.radarControllerHeaderObj.write(self.fp)
1411 self.processingHeaderObj.write(self.fp)
1417 self.processingHeaderObj.write(self.fp)
1412
1418
1413 def __setNewBlock(self):
1419 def __setNewBlock(self):
1414 """
1420 """
1415 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1421 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1416
1422
1417 Return:
1423 Return:
1418 0 : si no pudo escribir nada
1424 0 : si no pudo escribir nada
1419 1 : Si escribio el Basic el First Header
1425 1 : Si escribio el Basic el First Header
1420 """
1426 """
1421 if self.fp == None:
1427 if self.fp == None:
1422 self.setNextFile()
1428 self.setNextFile()
1423
1429
1424 if self.flagIsNewFile:
1430 if self.flagIsNewFile:
1425 return 1
1431 return 1
1426
1432
1427 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1433 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1428 self.basicHeaderObj.write(self.fp)
1434 self.basicHeaderObj.write(self.fp)
1429 return 1
1435 return 1
1430
1436
1431 if not(self.setNextFile()):
1437 if not(self.setNextFile()):
1432 return 0
1438 return 0
1433
1439
1434 return 1
1440 return 1
1435
1441
1436 def writeNextBlock(self):
1442 def writeNextBlock(self):
1437 """
1443 """
1438 Selecciona el bloque siguiente de datos y los escribe en un file
1444 Selecciona el bloque siguiente de datos y los escribe en un file
1439
1445
1440 Return:
1446 Return:
1441 0 : Si no hizo pudo escribir el bloque de datos
1447 0 : Si no hizo pudo escribir el bloque de datos
1442 1 : Si no pudo escribir el bloque de datos
1448 1 : Si no pudo escribir el bloque de datos
1443 """
1449 """
1444 if not(self.__setNewBlock()):
1450 if not(self.__setNewBlock()):
1445 return 0
1451 return 0
1446
1452
1447 self.writeBlock()
1453 self.writeBlock()
1448
1454
1449 print("[Writing] Block No. %d/%d" % (self.blockIndex,
1455 print("[Writing] Block No. %d/%d" % (self.blockIndex,
1450 self.processingHeaderObj.dataBlocksPerFile))
1456 self.processingHeaderObj.dataBlocksPerFile))
1451
1457
1452 return 1
1458 return 1
1453
1459
1454 def setNextFile(self):
1460 def setNextFile(self):
1455 """Determina el siguiente file que sera escrito
1461 """Determina el siguiente file que sera escrito
1456
1462
1457 Affected:
1463 Affected:
1458 self.filename
1464 self.filename
1459 self.subfolder
1465 self.subfolder
1460 self.fp
1466 self.fp
1461 self.setFile
1467 self.setFile
1462 self.flagIsNewFile
1468 self.flagIsNewFile
1463
1469
1464 Return:
1470 Return:
1465 0 : Si el archivo no puede ser escrito
1471 0 : Si el archivo no puede ser escrito
1466 1 : Si el archivo esta listo para ser escrito
1472 1 : Si el archivo esta listo para ser escrito
1467 """
1473 """
1468 ext = self.ext
1474 ext = self.ext
1469 path = self.path
1475 path = self.path
1470
1476
1471 if self.fp != None:
1477 if self.fp != None:
1472 self.fp.close()
1478 self.fp.close()
1473
1479
1474 if not os.path.exists(path):
1480 if not os.path.exists(path):
1475 os.mkdir(path)
1481 os.mkdir(path)
1476
1482
1477 timeTuple = time.localtime(self.dataOut.utctime)
1483 timeTuple = time.localtime(self.dataOut.utctime)
1478 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
1484 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
1479
1485
1480 fullpath = os.path.join(path, subfolder)
1486 fullpath = os.path.join(path, subfolder)
1481 setFile = self.setFile
1487 setFile = self.setFile
1482
1488
1483 if not(os.path.exists(fullpath)):
1489 if not(os.path.exists(fullpath)):
1484 os.mkdir(fullpath)
1490 os.mkdir(fullpath)
1485 setFile = -1 # inicializo mi contador de seteo
1491 setFile = -1 # inicializo mi contador de seteo
1486 else:
1492 else:
1487 filesList = os.listdir(fullpath)
1493 filesList = os.listdir(fullpath)
1488 if len(filesList) > 0:
1494 if len(filesList) > 0:
1489 filesList = sorted(filesList, key=str.lower)
1495 filesList = sorted(filesList, key=str.lower)
1490 filen = filesList[-1]
1496 filen = filesList[-1]
1491 # el filename debera tener el siguiente formato
1497 # el filename debera tener el siguiente formato
1492 # 0 1234 567 89A BCDE (hex)
1498 # 0 1234 567 89A BCDE (hex)
1493 # x YYYY DDD SSS .ext
1499 # x YYYY DDD SSS .ext
1494 if isNumber(filen[8:11]):
1500 if isNumber(filen[8:11]):
1495 # inicializo mi contador de seteo al seteo del ultimo file
1501 # inicializo mi contador de seteo al seteo del ultimo file
1496 setFile = int(filen[8:11])
1502 setFile = int(filen[8:11])
1497 else:
1503 else:
1498 setFile = -1
1504 setFile = -1
1499 else:
1505 else:
1500 setFile = -1 # inicializo mi contador de seteo
1506 setFile = -1 # inicializo mi contador de seteo
1501
1507
1502 setFile += 1
1508 setFile += 1
1503
1509
1504 # If this is a new day it resets some values
1510 # If this is a new day it resets some values
1505 if self.dataOut.datatime.date() > self.fileDate:
1511 if self.dataOut.datatime.date() > self.fileDate:
1506 setFile = 0
1512 setFile = 0
1507 self.nTotalBlocks = 0
1513 self.nTotalBlocks = 0
1508
1514
1509 filen = '{}{:04d}{:03d}{:03d}{}'.format(
1515 filen = '{}{:04d}{:03d}{:03d}{}'.format(
1510 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
1516 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
1511
1517
1512 filename = os.path.join(path, subfolder, filen)
1518 filename = os.path.join(path, subfolder, filen)
1513
1519
1514 fp = open(filename, 'wb')
1520 fp = open(filename, 'wb')
1515
1521
1516 self.blockIndex = 0
1522 self.blockIndex = 0
1517 self.filename = filename
1523 self.filename = filename
1518 self.subfolder = subfolder
1524 self.subfolder = subfolder
1519 self.fp = fp
1525 self.fp = fp
1520 self.setFile = setFile
1526 self.setFile = setFile
1521 self.flagIsNewFile = 1
1527 self.flagIsNewFile = 1
1522 self.fileDate = self.dataOut.datatime.date()
1528 self.fileDate = self.dataOut.datatime.date()
1523 self.setFirstHeader()
1529 self.setFirstHeader()
1524
1530
1525 print('[Writing] Opening file: %s' % self.filename)
1531 print('[Writing] Opening file: %s' % self.filename)
1526
1532
1527 self.__writeFirstHeader()
1533 self.__writeFirstHeader()
1528
1534
1529 return 1
1535 return 1
1530
1536
1531 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1537 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1532 """
1538 """
1533 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1539 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1534
1540
1535 Inputs:
1541 Inputs:
1536 path : directory where data will be saved
1542 path : directory where data will be saved
1537 profilesPerBlock : number of profiles per block
1543 profilesPerBlock : number of profiles per block
1538 set : initial file set
1544 set : initial file set
1539 datatype : An integer number that defines data type:
1545 datatype : An integer number that defines data type:
1540 0 : int8 (1 byte)
1546 0 : int8 (1 byte)
1541 1 : int16 (2 bytes)
1547 1 : int16 (2 bytes)
1542 2 : int32 (4 bytes)
1548 2 : int32 (4 bytes)
1543 3 : int64 (8 bytes)
1549 3 : int64 (8 bytes)
1544 4 : float32 (4 bytes)
1550 4 : float32 (4 bytes)
1545 5 : double64 (8 bytes)
1551 5 : double64 (8 bytes)
1546
1552
1547 Return:
1553 Return:
1548 0 : Si no realizo un buen seteo
1554 0 : Si no realizo un buen seteo
1549 1 : Si realizo un buen seteo
1555 1 : Si realizo un buen seteo
1550 """
1556 """
1551
1557
1552 if ext == None:
1558 if ext == None:
1553 ext = self.ext
1559 ext = self.ext
1554
1560
1555 self.ext = ext.lower()
1561 self.ext = ext.lower()
1556
1562
1557 self.path = path
1563 self.path = path
1558
1564
1559 if set is None:
1565 if set is None:
1560 self.setFile = -1
1566 self.setFile = -1
1561 else:
1567 else:
1562 self.setFile = set - 1
1568 self.setFile = set - 1
1563
1569
1564 self.blocksPerFile = blocksPerFile
1570 self.blocksPerFile = blocksPerFile
1565 self.profilesPerBlock = profilesPerBlock
1571 self.profilesPerBlock = profilesPerBlock
1566 self.dataOut = dataOut
1572 self.dataOut = dataOut
1567 self.fileDate = self.dataOut.datatime.date()
1573 self.fileDate = self.dataOut.datatime.date()
1568 self.dtype = self.dataOut.dtype
1574 self.dtype = self.dataOut.dtype
1569
1575
1570 if datatype is not None:
1576 if datatype is not None:
1571 self.dtype = get_numpy_dtype(datatype)
1577 self.dtype = get_numpy_dtype(datatype)
1572
1578
1573 if not(self.setNextFile()):
1579 if not(self.setNextFile()):
1574 print("[Writing] There isn't a next file")
1580 print("[Writing] There isn't a next file")
1575 return 0
1581 return 0
1576
1582
1577 self.setBlockDimension()
1583 self.setBlockDimension()
1578
1584
1579 return 1
1585 return 1
1580
1586
1581 def run(self, dataOut, path, blocksPerFile=100, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1587 def run(self, dataOut, path, blocksPerFile=100, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1582
1588
1583 if not(self.isConfig):
1589 if not(self.isConfig):
1584
1590
1585 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock,
1591 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock,
1586 set=set, ext=ext, datatype=datatype, **kwargs)
1592 set=set, ext=ext, datatype=datatype, **kwargs)
1587 self.isConfig = True
1593 self.isConfig = True
1588
1594
1589 self.dataOut = dataOut
1595 self.dataOut = dataOut
1590 self.putData()
1596 self.putData()
1591 return self.dataOut
1597 return self.dataOut
1592
1598
1593 @MPDecorator
1599 @MPDecorator
1594 class printInfo(Operation):
1600 class printInfo(Operation):
1595
1601
1596 def __init__(self):
1602 def __init__(self):
1597
1603
1598 Operation.__init__(self)
1604 Operation.__init__(self)
1599 self.__printInfo = True
1605 self.__printInfo = True
1600
1606
1601 def run(self, dataOut, headers=['systemHeaderObj', 'radarControllerHeaderObj', 'processingHeaderObj']):
1607 def run(self, dataOut, headers=['systemHeaderObj', 'radarControllerHeaderObj', 'processingHeaderObj']):
1602 if self.__printInfo == False:
1608 if self.__printInfo == False:
1603 return
1609 return
1604
1610
1605 for header in headers:
1611 for header in headers:
1606 if hasattr(dataOut, header):
1612 if hasattr(dataOut, header):
1607 obj = getattr(dataOut, header)
1613 obj = getattr(dataOut, header)
1608 if hasattr(obj, 'printInfo'):
1614 if hasattr(obj, 'printInfo'):
1609 obj.printInfo()
1615 obj.printInfo()
1610 else:
1616 else:
1611 print(obj)
1617 print(obj)
1612 else:
1618 else:
1613 log.warning('Header {} Not found in object'.format(header))
1619 log.warning('Header {} Not found in object'.format(header))
1614
1620
1615 self.__printInfo = False
1621 self.__printInfo = False
@@ -1,692 +1,699
1 '''
1 '''
2 Created on Jul 2, 2014
2 Created on Jul 2, 2014
3
3
4 @author: roj-idl71
4 @author: roj-idl71
5 '''
5 '''
6
6
7 import numpy
7 import numpy
8
8
9 from .jroIO_base import LOCALTIME, JRODataReader, JRODataWriter
9 from .jroIO_base import LOCALTIME, JRODataReader, JRODataWriter
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
11 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
12 from schainpy.model.data.jrodata import Voltage
12 from schainpy.model.data.jrodata import Voltage
13
13
14
14
15 class VoltageReader(JRODataReader, ProcessingUnit):
15 class VoltageReader(JRODataReader, ProcessingUnit):
16 """
16 """
17 Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura
17 Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura
18 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones:
18 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones:
19 perfiles*alturas*canales) son almacenados en la variable "buffer".
19 perfiles*alturas*canales) son almacenados en la variable "buffer".
20
20
21 perfiles * alturas * canales
21 perfiles * alturas * canales
22
22
23 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
23 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
24 RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la
24 RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la
25 cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de
25 cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de
26 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
26 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
27
27
28 Example:
28 Example:
29
29
30 dpath = "/home/myuser/data"
30 dpath = "/home/myuser/data"
31
31
32 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
32 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
33
33
34 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
34 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
35
35
36 readerObj = VoltageReader()
36 readerObj = VoltageReader()
37
37
38 readerObj.setup(dpath, startTime, endTime)
38 readerObj.setup(dpath, startTime, endTime)
39
39
40 while(True):
40 while(True):
41
41
42 #to get one profile
42 #to get one profile
43 profile = readerObj.getData()
43 profile = readerObj.getData()
44
44
45 #print the profile
45 #print the profile
46 print profile
46 print profile
47
47
48 #If you want to see all datablock
48 #If you want to see all datablock
49 print readerObj.datablock
49 print readerObj.datablock
50
50
51 if readerObj.flagNoMoreFiles:
51 if readerObj.flagNoMoreFiles:
52 break
52 break
53
53
54 """
54 """
55
55
56 def __init__(self):
56 def __init__(self):
57 """
57 """
58 Inicializador de la clase VoltageReader para la lectura de datos de voltage.
58 Inicializador de la clase VoltageReader para la lectura de datos de voltage.
59
59
60 Input:
60 Input:
61 dataOut : Objeto de la clase Voltage. Este objeto sera utilizado para
61 dataOut : Objeto de la clase Voltage. Este objeto sera utilizado para
62 almacenar un perfil de datos cada vez que se haga un requerimiento
62 almacenar un perfil de datos cada vez que se haga un requerimiento
63 (getData). El perfil sera obtenido a partir del buffer de datos,
63 (getData). El perfil sera obtenido a partir del buffer de datos,
64 si el buffer esta vacio se hara un nuevo proceso de lectura de un
64 si el buffer esta vacio se hara un nuevo proceso de lectura de un
65 bloque de datos.
65 bloque de datos.
66 Si este parametro no es pasado se creara uno internamente.
66 Si este parametro no es pasado se creara uno internamente.
67
67
68 Variables afectadas:
68 Variables afectadas:
69 self.dataOut
69 self.dataOut
70
70
71 Return:
71 Return:
72 None
72 None
73 """
73 """
74
74
75 ProcessingUnit.__init__(self)
75 ProcessingUnit.__init__(self)
76
76
77 self.ext = ".r"
77 self.ext = ".r"
78 self.optchar = "D"
78 self.optchar = "D"
79 self.basicHeaderObj = BasicHeader(LOCALTIME)
79 self.basicHeaderObj = BasicHeader(LOCALTIME)
80 self.systemHeaderObj = SystemHeader()
80 self.systemHeaderObj = SystemHeader()
81 self.radarControllerHeaderObj = RadarControllerHeader()
81 self.radarControllerHeaderObj = RadarControllerHeader()
82
82
83 self.processingHeaderObj = ProcessingHeader()
83 self.processingHeaderObj = ProcessingHeader()
84 self.lastUTTime = 0
84 self.lastUTTime = 0
85 self.profileIndex = 2 ** 32 - 1
85 self.profileIndex = 2 ** 32 - 1
86 self.dataOut = Voltage()
86 self.dataOut = Voltage()
87 self.selBlocksize = None
87 self.selBlocksize = None
88 self.selBlocktime = None
88 self.selBlocktime = None
89 ##print("1--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
89 ##print("1--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
90 def createObjByDefault(self):
90 def createObjByDefault(self):
91 ##print("2--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
91 ##print("2--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
92 dataObj = Voltage()
92 dataObj = Voltage()
93
93
94 return dataObj
94 return dataObj
95
95
96 def __hasNotDataInBuffer(self):
96 def __hasNotDataInBuffer(self):
97 ##print("3--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
97 ##print("3--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
98 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock * self.nTxs:
98 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock * self.nTxs:
99 return 1
99 return 1
100
100
101 return 0
101 return 0
102
102
103 def getBlockDimension(self):
103 def getBlockDimension(self):
104 """
104 """
105 Obtiene la cantidad de puntos a leer por cada bloque de datos
105 Obtiene la cantidad de puntos a leer por cada bloque de datos
106
106
107 Affected:
107 Affected:
108 self.blocksize
108 self.blocksize
109
109
110 Return:
110 Return:
111 None
111 None
112 """
112 """
113 ##print("4--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
113 ##print("4--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
114 pts2read = self.processingHeaderObj.profilesPerBlock * \
114 pts2read = self.processingHeaderObj.profilesPerBlock * \
115 self.processingHeaderObj.nHeights * self.systemHeaderObj.nChannels
115 self.processingHeaderObj.nHeights * self.systemHeaderObj.nChannels
116 self.blocksize = pts2read
116 self.blocksize = pts2read
117
117
118 def readBlock(self):
118 def readBlock(self):
119
119
120 """
120 """
121 readBlock lee el bloque de datos desde la posicion actual del puntero del archivo
121 readBlock lee el bloque de datos desde la posicion actual del puntero del archivo
122 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
122 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
123 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
123 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
124 es seteado a 0
124 es seteado a 0
125
125
126 Inputs:
126 Inputs:
127 None
127 None
128
128
129 Return:
129 Return:
130 None
130 None
131
131
132 Affected:
132 Affected:
133 self.profileIndex
133 self.profileIndex
134 self.datablock
134 self.datablock
135 self.flagIsNewFile
135 self.flagIsNewFile
136 self.flagIsNewBlock
136 self.flagIsNewBlock
137 self.nTotalBlocks
137 self.nTotalBlocks
138
138
139 Exceptions:
139 Exceptions:
140 Si un bloque leido no es un bloque valido
140 Si un bloque leido no es un bloque valido
141 """
141 """
142 ##print("5--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
142 ##print("5--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
143 # if self.server is not None:
143 # if self.server is not None:
144 # self.zBlock = self.receiver.recv()
144 # self.zBlock = self.receiver.recv()
145 # self.zHeader = self.zBlock[:24]
145 # self.zHeader = self.zBlock[:24]
146 # self.zDataBlock = self.zBlock[24:]
146 # self.zDataBlock = self.zBlock[24:]
147 # junk = numpy.fromstring(self.zDataBlock, numpy.dtype([('real','<i4'),('imag','<i4')]))
147 # junk = numpy.fromstring(self.zDataBlock, numpy.dtype([('real','<i4'),('imag','<i4')]))
148 # self.processingHeaderObj.profilesPerBlock = 240
148 # self.processingHeaderObj.profilesPerBlock = 240
149 # self.processingHeaderObj.nHeights = 248
149 # self.processingHeaderObj.nHeights = 248
150 # self.systemHeaderObj.nChannels
150 # self.systemHeaderObj.nChannels
151 # else:
151 # else:
152 current_pointer_location = self.fp.tell()
152 current_pointer_location = self.fp.tell()
153 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
153 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
154
154
155 try:
155 try:
156 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
156 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
157 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
157 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
158 except:
158 except:
159 # print "The read block (%3d) has not enough data" %self.nReadBlocks
159 # print "The read block (%3d) has not enough data" %self.nReadBlocks
160
160
161 if self.waitDataBlock(pointer_location=current_pointer_location):
161 if self.waitDataBlock(pointer_location=current_pointer_location):
162 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
162 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
163 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
163 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
164 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
164 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
165 # return 0
165 # return 0
166
166
167 # Dimensions : nChannels, nProfiles, nSamples
167 # Dimensions : nChannels, nProfiles, nSamples
168
168
169 junk = numpy.transpose(junk, (2, 0, 1))
169 junk = numpy.transpose(junk, (2, 0, 1))
170 self.datablock = junk['real'] + junk['imag'] * 1j
170 self.datablock = junk['real'] + junk['imag'] * 1j
171
171
172 self.profileIndex = 0
172 self.profileIndex = 0
173
173
174 self.flagIsNewFile = 0
174 self.flagIsNewFile = 0
175 self.flagIsNewBlock = 1
175 self.flagIsNewBlock = 1
176
176
177 self.nTotalBlocks += 1
177 self.nTotalBlocks += 1
178 self.nReadBlocks += 1
178 self.nReadBlocks += 1
179
179
180 return 1
180 return 1
181
181
182 def getFirstHeader(self):
182 def getFirstHeader(self):
183 ##print("6--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
183 ##print("6--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
184
184
185 self.getBasicHeader()
185 self.getBasicHeader()
186
186
187 self.dataOut.processingHeaderObj = self.processingHeaderObj.copy()
187 self.dataOut.processingHeaderObj = self.processingHeaderObj.copy()
188
188
189 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
189 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
190
190
191 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
191 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
192
192
193 #self.dataOut.ippSeconds_general=self.radarControllerHeaderObj.ippSeconds
193 #self.dataOut.ippSeconds_general=self.radarControllerHeaderObj.ippSeconds
194 #print(self.nTxs)
194 #print(self.nTxs)
195 if self.nTxs > 1:
195 if self.nTxs > 1:
196 #print(self.radarControllerHeaderObj.ippSeconds)
196 #print(self.radarControllerHeaderObj.ippSeconds)
197 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
197 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
198 #print(self.radarControllerHeaderObj.ippSeconds)
198 #print(self.radarControllerHeaderObj.ippSeconds)
199 # Time interval and code are propierties of dataOut. Its value depends of radarControllerHeaderObj.
199 # Time interval and code are propierties of dataOut. Its value depends of radarControllerHeaderObj.
200
200
201 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt
201 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt
202 #
202 #
203 # if self.radarControllerHeaderObj.code is not None:
203 # if self.radarControllerHeaderObj.code is not None:
204 #
204 #
205 # self.dataOut.nCode = self.radarControllerHeaderObj.nCode
205 # self.dataOut.nCode = self.radarControllerHeaderObj.nCode
206 #
206 #
207 # self.dataOut.nBaud = self.radarControllerHeaderObj.nBaud
207 # self.dataOut.nBaud = self.radarControllerHeaderObj.nBaud
208 #
208 #
209 # self.dataOut.code = self.radarControllerHeaderObj.code
209 # self.dataOut.code = self.radarControllerHeaderObj.code
210
210
211 self.dataOut.dtype = self.dtype
211 self.dataOut.dtype = self.dtype
212
212
213 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
213 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
214
214
215 self.dataOut.heightList = numpy.arange(
215 self.dataOut.heightList = numpy.arange(
216 self.processingHeaderObj.nHeights) * self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
216 self.processingHeaderObj.nHeights) * self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
217
217
218 self.dataOut.channelList = list(range(self.systemHeaderObj.nChannels))
218 self.dataOut.channelList = list(range(self.systemHeaderObj.nChannels))
219
219
220 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
220 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
221
221
222 # asumo q la data no esta decodificada
222 # asumo q la data no esta decodificada
223 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode
223 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode
224
224
225 # asumo q la data no esta sin flip
225 # asumo q la data no esta sin flip
226 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip
226 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip
227
227
228 self.dataOut.flagShiftFFT = self.processingHeaderObj.shif_fft
228 self.dataOut.flagShiftFFT = self.processingHeaderObj.shif_fft
229
229
230 def reshapeData(self):
230 def reshapeData(self):
231 ##print("7--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
231 ##print("7--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
232 if self.nTxs < 0:
232 if self.nTxs < 0:
233 return
233 return
234
234
235 if self.nTxs == 1:
235 if self.nTxs == 1:
236 return
236 return
237
237
238 if self.nTxs < 1 and self.processingHeaderObj.profilesPerBlock % (1. / self.nTxs) != 0:
238 if self.nTxs < 1 and self.processingHeaderObj.profilesPerBlock % (1. / self.nTxs) != 0:
239 raise ValueError("1./nTxs (=%f), should be a multiple of nProfiles (=%d)" % (
239 raise ValueError("1./nTxs (=%f), should be a multiple of nProfiles (=%d)" % (
240 1. / self.nTxs, self.processingHeaderObj.profilesPerBlock))
240 1. / self.nTxs, self.processingHeaderObj.profilesPerBlock))
241
241
242 if self.nTxs > 1 and self.processingHeaderObj.nHeights % self.nTxs != 0:
242 if self.nTxs > 1 and self.processingHeaderObj.nHeights % self.nTxs != 0:
243 raise ValueError("nTxs (=%d), should be a multiple of nHeights (=%d)" % (
243 raise ValueError("nTxs (=%d), should be a multiple of nHeights (=%d)" % (
244 self.nTxs, self.processingHeaderObj.nHeights))
244 self.nTxs, self.processingHeaderObj.nHeights))
245
245
246 self.datablock = self.datablock.reshape(
246 self.datablock = self.datablock.reshape(
247 (self.systemHeaderObj.nChannels, self.processingHeaderObj.profilesPerBlock * self.nTxs, int(self.processingHeaderObj.nHeights / self.nTxs)))
247 (self.systemHeaderObj.nChannels, self.processingHeaderObj.profilesPerBlock * self.nTxs, int(self.processingHeaderObj.nHeights / self.nTxs)))
248
248
249 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock * self.nTxs
249 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock * self.nTxs
250 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights / self.nTxs) * \
250 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights / self.nTxs) * \
251 self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
251 self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
252 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
252 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
253
253
254 return
254 return
255
255
256 def readFirstHeaderFromServer(self):
256 def readFirstHeaderFromServer(self):
257
257
258 ##print("8--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
258 ##print("8--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
259 self.getFirstHeader()
259 self.getFirstHeader()
260
260
261 self.firstHeaderSize = self.basicHeaderObj.size
261 self.firstHeaderSize = self.basicHeaderObj.size
262
262
263 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
263 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
264 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
264 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
265 if datatype == 0:
265 if datatype == 0:
266 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
266 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
267 elif datatype == 1:
267 elif datatype == 1:
268 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
268 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
269 elif datatype == 2:
269 elif datatype == 2:
270 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
270 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
271 elif datatype == 3:
271 elif datatype == 3:
272 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
272 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
273 elif datatype == 4:
273 elif datatype == 4:
274 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
274 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
275 elif datatype == 5:
275 elif datatype == 5:
276 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
276 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
277 else:
277 else:
278 raise ValueError('Data type was not defined')
278 raise ValueError('Data type was not defined')
279
279
280 self.dtype = datatype_str
280 self.dtype = datatype_str
281 # self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
281 # self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
282 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
282 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
283 self.firstHeaderSize + self.basicHeaderSize * \
283 self.firstHeaderSize + self.basicHeaderSize * \
284 (self.processingHeaderObj.dataBlocksPerFile - 1)
284 (self.processingHeaderObj.dataBlocksPerFile - 1)
285 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
285 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
286 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
286 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
287 self.getBlockDimension()
287 self.getBlockDimension()
288
288
289 def getFromServer(self):
289 def getFromServer(self):
290 ##print("9--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
290 ##print("9--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
291 self.flagDiscontinuousBlock = 0
291 self.flagDiscontinuousBlock = 0
292 self.profileIndex = 0
292 self.profileIndex = 0
293 self.flagIsNewBlock = 1
293 self.flagIsNewBlock = 1
294 self.dataOut.flagNoData = False
294 self.dataOut.flagNoData = False
295 self.nTotalBlocks += 1
295 self.nTotalBlocks += 1
296 self.nReadBlocks += 1
296 self.nReadBlocks += 1
297 self.blockPointer = 0
297 self.blockPointer = 0
298
298
299 block = self.receiver.recv()
299 block = self.receiver.recv()
300
300
301 self.basicHeaderObj.read(block[self.blockPointer:])
301 self.basicHeaderObj.read(block[self.blockPointer:])
302 self.blockPointer += self.basicHeaderObj.length
302 self.blockPointer += self.basicHeaderObj.length
303 self.systemHeaderObj.read(block[self.blockPointer:])
303 self.systemHeaderObj.read(block[self.blockPointer:])
304 self.blockPointer += self.systemHeaderObj.length
304 self.blockPointer += self.systemHeaderObj.length
305 self.radarControllerHeaderObj.read(block[self.blockPointer:])
305 self.radarControllerHeaderObj.read(block[self.blockPointer:])
306 self.blockPointer += self.radarControllerHeaderObj.length
306 self.blockPointer += self.radarControllerHeaderObj.length
307 self.processingHeaderObj.read(block[self.blockPointer:])
307 self.processingHeaderObj.read(block[self.blockPointer:])
308 self.blockPointer += self.processingHeaderObj.length
308 self.blockPointer += self.processingHeaderObj.length
309 self.readFirstHeaderFromServer()
309 self.readFirstHeaderFromServer()
310
310
311 timestamp = self.basicHeaderObj.get_datatime()
311 timestamp = self.basicHeaderObj.get_datatime()
312 print('[Reading] - Block {} - {}'.format(self.nTotalBlocks, timestamp))
312 print('[Receiving] - Block {} - {}'.format(self.nTotalBlocks, timestamp))
313 if self.nTotalBlocks == self.processingHeaderObj.dataBlocksPerFile:
314 self.nTotalBlocks = 0
315 self.nReadBlocks = 0
316 print('Receiving the next stream...')
313 current_pointer_location = self.blockPointer
317 current_pointer_location = self.blockPointer
314 junk = numpy.fromstring(
318 junk = numpy.fromstring(
315 block[self.blockPointer:], self.dtype, self.blocksize)
319 block[self.blockPointer:], self.dtype, self.blocksize)
316
320
317 try:
321 try:
318 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
322 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
319 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
323 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
320 except:
324 except:
321 # print "The read block (%3d) has not enough data" %self.nReadBlocks
325 # print "The read block (%3d) has not enough data" %self.nReadBlocks
322 if self.waitDataBlock(pointer_location=current_pointer_location):
326 if self.waitDataBlock(pointer_location=current_pointer_location):
323 junk = numpy.fromstring(
327 junk = numpy.fromstring(
324 block[self.blockPointer:], self.dtype, self.blocksize)
328 block[self.blockPointer:], self.dtype, self.blocksize)
325 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
329 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
326 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
330 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
327 # return 0
331 # return 0
328
332
329 # Dimensions : nChannels, nProfiles, nSamples
333 # Dimensions : nChannels, nProfiles, nSamples
330
334
331 junk = numpy.transpose(junk, (2, 0, 1))
335 junk = numpy.transpose(junk, (2, 0, 1))
332 self.datablock = junk['real'] + junk['imag'] * 1j
336 self.datablock = junk['real'] + junk['imag'] * 1j
333 self.profileIndex = 0
337 self.profileIndex = 0
334 if self.selBlocksize == None:
338 if self.selBlocksize == None:
335 self.selBlocksize = self.dataOut.nProfiles
339 self.selBlocksize = self.dataOut.nProfiles
336 if self.selBlocktime != None:
340 if self.selBlocktime != None:
337 if self.dataOut.nCohInt is not None:
341 if self.dataOut.nCohInt is not None:
338 nCohInt = self.dataOut.nCohInt
342 nCohInt = self.dataOut.nCohInt
339 else:
343 else:
340 nCohInt = 1
344 nCohInt = 1
341 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
345 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
342 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
346 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
343 self.dataOut.data = self.datablock[:,
347 self.dataOut.data = self.datablock[:,
344 self.profileIndex:self.profileIndex + self.selBlocksize, :]
348 self.profileIndex:self.profileIndex + self.selBlocksize, :]
345 datasize = self.dataOut.data.shape[1]
349 datasize = self.dataOut.data.shape[1]
346 if datasize < self.selBlocksize:
350 if datasize < self.selBlocksize:
347 buffer = numpy.zeros(
351 buffer = numpy.zeros(
348 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
352 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
349 buffer[:, :datasize, :] = self.dataOut.data
353 buffer[:, :datasize, :] = self.dataOut.data
350 self.dataOut.data = buffer
354 self.dataOut.data = buffer
351 self.profileIndex = blockIndex
355 self.profileIndex = blockIndex
352
356
353 self.dataOut.flagDataAsBlock = True
357 self.dataOut.flagDataAsBlock = True
354 self.flagIsNewBlock = 1
358 self.flagIsNewBlock = 1
355 self.dataOut.realtime = self.online
359 self.dataOut.realtime = self.online
356
360
357 return self.dataOut.data
361 return self.dataOut.data
358
362
359 def getData(self):
363 def getData(self):
360 """
364 """
361 getData obtiene una unidad de datos del buffer de lectura, un perfil, y la copia al objeto self.dataOut
365 getData obtiene una unidad de datos del buffer de lectura, un perfil, y la copia al objeto self.dataOut
362 del tipo "Voltage" con todos los parametros asociados a este (metadata). cuando no hay datos
366 del tipo "Voltage" con todos los parametros asociados a este (metadata). cuando no hay datos
363 en el buffer de lectura es necesario hacer una nueva lectura de los bloques de datos usando
367 en el buffer de lectura es necesario hacer una nueva lectura de los bloques de datos usando
364 "readNextBlock"
368 "readNextBlock"
365
369
366 Ademas incrementa el contador del buffer "self.profileIndex" en 1.
370 Ademas incrementa el contador del buffer "self.profileIndex" en 1.
367
371
368 Return:
372 Return:
369
373
370 Si el flag self.getByBlock ha sido seteado el bloque completo es copiado a self.dataOut y el self.profileIndex
374 Si el flag self.getByBlock ha sido seteado el bloque completo es copiado a self.dataOut y el self.profileIndex
371 es igual al total de perfiles leidos desde el archivo.
375 es igual al total de perfiles leidos desde el archivo.
372
376
373 Si self.getByBlock == False:
377 Si self.getByBlock == False:
374
378
375 self.dataOut.data = buffer[:, thisProfile, :]
379 self.dataOut.data = buffer[:, thisProfile, :]
376
380
377 shape = [nChannels, nHeis]
381 shape = [nChannels, nHeis]
378
382
379 Si self.getByBlock == True:
383 Si self.getByBlock == True:
380
384
381 self.dataOut.data = buffer[:, :, :]
385 self.dataOut.data = buffer[:, :, :]
382
386
383 shape = [nChannels, nProfiles, nHeis]
387 shape = [nChannels, nProfiles, nHeis]
384
388
385 Variables afectadas:
389 Variables afectadas:
386 self.dataOut
390 self.dataOut
387 self.profileIndex
391 self.profileIndex
388
392
389 Affected:
393 Affected:
390 self.dataOut
394 self.dataOut
391 self.profileIndex
395 self.profileIndex
392 self.flagDiscontinuousBlock
396 self.flagDiscontinuousBlock
393 self.flagIsNewBlock
397 self.flagIsNewBlock
394 """
398 """
395
399
396 ##print("10--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
400 ##print("10--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
397 if self.flagNoMoreFiles:
401 if self.flagNoMoreFiles:
398 self.dataOut.flagNoData = True
402 self.dataOut.flagNoData = True
399 return 0
403 return 0
400 self.flagDiscontinuousBlock = 0
404 self.flagDiscontinuousBlock = 0
401 self.flagIsNewBlock = 0
405 self.flagIsNewBlock = 0
402 if self.__hasNotDataInBuffer():
406 if self.__hasNotDataInBuffer():
403 if not(self.readNextBlock()):
407 if not(self.readNextBlock()):
404 return 0
408 return 0
405
409
406 self.getFirstHeader()
410 self.getFirstHeader()
407
411
408 self.reshapeData()
412 self.reshapeData()
409 if self.datablock is None:
413 if self.datablock is None:
410 self.dataOut.flagNoData = True
414 self.dataOut.flagNoData = True
411 return 0
415 return 0
412
416
413 if not self.getByBlock:
417 if not self.getByBlock:
414
418
415 """
419 """
416 Return profile by profile
420 Return profile by profile
417
421
418 If nTxs > 1 then one profile is divided by nTxs and number of total
422 If nTxs > 1 then one profile is divided by nTxs and number of total
419 blocks is increased by nTxs (nProfiles *= nTxs)
423 blocks is increased by nTxs (nProfiles *= nTxs)
420 """
424 """
421 self.dataOut.flagDataAsBlock = False
425 self.dataOut.flagDataAsBlock = False
422 self.dataOut.data = self.datablock[:, self.profileIndex, :]
426 self.dataOut.data = self.datablock[:, self.profileIndex, :]
423 self.dataOut.profileIndex = self.profileIndex
427 self.dataOut.profileIndex = self.profileIndex
424
428
425
429
426 self.profileIndex += 1
430 self.profileIndex += 1
427
431
428 else:
432 else:
429 """
433 """
430 Return a block
434 Return a block
431 """
435 """
432 if self.selBlocksize == None:
436 if self.selBlocksize == None:
433 self.selBlocksize = self.dataOut.nProfiles
437 self.selBlocksize = self.dataOut.nProfiles
434 if self.selBlocktime != None:
438 if self.selBlocktime != None:
435 if self.dataOut.nCohInt is not None:
439 if self.dataOut.nCohInt is not None:
436 nCohInt = self.dataOut.nCohInt
440 nCohInt = self.dataOut.nCohInt
437 else:
441 else:
438 nCohInt = 1
442 nCohInt = 1
439 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
443 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
440 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
444 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
441
445
442 self.dataOut.data = self.datablock[:,
446 self.dataOut.data = self.datablock[:,
443 self.profileIndex:self.profileIndex + self.selBlocksize, :]
447 self.profileIndex:self.profileIndex + self.selBlocksize, :]
444 self.profileIndex += self.selBlocksize
448 self.profileIndex += self.selBlocksize
445 datasize = self.dataOut.data.shape[1]
449 datasize = self.dataOut.data.shape[1]
446
450
447 if datasize < self.selBlocksize:
451 if datasize < self.selBlocksize:
448 buffer = numpy.zeros(
452 buffer = numpy.zeros(
449 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
453 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
450 buffer[:, :datasize, :] = self.dataOut.data
454 buffer[:, :datasize, :] = self.dataOut.data
451
455
452 while datasize < self.selBlocksize: # Not enough profiles to fill the block
456 while datasize < self.selBlocksize: # Not enough profiles to fill the block
453 if not(self.readNextBlock()):
457 if not(self.readNextBlock()):
454 return 0
458 return 0
455 self.getFirstHeader()
459 self.getFirstHeader()
456 self.reshapeData()
460 self.reshapeData()
457 if self.datablock is None:
461 if self.datablock is None:
458 self.dataOut.flagNoData = True
462 self.dataOut.flagNoData = True
459 return 0
463 return 0
460 # stack data
464 # stack data
461 blockIndex = self.selBlocksize - datasize
465 blockIndex = self.selBlocksize - datasize
462 datablock1 = self.datablock[:, :blockIndex, :]
466 datablock1 = self.datablock[:, :blockIndex, :]
463
467
464 buffer[:, datasize:datasize +
468 buffer[:, datasize:datasize +
465 datablock1.shape[1], :] = datablock1
469 datablock1.shape[1], :] = datablock1
466 datasize += datablock1.shape[1]
470 datasize += datablock1.shape[1]
467
471
468 self.dataOut.data = buffer
472 self.dataOut.data = buffer
469 self.profileIndex = blockIndex
473 self.profileIndex = blockIndex
470
474
471 self.dataOut.flagDataAsBlock = True
475 self.dataOut.flagDataAsBlock = True
472 self.dataOut.nProfiles = self.dataOut.data.shape[1]
476 self.dataOut.nProfiles = self.dataOut.data.shape[1]
473
477
474 #######################DP#######################
478 #######################DP#######################
475 self.dataOut.CurrentBlock=self.nReadBlocks
479 self.dataOut.CurrentBlock=self.nReadBlocks
476 self.dataOut.LastBlock=self.processingHeaderObj.dataBlocksPerFile
480 self.dataOut.LastBlock=self.processingHeaderObj.dataBlocksPerFile
477 #######################DP#######################
481 #######################DP#######################
478 self.dataOut.flagNoData = False
482 self.dataOut.flagNoData = False
479
483
480 #self.getBasicHeader()
484 #self.getBasicHeader()
481
485
482 self.dataOut.realtime = self.online
486 self.dataOut.realtime = self.online
483
487
484 return self.dataOut.data
488 return self.dataOut.data
485
489
486
490
487 @MPDecorator
491 @MPDecorator
488 class VoltageWriter(JRODataWriter, Operation):
492 class VoltageWriter(JRODataWriter, Operation):
489 """
493 """
490 Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura
494 Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura
491 de los datos siempre se realiza por bloques.
495 de los datos siempre se realiza por bloques.
492 """
496 """
493
497
494 ext = ".r"
498 ext = ".r"
495
499
496 optchar = "D"
500 optchar = "D"
497
501
498 shapeBuffer = None
502 shapeBuffer = None
499
503
500 def __init__(self): # , **kwargs):
504 def __init__(self): # , **kwargs):
501 """
505 """
502 Inicializador de la clase VoltageWriter para la escritura de datos de espectros.
506 Inicializador de la clase VoltageWriter para la escritura de datos de espectros.
503
507
504 Affected:
508 Affected:
505 self.dataOut
509 self.dataOut
506
510
507 Return: None
511 Return: None
508 """
512 """
509 Operation.__init__(self) # , **kwargs)
513 Operation.__init__(self) # , **kwargs)
510
514
511 self.nTotalBlocks = 0
515 self.nTotalBlocks = 0
512
516
513 self.profileIndex = 0
517 self.profileIndex = 0
514
518
515 self.isConfig = False
519 self.isConfig = False
516
520
517 self.fp = None
521 self.fp = None
518
522
519 self.flagIsNewFile = 1
523 self.flagIsNewFile = 1
520
524
521 self.blockIndex = 0
525 self.blockIndex = 0
522
526
523 self.flagIsNewBlock = 0
527 self.flagIsNewBlock = 0
524
528
525 self.setFile = None
529 self.setFile = None
526
530
527 self.dtype = None
531 self.dtype = None
528
532
529 self.path = None
533 self.path = None
530
534
531 self.filename = None
535 self.filename = None
532
536
533 self.basicHeaderObj = BasicHeader(LOCALTIME)
537 self.basicHeaderObj = BasicHeader(LOCALTIME)
534
538
535 self.systemHeaderObj = SystemHeader()
539 self.systemHeaderObj = SystemHeader()
536
540
537 self.radarControllerHeaderObj = RadarControllerHeader()
541 self.radarControllerHeaderObj = RadarControllerHeader()
538
542
539 self.processingHeaderObj = ProcessingHeader()
543 self.processingHeaderObj = ProcessingHeader()
540
544
541 def hasAllDataInBuffer(self):
545 def hasAllDataInBuffer(self):
542 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock:
546 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock:
543 return 1
547 return 1
544 return 0
548 return 0
545
549
546 def setBlockDimension(self):
550 def setBlockDimension(self):
547 """
551 """
548 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
552 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
549
553
550 Affected:
554 Affected:
551 self.shape_spc_Buffer
555 self.shape_spc_Buffer
552 self.shape_cspc_Buffer
556 self.shape_cspc_Buffer
553 self.shape_dc_Buffer
557 self.shape_dc_Buffer
554
558
555 Return: None
559 Return: None
556 """
560 """
557 self.shapeBuffer = (self.processingHeaderObj.profilesPerBlock,
561 self.shapeBuffer = (self.processingHeaderObj.profilesPerBlock,
558 self.processingHeaderObj.nHeights,
562 self.processingHeaderObj.nHeights,
559 self.systemHeaderObj.nChannels)
563 self.systemHeaderObj.nChannels)
560
564
561 self.datablock = numpy.zeros((self.systemHeaderObj.nChannels,
565 self.datablock = numpy.zeros((self.systemHeaderObj.nChannels,
562 self.processingHeaderObj.profilesPerBlock,
566 self.processingHeaderObj.profilesPerBlock,
563 self.processingHeaderObj.nHeights),
567 self.processingHeaderObj.nHeights),
564 dtype=numpy.dtype('complex64'))
568 dtype=numpy.dtype('complex64'))
565
569
566 def writeBlock(self):
570 def writeBlock(self):
567 """
571 """
568 Escribe el buffer en el file designado
572 Escribe el buffer en el file designado
569
573
570 Affected:
574 Affected:
571 self.profileIndex
575 self.profileIndex
572 self.flagIsNewFile
576 self.flagIsNewFile
573 self.flagIsNewBlock
577 self.flagIsNewBlock
574 self.nTotalBlocks
578 self.nTotalBlocks
575 self.blockIndex
579 self.blockIndex
576
580
577 Return: None
581 Return: None
578 """
582 """
579 data = numpy.zeros(self.shapeBuffer, self.dtype)
583 data = numpy.zeros(self.shapeBuffer, self.dtype)
580
584
581 junk = numpy.transpose(self.datablock, (1, 2, 0))
585 junk = numpy.transpose(self.datablock, (1, 2, 0))
582
586
583 data['real'] = junk.real
587 data['real'] = junk.real
584 data['imag'] = junk.imag
588 data['imag'] = junk.imag
585
589
586 data = data.reshape((-1))
590 data = data.reshape((-1))
587
591
588 data.tofile(self.fp)
592 data.tofile(self.fp)
589
593
590 self.datablock.fill(0)
594 self.datablock.fill(0)
591
595
592 self.profileIndex = 0
596 self.profileIndex = 0
593 self.flagIsNewFile = 0
597 self.flagIsNewFile = 0
594 self.flagIsNewBlock = 1
598 self.flagIsNewBlock = 1
595
599
596 self.blockIndex += 1
600 self.blockIndex += 1
597 self.nTotalBlocks += 1
601 self.nTotalBlocks += 1
598
602
599 # print "[Writing] Block = %04d" %self.blockIndex
603 # print "[Writing] Block = %04d" %self.blockIndex
600
604
601 def putData(self):
605 def putData(self):
602 """
606 """
603 Setea un bloque de datos y luego los escribe en un file
607 Setea un bloque de datos y luego los escribe en un file
604
608
605 Affected:
609 Affected:
606 self.flagIsNewBlock
610 self.flagIsNewBlock
607 self.profileIndex
611 self.profileIndex
608
612
609 Return:
613 Return:
610 0 : Si no hay data o no hay mas files que puedan escribirse
614 0 : Si no hay data o no hay mas files que puedan escribirse
611 1 : Si se escribio la data de un bloque en un file
615 1 : Si se escribio la data de un bloque en un file
612 """
616 """
613 if self.dataOut.flagNoData:
617 if self.dataOut.flagNoData:
614 return 0
618 return 0
615
619
616 self.flagIsNewBlock = 0
620 self.flagIsNewBlock = 0
617
621
618 if self.dataOut.flagDiscontinuousBlock:
622 if self.dataOut.flagDiscontinuousBlock:
619 self.datablock.fill(0)
623 self.datablock.fill(0)
620 self.profileIndex = 0
624 self.profileIndex = 0
621 self.setNextFile()
625 self.setNextFile()
622
626
623 if self.profileIndex == 0:
627 if self.profileIndex == 0:
624 self.setBasicHeader()
628 self.setBasicHeader()
625
629
626 self.datablock[:, self.profileIndex, :] = self.dataOut.data
630 if not self.dataOut.flagDataAsBlock:
627
631 self.datablock[:, self.profileIndex, :] = self.dataOut.data
628 self.profileIndex += 1
632 self.profileIndex += 1
629
633 else:
634 self.datablock[:, :, :] = self.dataOut.data
635 self.profileIndex = self.processingHeaderObj.profilesPerBlock
636
630 if self.hasAllDataInBuffer():
637 if self.hasAllDataInBuffer():
631 # if self.flagIsNewFile:
638 # if self.flagIsNewFile:
632 self.writeNextBlock()
639 self.writeNextBlock()
633 # self.setFirstHeader()
640 # self.setFirstHeader()
634
641
635 return 1
642 return 1
636
643
637 def __getBlockSize(self):
644 def __getBlockSize(self):
638 '''
645 '''
639 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Voltage
646 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Voltage
640 '''
647 '''
641
648
642 dtype_width = self.getDtypeWidth()
649 dtype_width = self.getDtypeWidth()
643
650
644 blocksize = int(self.dataOut.nHeights * self.dataOut.nChannels *
651 blocksize = int(self.dataOut.nHeights * self.dataOut.nChannels *
645 self.profilesPerBlock * dtype_width * 2)
652 self.profilesPerBlock * dtype_width * 2)
646
653
647 return blocksize
654 return blocksize
648
655
649 def setFirstHeader(self):
656 def setFirstHeader(self):
650 """
657 """
651 Obtiene una copia del First Header
658 Obtiene una copia del First Header
652
659
653 Affected:
660 Affected:
654 self.systemHeaderObj
661 self.systemHeaderObj
655 self.radarControllerHeaderObj
662 self.radarControllerHeaderObj
656 self.dtype
663 self.dtype
657
664
658 Return:
665 Return:
659 None
666 None
660 """
667 """
661
668
662 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
669 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
663 self.systemHeaderObj.nChannels = self.dataOut.nChannels
670 self.systemHeaderObj.nChannels = self.dataOut.nChannels
664 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
671 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
665
672
666 self.processingHeaderObj.dtype = 0 # Voltage
673 self.processingHeaderObj.dtype = 0 # Voltage
667 self.processingHeaderObj.blockSize = self.__getBlockSize()
674 self.processingHeaderObj.blockSize = self.__getBlockSize()
668 self.processingHeaderObj.profilesPerBlock = self.profilesPerBlock
675 self.processingHeaderObj.profilesPerBlock = self.profilesPerBlock
669 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
676 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
670 # podria ser 1 o self.dataOut.processingHeaderObj.nWindows
677 # podria ser 1 o self.dataOut.processingHeaderObj.nWindows
671 self.processingHeaderObj.nWindows = 1
678 self.processingHeaderObj.nWindows = 1
672 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt
679 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt
673 # Cuando la data de origen es de tipo Voltage
680 # Cuando la data de origen es de tipo Voltage
674 self.processingHeaderObj.nIncohInt = 1
681 self.processingHeaderObj.nIncohInt = 1
675 # Cuando la data de origen es de tipo Voltage
682 # Cuando la data de origen es de tipo Voltage
676 self.processingHeaderObj.totalSpectra = 0
683 self.processingHeaderObj.totalSpectra = 0
677
684
678 if self.dataOut.code is not None:
685 if self.dataOut.code is not None:
679 self.processingHeaderObj.code = self.dataOut.code
686 self.processingHeaderObj.code = self.dataOut.code
680 self.processingHeaderObj.nCode = self.dataOut.nCode
687 self.processingHeaderObj.nCode = self.dataOut.nCode
681 self.processingHeaderObj.nBaud = self.dataOut.nBaud
688 self.processingHeaderObj.nBaud = self.dataOut.nBaud
682
689
683 if self.processingHeaderObj.nWindows != 0:
690 if self.processingHeaderObj.nWindows != 0:
684 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
691 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
685 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - \
692 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - \
686 self.dataOut.heightList[0]
693 self.dataOut.heightList[0]
687 self.processingHeaderObj.nHeights = self.dataOut.nHeights
694 self.processingHeaderObj.nHeights = self.dataOut.nHeights
688 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
695 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
689
696
690 self.processingHeaderObj.processFlags = self.getProcessFlags()
697 self.processingHeaderObj.processFlags = self.getProcessFlags()
691
698
692 self.setBasicHeader()
699 self.setBasicHeader()
General Comments 0
You need to be logged in to leave comments. Login now