##// END OF EJS Templates
Merge branch 'v3.0-devel' of http://jro-dev.igp.gob.pe/rhodecode/schain into v3.0-devel
avaldez -
r1304:865648b7218f merge
parent child
Show More
@@ -1,648 +1,648
1 '''
1 '''
2 Main routines to create a Signal Chain project
2 Main routines to create a Signal Chain project
3 '''
3 '''
4
4
5 import re
5 import re
6 import sys
6 import sys
7 import ast
7 import ast
8 import datetime
8 import datetime
9 import traceback
9 import traceback
10 import time
10 import time
11 from multiprocessing import Process, Queue
11 from multiprocessing import Process, Queue
12 from threading import Thread
12 from threading import Thread
13 from xml.etree.ElementTree import ElementTree, Element, SubElement
13 from xml.etree.ElementTree import ElementTree, Element, SubElement
14
14
15 from schainpy.admin import Alarm, SchainWarning
15 from schainpy.admin import Alarm, SchainWarning
16 from schainpy.model import *
16 from schainpy.model import *
17 from schainpy.utils import log
17 from schainpy.utils import log
18
18
19
19
20 class ConfBase():
20 class ConfBase():
21
21
22 def __init__(self):
22 def __init__(self):
23
23
24 self.id = '0'
24 self.id = '0'
25 self.name = None
25 self.name = None
26 self.priority = None
26 self.priority = None
27 self.parameters = {}
27 self.parameters = {}
28 self.object = None
28 self.object = None
29 self.operations = []
29 self.operations = []
30
30
31 def getId(self):
31 def getId(self):
32
32
33 return self.id
33 return self.id
34
34
35 def getNewId(self):
35 def getNewId(self):
36
36
37 return int(self.id) * 10 + len(self.operations) + 1
37 return int(self.id) * 10 + len(self.operations) + 1
38
38
39 def updateId(self, new_id):
39 def updateId(self, new_id):
40
40
41 self.id = str(new_id)
41 self.id = str(new_id)
42
42
43 n = 1
43 n = 1
44 for conf in self.operations:
44 for conf in self.operations:
45 conf_id = str(int(new_id) * 10 + n)
45 conf_id = str(int(new_id) * 10 + n)
46 conf.updateId(conf_id)
46 conf.updateId(conf_id)
47 n += 1
47 n += 1
48
48
49 def getKwargs(self):
49 def getKwargs(self):
50
50
51 params = {}
51 params = {}
52
52
53 for key, value in self.parameters.items():
53 for key, value in self.parameters.items():
54 if value not in (None, '', ' '):
54 if value not in (None, '', ' '):
55 params[key] = value
55 params[key] = value
56
56
57 return params
57 return params
58
58
59 def update(self, **kwargs):
59 def update(self, **kwargs):
60
60
61 for key, value in kwargs.items():
61 for key, value in kwargs.items():
62 self.addParameter(name=key, value=value)
62 self.addParameter(name=key, value=value)
63
63
64 def addParameter(self, name, value, format=None):
64 def addParameter(self, name, value, format=None):
65 '''
65 '''
66 '''
66 '''
67
67
68 if isinstance(value, str) and re.search(r'(\d+/\d+/\d+)', value):
68 if isinstance(value, str) and re.search(r'(\d+/\d+/\d+)', value):
69 self.parameters[name] = datetime.date(*[int(x) for x in value.split('/')])
69 self.parameters[name] = datetime.date(*[int(x) for x in value.split('/')])
70 elif isinstance(value, str) and re.search(r'(\d+:\d+:\d+)', value):
70 elif isinstance(value, str) and re.search(r'(\d+:\d+:\d+)', value):
71 self.parameters[name] = datetime.time(*[int(x) for x in value.split(':')])
71 self.parameters[name] = datetime.time(*[int(x) for x in value.split(':')])
72 else:
72 else:
73 try:
73 try:
74 self.parameters[name] = ast.literal_eval(value)
74 self.parameters[name] = ast.literal_eval(value)
75 except:
75 except:
76 if isinstance(value, str) and ',' in value:
76 if isinstance(value, str) and ',' in value:
77 self.parameters[name] = value.split(',')
77 self.parameters[name] = value.split(',')
78 else:
78 else:
79 self.parameters[name] = value
79 self.parameters[name] = value
80
80
81 def getParameters(self):
81 def getParameters(self):
82
82
83 params = {}
83 params = {}
84 for key, value in self.parameters.items():
84 for key, value in self.parameters.items():
85 s = type(value).__name__
85 s = type(value).__name__
86 if s == 'date':
86 if s == 'date':
87 params[key] = value.strftime('%Y/%m/%d')
87 params[key] = value.strftime('%Y/%m/%d')
88 elif s == 'time':
88 elif s == 'time':
89 params[key] = value.strftime('%H:%M:%S')
89 params[key] = value.strftime('%H:%M:%S')
90 else:
90 else:
91 params[key] = str(value)
91 params[key] = str(value)
92
92
93 return params
93 return params
94
94
95 def makeXml(self, element):
95 def makeXml(self, element):
96
96
97 xml = SubElement(element, self.ELEMENTNAME)
97 xml = SubElement(element, self.ELEMENTNAME)
98 for label in self.xml_labels:
98 for label in self.xml_labels:
99 xml.set(label, str(getattr(self, label)))
99 xml.set(label, str(getattr(self, label)))
100
100
101 for key, value in self.getParameters().items():
101 for key, value in self.getParameters().items():
102 xml_param = SubElement(xml, 'Parameter')
102 xml_param = SubElement(xml, 'Parameter')
103 xml_param.set('name', key)
103 xml_param.set('name', key)
104 xml_param.set('value', value)
104 xml_param.set('value', value)
105
105
106 for conf in self.operations:
106 for conf in self.operations:
107 conf.makeXml(xml)
107 conf.makeXml(xml)
108
108
109 def __str__(self):
109 def __str__(self):
110
110
111 if self.ELEMENTNAME == 'Operation':
111 if self.ELEMENTNAME == 'Operation':
112 s = ' {}[id={}]\n'.format(self.name, self.id)
112 s = ' {}[id={}]\n'.format(self.name, self.id)
113 else:
113 else:
114 s = '{}[id={}, inputId={}]\n'.format(self.name, self.id, self.inputId)
114 s = '{}[id={}, inputId={}]\n'.format(self.name, self.id, self.inputId)
115
115
116 for key, value in self.parameters.items():
116 for key, value in self.parameters.items():
117 if self.ELEMENTNAME == 'Operation':
117 if self.ELEMENTNAME == 'Operation':
118 s += ' {}: {}\n'.format(key, value)
118 s += ' {}: {}\n'.format(key, value)
119 else:
119 else:
120 s += ' {}: {}\n'.format(key, value)
120 s += ' {}: {}\n'.format(key, value)
121
121
122 for conf in self.operations:
122 for conf in self.operations:
123 s += str(conf)
123 s += str(conf)
124
124
125 return s
125 return s
126
126
127 class OperationConf(ConfBase):
127 class OperationConf(ConfBase):
128
128
129 ELEMENTNAME = 'Operation'
129 ELEMENTNAME = 'Operation'
130 xml_labels = ['id', 'name']
130 xml_labels = ['id', 'name']
131
131
132 def setup(self, id, name, priority, project_id, err_queue):
132 def setup(self, id, name, priority, project_id, err_queue):
133
133
134 self.id = str(id)
134 self.id = str(id)
135 self.project_id = project_id
135 self.project_id = project_id
136 self.name = name
136 self.name = name
137 self.type = 'other'
137 self.type = 'other'
138 self.err_queue = err_queue
138 self.err_queue = err_queue
139
139
140 def readXml(self, element, project_id, err_queue):
140 def readXml(self, element, project_id, err_queue):
141
141
142 self.id = element.get('id')
142 self.id = element.get('id')
143 self.name = element.get('name')
143 self.name = element.get('name')
144 self.type = 'other'
144 self.type = 'other'
145 self.project_id = str(project_id)
145 self.project_id = str(project_id)
146 self.err_queue = err_queue
146 self.err_queue = err_queue
147
147
148 for elm in element.iter('Parameter'):
148 for elm in element.iter('Parameter'):
149 self.addParameter(elm.get('name'), elm.get('value'))
149 self.addParameter(elm.get('name'), elm.get('value'))
150
150
151 def createObject(self):
151 def createObject(self):
152
152
153 className = eval(self.name)
153 className = eval(self.name)
154
154
155 if 'Plot' in self.name or 'Writer' in self.name:
155 if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name:
156 kwargs = self.getKwargs()
156 kwargs = self.getKwargs()
157 opObj = className(self.id, self.id, self.project_id, self.err_queue, **kwargs)
157 opObj = className(self.id, self.id, self.project_id, self.err_queue, **kwargs)
158 opObj.start()
158 opObj.start()
159 self.type = 'external'
159 self.type = 'external'
160 else:
160 else:
161 opObj = className()
161 opObj = className()
162
162
163 self.object = opObj
163 self.object = opObj
164 return opObj
164 return opObj
165
165
166 class ProcUnitConf(ConfBase):
166 class ProcUnitConf(ConfBase):
167
167
168 ELEMENTNAME = 'ProcUnit'
168 ELEMENTNAME = 'ProcUnit'
169 xml_labels = ['id', 'inputId', 'name']
169 xml_labels = ['id', 'inputId', 'name']
170
170
171 def setup(self, project_id, id, name, datatype, inputId, err_queue):
171 def setup(self, project_id, id, name, datatype, inputId, err_queue):
172 '''
172 '''
173 '''
173 '''
174
174
175 if datatype == None and name == None:
175 if datatype == None and name == None:
176 raise ValueError('datatype or name should be defined')
176 raise ValueError('datatype or name should be defined')
177
177
178 if name == None:
178 if name == None:
179 if 'Proc' in datatype:
179 if 'Proc' in datatype:
180 name = datatype
180 name = datatype
181 else:
181 else:
182 name = '%sProc' % (datatype)
182 name = '%sProc' % (datatype)
183
183
184 if datatype == None:
184 if datatype == None:
185 datatype = name.replace('Proc', '')
185 datatype = name.replace('Proc', '')
186
186
187 self.id = str(id)
187 self.id = str(id)
188 self.project_id = project_id
188 self.project_id = project_id
189 self.name = name
189 self.name = name
190 self.datatype = datatype
190 self.datatype = datatype
191 self.inputId = inputId
191 self.inputId = inputId
192 self.err_queue = err_queue
192 self.err_queue = err_queue
193 self.operations = []
193 self.operations = []
194 self.parameters = {}
194 self.parameters = {}
195
195
196 def removeOperation(self, id):
196 def removeOperation(self, id):
197
197
198 i = [1 if x.id==id else 0 for x in self.operations]
198 i = [1 if x.id==id else 0 for x in self.operations]
199 self.operations.pop(i.index(1))
199 self.operations.pop(i.index(1))
200
200
201 def getOperation(self, id):
201 def getOperation(self, id):
202
202
203 for conf in self.operations:
203 for conf in self.operations:
204 if conf.id == id:
204 if conf.id == id:
205 return conf
205 return conf
206
206
207 def addOperation(self, name, optype='self'):
207 def addOperation(self, name, optype='self'):
208 '''
208 '''
209 '''
209 '''
210
210
211 id = self.getNewId()
211 id = self.getNewId()
212 conf = OperationConf()
212 conf = OperationConf()
213 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
213 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
214 self.operations.append(conf)
214 self.operations.append(conf)
215
215
216 return conf
216 return conf
217
217
218 def readXml(self, element, project_id, err_queue):
218 def readXml(self, element, project_id, err_queue):
219
219
220 self.id = element.get('id')
220 self.id = element.get('id')
221 self.name = element.get('name')
221 self.name = element.get('name')
222 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
222 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
223 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
223 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
224 self.project_id = str(project_id)
224 self.project_id = str(project_id)
225 self.err_queue = err_queue
225 self.err_queue = err_queue
226 self.operations = []
226 self.operations = []
227 self.parameters = {}
227 self.parameters = {}
228
228
229 for elm in element:
229 for elm in element:
230 if elm.tag == 'Parameter':
230 if elm.tag == 'Parameter':
231 self.addParameter(elm.get('name'), elm.get('value'))
231 self.addParameter(elm.get('name'), elm.get('value'))
232 elif elm.tag == 'Operation':
232 elif elm.tag == 'Operation':
233 conf = OperationConf()
233 conf = OperationConf()
234 conf.readXml(elm, project_id, err_queue)
234 conf.readXml(elm, project_id, err_queue)
235 self.operations.append(conf)
235 self.operations.append(conf)
236
236
237 def createObjects(self):
237 def createObjects(self):
238 '''
238 '''
239 Instancia de unidades de procesamiento.
239 Instancia de unidades de procesamiento.
240 '''
240 '''
241
241
242 className = eval(self.name)
242 className = eval(self.name)
243 kwargs = self.getKwargs()
243 kwargs = self.getKwargs()
244 procUnitObj = className()
244 procUnitObj = className()
245 procUnitObj.name = self.name
245 procUnitObj.name = self.name
246 log.success('creating process...', self.name)
246 log.success('creating process...', self.name)
247
247
248 for conf in self.operations:
248 for conf in self.operations:
249
249
250 opObj = conf.createObject()
250 opObj = conf.createObject()
251
251
252 log.success('adding operation: {}, type:{}'.format(
252 log.success('adding operation: {}, type:{}'.format(
253 conf.name,
253 conf.name,
254 conf.type), self.name)
254 conf.type), self.name)
255
255
256 procUnitObj.addOperation(conf, opObj)
256 procUnitObj.addOperation(conf, opObj)
257
257
258 self.object = procUnitObj
258 self.object = procUnitObj
259
259
260 def run(self):
260 def run(self):
261 '''
261 '''
262 '''
262 '''
263
263
264 return self.object.call(**self.getKwargs())
264 return self.object.call(**self.getKwargs())
265
265
266
266
267 class ReadUnitConf(ProcUnitConf):
267 class ReadUnitConf(ProcUnitConf):
268
268
269 ELEMENTNAME = 'ReadUnit'
269 ELEMENTNAME = 'ReadUnit'
270
270
271 def __init__(self):
271 def __init__(self):
272
272
273 self.id = None
273 self.id = None
274 self.datatype = None
274 self.datatype = None
275 self.name = None
275 self.name = None
276 self.inputId = None
276 self.inputId = None
277 self.operations = []
277 self.operations = []
278 self.parameters = {}
278 self.parameters = {}
279
279
280 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
280 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
281 startTime='', endTime='', server=None, **kwargs):
281 startTime='', endTime='', server=None, **kwargs):
282
282
283 if datatype == None and name == None:
283 if datatype == None and name == None:
284 raise ValueError('datatype or name should be defined')
284 raise ValueError('datatype or name should be defined')
285 if name == None:
285 if name == None:
286 if 'Reader' in datatype:
286 if 'Reader' in datatype:
287 name = datatype
287 name = datatype
288 datatype = name.replace('Reader','')
288 datatype = name.replace('Reader','')
289 else:
289 else:
290 name = '{}Reader'.format(datatype)
290 name = '{}Reader'.format(datatype)
291 if datatype == None:
291 if datatype == None:
292 if 'Reader' in name:
292 if 'Reader' in name:
293 datatype = name.replace('Reader','')
293 datatype = name.replace('Reader','')
294 else:
294 else:
295 datatype = name
295 datatype = name
296 name = '{}Reader'.format(name)
296 name = '{}Reader'.format(name)
297
297
298 self.id = id
298 self.id = id
299 self.project_id = project_id
299 self.project_id = project_id
300 self.name = name
300 self.name = name
301 self.datatype = datatype
301 self.datatype = datatype
302 self.err_queue = err_queue
302 self.err_queue = err_queue
303
303
304 self.addParameter(name='path', value=path)
304 self.addParameter(name='path', value=path)
305 self.addParameter(name='startDate', value=startDate)
305 self.addParameter(name='startDate', value=startDate)
306 self.addParameter(name='endDate', value=endDate)
306 self.addParameter(name='endDate', value=endDate)
307 self.addParameter(name='startTime', value=startTime)
307 self.addParameter(name='startTime', value=startTime)
308 self.addParameter(name='endTime', value=endTime)
308 self.addParameter(name='endTime', value=endTime)
309
309
310 for key, value in kwargs.items():
310 for key, value in kwargs.items():
311 self.addParameter(name=key, value=value)
311 self.addParameter(name=key, value=value)
312
312
313
313
314 class Project(Process):
314 class Project(Process):
315
315
316 ELEMENTNAME = 'Project'
316 ELEMENTNAME = 'Project'
317
317
318 def __init__(self):
318 def __init__(self):
319
319
320 Process.__init__(self)
320 Process.__init__(self)
321 self.id = None
321 self.id = None
322 self.filename = None
322 self.filename = None
323 self.description = None
323 self.description = None
324 self.email = None
324 self.email = None
325 self.alarm = []
325 self.alarm = []
326 self.configurations = {}
326 self.configurations = {}
327 # self.err_queue = Queue()
327 # self.err_queue = Queue()
328 self.err_queue = None
328 self.err_queue = None
329 self.started = False
329 self.started = False
330
330
331 def getNewId(self):
331 def getNewId(self):
332
332
333 idList = list(self.configurations.keys())
333 idList = list(self.configurations.keys())
334 id = int(self.id) * 10
334 id = int(self.id) * 10
335
335
336 while True:
336 while True:
337 id += 1
337 id += 1
338
338
339 if str(id) in idList:
339 if str(id) in idList:
340 continue
340 continue
341
341
342 break
342 break
343
343
344 return str(id)
344 return str(id)
345
345
346 def updateId(self, new_id):
346 def updateId(self, new_id):
347
347
348 self.id = str(new_id)
348 self.id = str(new_id)
349
349
350 keyList = list(self.configurations.keys())
350 keyList = list(self.configurations.keys())
351 keyList.sort()
351 keyList.sort()
352
352
353 n = 1
353 n = 1
354 new_confs = {}
354 new_confs = {}
355
355
356 for procKey in keyList:
356 for procKey in keyList:
357
357
358 conf = self.configurations[procKey]
358 conf = self.configurations[procKey]
359 idProcUnit = str(int(self.id) * 10 + n)
359 idProcUnit = str(int(self.id) * 10 + n)
360 conf.updateId(idProcUnit)
360 conf.updateId(idProcUnit)
361 new_confs[idProcUnit] = conf
361 new_confs[idProcUnit] = conf
362 n += 1
362 n += 1
363
363
364 self.configurations = new_confs
364 self.configurations = new_confs
365
365
366 def setup(self, id=1, name='', description='', email=None, alarm=[]):
366 def setup(self, id=1, name='', description='', email=None, alarm=[]):
367
367
368 self.id = str(id)
368 self.id = str(id)
369 self.description = description
369 self.description = description
370 self.email = email
370 self.email = email
371 self.alarm = alarm
371 self.alarm = alarm
372 if name:
372 if name:
373 self.name = '{} ({})'.format(Process.__name__, name)
373 self.name = '{} ({})'.format(Process.__name__, name)
374
374
375 def update(self, **kwargs):
375 def update(self, **kwargs):
376
376
377 for key, value in kwargs.items():
377 for key, value in kwargs.items():
378 setattr(self, key, value)
378 setattr(self, key, value)
379
379
380 def clone(self):
380 def clone(self):
381
381
382 p = Project()
382 p = Project()
383 p.id = self.id
383 p.id = self.id
384 p.name = self.name
384 p.name = self.name
385 p.description = self.description
385 p.description = self.description
386 p.configurations = self.configurations.copy()
386 p.configurations = self.configurations.copy()
387
387
388 return p
388 return p
389
389
390 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
390 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
391
391
392 '''
392 '''
393 '''
393 '''
394
394
395 if id is None:
395 if id is None:
396 idReadUnit = self.getNewId()
396 idReadUnit = self.getNewId()
397 else:
397 else:
398 idReadUnit = str(id)
398 idReadUnit = str(id)
399
399
400 conf = ReadUnitConf()
400 conf = ReadUnitConf()
401 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
401 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
402 self.configurations[conf.id] = conf
402 self.configurations[conf.id] = conf
403
403
404 return conf
404 return conf
405
405
406 def addProcUnit(self, id=None, inputId='0', datatype=None, name=None):
406 def addProcUnit(self, id=None, inputId='0', datatype=None, name=None):
407
407
408 '''
408 '''
409 '''
409 '''
410
410
411 if id is None:
411 if id is None:
412 idProcUnit = self.getNewId()
412 idProcUnit = self.getNewId()
413 else:
413 else:
414 idProcUnit = id
414 idProcUnit = id
415
415
416 conf = ProcUnitConf()
416 conf = ProcUnitConf()
417 conf.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue)
417 conf.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue)
418 self.configurations[conf.id] = conf
418 self.configurations[conf.id] = conf
419
419
420 return conf
420 return conf
421
421
422 def removeProcUnit(self, id):
422 def removeProcUnit(self, id):
423
423
424 if id in self.configurations:
424 if id in self.configurations:
425 self.configurations.pop(id)
425 self.configurations.pop(id)
426
426
427 def getReadUnit(self):
427 def getReadUnit(self):
428
428
429 for obj in list(self.configurations.values()):
429 for obj in list(self.configurations.values()):
430 if obj.ELEMENTNAME == 'ReadUnit':
430 if obj.ELEMENTNAME == 'ReadUnit':
431 return obj
431 return obj
432
432
433 return None
433 return None
434
434
435 def getProcUnit(self, id):
435 def getProcUnit(self, id):
436
436
437 return self.configurations[id]
437 return self.configurations[id]
438
438
439 def getUnits(self):
439 def getUnits(self):
440
440
441 keys = list(self.configurations)
441 keys = list(self.configurations)
442 keys.sort()
442 keys.sort()
443
443
444 for key in keys:
444 for key in keys:
445 yield self.configurations[key]
445 yield self.configurations[key]
446
446
447 def updateUnit(self, id, **kwargs):
447 def updateUnit(self, id, **kwargs):
448
448
449 conf = self.configurations[id].update(**kwargs)
449 conf = self.configurations[id].update(**kwargs)
450
450
451 def makeXml(self):
451 def makeXml(self):
452
452
453 xml = Element('Project')
453 xml = Element('Project')
454 xml.set('id', str(self.id))
454 xml.set('id', str(self.id))
455 xml.set('name', self.name)
455 xml.set('name', self.name)
456 xml.set('description', self.description)
456 xml.set('description', self.description)
457
457
458 for conf in self.configurations.values():
458 for conf in self.configurations.values():
459 conf.makeXml(xml)
459 conf.makeXml(xml)
460
460
461 self.xml = xml
461 self.xml = xml
462
462
463 def writeXml(self, filename=None):
463 def writeXml(self, filename=None):
464
464
465 if filename == None:
465 if filename == None:
466 if self.filename:
466 if self.filename:
467 filename = self.filename
467 filename = self.filename
468 else:
468 else:
469 filename = 'schain.xml'
469 filename = 'schain.xml'
470
470
471 if not filename:
471 if not filename:
472 print('filename has not been defined. Use setFilename(filename) for do it.')
472 print('filename has not been defined. Use setFilename(filename) for do it.')
473 return 0
473 return 0
474
474
475 abs_file = os.path.abspath(filename)
475 abs_file = os.path.abspath(filename)
476
476
477 if not os.access(os.path.dirname(abs_file), os.W_OK):
477 if not os.access(os.path.dirname(abs_file), os.W_OK):
478 print('No write permission on %s' % os.path.dirname(abs_file))
478 print('No write permission on %s' % os.path.dirname(abs_file))
479 return 0
479 return 0
480
480
481 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
481 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
482 print('File %s already exists and it could not be overwriten' % abs_file)
482 print('File %s already exists and it could not be overwriten' % abs_file)
483 return 0
483 return 0
484
484
485 self.makeXml()
485 self.makeXml()
486
486
487 ElementTree(self.xml).write(abs_file, method='xml')
487 ElementTree(self.xml).write(abs_file, method='xml')
488
488
489 self.filename = abs_file
489 self.filename = abs_file
490
490
491 return 1
491 return 1
492
492
493 def readXml(self, filename):
493 def readXml(self, filename):
494
494
495 abs_file = os.path.abspath(filename)
495 abs_file = os.path.abspath(filename)
496
496
497 self.configurations = {}
497 self.configurations = {}
498
498
499 try:
499 try:
500 self.xml = ElementTree().parse(abs_file)
500 self.xml = ElementTree().parse(abs_file)
501 except:
501 except:
502 log.error('Error reading %s, verify file format' % filename)
502 log.error('Error reading %s, verify file format' % filename)
503 return 0
503 return 0
504
504
505 self.id = self.xml.get('id')
505 self.id = self.xml.get('id')
506 self.name = self.xml.get('name')
506 self.name = self.xml.get('name')
507 self.description = self.xml.get('description')
507 self.description = self.xml.get('description')
508
508
509 for element in self.xml:
509 for element in self.xml:
510 if element.tag == 'ReadUnit':
510 if element.tag == 'ReadUnit':
511 conf = ReadUnitConf()
511 conf = ReadUnitConf()
512 conf.readXml(element, self.id, self.err_queue)
512 conf.readXml(element, self.id, self.err_queue)
513 self.configurations[conf.id] = conf
513 self.configurations[conf.id] = conf
514 elif element.tag == 'ProcUnit':
514 elif element.tag == 'ProcUnit':
515 conf = ProcUnitConf()
515 conf = ProcUnitConf()
516 input_proc = self.configurations[element.get('inputId')]
516 input_proc = self.configurations[element.get('inputId')]
517 conf.readXml(element, self.id, self.err_queue)
517 conf.readXml(element, self.id, self.err_queue)
518 self.configurations[conf.id] = conf
518 self.configurations[conf.id] = conf
519
519
520 self.filename = abs_file
520 self.filename = abs_file
521
521
522 return 1
522 return 1
523
523
524 def __str__(self):
524 def __str__(self):
525
525
526 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
526 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
527 self.id,
527 self.id,
528 self.name,
528 self.name,
529 self.description,
529 self.description,
530 )
530 )
531
531
532 for conf in self.configurations.values():
532 for conf in self.configurations.values():
533 text += '{}'.format(conf)
533 text += '{}'.format(conf)
534
534
535 return text
535 return text
536
536
537 def createObjects(self):
537 def createObjects(self):
538
538
539 keys = list(self.configurations.keys())
539 keys = list(self.configurations.keys())
540 keys.sort()
540 keys.sort()
541 for key in keys:
541 for key in keys:
542 conf = self.configurations[key]
542 conf = self.configurations[key]
543 conf.createObjects()
543 conf.createObjects()
544 if conf.inputId is not None:
544 if conf.inputId is not None:
545 conf.object.setInput(self.configurations[conf.inputId].object)
545 conf.object.setInput(self.configurations[conf.inputId].object)
546
546
547 def monitor(self):
547 def monitor(self):
548
548
549 t = Thread(target=self._monitor, args=(self.err_queue, self.ctx))
549 t = Thread(target=self._monitor, args=(self.err_queue, self.ctx))
550 t.start()
550 t.start()
551
551
552 def _monitor(self, queue, ctx):
552 def _monitor(self, queue, ctx):
553
553
554 import socket
554 import socket
555
555
556 procs = 0
556 procs = 0
557 err_msg = ''
557 err_msg = ''
558
558
559 while True:
559 while True:
560 msg = queue.get()
560 msg = queue.get()
561 if '#_start_#' in msg:
561 if '#_start_#' in msg:
562 procs += 1
562 procs += 1
563 elif '#_end_#' in msg:
563 elif '#_end_#' in msg:
564 procs -=1
564 procs -=1
565 else:
565 else:
566 err_msg = msg
566 err_msg = msg
567
567
568 if procs == 0 or 'Traceback' in err_msg:
568 if procs == 0 or 'Traceback' in err_msg:
569 break
569 break
570 time.sleep(0.1)
570 time.sleep(0.1)
571
571
572 if '|' in err_msg:
572 if '|' in err_msg:
573 name, err = err_msg.split('|')
573 name, err = err_msg.split('|')
574 if 'SchainWarning' in err:
574 if 'SchainWarning' in err:
575 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
575 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
576 elif 'SchainError' in err:
576 elif 'SchainError' in err:
577 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
577 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
578 else:
578 else:
579 log.error(err, name)
579 log.error(err, name)
580 else:
580 else:
581 name, err = self.name, err_msg
581 name, err = self.name, err_msg
582
582
583 time.sleep(1)
583 time.sleep(1)
584
584
585 ctx.term()
585 ctx.term()
586
586
587 message = ''.join(err)
587 message = ''.join(err)
588
588
589 if err_msg:
589 if err_msg:
590 subject = 'SChain v%s: Error running %s\n' % (
590 subject = 'SChain v%s: Error running %s\n' % (
591 schainpy.__version__, self.name)
591 schainpy.__version__, self.name)
592
592
593 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
593 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
594 socket.gethostname())
594 socket.gethostname())
595 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
595 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
596 subtitle += 'Configuration file: %s\n' % self.filename
596 subtitle += 'Configuration file: %s\n' % self.filename
597 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
597 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
598
598
599 readUnitConfObj = self.getReadUnit()
599 readUnitConfObj = self.getReadUnit()
600 if readUnitConfObj:
600 if readUnitConfObj:
601 subtitle += '\nInput parameters:\n'
601 subtitle += '\nInput parameters:\n'
602 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
602 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
603 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
603 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
604 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
604 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
605 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
605 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
606 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
606 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
607
607
608 a = Alarm(
608 a = Alarm(
609 modes=self.alarm,
609 modes=self.alarm,
610 email=self.email,
610 email=self.email,
611 message=message,
611 message=message,
612 subject=subject,
612 subject=subject,
613 subtitle=subtitle,
613 subtitle=subtitle,
614 filename=self.filename
614 filename=self.filename
615 )
615 )
616
616
617 a.start()
617 a.start()
618
618
619 def setFilename(self, filename):
619 def setFilename(self, filename):
620
620
621 self.filename = filename
621 self.filename = filename
622
622
623 def runProcs(self):
623 def runProcs(self):
624
624
625 err = False
625 err = False
626 n = len(self.configurations)
626 n = len(self.configurations)
627
627
628 while not err:
628 while not err:
629 for conf in self.getUnits():
629 for conf in self.getUnits():
630 ok = conf.run()
630 ok = conf.run()
631 if ok is 'Error':
631 if ok is 'Error':
632 n -= 1
632 n -= 1
633 continue
633 continue
634 elif not ok:
634 elif not ok:
635 break
635 break
636 if n == 0:
636 if n == 0:
637 err = True
637 err = True
638
638
639 def run(self):
639 def run(self):
640
640
641 log.success('\nStarting Project {} [id={}]'.format(self.name, self.id), tag='')
641 log.success('\nStarting Project {} [id={}]'.format(self.name, self.id), tag='')
642 self.started = True
642 self.started = True
643 self.start_time = time.time()
643 self.start_time = time.time()
644 self.createObjects()
644 self.createObjects()
645 self.runProcs()
645 self.runProcs()
646 log.success('{} Done (Time: {:4.2f}s)'.format(
646 log.success('{} Done (Time: {:4.2f}s)'.format(
647 self.name,
647 self.name,
648 time.time()-self.start_time), '')
648 time.time()-self.start_time), '')
@@ -1,1398 +1,1399
1 '''
1 '''
2
2
3 $Author: murco $
3 $Author: murco $
4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
5 '''
5 '''
6
6
7 import copy
7 import copy
8 import numpy
8 import numpy
9 import datetime
9 import datetime
10 import json
10 import json
11
11
12 import schainpy.admin
12 import schainpy.admin
13 from schainpy.utils import log
13 from schainpy.utils import log
14 from .jroheaderIO import SystemHeader, RadarControllerHeader
14 from .jroheaderIO import SystemHeader, RadarControllerHeader
15 from schainpy.model.data import _noise
15 from schainpy.model.data import _noise
16
16
17
17
18 def getNumpyDtype(dataTypeCode):
18 def getNumpyDtype(dataTypeCode):
19
19
20 if dataTypeCode == 0:
20 if dataTypeCode == 0:
21 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
21 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
22 elif dataTypeCode == 1:
22 elif dataTypeCode == 1:
23 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
23 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
24 elif dataTypeCode == 2:
24 elif dataTypeCode == 2:
25 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
25 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
26 elif dataTypeCode == 3:
26 elif dataTypeCode == 3:
27 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
27 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
28 elif dataTypeCode == 4:
28 elif dataTypeCode == 4:
29 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
29 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
30 elif dataTypeCode == 5:
30 elif dataTypeCode == 5:
31 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
31 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
32 else:
32 else:
33 raise ValueError('dataTypeCode was not defined')
33 raise ValueError('dataTypeCode was not defined')
34
34
35 return numpyDtype
35 return numpyDtype
36
36
37
37
38 def getDataTypeCode(numpyDtype):
38 def getDataTypeCode(numpyDtype):
39
39
40 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
40 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
41 datatype = 0
41 datatype = 0
42 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
42 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
43 datatype = 1
43 datatype = 1
44 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
44 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
45 datatype = 2
45 datatype = 2
46 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
46 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
47 datatype = 3
47 datatype = 3
48 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
48 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
49 datatype = 4
49 datatype = 4
50 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
50 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
51 datatype = 5
51 datatype = 5
52 else:
52 else:
53 datatype = None
53 datatype = None
54
54
55 return datatype
55 return datatype
56
56
57
57
58 def hildebrand_sekhon(data, navg):
58 def hildebrand_sekhon(data, navg):
59 """
59 """
60 This method is for the objective determination of the noise level in Doppler spectra. This
60 This method is for the objective determination of the noise level in Doppler spectra. This
61 implementation technique is based on the fact that the standard deviation of the spectral
61 implementation technique is based on the fact that the standard deviation of the spectral
62 densities is equal to the mean spectral density for white Gaussian noise
62 densities is equal to the mean spectral density for white Gaussian noise
63
63
64 Inputs:
64 Inputs:
65 Data : heights
65 Data : heights
66 navg : numbers of averages
66 navg : numbers of averages
67
67
68 Return:
68 Return:
69 mean : noise's level
69 mean : noise's level
70 """
70 """
71
71
72 sortdata = numpy.sort(data, axis=None)
72 sortdata = numpy.sort(data, axis=None)
73 '''
73 '''
74 lenOfData = len(sortdata)
74 lenOfData = len(sortdata)
75 nums_min = lenOfData*0.2
75 nums_min = lenOfData*0.2
76
76
77 if nums_min <= 5:
77 if nums_min <= 5:
78
78
79 nums_min = 5
79 nums_min = 5
80
80
81 sump = 0.
81 sump = 0.
82 sumq = 0.
82 sumq = 0.
83
83
84 j = 0
84 j = 0
85 cont = 1
85 cont = 1
86
86
87 while((cont == 1)and(j < lenOfData)):
87 while((cont == 1)and(j < lenOfData)):
88
88
89 sump += sortdata[j]
89 sump += sortdata[j]
90 sumq += sortdata[j]**2
90 sumq += sortdata[j]**2
91
91
92 if j > nums_min:
92 if j > nums_min:
93 rtest = float(j)/(j-1) + 1.0/navg
93 rtest = float(j)/(j-1) + 1.0/navg
94 if ((sumq*j) > (rtest*sump**2)):
94 if ((sumq*j) > (rtest*sump**2)):
95 j = j - 1
95 j = j - 1
96 sump = sump - sortdata[j]
96 sump = sump - sortdata[j]
97 sumq = sumq - sortdata[j]**2
97 sumq = sumq - sortdata[j]**2
98 cont = 0
98 cont = 0
99
99
100 j += 1
100 j += 1
101
101
102 lnoise = sump / j
102 lnoise = sump / j
103 '''
103 '''
104 return _noise.hildebrand_sekhon(sortdata, navg)
104 return _noise.hildebrand_sekhon(sortdata, navg)
105
105
106
106
107 class Beam:
107 class Beam:
108
108
109 def __init__(self):
109 def __init__(self):
110 self.codeList = []
110 self.codeList = []
111 self.azimuthList = []
111 self.azimuthList = []
112 self.zenithList = []
112 self.zenithList = []
113
113
114
114
115 class GenericData(object):
115 class GenericData(object):
116
116
117 flagNoData = True
117 flagNoData = True
118
118
119 def copy(self, inputObj=None):
119 def copy(self, inputObj=None):
120
120
121 if inputObj == None:
121 if inputObj == None:
122 return copy.deepcopy(self)
122 return copy.deepcopy(self)
123
123
124 for key in list(inputObj.__dict__.keys()):
124 for key in list(inputObj.__dict__.keys()):
125
125
126 attribute = inputObj.__dict__[key]
126 attribute = inputObj.__dict__[key]
127
127
128 # If this attribute is a tuple or list
128 # If this attribute is a tuple or list
129 if type(inputObj.__dict__[key]) in (tuple, list):
129 if type(inputObj.__dict__[key]) in (tuple, list):
130 self.__dict__[key] = attribute[:]
130 self.__dict__[key] = attribute[:]
131 continue
131 continue
132
132
133 # If this attribute is another object or instance
133 # If this attribute is another object or instance
134 if hasattr(attribute, '__dict__'):
134 if hasattr(attribute, '__dict__'):
135 self.__dict__[key] = attribute.copy()
135 self.__dict__[key] = attribute.copy()
136 continue
136 continue
137
137
138 self.__dict__[key] = inputObj.__dict__[key]
138 self.__dict__[key] = inputObj.__dict__[key]
139
139
140 def deepcopy(self):
140 def deepcopy(self):
141
141
142 return copy.deepcopy(self)
142 return copy.deepcopy(self)
143
143
144 def isEmpty(self):
144 def isEmpty(self):
145
145
146 return self.flagNoData
146 return self.flagNoData
147
147
148 def isReady(self):
148 def isReady(self):
149
149
150 return not self.flagNoData
150 return not self.flagNoData
151
151
152
152
153 class JROData(GenericData):
153 class JROData(GenericData):
154
154
155 # m_BasicHeader = BasicHeader()
155 # m_BasicHeader = BasicHeader()
156 # m_ProcessingHeader = ProcessingHeader()
156 # m_ProcessingHeader = ProcessingHeader()
157
157
158 systemHeaderObj = SystemHeader()
158 systemHeaderObj = SystemHeader()
159 radarControllerHeaderObj = RadarControllerHeader()
159 radarControllerHeaderObj = RadarControllerHeader()
160 # data = None
160 # data = None
161 type = None
161 type = None
162 datatype = None # dtype but in string
162 datatype = None # dtype but in string
163 # dtype = None
163 # dtype = None
164 # nChannels = None
164 # nChannels = None
165 # nHeights = None
165 # nHeights = None
166 nProfiles = None
166 nProfiles = None
167 heightList = None
167 heightList = None
168 channelList = None
168 channelList = None
169 flagDiscontinuousBlock = False
169 flagDiscontinuousBlock = False
170 useLocalTime = False
170 useLocalTime = False
171 utctime = None
171 utctime = None
172 timeZone = None
172 timeZone = None
173 dstFlag = None
173 dstFlag = None
174 errorCount = None
174 errorCount = None
175 blocksize = None
175 blocksize = None
176 # nCode = None
176 # nCode = None
177 # nBaud = None
177 # nBaud = None
178 # code = None
178 # code = None
179 flagDecodeData = False # asumo q la data no esta decodificada
179 flagDecodeData = False # asumo q la data no esta decodificada
180 flagDeflipData = False # asumo q la data no esta sin flip
180 flagDeflipData = False # asumo q la data no esta sin flip
181 flagShiftFFT = False
181 flagShiftFFT = False
182 # ippSeconds = None
182 # ippSeconds = None
183 # timeInterval = None
183 # timeInterval = None
184 nCohInt = None
184 nCohInt = None
185 # noise = None
185 # noise = None
186 windowOfFilter = 1
186 windowOfFilter = 1
187 # Speed of ligth
187 # Speed of ligth
188 C = 3e8
188 C = 3e8
189 frequency = 49.92e6
189 frequency = 49.92e6
190 realtime = False
190 realtime = False
191 beacon_heiIndexList = None
191 beacon_heiIndexList = None
192 last_block = None
192 last_block = None
193 blocknow = None
193 blocknow = None
194 azimuth = None
194 azimuth = None
195 zenith = None
195 zenith = None
196 beam = Beam()
196 beam = Beam()
197 profileIndex = None
197 profileIndex = None
198 error = None
198 error = None
199 data = None
199 data = None
200 nmodes = None
200 nmodes = None
201
201
202 def __str__(self):
202 def __str__(self):
203
203
204 return '{} - {}'.format(self.type, self.getDatatime())
204 return '{} - {}'.format(self.type, self.getDatatime())
205
205
206 def getNoise(self):
206 def getNoise(self):
207
207
208 raise NotImplementedError
208 raise NotImplementedError
209
209
210 def getNChannels(self):
210 def getNChannels(self):
211
211
212 return len(self.channelList)
212 return len(self.channelList)
213
213
214 def getChannelIndexList(self):
214 def getChannelIndexList(self):
215
215
216 return list(range(self.nChannels))
216 return list(range(self.nChannels))
217
217
218 def getNHeights(self):
218 def getNHeights(self):
219
219
220 return len(self.heightList)
220 return len(self.heightList)
221
221
222 def getHeiRange(self, extrapoints=0):
222 def getHeiRange(self, extrapoints=0):
223
223
224 heis = self.heightList
224 heis = self.heightList
225 # deltah = self.heightList[1] - self.heightList[0]
225 # deltah = self.heightList[1] - self.heightList[0]
226 #
226 #
227 # heis.append(self.heightList[-1])
227 # heis.append(self.heightList[-1])
228
228
229 return heis
229 return heis
230
230
231 def getDeltaH(self):
231 def getDeltaH(self):
232
232
233 delta = self.heightList[1] - self.heightList[0]
233 delta = self.heightList[1] - self.heightList[0]
234
234
235 return delta
235 return delta
236
236
237 def getltctime(self):
237 def getltctime(self):
238
238
239 if self.useLocalTime:
239 if self.useLocalTime:
240 return self.utctime - self.timeZone * 60
240 return self.utctime - self.timeZone * 60
241
241
242 return self.utctime
242 return self.utctime
243
243
244 def getDatatime(self):
244 def getDatatime(self):
245
245
246 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
246 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
247 return datatimeValue
247 return datatimeValue
248
248
249 def getTimeRange(self):
249 def getTimeRange(self):
250
250
251 datatime = []
251 datatime = []
252
252
253 datatime.append(self.ltctime)
253 datatime.append(self.ltctime)
254 datatime.append(self.ltctime + self.timeInterval + 1)
254 datatime.append(self.ltctime + self.timeInterval + 1)
255
255
256 datatime = numpy.array(datatime)
256 datatime = numpy.array(datatime)
257
257
258 return datatime
258 return datatime
259
259
260 def getFmaxTimeResponse(self):
260 def getFmaxTimeResponse(self):
261
261
262 period = (10**-6) * self.getDeltaH() / (0.15)
262 period = (10**-6) * self.getDeltaH() / (0.15)
263
263
264 PRF = 1. / (period * self.nCohInt)
264 PRF = 1. / (period * self.nCohInt)
265
265
266 fmax = PRF
266 fmax = PRF
267
267
268 return fmax
268 return fmax
269
269
270 def getFmax(self):
270 def getFmax(self):
271 PRF = 1. / (self.ippSeconds * self.nCohInt)
271 PRF = 1. / (self.ippSeconds * self.nCohInt)
272
272
273 fmax = PRF
273 fmax = PRF
274 return fmax
274 return fmax
275
275
276 def getVmax(self):
276 def getVmax(self):
277
277
278 _lambda = self.C / self.frequency
278 _lambda = self.C / self.frequency
279
279
280 vmax = self.getFmax() * _lambda / 2
280 vmax = self.getFmax() * _lambda / 2
281
281
282 return vmax
282 return vmax
283
283
284 def get_ippSeconds(self):
284 def get_ippSeconds(self):
285 '''
285 '''
286 '''
286 '''
287 return self.radarControllerHeaderObj.ippSeconds
287 return self.radarControllerHeaderObj.ippSeconds
288
288
289 def set_ippSeconds(self, ippSeconds):
289 def set_ippSeconds(self, ippSeconds):
290 '''
290 '''
291 '''
291 '''
292
292
293 self.radarControllerHeaderObj.ippSeconds = ippSeconds
293 self.radarControllerHeaderObj.ippSeconds = ippSeconds
294
294
295 return
295 return
296
296
297 def get_dtype(self):
297 def get_dtype(self):
298 '''
298 '''
299 '''
299 '''
300 return getNumpyDtype(self.datatype)
300 return getNumpyDtype(self.datatype)
301
301
302 def set_dtype(self, numpyDtype):
302 def set_dtype(self, numpyDtype):
303 '''
303 '''
304 '''
304 '''
305
305
306 self.datatype = getDataTypeCode(numpyDtype)
306 self.datatype = getDataTypeCode(numpyDtype)
307
307
308 def get_code(self):
308 def get_code(self):
309 '''
309 '''
310 '''
310 '''
311 return self.radarControllerHeaderObj.code
311 return self.radarControllerHeaderObj.code
312
312
313 def set_code(self, code):
313 def set_code(self, code):
314 '''
314 '''
315 '''
315 '''
316 self.radarControllerHeaderObj.code = code
316 self.radarControllerHeaderObj.code = code
317
317
318 return
318 return
319
319
320 def get_ncode(self):
320 def get_ncode(self):
321 '''
321 '''
322 '''
322 '''
323 return self.radarControllerHeaderObj.nCode
323 return self.radarControllerHeaderObj.nCode
324
324
325 def set_ncode(self, nCode):
325 def set_ncode(self, nCode):
326 '''
326 '''
327 '''
327 '''
328 self.radarControllerHeaderObj.nCode = nCode
328 self.radarControllerHeaderObj.nCode = nCode
329
329
330 return
330 return
331
331
332 def get_nbaud(self):
332 def get_nbaud(self):
333 '''
333 '''
334 '''
334 '''
335 return self.radarControllerHeaderObj.nBaud
335 return self.radarControllerHeaderObj.nBaud
336
336
337 def set_nbaud(self, nBaud):
337 def set_nbaud(self, nBaud):
338 '''
338 '''
339 '''
339 '''
340 self.radarControllerHeaderObj.nBaud = nBaud
340 self.radarControllerHeaderObj.nBaud = nBaud
341
341
342 return
342 return
343
343
344 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
344 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
345 channelIndexList = property(
345 channelIndexList = property(
346 getChannelIndexList, "I'm the 'channelIndexList' property.")
346 getChannelIndexList, "I'm the 'channelIndexList' property.")
347 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
347 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
348 #noise = property(getNoise, "I'm the 'nHeights' property.")
348 #noise = property(getNoise, "I'm the 'nHeights' property.")
349 datatime = property(getDatatime, "I'm the 'datatime' property")
349 datatime = property(getDatatime, "I'm the 'datatime' property")
350 ltctime = property(getltctime, "I'm the 'ltctime' property")
350 ltctime = property(getltctime, "I'm the 'ltctime' property")
351 ippSeconds = property(get_ippSeconds, set_ippSeconds)
351 ippSeconds = property(get_ippSeconds, set_ippSeconds)
352 dtype = property(get_dtype, set_dtype)
352 dtype = property(get_dtype, set_dtype)
353 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
353 # timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
354 code = property(get_code, set_code)
354 code = property(get_code, set_code)
355 nCode = property(get_ncode, set_ncode)
355 nCode = property(get_ncode, set_ncode)
356 nBaud = property(get_nbaud, set_nbaud)
356 nBaud = property(get_nbaud, set_nbaud)
357
357
358
358
359 class Voltage(JROData):
359 class Voltage(JROData):
360
360
361 # data es un numpy array de 2 dmensiones (canales, alturas)
361 # data es un numpy array de 2 dmensiones (canales, alturas)
362 data = None
362 data = None
363 data_intensity = None
363 data_intensity = None
364 data_velocity = None
364 data_velocity = None
365 data_specwidth = None
365 data_specwidth = None
366 def __init__(self):
366 def __init__(self):
367 '''
367 '''
368 Constructor
368 Constructor
369 '''
369 '''
370
370
371 self.useLocalTime = True
371 self.useLocalTime = True
372 self.radarControllerHeaderObj = RadarControllerHeader()
372 self.radarControllerHeaderObj = RadarControllerHeader()
373 self.systemHeaderObj = SystemHeader()
373 self.systemHeaderObj = SystemHeader()
374 self.type = "Voltage"
374 self.type = "Voltage"
375 self.data = None
375 self.data = None
376 # self.dtype = None
376 # self.dtype = None
377 # self.nChannels = 0
377 # self.nChannels = 0
378 # self.nHeights = 0
378 # self.nHeights = 0
379 self.nProfiles = None
379 self.nProfiles = None
380 self.heightList = None
380 self.heightList = None
381 self.channelList = None
381 self.channelList = None
382 # self.channelIndexList = None
382 # self.channelIndexList = None
383 self.flagNoData = True
383 self.flagNoData = True
384 self.flagDiscontinuousBlock = False
384 self.flagDiscontinuousBlock = False
385 self.utctime = None
385 self.utctime = None
386 self.timeZone = None
386 self.timeZone = None
387 self.dstFlag = None
387 self.dstFlag = None
388 self.errorCount = None
388 self.errorCount = None
389 self.nCohInt = None
389 self.nCohInt = None
390 self.blocksize = None
390 self.blocksize = None
391 self.flagDecodeData = False # asumo q la data no esta decodificada
391 self.flagDecodeData = False # asumo q la data no esta decodificada
392 self.flagDeflipData = False # asumo q la data no esta sin flip
392 self.flagDeflipData = False # asumo q la data no esta sin flip
393 self.flagShiftFFT = False
393 self.flagShiftFFT = False
394 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
394 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
395 self.profileIndex = 0
395 self.profileIndex = 0
396
396
397 def getNoisebyHildebrand(self, channel=None):
397 def getNoisebyHildebrand(self, channel=None):
398 """
398 """
399 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
399 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
400
400
401 Return:
401 Return:
402 noiselevel
402 noiselevel
403 """
403 """
404
404
405 if channel != None:
405 if channel != None:
406 data = self.data[channel]
406 data = self.data[channel]
407 nChannels = 1
407 nChannels = 1
408 else:
408 else:
409 data = self.data
409 data = self.data
410 nChannels = self.nChannels
410 nChannels = self.nChannels
411
411
412 noise = numpy.zeros(nChannels)
412 noise = numpy.zeros(nChannels)
413 power = data * numpy.conjugate(data)
413 power = data * numpy.conjugate(data)
414
414
415 for thisChannel in range(nChannels):
415 for thisChannel in range(nChannels):
416 if nChannels == 1:
416 if nChannels == 1:
417 daux = power[:].real
417 daux = power[:].real
418 else:
418 else:
419 daux = power[thisChannel, :].real
419 daux = power[thisChannel, :].real
420 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
420 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
421
421
422 return noise
422 return noise
423
423
424 def getNoise(self, type=1, channel=None):
424 def getNoise(self, type=1, channel=None):
425
425
426 if type == 1:
426 if type == 1:
427 noise = self.getNoisebyHildebrand(channel)
427 noise = self.getNoisebyHildebrand(channel)
428
428
429 return noise
429 return noise
430
430
431 def getPower(self, channel=None):
431 def getPower(self, channel=None):
432
432
433 if channel != None:
433 if channel != None:
434 data = self.data[channel]
434 data = self.data[channel]
435 else:
435 else:
436 data = self.data
436 data = self.data
437
437
438 power = data * numpy.conjugate(data)
438 power = data * numpy.conjugate(data)
439 powerdB = 10 * numpy.log10(power.real)
439 powerdB = 10 * numpy.log10(power.real)
440 powerdB = numpy.squeeze(powerdB)
440 powerdB = numpy.squeeze(powerdB)
441
441
442 return powerdB
442 return powerdB
443
443
444 def getTimeInterval(self):
444 def getTimeInterval(self):
445
445
446 timeInterval = self.ippSeconds * self.nCohInt
446 timeInterval = self.ippSeconds * self.nCohInt
447
447
448 return timeInterval
448 return timeInterval
449
449
450 noise = property(getNoise, "I'm the 'nHeights' property.")
450 noise = property(getNoise, "I'm the 'nHeights' property.")
451 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
451 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
452
452
453
453
454 class Spectra(JROData):
454 class Spectra(JROData):
455
455
456 # data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
456 # data spc es un numpy array de 2 dmensiones (canales, perfiles, alturas)
457 data_spc = None
457 data_spc = None
458 # data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
458 # data cspc es un numpy array de 2 dmensiones (canales, pares, alturas)
459 data_cspc = None
459 data_cspc = None
460 # data dc es un numpy array de 2 dmensiones (canales, alturas)
460 # data dc es un numpy array de 2 dmensiones (canales, alturas)
461 data_dc = None
461 data_dc = None
462 # data power
462 # data power
463 data_pwr = None
463 data_pwr = None
464 nFFTPoints = None
464 nFFTPoints = None
465 # nPairs = None
465 # nPairs = None
466 pairsList = None
466 pairsList = None
467 nIncohInt = None
467 nIncohInt = None
468 wavelength = None # Necesario para cacular el rango de velocidad desde la frecuencia
468 wavelength = None # Necesario para cacular el rango de velocidad desde la frecuencia
469 nCohInt = None # se requiere para determinar el valor de timeInterval
469 nCohInt = None # se requiere para determinar el valor de timeInterval
470 ippFactor = None
470 ippFactor = None
471 profileIndex = 0
471 profileIndex = 0
472 plotting = "spectra"
472 plotting = "spectra"
473
473
474 def __init__(self):
474 def __init__(self):
475 '''
475 '''
476 Constructor
476 Constructor
477 '''
477 '''
478
478
479 self.useLocalTime = True
479 self.useLocalTime = True
480 self.radarControllerHeaderObj = RadarControllerHeader()
480 self.radarControllerHeaderObj = RadarControllerHeader()
481 self.systemHeaderObj = SystemHeader()
481 self.systemHeaderObj = SystemHeader()
482 self.type = "Spectra"
482 self.type = "Spectra"
483 # self.data = None
483 # self.data = None
484 # self.dtype = None
484 # self.dtype = None
485 # self.nChannels = 0
485 # self.nChannels = 0
486 # self.nHeights = 0
486 # self.nHeights = 0
487 self.nProfiles = None
487 self.nProfiles = None
488 self.heightList = None
488 self.heightList = None
489 self.channelList = None
489 self.channelList = None
490 # self.channelIndexList = None
490 # self.channelIndexList = None
491 self.pairsList = None
491 self.pairsList = None
492 self.flagNoData = True
492 self.flagNoData = True
493 self.flagDiscontinuousBlock = False
493 self.flagDiscontinuousBlock = False
494 self.utctime = None
494 self.utctime = None
495 self.nCohInt = None
495 self.nCohInt = None
496 self.nIncohInt = None
496 self.nIncohInt = None
497 self.blocksize = None
497 self.blocksize = None
498 self.nFFTPoints = None
498 self.nFFTPoints = None
499 self.wavelength = None
499 self.wavelength = None
500 self.flagDecodeData = False # asumo q la data no esta decodificada
500 self.flagDecodeData = False # asumo q la data no esta decodificada
501 self.flagDeflipData = False # asumo q la data no esta sin flip
501 self.flagDeflipData = False # asumo q la data no esta sin flip
502 self.flagShiftFFT = False
502 self.flagShiftFFT = False
503 self.ippFactor = 1
503 self.ippFactor = 1
504 #self.noise = None
504 #self.noise = None
505 self.beacon_heiIndexList = []
505 self.beacon_heiIndexList = []
506 self.noise_estimation = None
506 self.noise_estimation = None
507
507
508 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
508 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
509 """
509 """
510 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
510 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
511
511
512 Return:
512 Return:
513 noiselevel
513 noiselevel
514 """
514 """
515
515
516 noise = numpy.zeros(self.nChannels)
516 noise = numpy.zeros(self.nChannels)
517
517
518 for channel in range(self.nChannels):
518 for channel in range(self.nChannels):
519 daux = self.data_spc[channel,
519 daux = self.data_spc[channel,
520 xmin_index:xmax_index, ymin_index:ymax_index]
520 xmin_index:xmax_index, ymin_index:ymax_index]
521 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
521 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
522
522
523 return noise
523 return noise
524
524
525 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
525 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
526
526
527 if self.noise_estimation is not None:
527 if self.noise_estimation is not None:
528 # this was estimated by getNoise Operation defined in jroproc_spectra.py
528 # this was estimated by getNoise Operation defined in jroproc_spectra.py
529 return self.noise_estimation
529 return self.noise_estimation
530 else:
530 else:
531 noise = self.getNoisebyHildebrand(
531 noise = self.getNoisebyHildebrand(
532 xmin_index, xmax_index, ymin_index, ymax_index)
532 xmin_index, xmax_index, ymin_index, ymax_index)
533 return noise
533 return noise
534
534
535 def getFreqRangeTimeResponse(self, extrapoints=0):
535 def getFreqRangeTimeResponse(self, extrapoints=0):
536
536
537 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
537 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
538 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
538 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
539
539
540 return freqrange
540 return freqrange
541
541
542 def getAcfRange(self, extrapoints=0):
542 def getAcfRange(self, extrapoints=0):
543
543
544 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
544 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
545 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
545 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
546
546
547 return freqrange
547 return freqrange
548
548
549 def getFreqRange(self, extrapoints=0):
549 def getFreqRange(self, extrapoints=0):
550
550
551 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
551 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
552 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
552 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
553
553
554 return freqrange
554 return freqrange
555
555
556 def getVelRange(self, extrapoints=0):
556 def getVelRange(self, extrapoints=0):
557
557
558 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
558 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
559 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
559 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
560
560
561 if self.nmodes:
561 if self.nmodes:
562 return velrange/self.nmodes
562 return velrange/self.nmodes
563 else:
563 else:
564 return velrange
564 return velrange
565
565
566 def getNPairs(self):
566 def getNPairs(self):
567
567
568 return len(self.pairsList)
568 return len(self.pairsList)
569
569
570 def getPairsIndexList(self):
570 def getPairsIndexList(self):
571
571
572 return list(range(self.nPairs))
572 return list(range(self.nPairs))
573
573
574 def getNormFactor(self):
574 def getNormFactor(self):
575
575
576 pwcode = 1
576 pwcode = 1
577
577
578 if self.flagDecodeData:
578 if self.flagDecodeData:
579 pwcode = numpy.sum(self.code[0]**2)
579 pwcode = numpy.sum(self.code[0]**2)
580 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
580 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
581 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
581 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
582
582
583 return normFactor
583 return normFactor
584
584
585 def getFlagCspc(self):
585 def getFlagCspc(self):
586
586
587 if self.data_cspc is None:
587 if self.data_cspc is None:
588 return True
588 return True
589
589
590 return False
590 return False
591
591
592 def getFlagDc(self):
592 def getFlagDc(self):
593
593
594 if self.data_dc is None:
594 if self.data_dc is None:
595 return True
595 return True
596
596
597 return False
597 return False
598
598
599 def getTimeInterval(self):
599 def getTimeInterval(self):
600
600
601 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
601 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
602 if self.nmodes:
602 if self.nmodes:
603 return self.nmodes*timeInterval
603 return self.nmodes*timeInterval
604 else:
604 else:
605 return timeInterval
605 return timeInterval
606
606
607 def getPower(self):
607 def getPower(self):
608
608
609 factor = self.normFactor
609 factor = self.normFactor
610 z = self.data_spc / factor
610 z = self.data_spc / factor
611 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
611 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
612 avg = numpy.average(z, axis=1)
612 avg = numpy.average(z, axis=1)
613
613
614 return 10 * numpy.log10(avg)
614 return 10 * numpy.log10(avg)
615
615
616 def getCoherence(self, pairsList=None, phase=False):
616 def getCoherence(self, pairsList=None, phase=False):
617
617
618 z = []
618 z = []
619 if pairsList is None:
619 if pairsList is None:
620 pairsIndexList = self.pairsIndexList
620 pairsIndexList = self.pairsIndexList
621 else:
621 else:
622 pairsIndexList = []
622 pairsIndexList = []
623 for pair in pairsList:
623 for pair in pairsList:
624 if pair not in self.pairsList:
624 if pair not in self.pairsList:
625 raise ValueError("Pair %s is not in dataOut.pairsList" % (
625 raise ValueError("Pair %s is not in dataOut.pairsList" % (
626 pair))
626 pair))
627 pairsIndexList.append(self.pairsList.index(pair))
627 pairsIndexList.append(self.pairsList.index(pair))
628 for i in range(len(pairsIndexList)):
628 for i in range(len(pairsIndexList)):
629 pair = self.pairsList[pairsIndexList[i]]
629 pair = self.pairsList[pairsIndexList[i]]
630 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
630 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
631 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
631 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
632 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
632 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
633 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
633 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
634 if phase:
634 if phase:
635 data = numpy.arctan2(avgcoherenceComplex.imag,
635 data = numpy.arctan2(avgcoherenceComplex.imag,
636 avgcoherenceComplex.real) * 180 / numpy.pi
636 avgcoherenceComplex.real) * 180 / numpy.pi
637 else:
637 else:
638 data = numpy.abs(avgcoherenceComplex)
638 data = numpy.abs(avgcoherenceComplex)
639
639
640 z.append(data)
640 z.append(data)
641
641
642 return numpy.array(z)
642 return numpy.array(z)
643
643
644 def setValue(self, value):
644 def setValue(self, value):
645
645
646 print("This property should not be initialized")
646 print("This property should not be initialized")
647
647
648 return
648 return
649
649
650 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
650 nPairs = property(getNPairs, setValue, "I'm the 'nPairs' property.")
651 pairsIndexList = property(
651 pairsIndexList = property(
652 getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
652 getPairsIndexList, setValue, "I'm the 'pairsIndexList' property.")
653 normFactor = property(getNormFactor, setValue,
653 normFactor = property(getNormFactor, setValue,
654 "I'm the 'getNormFactor' property.")
654 "I'm the 'getNormFactor' property.")
655 flag_cspc = property(getFlagCspc, setValue)
655 flag_cspc = property(getFlagCspc, setValue)
656 flag_dc = property(getFlagDc, setValue)
656 flag_dc = property(getFlagDc, setValue)
657 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
657 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
658 timeInterval = property(getTimeInterval, setValue,
658 timeInterval = property(getTimeInterval, setValue,
659 "I'm the 'timeInterval' property")
659 "I'm the 'timeInterval' property")
660
660
661
661
662 class SpectraHeis(Spectra):
662 class SpectraHeis(Spectra):
663
663
664 data_spc = None
664 data_spc = None
665 data_cspc = None
665 data_cspc = None
666 data_dc = None
666 data_dc = None
667 nFFTPoints = None
667 nFFTPoints = None
668 # nPairs = None
668 # nPairs = None
669 pairsList = None
669 pairsList = None
670 nCohInt = None
670 nCohInt = None
671 nIncohInt = None
671 nIncohInt = None
672
672
673 def __init__(self):
673 def __init__(self):
674
674
675 self.radarControllerHeaderObj = RadarControllerHeader()
675 self.radarControllerHeaderObj = RadarControllerHeader()
676
676
677 self.systemHeaderObj = SystemHeader()
677 self.systemHeaderObj = SystemHeader()
678
678
679 self.type = "SpectraHeis"
679 self.type = "SpectraHeis"
680
680
681 # self.dtype = None
681 # self.dtype = None
682
682
683 # self.nChannels = 0
683 # self.nChannels = 0
684
684
685 # self.nHeights = 0
685 # self.nHeights = 0
686
686
687 self.nProfiles = None
687 self.nProfiles = None
688
688
689 self.heightList = None
689 self.heightList = None
690
690
691 self.channelList = None
691 self.channelList = None
692
692
693 # self.channelIndexList = None
693 # self.channelIndexList = None
694
694
695 self.flagNoData = True
695 self.flagNoData = True
696
696
697 self.flagDiscontinuousBlock = False
697 self.flagDiscontinuousBlock = False
698
698
699 # self.nPairs = 0
699 # self.nPairs = 0
700
700
701 self.utctime = None
701 self.utctime = None
702
702
703 self.blocksize = None
703 self.blocksize = None
704
704
705 self.profileIndex = 0
705 self.profileIndex = 0
706
706
707 self.nCohInt = 1
707 self.nCohInt = 1
708
708
709 self.nIncohInt = 1
709 self.nIncohInt = 1
710
710
711 def getNormFactor(self):
711 def getNormFactor(self):
712 pwcode = 1
712 pwcode = 1
713 if self.flagDecodeData:
713 if self.flagDecodeData:
714 pwcode = numpy.sum(self.code[0]**2)
714 pwcode = numpy.sum(self.code[0]**2)
715
715
716 normFactor = self.nIncohInt * self.nCohInt * pwcode
716 normFactor = self.nIncohInt * self.nCohInt * pwcode
717
717
718 return normFactor
718 return normFactor
719
719
720 def getTimeInterval(self):
720 def getTimeInterval(self):
721
721
722 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
722 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
723
723
724 return timeInterval
724 return timeInterval
725
725
726 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
726 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
727 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
727 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
728
728
729
729
730 class Fits(JROData):
730 class Fits(JROData):
731
731
732 heightList = None
732 heightList = None
733 channelList = None
733 channelList = None
734 flagNoData = True
734 flagNoData = True
735 flagDiscontinuousBlock = False
735 flagDiscontinuousBlock = False
736 useLocalTime = False
736 useLocalTime = False
737 utctime = None
737 utctime = None
738 timeZone = None
738 timeZone = None
739 # ippSeconds = None
739 # ippSeconds = None
740 # timeInterval = None
740 # timeInterval = None
741 nCohInt = None
741 nCohInt = None
742 nIncohInt = None
742 nIncohInt = None
743 noise = None
743 noise = None
744 windowOfFilter = 1
744 windowOfFilter = 1
745 # Speed of ligth
745 # Speed of ligth
746 C = 3e8
746 C = 3e8
747 frequency = 49.92e6
747 frequency = 49.92e6
748 realtime = False
748 realtime = False
749
749
750 def __init__(self):
750 def __init__(self):
751
751
752 self.type = "Fits"
752 self.type = "Fits"
753
753
754 self.nProfiles = None
754 self.nProfiles = None
755
755
756 self.heightList = None
756 self.heightList = None
757
757
758 self.channelList = None
758 self.channelList = None
759
759
760 # self.channelIndexList = None
760 # self.channelIndexList = None
761
761
762 self.flagNoData = True
762 self.flagNoData = True
763
763
764 self.utctime = None
764 self.utctime = None
765
765
766 self.nCohInt = 1
766 self.nCohInt = 1
767
767
768 self.nIncohInt = 1
768 self.nIncohInt = 1
769
769
770 self.useLocalTime = True
770 self.useLocalTime = True
771
771
772 self.profileIndex = 0
772 self.profileIndex = 0
773
773
774 # self.utctime = None
774 # self.utctime = None
775 # self.timeZone = None
775 # self.timeZone = None
776 # self.ltctime = None
776 # self.ltctime = None
777 # self.timeInterval = None
777 # self.timeInterval = None
778 # self.header = None
778 # self.header = None
779 # self.data_header = None
779 # self.data_header = None
780 # self.data = None
780 # self.data = None
781 # self.datatime = None
781 # self.datatime = None
782 # self.flagNoData = False
782 # self.flagNoData = False
783 # self.expName = ''
783 # self.expName = ''
784 # self.nChannels = None
784 # self.nChannels = None
785 # self.nSamples = None
785 # self.nSamples = None
786 # self.dataBlocksPerFile = None
786 # self.dataBlocksPerFile = None
787 # self.comments = ''
787 # self.comments = ''
788 #
788 #
789
789
790 def getltctime(self):
790 def getltctime(self):
791
791
792 if self.useLocalTime:
792 if self.useLocalTime:
793 return self.utctime - self.timeZone * 60
793 return self.utctime - self.timeZone * 60
794
794
795 return self.utctime
795 return self.utctime
796
796
797 def getDatatime(self):
797 def getDatatime(self):
798
798
799 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
799 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
800 return datatime
800 return datatime
801
801
802 def getTimeRange(self):
802 def getTimeRange(self):
803
803
804 datatime = []
804 datatime = []
805
805
806 datatime.append(self.ltctime)
806 datatime.append(self.ltctime)
807 datatime.append(self.ltctime + self.timeInterval)
807 datatime.append(self.ltctime + self.timeInterval)
808
808
809 datatime = numpy.array(datatime)
809 datatime = numpy.array(datatime)
810
810
811 return datatime
811 return datatime
812
812
813 def getHeiRange(self):
813 def getHeiRange(self):
814
814
815 heis = self.heightList
815 heis = self.heightList
816
816
817 return heis
817 return heis
818
818
819 def getNHeights(self):
819 def getNHeights(self):
820
820
821 return len(self.heightList)
821 return len(self.heightList)
822
822
823 def getNChannels(self):
823 def getNChannels(self):
824
824
825 return len(self.channelList)
825 return len(self.channelList)
826
826
827 def getChannelIndexList(self):
827 def getChannelIndexList(self):
828
828
829 return list(range(self.nChannels))
829 return list(range(self.nChannels))
830
830
831 def getNoise(self, type=1):
831 def getNoise(self, type=1):
832
832
833 #noise = numpy.zeros(self.nChannels)
833 #noise = numpy.zeros(self.nChannels)
834
834
835 if type == 1:
835 if type == 1:
836 noise = self.getNoisebyHildebrand()
836 noise = self.getNoisebyHildebrand()
837
837
838 if type == 2:
838 if type == 2:
839 noise = self.getNoisebySort()
839 noise = self.getNoisebySort()
840
840
841 if type == 3:
841 if type == 3:
842 noise = self.getNoisebyWindow()
842 noise = self.getNoisebyWindow()
843
843
844 return noise
844 return noise
845
845
846 def getTimeInterval(self):
846 def getTimeInterval(self):
847
847
848 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
848 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
849
849
850 return timeInterval
850 return timeInterval
851
851
852 def get_ippSeconds(self):
852 def get_ippSeconds(self):
853 '''
853 '''
854 '''
854 '''
855 return self.ipp_sec
855 return self.ipp_sec
856
856
857
857
858 datatime = property(getDatatime, "I'm the 'datatime' property")
858 datatime = property(getDatatime, "I'm the 'datatime' property")
859 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
859 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
860 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
860 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
861 channelIndexList = property(
861 channelIndexList = property(
862 getChannelIndexList, "I'm the 'channelIndexList' property.")
862 getChannelIndexList, "I'm the 'channelIndexList' property.")
863 noise = property(getNoise, "I'm the 'nHeights' property.")
863 noise = property(getNoise, "I'm the 'nHeights' property.")
864
864
865 ltctime = property(getltctime, "I'm the 'ltctime' property")
865 ltctime = property(getltctime, "I'm the 'ltctime' property")
866 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
866 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
867 ippSeconds = property(get_ippSeconds, '')
867 ippSeconds = property(get_ippSeconds, '')
868
868
869 class Correlation(JROData):
869 class Correlation(JROData):
870
870
871 noise = None
871 noise = None
872 SNR = None
872 SNR = None
873 #--------------------------------------------------
873 #--------------------------------------------------
874 mode = None
874 mode = None
875 split = False
875 split = False
876 data_cf = None
876 data_cf = None
877 lags = None
877 lags = None
878 lagRange = None
878 lagRange = None
879 pairsList = None
879 pairsList = None
880 normFactor = None
880 normFactor = None
881 #--------------------------------------------------
881 #--------------------------------------------------
882 # calculateVelocity = None
882 # calculateVelocity = None
883 nLags = None
883 nLags = None
884 nPairs = None
884 nPairs = None
885 nAvg = None
885 nAvg = None
886
886
887 def __init__(self):
887 def __init__(self):
888 '''
888 '''
889 Constructor
889 Constructor
890 '''
890 '''
891 self.radarControllerHeaderObj = RadarControllerHeader()
891 self.radarControllerHeaderObj = RadarControllerHeader()
892
892
893 self.systemHeaderObj = SystemHeader()
893 self.systemHeaderObj = SystemHeader()
894
894
895 self.type = "Correlation"
895 self.type = "Correlation"
896
896
897 self.data = None
897 self.data = None
898
898
899 self.dtype = None
899 self.dtype = None
900
900
901 self.nProfiles = None
901 self.nProfiles = None
902
902
903 self.heightList = None
903 self.heightList = None
904
904
905 self.channelList = None
905 self.channelList = None
906
906
907 self.flagNoData = True
907 self.flagNoData = True
908
908
909 self.flagDiscontinuousBlock = False
909 self.flagDiscontinuousBlock = False
910
910
911 self.utctime = None
911 self.utctime = None
912
912
913 self.timeZone = None
913 self.timeZone = None
914
914
915 self.dstFlag = None
915 self.dstFlag = None
916
916
917 self.errorCount = None
917 self.errorCount = None
918
918
919 self.blocksize = None
919 self.blocksize = None
920
920
921 self.flagDecodeData = False # asumo q la data no esta decodificada
921 self.flagDecodeData = False # asumo q la data no esta decodificada
922
922
923 self.flagDeflipData = False # asumo q la data no esta sin flip
923 self.flagDeflipData = False # asumo q la data no esta sin flip
924
924
925 self.pairsList = None
925 self.pairsList = None
926
926
927 self.nPoints = None
927 self.nPoints = None
928
928
929 def getPairsList(self):
929 def getPairsList(self):
930
930
931 return self.pairsList
931 return self.pairsList
932
932
933 def getNoise(self, mode=2):
933 def getNoise(self, mode=2):
934
934
935 indR = numpy.where(self.lagR == 0)[0][0]
935 indR = numpy.where(self.lagR == 0)[0][0]
936 indT = numpy.where(self.lagT == 0)[0][0]
936 indT = numpy.where(self.lagT == 0)[0][0]
937
937
938 jspectra0 = self.data_corr[:, :, indR, :]
938 jspectra0 = self.data_corr[:, :, indR, :]
939 jspectra = copy.copy(jspectra0)
939 jspectra = copy.copy(jspectra0)
940
940
941 num_chan = jspectra.shape[0]
941 num_chan = jspectra.shape[0]
942 num_hei = jspectra.shape[2]
942 num_hei = jspectra.shape[2]
943
943
944 freq_dc = jspectra.shape[1] / 2
944 freq_dc = jspectra.shape[1] / 2
945 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
945 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
946
946
947 if ind_vel[0] < 0:
947 if ind_vel[0] < 0:
948 ind_vel[list(range(0, 1))] = ind_vel[list(
948 ind_vel[list(range(0, 1))] = ind_vel[list(
949 range(0, 1))] + self.num_prof
949 range(0, 1))] + self.num_prof
950
950
951 if mode == 1:
951 if mode == 1:
952 jspectra[:, freq_dc, :] = (
952 jspectra[:, freq_dc, :] = (
953 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
953 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
954
954
955 if mode == 2:
955 if mode == 2:
956
956
957 vel = numpy.array([-2, -1, 1, 2])
957 vel = numpy.array([-2, -1, 1, 2])
958 xx = numpy.zeros([4, 4])
958 xx = numpy.zeros([4, 4])
959
959
960 for fil in range(4):
960 for fil in range(4):
961 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
961 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
962
962
963 xx_inv = numpy.linalg.inv(xx)
963 xx_inv = numpy.linalg.inv(xx)
964 xx_aux = xx_inv[0, :]
964 xx_aux = xx_inv[0, :]
965
965
966 for ich in range(num_chan):
966 for ich in range(num_chan):
967 yy = jspectra[ich, ind_vel, :]
967 yy = jspectra[ich, ind_vel, :]
968 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
968 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
969
969
970 junkid = jspectra[ich, freq_dc, :] <= 0
970 junkid = jspectra[ich, freq_dc, :] <= 0
971 cjunkid = sum(junkid)
971 cjunkid = sum(junkid)
972
972
973 if cjunkid.any():
973 if cjunkid.any():
974 jspectra[ich, freq_dc, junkid.nonzero()] = (
974 jspectra[ich, freq_dc, junkid.nonzero()] = (
975 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
975 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
976
976
977 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
977 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
978
978
979 return noise
979 return noise
980
980
981 def getTimeInterval(self):
981 def getTimeInterval(self):
982
982
983 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
983 timeInterval = self.ippSeconds * self.nCohInt * self.nProfiles
984
984
985 return timeInterval
985 return timeInterval
986
986
987 def splitFunctions(self):
987 def splitFunctions(self):
988
988
989 pairsList = self.pairsList
989 pairsList = self.pairsList
990 ccf_pairs = []
990 ccf_pairs = []
991 acf_pairs = []
991 acf_pairs = []
992 ccf_ind = []
992 ccf_ind = []
993 acf_ind = []
993 acf_ind = []
994 for l in range(len(pairsList)):
994 for l in range(len(pairsList)):
995 chan0 = pairsList[l][0]
995 chan0 = pairsList[l][0]
996 chan1 = pairsList[l][1]
996 chan1 = pairsList[l][1]
997
997
998 # Obteniendo pares de Autocorrelacion
998 # Obteniendo pares de Autocorrelacion
999 if chan0 == chan1:
999 if chan0 == chan1:
1000 acf_pairs.append(chan0)
1000 acf_pairs.append(chan0)
1001 acf_ind.append(l)
1001 acf_ind.append(l)
1002 else:
1002 else:
1003 ccf_pairs.append(pairsList[l])
1003 ccf_pairs.append(pairsList[l])
1004 ccf_ind.append(l)
1004 ccf_ind.append(l)
1005
1005
1006 data_acf = self.data_cf[acf_ind]
1006 data_acf = self.data_cf[acf_ind]
1007 data_ccf = self.data_cf[ccf_ind]
1007 data_ccf = self.data_cf[ccf_ind]
1008
1008
1009 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1009 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
1010
1010
1011 def getNormFactor(self):
1011 def getNormFactor(self):
1012 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1012 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
1013 acf_pairs = numpy.array(acf_pairs)
1013 acf_pairs = numpy.array(acf_pairs)
1014 normFactor = numpy.zeros((self.nPairs, self.nHeights))
1014 normFactor = numpy.zeros((self.nPairs, self.nHeights))
1015
1015
1016 for p in range(self.nPairs):
1016 for p in range(self.nPairs):
1017 pair = self.pairsList[p]
1017 pair = self.pairsList[p]
1018
1018
1019 ch0 = pair[0]
1019 ch0 = pair[0]
1020 ch1 = pair[1]
1020 ch1 = pair[1]
1021
1021
1022 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
1022 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
1023 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
1023 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
1024 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
1024 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
1025
1025
1026 return normFactor
1026 return normFactor
1027
1027
1028 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1028 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
1029 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1029 normFactor = property(getNormFactor, "I'm the 'normFactor property'")
1030
1030
1031
1031
1032 class Parameters(Spectra):
1032 class Parameters(Spectra):
1033
1033
1034 experimentInfo = None # Information about the experiment
1034 experimentInfo = None # Information about the experiment
1035 # Information from previous data
1035 # Information from previous data
1036 inputUnit = None # Type of data to be processed
1036 inputUnit = None # Type of data to be processed
1037 operation = None # Type of operation to parametrize
1037 operation = None # Type of operation to parametrize
1038 # normFactor = None #Normalization Factor
1038 # normFactor = None #Normalization Factor
1039 groupList = None # List of Pairs, Groups, etc
1039 groupList = None # List of Pairs, Groups, etc
1040 # Parameters
1040 # Parameters
1041 data_param = None # Parameters obtained
1041 data_param = None # Parameters obtained
1042 data_pre = None # Data Pre Parametrization
1042 data_pre = None # Data Pre Parametrization
1043 data_SNR = None # Signal to Noise Ratio
1043 data_SNR = None # Signal to Noise Ratio
1044 # heightRange = None #Heights
1044 # heightRange = None #Heights
1045 abscissaList = None # Abscissa, can be velocities, lags or time
1045 abscissaList = None # Abscissa, can be velocities, lags or time
1046 # noise = None #Noise Potency
1046 # noise = None #Noise Potency
1047 utctimeInit = None # Initial UTC time
1047 utctimeInit = None # Initial UTC time
1048 paramInterval = None # Time interval to calculate Parameters in seconds
1048 paramInterval = None # Time interval to calculate Parameters in seconds
1049 useLocalTime = True
1049 useLocalTime = True
1050 # Fitting
1050 # Fitting
1051 data_error = None # Error of the estimation
1051 data_error = None # Error of the estimation
1052 constants = None
1052 constants = None
1053 library = None
1053 library = None
1054 # Output signal
1054 # Output signal
1055 outputInterval = None # Time interval to calculate output signal in seconds
1055 outputInterval = None # Time interval to calculate output signal in seconds
1056 data_output = None # Out signal
1056 data_output = None # Out signal
1057 nAvg = None
1057 nAvg = None
1058 noise_estimation = None
1058 noise_estimation = None
1059 GauSPC = None # Fit gaussian SPC
1059 GauSPC = None # Fit gaussian SPC
1060
1060
1061 def __init__(self):
1061 def __init__(self):
1062 '''
1062 '''
1063 Constructor
1063 Constructor
1064 '''
1064 '''
1065 self.radarControllerHeaderObj = RadarControllerHeader()
1065 self.radarControllerHeaderObj = RadarControllerHeader()
1066
1066
1067 self.systemHeaderObj = SystemHeader()
1067 self.systemHeaderObj = SystemHeader()
1068
1068
1069 self.type = "Parameters"
1069 self.type = "Parameters"
1070
1070
1071 def getTimeRange1(self, interval):
1071 def getTimeRange1(self, interval):
1072
1072
1073 datatime = []
1073 datatime = []
1074
1074
1075 if self.useLocalTime:
1075 if self.useLocalTime:
1076 time1 = self.utctimeInit - self.timeZone * 60
1076 time1 = self.utctimeInit - self.timeZone * 60
1077 else:
1077 else:
1078 time1 = self.utctimeInit
1078 time1 = self.utctimeInit
1079
1079
1080 datatime.append(time1)
1080 datatime.append(time1)
1081 datatime.append(time1 + interval)
1081 datatime.append(time1 + interval)
1082 datatime = numpy.array(datatime)
1082 datatime = numpy.array(datatime)
1083
1083
1084 return datatime
1084 return datatime
1085
1085
1086 def getTimeInterval(self):
1086 def getTimeInterval(self):
1087
1087
1088 if hasattr(self, 'timeInterval1'):
1088 if hasattr(self, 'timeInterval1'):
1089 return self.timeInterval1
1089 return self.timeInterval1
1090 else:
1090 else:
1091 return self.paramInterval
1091 return self.paramInterval
1092
1092
1093 def setValue(self, value):
1093 def setValue(self, value):
1094
1094
1095 print("This property should not be initialized")
1095 print("This property should not be initialized")
1096
1096
1097 return
1097 return
1098
1098
1099 def getNoise(self):
1099 def getNoise(self):
1100
1100
1101 return self.spc_noise
1101 return self.spc_noise
1102
1102
1103 timeInterval = property(getTimeInterval)
1103 timeInterval = property(getTimeInterval)
1104 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
1104 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
1105
1105
1106
1106
1107 class PlotterData(object):
1107 class PlotterData(object):
1108 '''
1108 '''
1109 Object to hold data to be plotted
1109 Object to hold data to be plotted
1110 '''
1110 '''
1111
1111
1112 MAXNUMX = 100
1112 MAXNUMX = 200
1113 MAXNUMY = 100
1113 MAXNUMY = 200
1114
1114
1115 def __init__(self, code, throttle_value, exp_code, buffering=True, snr=False):
1115 def __init__(self, code, throttle_value, exp_code, buffering=True, snr=False):
1116
1116
1117 self.key = code
1117 self.key = code
1118 self.throttle = throttle_value
1118 self.throttle = throttle_value
1119 self.exp_code = exp_code
1119 self.exp_code = exp_code
1120 self.buffering = buffering
1120 self.buffering = buffering
1121 self.ready = False
1121 self.ready = False
1122 self.flagNoData = False
1122 self.flagNoData = False
1123 self.localtime = False
1123 self.localtime = False
1124 self.data = {}
1124 self.data = {}
1125 self.meta = {}
1125 self.meta = {}
1126 self.__times = []
1126 self.__times = []
1127 self.__heights = []
1127 self.__heights = []
1128
1128
1129 if 'snr' in code:
1129 if 'snr' in code:
1130 self.plottypes = ['snr']
1130 self.plottypes = ['snr']
1131 elif code == 'spc':
1131 elif code == 'spc':
1132 self.plottypes = ['spc', 'noise', 'rti']
1132 self.plottypes = ['spc', 'noise', 'rti']
1133 elif code == 'rti':
1133 elif code == 'rti':
1134 self.plottypes = ['noise', 'rti']
1134 self.plottypes = ['noise', 'rti']
1135 else:
1135 else:
1136 self.plottypes = [code]
1136 self.plottypes = [code]
1137
1137
1138 if 'snr' not in self.plottypes and snr:
1138 if 'snr' not in self.plottypes and snr:
1139 self.plottypes.append('snr')
1139 self.plottypes.append('snr')
1140
1140
1141 for plot in self.plottypes:
1141 for plot in self.plottypes:
1142 self.data[plot] = {}
1142 self.data[plot] = {}
1143
1143
1144
1144
1145 def __str__(self):
1145 def __str__(self):
1146 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1146 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1147 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
1147 return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times))
1148
1148
1149 def __len__(self):
1149 def __len__(self):
1150 return len(self.__times)
1150 return len(self.__times)
1151
1151
1152 def __getitem__(self, key):
1152 def __getitem__(self, key):
1153
1153
1154 if key not in self.data:
1154 if key not in self.data:
1155 raise KeyError(log.error('Missing key: {}'.format(key)))
1155 raise KeyError(log.error('Missing key: {}'.format(key)))
1156 if 'spc' in key or not self.buffering:
1156 if 'spc' in key or not self.buffering:
1157 ret = self.data[key]
1157 ret = self.data[key]
1158 elif 'scope' in key:
1158 elif 'scope' in key:
1159 ret = numpy.array(self.data[key][float(self.tm)])
1159 ret = numpy.array(self.data[key][float(self.tm)])
1160 else:
1160 else:
1161 ret = numpy.array([self.data[key][x] for x in self.times])
1161 ret = numpy.array([self.data[key][x] for x in self.times])
1162 if ret.ndim > 1:
1162 if ret.ndim > 1:
1163 ret = numpy.swapaxes(ret, 0, 1)
1163 ret = numpy.swapaxes(ret, 0, 1)
1164 return ret
1164 return ret
1165
1165
1166 def __contains__(self, key):
1166 def __contains__(self, key):
1167 return key in self.data
1167 return key in self.data
1168
1168
1169 def setup(self):
1169 def setup(self):
1170 '''
1170 '''
1171 Configure object
1171 Configure object
1172 '''
1172 '''
1173 self.type = ''
1173 self.type = ''
1174 self.ready = False
1174 self.ready = False
1175 self.data = {}
1175 self.data = {}
1176 self.__times = []
1176 self.__times = []
1177 self.__heights = []
1177 self.__heights = []
1178 self.__all_heights = set()
1178 self.__all_heights = set()
1179 for plot in self.plottypes:
1179 for plot in self.plottypes:
1180 if 'snr' in plot:
1180 if 'snr' in plot:
1181 plot = 'snr'
1181 plot = 'snr'
1182 elif 'spc_moments' == plot:
1182 elif 'spc_moments' == plot:
1183 plot = 'moments'
1183 plot = 'moments'
1184 self.data[plot] = {}
1184 self.data[plot] = {}
1185
1185
1186 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data or 'moments' in self.data:
1186 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data or 'moments' in self.data:
1187 self.data['noise'] = {}
1187 self.data['noise'] = {}
1188 self.data['rti'] = {}
1188 self.data['rti'] = {}
1189 if 'noise' not in self.plottypes:
1189 if 'noise' not in self.plottypes:
1190 self.plottypes.append('noise')
1190 self.plottypes.append('noise')
1191 if 'rti' not in self.plottypes:
1191 if 'rti' not in self.plottypes:
1192 self.plottypes.append('rti')
1192 self.plottypes.append('rti')
1193
1193
1194 def shape(self, key):
1194 def shape(self, key):
1195 '''
1195 '''
1196 Get the shape of the one-element data for the given key
1196 Get the shape of the one-element data for the given key
1197 '''
1197 '''
1198
1198
1199 if len(self.data[key]):
1199 if len(self.data[key]):
1200 if 'spc' in key or not self.buffering:
1200 if 'spc' in key or not self.buffering:
1201 return self.data[key].shape
1201 return self.data[key].shape
1202 return self.data[key][self.__times[0]].shape
1202 return self.data[key][self.__times[0]].shape
1203 return (0,)
1203 return (0,)
1204
1204
1205 def update(self, dataOut, tm):
1205 def update(self, dataOut, tm):
1206 '''
1206 '''
1207 Update data object with new dataOut
1207 Update data object with new dataOut
1208 '''
1208 '''
1209 if tm in self.__times:
1209 if tm in self.__times:
1210 return
1210 return
1211 self.profileIndex = dataOut.profileIndex
1211 self.profileIndex = dataOut.profileIndex
1212 self.tm = tm
1212 self.tm = tm
1213 self.type = dataOut.type
1213 self.type = dataOut.type
1214 self.parameters = getattr(dataOut, 'parameters', [])
1214 self.parameters = getattr(dataOut, 'parameters', [])
1215
1215
1216 if hasattr(dataOut, 'meta'):
1216 if hasattr(dataOut, 'meta'):
1217 self.meta.update(dataOut.meta)
1217 self.meta.update(dataOut.meta)
1218
1218
1219 if hasattr(dataOut, 'pairsList'):
1219 if hasattr(dataOut, 'pairsList'):
1220 self.pairs = dataOut.pairsList
1220 self.pairs = dataOut.pairsList
1221
1221
1222 self.interval = dataOut.getTimeInterval()
1222 self.interval = dataOut.getTimeInterval()
1223 self.localtime = dataOut.useLocalTime
1223 self.localtime = dataOut.useLocalTime
1224 if True in ['spc' in ptype for ptype in self.plottypes]:
1224 if True in ['spc' in ptype for ptype in self.plottypes]:
1225 self.xrange = (dataOut.getFreqRange(1)/1000.,
1225 self.xrange = (dataOut.getFreqRange(1)/1000.,
1226 dataOut.getAcfRange(1), dataOut.getVelRange(1))
1226 dataOut.getAcfRange(1), dataOut.getVelRange(1))
1227 self.factor = dataOut.normFactor
1227 self.factor = dataOut.normFactor
1228 self.__heights.append(dataOut.heightList)
1228 self.__heights.append(dataOut.heightList)
1229 self.__all_heights.update(dataOut.heightList)
1229 self.__all_heights.update(dataOut.heightList)
1230 self.__times.append(tm)
1230 self.__times.append(tm)
1231 for plot in self.plottypes:
1231 for plot in self.plottypes:
1232 if plot in ('spc', 'spc_moments', 'spc_cut'):
1232 if plot in ('spc', 'spc_moments', 'spc_cut'):
1233 z = dataOut.data_spc/dataOut.normFactor
1233 z = dataOut.data_spc/dataOut.normFactor
1234 buffer = 10*numpy.log10(z)
1234 buffer = 10*numpy.log10(z)
1235 if plot == 'cspc':
1235 if plot == 'cspc':
1236 z = dataOut.data_spc/dataOut.normFactor
1236 z = dataOut.data_spc/dataOut.normFactor
1237 buffer = (dataOut.data_spc, dataOut.data_cspc)
1237 buffer = (dataOut.data_spc, dataOut.data_cspc)
1238 if plot == 'noise':
1238 if plot == 'noise':
1239 buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
1239 buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
1240 if plot in ('rti', 'spcprofile'):
1240 if plot in ('rti', 'spcprofile'):
1241 buffer = dataOut.getPower()
1241 buffer = dataOut.getPower()
1242 if plot == 'snr_db':
1242 if plot == 'snr_db':
1243 buffer = dataOut.data_SNR
1243 buffer = dataOut.data_SNR
1244 if plot == 'snr':
1244 if plot == 'snr':
1245 buffer = 10*numpy.log10(dataOut.data_SNR)
1245 buffer = 10*numpy.log10(dataOut.data_SNR)
1246 if plot == 'dop':
1246 if plot == 'dop':
1247 buffer = dataOut.data_DOP
1247 buffer = dataOut.data_DOP
1248 if plot == 'pow':
1248 if plot == 'pow':
1249 buffer = 10*numpy.log10(dataOut.data_POW)
1249 buffer = 10*numpy.log10(dataOut.data_POW)
1250 if plot == 'width':
1250 if plot == 'width':
1251 buffer = dataOut.data_WIDTH
1251 buffer = dataOut.data_WIDTH
1252 if plot == 'coh':
1252 if plot == 'coh':
1253 buffer = dataOut.getCoherence()
1253 buffer = dataOut.getCoherence()
1254 if plot == 'phase':
1254 if plot == 'phase':
1255 buffer = dataOut.getCoherence(phase=True)
1255 buffer = dataOut.getCoherence(phase=True)
1256 if plot == 'output':
1256 if plot == 'output':
1257 buffer = dataOut.data_output
1257 buffer = dataOut.data_output
1258 if plot == 'param':
1258 if plot == 'param':
1259 buffer = dataOut.data_param
1259 buffer = dataOut.data_param
1260 if plot == 'scope':
1260 if plot == 'scope':
1261 buffer = dataOut.data
1261 buffer = dataOut.data
1262 self.flagDataAsBlock = dataOut.flagDataAsBlock
1262 self.flagDataAsBlock = dataOut.flagDataAsBlock
1263 self.nProfiles = dataOut.nProfiles
1263 self.nProfiles = dataOut.nProfiles
1264 if plot == 'pp_power':
1264 if plot == 'pp_power':
1265 buffer = dataOut.data_intensity
1265 buffer = dataOut.data_intensity
1266 self.flagDataAsBlock = dataOut.flagDataAsBlock
1266 self.flagDataAsBlock = dataOut.flagDataAsBlock
1267 self.nProfiles = dataOut.nProfiles
1267 self.nProfiles = dataOut.nProfiles
1268 if plot == 'pp_velocity':
1268 if plot == 'pp_velocity':
1269 buffer = dataOut.data_velocity
1269 buffer = dataOut.data_velocity
1270 self.flagDataAsBlock = dataOut.flagDataAsBlock
1270 self.flagDataAsBlock = dataOut.flagDataAsBlock
1271 self.nProfiles = dataOut.nProfiles
1271 self.nProfiles = dataOut.nProfiles
1272 if plot == 'pp_specwidth':
1272 if plot == 'pp_specwidth':
1273 buffer = dataOut.data_specwidth
1273 buffer = dataOut.data_specwidth
1274 self.flagDataAsBlock = dataOut.flagDataAsBlock
1274 self.flagDataAsBlock = dataOut.flagDataAsBlock
1275 self.nProfiles = dataOut.nProfiles
1275 self.nProfiles = dataOut.nProfiles
1276
1276
1277 if plot == 'spc':
1277 if plot == 'spc':
1278 self.data['spc'] = buffer
1278 self.data['spc'] = buffer
1279 elif plot == 'cspc':
1279 elif plot == 'cspc':
1280 self.data['spc'] = buffer[0]
1280 self.data['spc'] = buffer[0]
1281 self.data['cspc'] = buffer[1]
1281 self.data['cspc'] = buffer[1]
1282 elif plot == 'spc_moments':
1282 elif plot == 'spc_moments':
1283 self.data['spc'] = buffer
1283 self.data['spc'] = buffer
1284 self.data['moments'][tm] = dataOut.moments
1284 self.data['moments'][tm] = dataOut.moments
1285 else:
1285 else:
1286 if self.buffering:
1286 if self.buffering:
1287 self.data[plot][tm] = buffer
1287 self.data[plot][tm] = buffer
1288 else:
1288 else:
1289 self.data[plot] = buffer
1289 self.data[plot] = buffer
1290
1290
1291 if dataOut.channelList is None:
1291 if dataOut.channelList is None:
1292 self.channels = range(buffer.shape[0])
1292 self.channels = range(buffer.shape[0])
1293 else:
1293 else:
1294 self.channels = dataOut.channelList
1294 self.channels = dataOut.channelList
1295
1295
1296 if buffer is None:
1296 if buffer is None:
1297 self.flagNoData = True
1297 self.flagNoData = True
1298 raise schainpy.admin.SchainWarning('Attribute data_{} is empty'.format(self.key))
1298 raise schainpy.admin.SchainWarning('Attribute data_{} is empty'.format(self.key))
1299
1299
1300 def normalize_heights(self):
1300 def normalize_heights(self):
1301 '''
1301 '''
1302 Ensure same-dimension of the data for different heighList
1302 Ensure same-dimension of the data for different heighList
1303 '''
1303 '''
1304
1304
1305 H = numpy.array(list(self.__all_heights))
1305 H = numpy.array(list(self.__all_heights))
1306 H.sort()
1306 H.sort()
1307 for key in self.data:
1307 for key in self.data:
1308 shape = self.shape(key)[:-1] + H.shape
1308 shape = self.shape(key)[:-1] + H.shape
1309 for tm, obj in list(self.data[key].items()):
1309 for tm, obj in list(self.data[key].items()):
1310 h = self.__heights[self.__times.index(tm)]
1310 h = self.__heights[self.__times.index(tm)]
1311 if H.size == h.size:
1311 if H.size == h.size:
1312 continue
1312 continue
1313 index = numpy.where(numpy.in1d(H, h))[0]
1313 index = numpy.where(numpy.in1d(H, h))[0]
1314 dummy = numpy.zeros(shape) + numpy.nan
1314 dummy = numpy.zeros(shape) + numpy.nan
1315 if len(shape) == 2:
1315 if len(shape) == 2:
1316 dummy[:, index] = obj
1316 dummy[:, index] = obj
1317 else:
1317 else:
1318 dummy[index] = obj
1318 dummy[index] = obj
1319 self.data[key][tm] = dummy
1319 self.data[key][tm] = dummy
1320
1320
1321 self.__heights = [H for tm in self.__times]
1321 self.__heights = [H for tm in self.__times]
1322
1322
1323 def jsonify(self, plot_name, plot_type, decimate=False):
1323 def jsonify(self, plot_name, plot_type, decimate=False):
1324 '''
1324 '''
1325 Convert data to json
1325 Convert data to json
1326 '''
1326 '''
1327
1327
1328 tm = self.times[-1]
1328 tm = self.times[-1]
1329 dy = int(self.heights.size/self.MAXNUMY) + 1
1329 dy = int(self.heights.size/self.MAXNUMY) + 1
1330 if self.key in ('spc', 'cspc') or not self.buffering:
1330 if self.key in ('spc', 'cspc') or not self.buffering:
1331 dx = int(self.data[self.key].shape[1]/self.MAXNUMX) + 1
1331 dx = int(self.data[self.key].shape[1]/self.MAXNUMX) + 1
1332 data = self.roundFloats(
1332 data = self.roundFloats(
1333 self.data[self.key][::, ::dx, ::dy].tolist())
1333 self.data[self.key][::, ::dx, ::dy].tolist())
1334 else:
1334 else:
1335 data = self.roundFloats(self.data[self.key][tm].tolist())
1336 if self.key is 'noise':
1335 if self.key is 'noise':
1337 data = [[x] for x in data]
1336 data = [[x] for x in self.roundFloats(self.data[self.key][tm].tolist())]
1337 else:
1338 data = self.roundFloats(self.data[self.key][tm][::, ::dy].tolist())
1338
1339
1339 meta = {}
1340 meta = {}
1340 ret = {
1341 ret = {
1341 'plot': plot_name,
1342 'plot': plot_name,
1342 'code': self.exp_code,
1343 'code': self.exp_code,
1343 'time': float(tm),
1344 'time': float(tm),
1344 'data': data,
1345 'data': data,
1345 }
1346 }
1346 meta['type'] = plot_type
1347 meta['type'] = plot_type
1347 meta['interval'] = float(self.interval)
1348 meta['interval'] = float(self.interval)
1348 meta['localtime'] = self.localtime
1349 meta['localtime'] = self.localtime
1349 meta['yrange'] = self.roundFloats(self.heights[::dy].tolist())
1350 meta['yrange'] = self.roundFloats(self.heights[::dy].tolist())
1350 if 'spc' in self.data or 'cspc' in self.data:
1351 if 'spc' in self.data or 'cspc' in self.data:
1351 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1352 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1352 else:
1353 else:
1353 meta['xrange'] = []
1354 meta['xrange'] = []
1354
1355
1355 meta.update(self.meta)
1356 meta.update(self.meta)
1356 ret['metadata'] = meta
1357 ret['metadata'] = meta
1357 return json.dumps(ret)
1358 return json.dumps(ret)
1358
1359
1359 @property
1360 @property
1360 def times(self):
1361 def times(self):
1361 '''
1362 '''
1362 Return the list of times of the current data
1363 Return the list of times of the current data
1363 '''
1364 '''
1364
1365
1365 ret = numpy.array(self.__times)
1366 ret = numpy.array(self.__times)
1366 ret.sort()
1367 ret.sort()
1367 return ret
1368 return ret
1368
1369
1369 @property
1370 @property
1370 def min_time(self):
1371 def min_time(self):
1371 '''
1372 '''
1372 Return the minimun time value
1373 Return the minimun time value
1373 '''
1374 '''
1374
1375
1375 return self.times[0]
1376 return self.times[0]
1376
1377
1377 @property
1378 @property
1378 def max_time(self):
1379 def max_time(self):
1379 '''
1380 '''
1380 Return the maximun time value
1381 Return the maximun time value
1381 '''
1382 '''
1382
1383
1383 return self.times[-1]
1384 return self.times[-1]
1384
1385
1385 @property
1386 @property
1386 def heights(self):
1387 def heights(self):
1387 '''
1388 '''
1388 Return the list of heights of the current data
1389 Return the list of heights of the current data
1389 '''
1390 '''
1390
1391
1391 return numpy.array(self.__heights[-1])
1392 return numpy.array(self.__heights[-1])
1392
1393
1393 @staticmethod
1394 @staticmethod
1394 def roundFloats(obj):
1395 def roundFloats(obj):
1395 if isinstance(obj, list):
1396 if isinstance(obj, list):
1396 return list(map(PlotterData.roundFloats, obj))
1397 return list(map(PlotterData.roundFloats, obj))
1397 elif isinstance(obj, float):
1398 elif isinstance(obj, float):
1398 return round(obj, 2)
1399 return round(obj, 2)
@@ -1,700 +1,705
1
1
2 import os
2 import os
3 import sys
3 import sys
4 import zmq
4 import zmq
5 import time
5 import time
6 import numpy
6 import numpy
7 import datetime
7 import datetime
8 from queue import Queue
8 from functools import wraps
9 from functools import wraps
9 from threading import Thread
10 from threading import Thread
10 import matplotlib
11 import matplotlib
11
12
12 if 'BACKEND' in os.environ:
13 if 'BACKEND' in os.environ:
13 matplotlib.use(os.environ['BACKEND'])
14 matplotlib.use(os.environ['BACKEND'])
14 elif 'linux' in sys.platform:
15 elif 'linux' in sys.platform:
15 matplotlib.use("TkAgg")
16 matplotlib.use("TkAgg")
16 elif 'darwin' in sys.platform:
17 elif 'darwin' in sys.platform:
17 matplotlib.use('WxAgg')
18 matplotlib.use('WxAgg')
18 else:
19 else:
19 from schainpy.utils import log
20 from schainpy.utils import log
20 log.warning('Using default Backend="Agg"', 'INFO')
21 log.warning('Using default Backend="Agg"', 'INFO')
21 matplotlib.use('Agg')
22 matplotlib.use('Agg')
22
23
23 import matplotlib.pyplot as plt
24 import matplotlib.pyplot as plt
24 from matplotlib.patches import Polygon
25 from matplotlib.patches import Polygon
25 from mpl_toolkits.axes_grid1 import make_axes_locatable
26 from mpl_toolkits.axes_grid1 import make_axes_locatable
26 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
27 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
27
28
28 from schainpy.model.data.jrodata import PlotterData
29 from schainpy.model.data.jrodata import PlotterData
29 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
30 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
30 from schainpy.utils import log
31 from schainpy.utils import log
31
32
32 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
33 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
33 blu_values = matplotlib.pyplot.get_cmap(
34 blu_values = matplotlib.pyplot.get_cmap(
34 'seismic_r', 20)(numpy.arange(20))[10:15]
35 'seismic_r', 20)(numpy.arange(20))[10:15]
35 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
36 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
36 'jro', numpy.vstack((blu_values, jet_values)))
37 'jro', numpy.vstack((blu_values, jet_values)))
37 matplotlib.pyplot.register_cmap(cmap=ncmap)
38 matplotlib.pyplot.register_cmap(cmap=ncmap)
38
39
39 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
40 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
40 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
41 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
41
42
42 EARTH_RADIUS = 6.3710e3
43 EARTH_RADIUS = 6.3710e3
43
44
44 def ll2xy(lat1, lon1, lat2, lon2):
45 def ll2xy(lat1, lon1, lat2, lon2):
45
46
46 p = 0.017453292519943295
47 p = 0.017453292519943295
47 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
48 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
48 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
49 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
49 r = 12742 * numpy.arcsin(numpy.sqrt(a))
50 r = 12742 * numpy.arcsin(numpy.sqrt(a))
50 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
51 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
51 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
52 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
52 theta = -theta + numpy.pi/2
53 theta = -theta + numpy.pi/2
53 return r*numpy.cos(theta), r*numpy.sin(theta)
54 return r*numpy.cos(theta), r*numpy.sin(theta)
54
55
55
56
56 def km2deg(km):
57 def km2deg(km):
57 '''
58 '''
58 Convert distance in km to degrees
59 Convert distance in km to degrees
59 '''
60 '''
60
61
61 return numpy.rad2deg(km/EARTH_RADIUS)
62 return numpy.rad2deg(km/EARTH_RADIUS)
62
63
63
64
64 def figpause(interval):
65 def figpause(interval):
65 backend = plt.rcParams['backend']
66 backend = plt.rcParams['backend']
66 if backend in matplotlib.rcsetup.interactive_bk:
67 if backend in matplotlib.rcsetup.interactive_bk:
67 figManager = matplotlib._pylab_helpers.Gcf.get_active()
68 figManager = matplotlib._pylab_helpers.Gcf.get_active()
68 if figManager is not None:
69 if figManager is not None:
69 canvas = figManager.canvas
70 canvas = figManager.canvas
70 if canvas.figure.stale:
71 if canvas.figure.stale:
71 canvas.draw()
72 canvas.draw()
72 try:
73 try:
73 canvas.start_event_loop(interval)
74 canvas.start_event_loop(interval)
74 except:
75 except:
75 pass
76 pass
76 return
77 return
77
78
78
79
79 def popup(message):
80 def popup(message):
80 '''
81 '''
81 '''
82 '''
82
83
83 fig = plt.figure(figsize=(12, 8), facecolor='r')
84 fig = plt.figure(figsize=(12, 8), facecolor='r')
84 text = '\n'.join([s.strip() for s in message.split(':')])
85 text = '\n'.join([s.strip() for s in message.split(':')])
85 fig.text(0.01, 0.5, text, ha='left', va='center',
86 fig.text(0.01, 0.5, text, ha='left', va='center',
86 size='20', weight='heavy', color='w')
87 size='20', weight='heavy', color='w')
87 fig.show()
88 fig.show()
88 figpause(1000)
89 figpause(1000)
89
90
90
91
91 class Throttle(object):
92 class Throttle(object):
92 '''
93 '''
93 Decorator that prevents a function from being called more than once every
94 Decorator that prevents a function from being called more than once every
94 time period.
95 time period.
95 To create a function that cannot be called more than once a minute, but
96 To create a function that cannot be called more than once a minute, but
96 will sleep until it can be called:
97 will sleep until it can be called:
97 @Throttle(minutes=1)
98 @Throttle(minutes=1)
98 def foo():
99 def foo():
99 pass
100 pass
100
101
101 for i in range(10):
102 for i in range(10):
102 foo()
103 foo()
103 print "This function has run %s times." % i
104 print "This function has run %s times." % i
104 '''
105 '''
105
106
106 def __init__(self, seconds=0, minutes=0, hours=0):
107 def __init__(self, seconds=0, minutes=0, hours=0):
107 self.throttle_period = datetime.timedelta(
108 self.throttle_period = datetime.timedelta(
108 seconds=seconds, minutes=minutes, hours=hours
109 seconds=seconds, minutes=minutes, hours=hours
109 )
110 )
110
111
111 self.time_of_last_call = datetime.datetime.min
112 self.time_of_last_call = datetime.datetime.min
112
113
113 def __call__(self, fn):
114 def __call__(self, fn):
114 @wraps(fn)
115 @wraps(fn)
115 def wrapper(*args, **kwargs):
116 def wrapper(*args, **kwargs):
116 coerce = kwargs.pop('coerce', None)
117 coerce = kwargs.pop('coerce', None)
117 if coerce:
118 if coerce:
118 self.time_of_last_call = datetime.datetime.now()
119 self.time_of_last_call = datetime.datetime.now()
119 return fn(*args, **kwargs)
120 return fn(*args, **kwargs)
120 else:
121 else:
121 now = datetime.datetime.now()
122 now = datetime.datetime.now()
122 time_since_last_call = now - self.time_of_last_call
123 time_since_last_call = now - self.time_of_last_call
123 time_left = self.throttle_period - time_since_last_call
124 time_left = self.throttle_period - time_since_last_call
124
125
125 if time_left > datetime.timedelta(seconds=0):
126 if time_left > datetime.timedelta(seconds=0):
126 return
127 return
127
128
128 self.time_of_last_call = datetime.datetime.now()
129 self.time_of_last_call = datetime.datetime.now()
129 return fn(*args, **kwargs)
130 return fn(*args, **kwargs)
130
131
131 return wrapper
132 return wrapper
132
133
133 def apply_throttle(value):
134 def apply_throttle(value):
134
135
135 @Throttle(seconds=value)
136 @Throttle(seconds=value)
136 def fnThrottled(fn):
137 def fnThrottled(fn):
137 fn()
138 fn()
138
139
139 return fnThrottled
140 return fnThrottled
140
141
141
142
142 @MPDecorator
143 @MPDecorator
143 class Plot(Operation):
144 class Plot(Operation):
144 '''
145 '''
145 Base class for Schain plotting operations
146 Base class for Schain plotting operations
146 '''
147 '''
147
148
148 CODE = 'Figure'
149 CODE = 'Figure'
149 colormap = 'jet'
150 colormap = 'jet'
150 bgcolor = 'white'
151 bgcolor = 'white'
151 buffering = True
152 buffering = True
152 __missing = 1E30
153 __missing = 1E30
153
154
154 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
155 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
155 'showprofile']
156 'showprofile']
156
157
157 def __init__(self):
158 def __init__(self):
158
159
159 Operation.__init__(self)
160 Operation.__init__(self)
160 self.isConfig = False
161 self.isConfig = False
161 self.isPlotConfig = False
162 self.isPlotConfig = False
162 self.save_counter = 1
163 self.save_counter = 1
163 self.sender_counter = 1
164 self.sender_time = 0
164 self.data = None
165 self.data = None
165 self.firsttime = True
166 self.firsttime = True
167 self.sender_queue = Queue(maxsize=10)
166 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
168 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
167
169
168 def __fmtTime(self, x, pos):
170 def __fmtTime(self, x, pos):
169 '''
171 '''
170 '''
172 '''
171
173
172 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
174 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
173
175
174 def __setup(self, **kwargs):
176 def __setup(self, **kwargs):
175 '''
177 '''
176 Initialize variables
178 Initialize variables
177 '''
179 '''
178
180
179 self.figures = []
181 self.figures = []
180 self.axes = []
182 self.axes = []
181 self.cb_axes = []
183 self.cb_axes = []
182 self.localtime = kwargs.pop('localtime', True)
184 self.localtime = kwargs.pop('localtime', True)
183 self.show = kwargs.get('show', True)
185 self.show = kwargs.get('show', True)
184 self.save = kwargs.get('save', False)
186 self.save = kwargs.get('save', False)
185 self.save_period = kwargs.get('save_period', 1)
187 self.save_period = kwargs.get('save_period', 1)
186 self.ftp = kwargs.get('ftp', False)
188 self.ftp = kwargs.get('ftp', False)
187 self.colormap = kwargs.get('colormap', self.colormap)
189 self.colormap = kwargs.get('colormap', self.colormap)
188 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
190 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
189 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
191 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
190 self.colormaps = kwargs.get('colormaps', None)
192 self.colormaps = kwargs.get('colormaps', None)
191 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
193 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
192 self.showprofile = kwargs.get('showprofile', False)
194 self.showprofile = kwargs.get('showprofile', False)
193 self.title = kwargs.get('wintitle', self.CODE.upper())
195 self.title = kwargs.get('wintitle', self.CODE.upper())
194 self.cb_label = kwargs.get('cb_label', None)
196 self.cb_label = kwargs.get('cb_label', None)
195 self.cb_labels = kwargs.get('cb_labels', None)
197 self.cb_labels = kwargs.get('cb_labels', None)
196 self.labels = kwargs.get('labels', None)
198 self.labels = kwargs.get('labels', None)
197 self.xaxis = kwargs.get('xaxis', 'frequency')
199 self.xaxis = kwargs.get('xaxis', 'frequency')
198 self.zmin = kwargs.get('zmin', None)
200 self.zmin = kwargs.get('zmin', None)
199 self.zmax = kwargs.get('zmax', None)
201 self.zmax = kwargs.get('zmax', None)
200 self.zlimits = kwargs.get('zlimits', None)
202 self.zlimits = kwargs.get('zlimits', None)
201 self.xmin = kwargs.get('xmin', None)
203 self.xmin = kwargs.get('xmin', None)
202 self.xmax = kwargs.get('xmax', None)
204 self.xmax = kwargs.get('xmax', None)
203 self.xrange = kwargs.get('xrange', 24)
205 self.xrange = kwargs.get('xrange', 24)
204 self.xscale = kwargs.get('xscale', None)
206 self.xscale = kwargs.get('xscale', None)
205 self.ymin = kwargs.get('ymin', None)
207 self.ymin = kwargs.get('ymin', None)
206 self.ymax = kwargs.get('ymax', None)
208 self.ymax = kwargs.get('ymax', None)
207 self.yscale = kwargs.get('yscale', None)
209 self.yscale = kwargs.get('yscale', None)
208 self.xlabel = kwargs.get('xlabel', None)
210 self.xlabel = kwargs.get('xlabel', None)
209 self.attr_time = kwargs.get('attr_time', 'utctime')
211 self.attr_time = kwargs.get('attr_time', 'utctime')
210 self.decimation = kwargs.get('decimation', None)
212 self.decimation = kwargs.get('decimation', None)
211 self.showSNR = kwargs.get('showSNR', False)
213 self.showSNR = kwargs.get('showSNR', False)
212 self.oneFigure = kwargs.get('oneFigure', True)
214 self.oneFigure = kwargs.get('oneFigure', True)
213 self.width = kwargs.get('width', None)
215 self.width = kwargs.get('width', None)
214 self.height = kwargs.get('height', None)
216 self.height = kwargs.get('height', None)
215 self.colorbar = kwargs.get('colorbar', True)
217 self.colorbar = kwargs.get('colorbar', True)
216 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
218 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
217 self.channels = kwargs.get('channels', None)
219 self.channels = kwargs.get('channels', None)
218 self.titles = kwargs.get('titles', [])
220 self.titles = kwargs.get('titles', [])
219 self.polar = False
221 self.polar = False
220 self.type = kwargs.get('type', 'iq')
222 self.type = kwargs.get('type', 'iq')
221 self.grid = kwargs.get('grid', False)
223 self.grid = kwargs.get('grid', False)
222 self.pause = kwargs.get('pause', False)
224 self.pause = kwargs.get('pause', False)
223 self.save_code = kwargs.get('save_code', None)
225 self.save_code = kwargs.get('save_code', None)
224 self.realtime = kwargs.get('realtime', True)
226 self.realtime = kwargs.get('realtime', True)
225 self.throttle = kwargs.get('throttle', 0)
227 self.throttle = kwargs.get('throttle', 0)
226 self.exp_code = kwargs.get('exp_code', None)
228 self.exp_code = kwargs.get('exp_code', None)
227 self.plot_server = kwargs.get('plot_server', False)
229 self.plot_server = kwargs.get('plot_server', False)
228 self.sender_period = kwargs.get('sender_period', 1)
230 self.sender_period = kwargs.get('sender_period', 60)
229 self.height_index = kwargs.get('height_index', None)
231 self.height_index = kwargs.get('height_index', None)
230 self.__throttle_plot = apply_throttle(self.throttle)
232 self.__throttle_plot = apply_throttle(self.throttle)
231 self.data = PlotterData(
233 self.data = PlotterData(
232 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
234 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
233
235
234 if self.plot_server:
236 if self.plot_server:
235 if not self.plot_server.startswith('tcp://'):
237 if not self.plot_server.startswith('tcp://'):
236 self.plot_server = 'tcp://{}'.format(self.plot_server)
238 self.plot_server = 'tcp://{}'.format(self.plot_server)
237 log.success(
239 log.success(
238 'Sending to server: {}'.format(self.plot_server),
240 'Sending to server: {}'.format(self.plot_server),
239 self.name
241 self.name
240 )
242 )
241 if 'plot_name' in kwargs:
243 if 'plot_name' in kwargs:
242 self.plot_name = kwargs['plot_name']
244 self.plot_name = kwargs['plot_name']
243
245
244 def __setup_plot(self):
246 def __setup_plot(self):
245 '''
247 '''
246 Common setup for all figures, here figures and axes are created
248 Common setup for all figures, here figures and axes are created
247 '''
249 '''
248
250
249 self.setup()
251 self.setup()
250
252
251 self.time_label = 'LT' if self.localtime else 'UTC'
253 self.time_label = 'LT' if self.localtime else 'UTC'
252
254
253 if self.width is None:
255 if self.width is None:
254 self.width = 8
256 self.width = 8
255
257
256 self.figures = []
258 self.figures = []
257 self.axes = []
259 self.axes = []
258 self.cb_axes = []
260 self.cb_axes = []
259 self.pf_axes = []
261 self.pf_axes = []
260 self.cmaps = []
262 self.cmaps = []
261
263
262 size = '15%' if self.ncols == 1 else '30%'
264 size = '15%' if self.ncols == 1 else '30%'
263 pad = '4%' if self.ncols == 1 else '8%'
265 pad = '4%' if self.ncols == 1 else '8%'
264
266
265 if self.oneFigure:
267 if self.oneFigure:
266 if self.height is None:
268 if self.height is None:
267 self.height = 1.4 * self.nrows + 1
269 self.height = 1.4 * self.nrows + 1
268 fig = plt.figure(figsize=(self.width, self.height),
270 fig = plt.figure(figsize=(self.width, self.height),
269 edgecolor='k',
271 edgecolor='k',
270 facecolor='w')
272 facecolor='w')
271 self.figures.append(fig)
273 self.figures.append(fig)
272 for n in range(self.nplots):
274 for n in range(self.nplots):
273 ax = fig.add_subplot(self.nrows, self.ncols,
275 ax = fig.add_subplot(self.nrows, self.ncols,
274 n + 1, polar=self.polar)
276 n + 1, polar=self.polar)
275 ax.tick_params(labelsize=8)
277 ax.tick_params(labelsize=8)
276 ax.firsttime = True
278 ax.firsttime = True
277 ax.index = 0
279 ax.index = 0
278 ax.press = None
280 ax.press = None
279 self.axes.append(ax)
281 self.axes.append(ax)
280 if self.showprofile:
282 if self.showprofile:
281 cax = self.__add_axes(ax, size=size, pad=pad)
283 cax = self.__add_axes(ax, size=size, pad=pad)
282 cax.tick_params(labelsize=8)
284 cax.tick_params(labelsize=8)
283 self.pf_axes.append(cax)
285 self.pf_axes.append(cax)
284 else:
286 else:
285 if self.height is None:
287 if self.height is None:
286 self.height = 3
288 self.height = 3
287 for n in range(self.nplots):
289 for n in range(self.nplots):
288 fig = plt.figure(figsize=(self.width, self.height),
290 fig = plt.figure(figsize=(self.width, self.height),
289 edgecolor='k',
291 edgecolor='k',
290 facecolor='w')
292 facecolor='w')
291 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
293 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
292 ax.tick_params(labelsize=8)
294 ax.tick_params(labelsize=8)
293 ax.firsttime = True
295 ax.firsttime = True
294 ax.index = 0
296 ax.index = 0
295 ax.press = None
297 ax.press = None
296 self.figures.append(fig)
298 self.figures.append(fig)
297 self.axes.append(ax)
299 self.axes.append(ax)
298 if self.showprofile:
300 if self.showprofile:
299 cax = self.__add_axes(ax, size=size, pad=pad)
301 cax = self.__add_axes(ax, size=size, pad=pad)
300 cax.tick_params(labelsize=8)
302 cax.tick_params(labelsize=8)
301 self.pf_axes.append(cax)
303 self.pf_axes.append(cax)
302
304
303 for n in range(self.nrows):
305 for n in range(self.nrows):
304 if self.colormaps is not None:
306 if self.colormaps is not None:
305 cmap = plt.get_cmap(self.colormaps[n])
307 cmap = plt.get_cmap(self.colormaps[n])
306 else:
308 else:
307 cmap = plt.get_cmap(self.colormap)
309 cmap = plt.get_cmap(self.colormap)
308 cmap.set_bad(self.bgcolor, 1.)
310 cmap.set_bad(self.bgcolor, 1.)
309 self.cmaps.append(cmap)
311 self.cmaps.append(cmap)
310
312
311 def __add_axes(self, ax, size='30%', pad='8%'):
313 def __add_axes(self, ax, size='30%', pad='8%'):
312 '''
314 '''
313 Add new axes to the given figure
315 Add new axes to the given figure
314 '''
316 '''
315 divider = make_axes_locatable(ax)
317 divider = make_axes_locatable(ax)
316 nax = divider.new_horizontal(size=size, pad=pad)
318 nax = divider.new_horizontal(size=size, pad=pad)
317 ax.figure.add_axes(nax)
319 ax.figure.add_axes(nax)
318 return nax
320 return nax
319
321
320 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
322 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
321 '''
323 '''
322 Create a masked array for missing data
324 Create a masked array for missing data
323 '''
325 '''
324 if x_buffer.shape[0] < 2:
326 if x_buffer.shape[0] < 2:
325 return x_buffer, y_buffer, z_buffer
327 return x_buffer, y_buffer, z_buffer
326
328
327 deltas = x_buffer[1:] - x_buffer[0:-1]
329 deltas = x_buffer[1:] - x_buffer[0:-1]
328 x_median = numpy.median(deltas)
330 x_median = numpy.median(deltas)
329
331
330 index = numpy.where(deltas > 5 * x_median)
332 index = numpy.where(deltas > 5 * x_median)
331
333
332 if len(index[0]) != 0:
334 if len(index[0]) != 0:
333 z_buffer[::, index[0], ::] = self.__missing
335 z_buffer[::, index[0], ::] = self.__missing
334 z_buffer = numpy.ma.masked_inside(z_buffer,
336 z_buffer = numpy.ma.masked_inside(z_buffer,
335 0.99 * self.__missing,
337 0.99 * self.__missing,
336 1.01 * self.__missing)
338 1.01 * self.__missing)
337
339
338 return x_buffer, y_buffer, z_buffer
340 return x_buffer, y_buffer, z_buffer
339
341
340 def decimate(self):
342 def decimate(self):
341
343
342 # dx = int(len(self.x)/self.__MAXNUMX) + 1
344 # dx = int(len(self.x)/self.__MAXNUMX) + 1
343 dy = int(len(self.y) / self.decimation) + 1
345 dy = int(len(self.y) / self.decimation) + 1
344
346
345 # x = self.x[::dx]
347 # x = self.x[::dx]
346 x = self.x
348 x = self.x
347 y = self.y[::dy]
349 y = self.y[::dy]
348 z = self.z[::, ::, ::dy]
350 z = self.z[::, ::, ::dy]
349
351
350 return x, y, z
352 return x, y, z
351
353
352 def format(self):
354 def format(self):
353 '''
355 '''
354 Set min and max values, labels, ticks and titles
356 Set min and max values, labels, ticks and titles
355 '''
357 '''
356
358
357 if self.xmin is None:
359 if self.xmin is None:
358 xmin = self.data.min_time
360 xmin = self.data.min_time
359 else:
361 else:
360 if self.xaxis is 'time':
362 if self.xaxis is 'time':
361 dt = self.getDateTime(self.data.min_time)
363 dt = self.getDateTime(self.data.min_time)
362 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
364 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
363 datetime.datetime(1970, 1, 1)).total_seconds()
365 datetime.datetime(1970, 1, 1)).total_seconds()
364 if self.data.localtime:
366 if self.data.localtime:
365 xmin += time.timezone
367 xmin += time.timezone
366 else:
368 else:
367 xmin = self.xmin
369 xmin = self.xmin
368
370
369 if self.xmax is None:
371 if self.xmax is None:
370 xmax = xmin + self.xrange * 60 * 60
372 xmax = xmin + self.xrange * 60 * 60
371 else:
373 else:
372 if self.xaxis is 'time':
374 if self.xaxis is 'time':
373 dt = self.getDateTime(self.data.max_time)
375 dt = self.getDateTime(self.data.max_time)
374 xmax = self.xmax - 1
376 xmax = self.xmax - 1
375 xmax = (dt.replace(hour=int(xmax), minute=59, second=59) -
377 xmax = (dt.replace(hour=int(xmax), minute=59, second=59) -
376 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
378 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
377 if self.data.localtime:
379 if self.data.localtime:
378 xmax += time.timezone
380 xmax += time.timezone
379 else:
381 else:
380 xmax = self.xmax
382 xmax = self.xmax
381
383
382 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
384 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
383 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
385 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
384
386
385 for n, ax in enumerate(self.axes):
387 for n, ax in enumerate(self.axes):
386 if ax.firsttime:
388 if ax.firsttime:
387
389
388 dig = int(numpy.log10(ymax))
390 dig = int(numpy.log10(ymax))
389 if dig == 0:
391 if dig == 0:
390 digD = len(str(ymax)) - 2
392 digD = len(str(ymax)) - 2
391 ydec = ymax*(10**digD)
393 ydec = ymax*(10**digD)
392
394
393 dig = int(numpy.log10(ydec))
395 dig = int(numpy.log10(ydec))
394 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
396 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
395 ystep = ystep/5
397 ystep = ystep/5
396 ystep = ystep/(10**digD)
398 ystep = ystep/(10**digD)
397
399
398 else:
400 else:
399 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
401 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
400 ystep = ystep/5
402 ystep = ystep/5
401
403
402 if self.xaxis is not 'time':
404 if self.xaxis is not 'time':
403
405
404 dig = int(numpy.log10(xmax))
406 dig = int(numpy.log10(xmax))
405
407
406 if dig <= 0:
408 if dig <= 0:
407 digD = len(str(xmax)) - 2
409 digD = len(str(xmax)) - 2
408 xdec = xmax*(10**digD)
410 xdec = xmax*(10**digD)
409
411
410 dig = int(numpy.log10(xdec))
412 dig = int(numpy.log10(xdec))
411 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
413 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
412 xstep = xstep*0.5
414 xstep = xstep*0.5
413 xstep = xstep/(10**digD)
415 xstep = xstep/(10**digD)
414
416
415 else:
417 else:
416 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
418 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
417 xstep = xstep/5
419 xstep = xstep/5
418
420
419 ax.set_facecolor(self.bgcolor)
421 ax.set_facecolor(self.bgcolor)
420 ax.yaxis.set_major_locator(MultipleLocator(ystep))
422 ax.yaxis.set_major_locator(MultipleLocator(ystep))
421 if self.xscale:
423 if self.xscale:
422 ax.xaxis.set_major_formatter(FuncFormatter(
424 ax.xaxis.set_major_formatter(FuncFormatter(
423 lambda x, pos: '{0:g}'.format(x*self.xscale)))
425 lambda x, pos: '{0:g}'.format(x*self.xscale)))
424 if self.xscale:
426 if self.xscale:
425 ax.yaxis.set_major_formatter(FuncFormatter(
427 ax.yaxis.set_major_formatter(FuncFormatter(
426 lambda x, pos: '{0:g}'.format(x*self.yscale)))
428 lambda x, pos: '{0:g}'.format(x*self.yscale)))
427 if self.xaxis is 'time':
429 if self.xaxis is 'time':
428 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
430 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
429 ax.xaxis.set_major_locator(LinearLocator(9))
431 ax.xaxis.set_major_locator(LinearLocator(9))
430 else:
432 else:
431 ax.xaxis.set_major_locator(MultipleLocator(xstep))
433 ax.xaxis.set_major_locator(MultipleLocator(xstep))
432 if self.xlabel is not None:
434 if self.xlabel is not None:
433 ax.set_xlabel(self.xlabel)
435 ax.set_xlabel(self.xlabel)
434 ax.set_ylabel(self.ylabel)
436 ax.set_ylabel(self.ylabel)
435 ax.firsttime = False
437 ax.firsttime = False
436 if self.showprofile:
438 if self.showprofile:
437 self.pf_axes[n].set_ylim(ymin, ymax)
439 self.pf_axes[n].set_ylim(ymin, ymax)
438 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
440 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
439 self.pf_axes[n].set_xlabel('dB')
441 self.pf_axes[n].set_xlabel('dB')
440 self.pf_axes[n].grid(b=True, axis='x')
442 self.pf_axes[n].grid(b=True, axis='x')
441 [tick.set_visible(False)
443 [tick.set_visible(False)
442 for tick in self.pf_axes[n].get_yticklabels()]
444 for tick in self.pf_axes[n].get_yticklabels()]
443 if self.colorbar:
445 if self.colorbar:
444 ax.cbar = plt.colorbar(
446 ax.cbar = plt.colorbar(
445 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
447 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
446 ax.cbar.ax.tick_params(labelsize=8)
448 ax.cbar.ax.tick_params(labelsize=8)
447 ax.cbar.ax.press = None
449 ax.cbar.ax.press = None
448 if self.cb_label:
450 if self.cb_label:
449 ax.cbar.set_label(self.cb_label, size=8)
451 ax.cbar.set_label(self.cb_label, size=8)
450 elif self.cb_labels:
452 elif self.cb_labels:
451 ax.cbar.set_label(self.cb_labels[n], size=8)
453 ax.cbar.set_label(self.cb_labels[n], size=8)
452 else:
454 else:
453 ax.cbar = None
455 ax.cbar = None
454 if self.grid:
456 if self.grid:
455 ax.grid(True)
457 ax.grid(True)
456
458
457 if not self.polar:
459 if not self.polar:
458 ax.set_xlim(xmin, xmax)
460 ax.set_xlim(xmin, xmax)
459 ax.set_ylim(ymin, ymax)
461 ax.set_ylim(ymin, ymax)
460 ax.set_title('{} {} {}'.format(
462 ax.set_title('{} {} {}'.format(
461 self.titles[n],
463 self.titles[n],
462 self.getDateTime(self.data.max_time).strftime(
464 self.getDateTime(self.data.max_time).strftime(
463 '%Y-%m-%d %H:%M:%S'),
465 '%Y-%m-%d %H:%M:%S'),
464 self.time_label),
466 self.time_label),
465 size=8)
467 size=8)
466 else:
468 else:
467 ax.set_title('{}'.format(self.titles[n]), size=8)
469 ax.set_title('{}'.format(self.titles[n]), size=8)
468 ax.set_ylim(0, 90)
470 ax.set_ylim(0, 90)
469 ax.set_yticks(numpy.arange(0, 90, 20))
471 ax.set_yticks(numpy.arange(0, 90, 20))
470 ax.yaxis.labelpad = 40
472 ax.yaxis.labelpad = 40
471
473
472 if self.firsttime:
474 if self.firsttime:
473 for n, fig in enumerate(self.figures):
475 for n, fig in enumerate(self.figures):
474 fig.subplots_adjust(**self.plots_adjust)
476 fig.subplots_adjust(**self.plots_adjust)
475 self.firsttime = False
477 self.firsttime = False
476
478
477 def clear_figures(self):
479 def clear_figures(self):
478 '''
480 '''
479 Reset axes for redraw plots
481 Reset axes for redraw plots
480 '''
482 '''
481
483
482 for ax in self.axes+self.pf_axes+self.cb_axes:
484 for ax in self.axes+self.pf_axes+self.cb_axes:
483 ax.clear()
485 ax.clear()
484 ax.firsttime = True
486 ax.firsttime = True
485 if ax.cbar:
487 if ax.cbar:
486 ax.cbar.remove()
488 ax.cbar.remove()
487
489
488 def __plot(self):
490 def __plot(self):
489 '''
491 '''
490 Main function to plot, format and save figures
492 Main function to plot, format and save figures
491 '''
493 '''
492
494
493 self.plot()
495 self.plot()
494 self.format()
496 self.format()
495
497
496 for n, fig in enumerate(self.figures):
498 for n, fig in enumerate(self.figures):
497 if self.nrows == 0 or self.nplots == 0:
499 if self.nrows == 0 or self.nplots == 0:
498 log.warning('No data', self.name)
500 log.warning('No data', self.name)
499 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
501 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
500 fig.canvas.manager.set_window_title(self.CODE)
502 fig.canvas.manager.set_window_title(self.CODE)
501 continue
503 continue
502
504
503 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
505 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
504 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
506 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
505 fig.canvas.draw()
507 fig.canvas.draw()
506 if self.show:
508 if self.show:
507 fig.show()
509 fig.show()
508 figpause(0.01)
510 figpause(0.01)
509
511
510 if self.save:
512 if self.save:
511 self.save_figure(n)
513 self.save_figure(n)
512
514
513 if self.plot_server:
515 if self.plot_server:
514 self.send_to_server()
516 self.send_to_server()
515
517
516 def save_figure(self, n):
518 def save_figure(self, n):
517 '''
519 '''
518 '''
520 '''
519
521
520 if self.save_counter < self.save_period:
522 if self.save_counter < self.save_period:
521 self.save_counter += 1
523 self.save_counter += 1
522 return
524 return
523
525
524 self.save_counter = 1
526 self.save_counter = 1
525
527
526 fig = self.figures[n]
528 fig = self.figures[n]
527
529
528 if self.save_code:
530 if self.save_code:
529 if isinstance(self.save_code, str):
531 if isinstance(self.save_code, str):
530 labels = [self.save_code for x in self.figures]
532 labels = [self.save_code for x in self.figures]
531 else:
533 else:
532 labels = self.save_code
534 labels = self.save_code
533 else:
535 else:
534 labels = [self.CODE for x in self.figures]
536 labels = [self.CODE for x in self.figures]
535
537
536 figname = os.path.join(
538 figname = os.path.join(
537 self.save,
539 self.save,
538 labels[n],
540 labels[n],
539 '{}_{}.png'.format(
541 '{}_{}.png'.format(
540 labels[n],
542 labels[n],
541 self.getDateTime(self.data.max_time).strftime(
543 self.getDateTime(self.data.max_time).strftime(
542 '%Y%m%d_%H%M%S'
544 '%Y%m%d_%H%M%S'
543 ),
545 ),
544 )
546 )
545 )
547 )
546 log.log('Saving figure: {}'.format(figname), self.name)
548 log.log('Saving figure: {}'.format(figname), self.name)
547 if not os.path.isdir(os.path.dirname(figname)):
549 if not os.path.isdir(os.path.dirname(figname)):
548 os.makedirs(os.path.dirname(figname))
550 os.makedirs(os.path.dirname(figname))
549 fig.savefig(figname)
551 fig.savefig(figname)
550
552
551 if self.throttle == 0:
553 if self.throttle == 0:
552 figname = os.path.join(
554 figname = os.path.join(
553 self.save,
555 self.save,
554 '{}_{}.png'.format(
556 '{}_{}.png'.format(
555 labels[n],
557 labels[n],
556 self.getDateTime(self.data.min_time).strftime(
558 self.getDateTime(self.data.min_time).strftime(
557 '%Y%m%d'
559 '%Y%m%d'
558 ),
560 ),
559 )
561 )
560 )
562 )
561 fig.savefig(figname)
563 fig.savefig(figname)
562
564
563 def send_to_server(self):
565 def send_to_server(self):
564 '''
566 '''
565 '''
567 '''
566
568
567 if self.sender_counter < self.sender_period:
569 interval = self.data.tm - self.sender_time
568 self.sender_counter += 1
570 if interval < self.sender_period:
569 return
571 return
570
572
571 self.sender_counter = 1
573 self.sender_time = self.data.tm
572 self.data.meta['titles'] = self.titles
574
573 retries = 2
575 attrs = ['titles', 'zmin', 'zmax', 'colormap']
576 for attr in attrs:
577 value = getattr(self, attr)
578 if value is not None:
579 self.data.meta[attr] = getattr(self, attr)
580 self.data.meta['interval'] = int(interval)
581 msg = self.data.jsonify(self.plot_name, self.plot_type)
582 self.sender_queue.put(msg)
583
574 while True:
584 while True:
575 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
585 if self.sender_queue.empty():
586 break
587 self.socket.send_string(self.sender_queue.get())
576 socks = dict(self.poll.poll(5000))
588 socks = dict(self.poll.poll(5000))
577 if socks.get(self.socket) == zmq.POLLIN:
589 if socks.get(self.socket) == zmq.POLLIN:
578 reply = self.socket.recv_string()
590 reply = self.socket.recv_string()
579 if reply == 'ok':
591 if reply == 'ok':
580 log.log("Response from server ok", self.name)
592 log.log("Response from server ok", self.name)
581 break
593 time.sleep(0.1)
594 continue
582 else:
595 else:
583 log.warning(
596 log.warning(
584 "Malformed reply from server: {}".format(reply), self.name)
597 "Malformed reply from server: {}".format(reply), self.name)
585
586 else:
598 else:
587 log.warning(
599 log.warning(
588 "No response from server, retrying...", self.name)
600 "No response from server, retrying...", self.name)
601 self.sender_queue.put(msg)
589 self.socket.setsockopt(zmq.LINGER, 0)
602 self.socket.setsockopt(zmq.LINGER, 0)
590 self.socket.close()
603 self.socket.close()
591 self.poll.unregister(self.socket)
604 self.poll.unregister(self.socket)
592 retries -= 1
605 time.sleep(0.1)
593 if retries == 0:
594 log.error(
595 "Server seems to be offline, abandoning", self.name)
596 self.socket = self.context.socket(zmq.REQ)
597 self.socket.connect(self.plot_server)
598 self.poll.register(self.socket, zmq.POLLIN)
599 time.sleep(1)
600 break
601 self.socket = self.context.socket(zmq.REQ)
606 self.socket = self.context.socket(zmq.REQ)
602 self.socket.connect(self.plot_server)
607 self.socket.connect(self.plot_server)
603 self.poll.register(self.socket, zmq.POLLIN)
608 self.poll.register(self.socket, zmq.POLLIN)
604 time.sleep(0.5)
609 break
605
610
606 def setup(self):
611 def setup(self):
607 '''
612 '''
608 This method should be implemented in the child class, the following
613 This method should be implemented in the child class, the following
609 attributes should be set:
614 attributes should be set:
610
615
611 self.nrows: number of rows
616 self.nrows: number of rows
612 self.ncols: number of cols
617 self.ncols: number of cols
613 self.nplots: number of plots (channels or pairs)
618 self.nplots: number of plots (channels or pairs)
614 self.ylabel: label for Y axes
619 self.ylabel: label for Y axes
615 self.titles: list of axes title
620 self.titles: list of axes title
616
621
617 '''
622 '''
618 raise NotImplementedError
623 raise NotImplementedError
619
624
620 def plot(self):
625 def plot(self):
621 '''
626 '''
622 Must be defined in the child class
627 Must be defined in the child class
623 '''
628 '''
624 raise NotImplementedError
629 raise NotImplementedError
625
630
626 def run(self, dataOut, **kwargs):
631 def run(self, dataOut, **kwargs):
627 '''
632 '''
628 Main plotting routine
633 Main plotting routine
629 '''
634 '''
630
635
631 if self.isConfig is False:
636 if self.isConfig is False:
632 self.__setup(**kwargs)
637 self.__setup(**kwargs)
633
638
634 t = getattr(dataOut, self.attr_time)
639 t = getattr(dataOut, self.attr_time)
635
640
636 if dataOut.useLocalTime:
641 if dataOut.useLocalTime:
637 self.getDateTime = datetime.datetime.fromtimestamp
642 self.getDateTime = datetime.datetime.fromtimestamp
638 if not self.localtime:
643 if not self.localtime:
639 t += time.timezone
644 t += time.timezone
640 else:
645 else:
641 self.getDateTime = datetime.datetime.utcfromtimestamp
646 self.getDateTime = datetime.datetime.utcfromtimestamp
642 if self.localtime:
647 if self.localtime:
643 t -= time.timezone
648 t -= time.timezone
644
649
645 if 'buffer' in self.plot_type:
650 if 'buffer' in self.plot_type:
646 if self.xmin is None:
651 if self.xmin is None:
647 self.tmin = t
652 self.tmin = t
648 self.xmin = self.getDateTime(t).hour
653 self.xmin = self.getDateTime(t).hour
649 else:
654 else:
650 self.tmin = (
655 self.tmin = (
651 self.getDateTime(t).replace(
656 self.getDateTime(t).replace(
652 hour=int(self.xmin),
657 hour=int(self.xmin),
653 minute=0,
658 minute=0,
654 second=0) - self.getDateTime(0)).total_seconds()
659 second=0) - self.getDateTime(0)).total_seconds()
655
660
656 self.data.setup()
661 self.data.setup()
657 self.isConfig = True
662 self.isConfig = True
658 if self.plot_server:
663 if self.plot_server:
659 self.context = zmq.Context()
664 self.context = zmq.Context()
660 self.socket = self.context.socket(zmq.REQ)
665 self.socket = self.context.socket(zmq.REQ)
661 self.socket.connect(self.plot_server)
666 self.socket.connect(self.plot_server)
662 self.poll = zmq.Poller()
667 self.poll = zmq.Poller()
663 self.poll.register(self.socket, zmq.POLLIN)
668 self.poll.register(self.socket, zmq.POLLIN)
664
669
665 tm = getattr(dataOut, self.attr_time)
670 tm = getattr(dataOut, self.attr_time)
666
671
667 if not dataOut.useLocalTime and self.localtime:
672 if not dataOut.useLocalTime and self.localtime:
668 tm -= time.timezone
673 tm -= time.timezone
669 if dataOut.useLocalTime and not self.localtime:
674 if dataOut.useLocalTime and not self.localtime:
670 tm += time.timezone
675 tm += time.timezone
671
676
672 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
677 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
673 self.save_counter = self.save_period
678 self.save_counter = self.save_period
674 self.__plot()
679 self.__plot()
675 self.xmin += self.xrange
680 self.xmin += self.xrange
676 if self.xmin >= 24:
681 if self.xmin >= 24:
677 self.xmin -= 24
682 self.xmin -= 24
678 self.tmin += self.xrange*60*60
683 self.tmin += self.xrange*60*60
679 self.data.setup()
684 self.data.setup()
680 self.clear_figures()
685 self.clear_figures()
681
686
682 self.data.update(dataOut, tm)
687 self.data.update(dataOut, tm)
683
688
684 if self.isPlotConfig is False:
689 if self.isPlotConfig is False:
685 self.__setup_plot()
690 self.__setup_plot()
686 self.isPlotConfig = True
691 self.isPlotConfig = True
687
692
688 if self.throttle == 0:
693 if self.throttle == 0:
689 self.__plot()
694 self.__plot()
690 else:
695 else:
691 self.__throttle_plot(self.__plot)#, coerce=coerce)
696 self.__throttle_plot(self.__plot)#, coerce=coerce)
692
697
693 def close(self):
698 def close(self):
694
699
695 if self.data and not self.data.flagNoData:
700 if self.data and not self.data.flagNoData:
696 self.save_counter = self.save_period
701 self.save_counter = self.save_period
697 self.__plot()
702 self.__plot()
698 if self.data and not self.data.flagNoData and self.pause:
703 if self.data and not self.data.flagNoData and self.pause:
699 figpause(10)
704 figpause(10)
700
705
General Comments 0
You need to be logged in to leave comments. Login now