##// END OF EJS Templates
updated with changes in v3.0-devel
rflores -
r1737:23e53bebbd06
parent child
Show More

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

@@ -1,669 +1,677
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """API to create signal chain projects
5 """API to create signal chain projects
6
6
7 The API is provide through class: Project
7 The API is provide through class: Project
8 """
8 """
9
9
10 import re
10 import re
11 import sys
11 import sys
12 import ast
12 import ast
13 import datetime
13 import datetime
14 import traceback
14 import traceback
15 import time
15 import time
16 import multiprocessing
16 import multiprocessing
17 from multiprocessing import Process, Queue
17 from multiprocessing import Process, Queue
18 from threading import Thread
18 from threading import Thread
19 from xml.etree.ElementTree import ElementTree, Element, SubElement
19 from xml.etree.ElementTree import ElementTree, Element, SubElement
20
20
21 from schainpy.admin import Alarm, SchainWarning
21 from schainpy.admin import Alarm, SchainWarning
22 from schainpy.model import *
22 from schainpy.model import *
23 from schainpy.utils import log
23 from schainpy.utils import log
24
24
25 if 'darwin' in sys.platform and sys.version_info[0] == 3 and sys.version_info[1] > 7:
25 if 'darwin' in sys.platform and sys.version_info[0] == 3 and sys.version_info[1] > 7:
26 multiprocessing.set_start_method('fork')
26 multiprocessing.set_start_method('fork')
27
27
28 class ConfBase():
28 class ConfBase():
29
29
30 def __init__(self):
30 def __init__(self):
31
31
32 self.id = '0'
32 self.id = '0'
33 self.name = None
33 self.name = None
34 self.priority = None
34 self.priority = None
35 self.parameters = {}
35 self.parameters = {}
36 self.object = None
36 self.object = None
37 self.operations = []
37 self.operations = []
38
38
39 def getId(self):
39 def getId(self):
40
40
41 return self.id
41 return self.id
42
42
43 def getNewId(self):
43 def getNewId(self):
44
44
45 return int(self.id) * 10 + len(self.operations) + 1
45 return int(self.id) * 10 + len(self.operations) + 1
46
46
47 def updateId(self, new_id):
47 def updateId(self, new_id):
48
48
49 self.id = str(new_id)
49 self.id = str(new_id)
50
50
51 n = 1
51 n = 1
52 for conf in self.operations:
52 for conf in self.operations:
53 conf_id = str(int(new_id) * 10 + n)
53 conf_id = str(int(new_id) * 10 + n)
54 conf.updateId(conf_id)
54 conf.updateId(conf_id)
55 n += 1
55 n += 1
56
56
57 def getKwargs(self):
57 def getKwargs(self):
58
58
59 params = {}
59 params = {}
60
60
61 for key, value in self.parameters.items():
61 for key, value in self.parameters.items():
62 if value not in (None, '', ' '):
62 if value not in (None, '', ' '):
63 params[key] = value
63 params[key] = value
64
64
65 return params
65 return params
66
66
67 def update(self, **kwargs):
67 def update(self, **kwargs):
68
68
69 for key, value in kwargs.items():
69 for key, value in kwargs.items():
70 self.addParameter(name=key, value=value)
70 self.addParameter(name=key, value=value)
71
71
72 def addParameter(self, name, value, format=None):
72 def addParameter(self, name, value, format=None):
73 '''
73 '''
74 '''
74 '''
75
75
76 if isinstance(value, str) and re.search(r'(\d+/\d+/\d+)', value):
76 if format is not None:
77 self.parameters[name] = eval(format)(value)
78 elif isinstance(value, str) and re.search(r'(\d+/\d+/\d+)', value):
77 self.parameters[name] = datetime.date(*[int(x) for x in value.split('/')])
79 self.parameters[name] = datetime.date(*[int(x) for x in value.split('/')])
78 elif isinstance(value, str) and re.search(r'(\d+:\d+:\d+)', value):
80 elif isinstance(value, str) and re.search(r'(\d+:\d+:\d+)', value):
79 self.parameters[name] = datetime.time(*[int(x) for x in value.split(':')])
81 self.parameters[name] = datetime.time(*[int(x) for x in value.split(':')])
80 else:
82 else:
81 try:
83 try:
82 self.parameters[name] = ast.literal_eval(value)
84 self.parameters[name] = ast.literal_eval(value)
83 except:
85 except:
84 if isinstance(value, str) and ',' in value:
86 if isinstance(value, str) and ',' in value:
85 self.parameters[name] = value.split(',')
87 self.parameters[name] = value.split(',')
86 else:
88 else:
87 self.parameters[name] = value
89 self.parameters[name] = value
88
90
89 def getParameters(self):
91 def getParameters(self):
90
92
91 params = {}
93 params = {}
92 for key, value in self.parameters.items():
94 for key, value in self.parameters.items():
93 s = type(value).__name__
95 s = type(value).__name__
94 if s == 'date':
96 if s == 'date':
95 params[key] = value.strftime('%Y/%m/%d')
97 params[key] = value.strftime('%Y/%m/%d')
96 elif s == 'time':
98 elif s == 'time':
97 params[key] = value.strftime('%H:%M:%S')
99 params[key] = value.strftime('%H:%M:%S')
98 else:
100 else:
99 params[key] = str(value)
101 params[key] = str(value)
100
102
101 return params
103 return params
102
104
103 def makeXml(self, element):
105 def makeXml(self, element):
104
106
105 xml = SubElement(element, self.ELEMENTNAME)
107 xml = SubElement(element, self.ELEMENTNAME)
106 for label in self.xml_labels:
108 for label in self.xml_labels:
107 xml.set(label, str(getattr(self, label)))
109 xml.set(label, str(getattr(self, label)))
108
110
109 for key, value in self.getParameters().items():
111 for key, value in self.getParameters().items():
110 xml_param = SubElement(xml, 'Parameter')
112 xml_param = SubElement(xml, 'Parameter')
111 xml_param.set('name', key)
113 xml_param.set('name', key)
112 xml_param.set('value', value)
114 xml_param.set('value', value)
113
115
114 for conf in self.operations:
116 for conf in self.operations:
115 conf.makeXml(xml)
117 conf.makeXml(xml)
116
118
117 def __str__(self):
119 def __str__(self):
118
120
119 if self.ELEMENTNAME == 'Operation':
121 if self.ELEMENTNAME == 'Operation':
120 s = ' {}[id={}]\n'.format(self.name, self.id)
122 s = ' {}[id={}]\n'.format(self.name, self.id)
121 else:
123 else:
122 s = '{}[id={}, inputId={}]\n'.format(self.name, self.id, self.inputId)
124 s = '{}[id={}, inputId={}]\n'.format(self.name, self.id, self.inputId)
123
125
124 for key, value in self.parameters.items():
126 for key, value in self.parameters.items():
125 if self.ELEMENTNAME == 'Operation':
127 if self.ELEMENTNAME == 'Operation':
126 s += ' {}: {}\n'.format(key, value)
128 s += ' {}: {}\n'.format(key, value)
127 else:
129 else:
128 s += ' {}: {}\n'.format(key, value)
130 s += ' {}: {}\n'.format(key, value)
129
131
130 for conf in self.operations:
132 for conf in self.operations:
131 s += str(conf)
133 s += str(conf)
132
134
133 return s
135 return s
134
136
135 class OperationConf(ConfBase):
137 class OperationConf(ConfBase):
136
138
137 ELEMENTNAME = 'Operation'
139 ELEMENTNAME = 'Operation'
138 xml_labels = ['id', 'name']
140 xml_labels = ['id', 'name']
139
141
140 def setup(self, id, name, priority, project_id, err_queue):
142 def setup(self, id, name, priority, project_id, err_queue):
141
143
142 self.id = str(id)
144 self.id = str(id)
143 self.project_id = project_id
145 self.project_id = project_id
144 self.name = name
146 self.name = name
145 self.type = 'other'
147 self.type = 'other'
146 self.err_queue = err_queue
148 self.err_queue = err_queue
147
149
148 def readXml(self, element, project_id, err_queue):
150 def readXml(self, element, project_id, err_queue):
149
151
150 self.id = element.get('id')
152 self.id = element.get('id')
151 self.name = element.get('name')
153 self.name = element.get('name')
152 self.type = 'other'
154 self.type = 'other'
153 self.project_id = str(project_id)
155 self.project_id = str(project_id)
154 self.err_queue = err_queue
156 self.err_queue = err_queue
155
157
156 for elm in element.iter('Parameter'):
158 for elm in element.iter('Parameter'):
157 self.addParameter(elm.get('name'), elm.get('value'))
159 self.addParameter(elm.get('name'), elm.get('value'))
158
160
159 def createObject(self):
161 def createObject(self):
160
162
161 className = eval(self.name)
163 className = eval(self.name)
162
164
163 if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name or 'print' in self.name:
165 if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name or 'print' in self.name:
164 kwargs = self.getKwargs()
166 kwargs = self.getKwargs()
165 opObj = className(self.id, self.id, self.project_id, self.err_queue, **kwargs)
167 opObj = className(self.id, self.id, self.project_id, self.err_queue, **kwargs)
166 opObj.start()
168 opObj.start()
167 self.type = 'external'
169 self.type = 'external'
168 else:
170 else:
169 opObj = className()
171 opObj = className()
170
172
171 self.object = opObj
173 self.object = opObj
172 return opObj
174 return opObj
173
175
174 class ProcUnitConf(ConfBase):
176 class ProcUnitConf(ConfBase):
175
177
176 ELEMENTNAME = 'ProcUnit'
178 ELEMENTNAME = 'ProcUnit'
177 xml_labels = ['id', 'inputId', 'name']
179 xml_labels = ['id', 'inputId', 'name']
178
180
179 def setup(self, project_id, id, name, datatype, inputId, err_queue):
181 def setup(self, project_id, id, name, datatype, inputId, err_queue):
180 '''
182 '''
181 '''
183 '''
182
184
183 if datatype == None and name == None:
185 if datatype == None and name == None:
184 raise ValueError('datatype or name should be defined')
186 raise ValueError('datatype or name should be defined')
185
187
186 if name == None:
188 if name == None:
187 if 'Proc' in datatype:
189 if 'Proc' in datatype:
188 name = datatype
190 name = datatype
189 else:
191 else:
190 name = '%sProc' % (datatype)
192 name = '%sProc' % (datatype)
191
193
192 if datatype == None:
194 if datatype == None:
193 datatype = name.replace('Proc', '')
195 datatype = name.replace('Proc', '')
194
196
195 self.id = str(id)
197 self.id = str(id)
196 self.project_id = project_id
198 self.project_id = project_id
197 self.name = name
199 self.name = name
198 self.datatype = datatype
200 self.datatype = datatype
199 self.inputId = inputId
201 self.inputId = inputId
200 self.err_queue = err_queue
202 self.err_queue = err_queue
201 self.operations = []
203 self.operations = []
202 self.parameters = {}
204 self.parameters = {}
203
205
204 def removeOperation(self, id):
206 def removeOperation(self, id):
205
207
206 i = [1 if x.id == id else 0 for x in self.operations]
208 i = [1 if x.id == id else 0 for x in self.operations]
207 self.operations.pop(i.index(1))
209 self.operations.pop(i.index(1))
208
210
209 def getOperation(self, id):
211 def getOperation(self, id):
210
212
211 for conf in self.operations:
213 for conf in self.operations:
212 if conf.id == id:
214 if conf.id == id:
213 return conf
215 return conf
214
216
215 def addOperation(self, name, optype='self'):
217 def addOperation(self, name, optype='self'):
216 '''
218 '''
217 '''
219 '''
218
220
219 id = self.getNewId()
221 id = self.getNewId()
220 conf = OperationConf()
222 conf = OperationConf()
221 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
223 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
222 self.operations.append(conf)
224 self.operations.append(conf)
223
225
224 return conf
226 return conf
225
227
226 def readXml(self, element, project_id, err_queue):
228 def readXml(self, element, project_id, err_queue):
227
229
228 self.id = element.get('id')
230 self.id = element.get('id')
229 self.name = element.get('name')
231 self.name = element.get('name')
230 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
232 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
231 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
233 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
232 self.project_id = str(project_id)
234 self.project_id = str(project_id)
233 self.err_queue = err_queue
235 self.err_queue = err_queue
234 self.operations = []
236 self.operations = []
235 self.parameters = {}
237 self.parameters = {}
236
238
237 for elm in element:
239 for elm in element:
238 if elm.tag == 'Parameter':
240 if elm.tag == 'Parameter':
239 self.addParameter(elm.get('name'), elm.get('value'))
241 self.addParameter(elm.get('name'), elm.get('value'))
240 elif elm.tag == 'Operation':
242 elif elm.tag == 'Operation':
241 conf = OperationConf()
243 conf = OperationConf()
242 conf.readXml(elm, project_id, err_queue)
244 conf.readXml(elm, project_id, err_queue)
243 self.operations.append(conf)
245 self.operations.append(conf)
244
246
245 def createObjects(self):
247 def createObjects(self):
246 '''
248 '''
247 Instancia de unidades de procesamiento.
249 Instancia de unidades de procesamiento.
248 '''
250 '''
249
251
250 className = eval(self.name)
252 className = eval(self.name)
251 kwargs = self.getKwargs()
253 kwargs = self.getKwargs()
252 procUnitObj = className()
254 procUnitObj = className()
253 procUnitObj.name = self.name
255 procUnitObj.name = self.name
254 log.success('creating process...', self.name)
256 log.success('creating process...', self.name)
255
257
256 for conf in self.operations:
258 for conf in self.operations:
257
259
258 opObj = conf.createObject()
260 opObj = conf.createObject()
259
261
260 log.success('adding operation: {}, type:{}'.format(
262 log.success('adding operation: {}, type:{}'.format(
261 conf.name,
263 conf.name,
262 conf.type), self.name)
264 conf.type), self.name)
263
265
264 procUnitObj.addOperation(conf, opObj)
266 procUnitObj.addOperation(conf, opObj)
265
267
266 self.object = procUnitObj
268 self.object = procUnitObj
267
269
268 def run(self):
270 def run(self):
269 '''
271 '''
270 '''
272 '''
271 #self.object.call(**self.getKwargs())
273 #self.object.call(**self.getKwargs())
272
274
273 return self.object.call(**self.getKwargs())
275 return self.object.call(**self.getKwargs())
274
276
275
277
276 class ReadUnitConf(ProcUnitConf):
278 class ReadUnitConf(ProcUnitConf):
277
279
278 ELEMENTNAME = 'ReadUnit'
280 ELEMENTNAME = 'ReadUnit'
279
281
280 def __init__(self):
282 def __init__(self):
281
283
282 self.id = None
284 self.id = None
283 self.datatype = None
285 self.datatype = None
284 self.name = None
286 self.name = None
285 self.inputId = None
287 self.inputId = None
286 self.operations = []
288 self.operations = []
287 self.parameters = {}
289 self.parameters = {}
288
290
289 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
291 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
290 startTime='', endTime='', server=None, **kwargs):
292 startTime='', endTime='', server=None, topic='', **kwargs):
291
293
292 if datatype == None and name == None:
294 if datatype == None and name == None:
293 raise ValueError('datatype or name should be defined')
295 raise ValueError('datatype or name should be defined')
294 if name == None:
296 if name == None:
295 if 'Reader' in datatype:
297 if 'Reader' in datatype:
296 name = datatype
298 name = datatype
297 datatype = name.replace('Reader', '')
299 datatype = name.replace('Reader', '')
298 else:
300 else:
299 name = '{}Reader'.format(datatype)
301 name = '{}Reader'.format(datatype)
300 if datatype == None:
302 if datatype == None:
301 if 'Reader' in name:
303 if 'Reader' in name:
302 datatype = name.replace('Reader', '')
304 datatype = name.replace('Reader', '')
303 else:
305 else:
304 datatype = name
306 datatype = name
305 name = '{}Reader'.format(name)
307 name = '{}Reader'.format(name)
306
308
307 self.id = id
309 self.id = id
308 self.project_id = project_id
310 self.project_id = project_id
309 self.name = name
311 self.name = name
310 self.datatype = datatype
312 self.datatype = datatype
311 self.err_queue = err_queue
313 self.err_queue = err_queue
312
314
313 self.addParameter(name='path', value=path)
315 self.addParameter(name='path', value=path)
314 self.addParameter(name='startDate', value=startDate)
316 self.addParameter(name='startDate', value=startDate)
315 self.addParameter(name='endDate', value=endDate)
317 self.addParameter(name='endDate', value=endDate)
316 self.addParameter(name='startTime', value=startTime)
318 self.addParameter(name='startTime', value=startTime)
317 self.addParameter(name='endTime', value=endTime)
319 self.addParameter(name='endTime', value=endTime)
320 self.addParameter(name='server', value=server)
321 self.addParameter(name='topic', value=topic)
318
322
319 for key, value in kwargs.items():
323 for key, value in kwargs.items():
320 self.addParameter(name=key, value=value)
324 self.addParameter(name=key, value=value)
321
325
322
326
323 class Project(Process):
327 class Project(Process):
324 """API to create signal chain projects"""
328 """API to create signal chain projects"""
325
329
326 ELEMENTNAME = 'Project'
330 ELEMENTNAME = 'Project'
327
331
328 def __init__(self, name=''):
332 def __init__(self, name=''):
329
333
330 Process.__init__(self)
334 Process.__init__(self)
331 self.id = '1'
335 self.id = '1'
332 if name:
336 if name:
333 self.name = '{} ({})'.format(Process.__name__, name)
337 self.name = '{} ({})'.format(Process.__name__, name)
334 self.filename = None
338 self.filename = None
335 self.description = None
339 self.description = None
336 self.email = None
340 self.email = None
337 self.alarm = []
341 self.alarm = []
338 self.configurations = {}
342 self.configurations = {}
339 # self.err_queue = Queue()
343 # self.err_queue = Queue()
340 self.err_queue = None
344 self.err_queue = None
341 self.started = False
345 self.started = False
342
346
343 def getNewId(self):
347 def getNewId(self):
344
348
345 idList = list(self.configurations.keys())
349 idList = list(self.configurations.keys())
346 id = int(self.id) * 10
350 id = int(self.id) * 10
347
351
348 while True:
352 while True:
349 id += 1
353 id += 1
350
354
351 if str(id) in idList:
355 if str(id) in idList:
352 continue
356 continue
353
357
354 break
358 break
355
359
356 return str(id)
360 return str(id)
357
361
358 def updateId(self, new_id):
362 def updateId(self, new_id):
359
363
360 self.id = str(new_id)
364 self.id = str(new_id)
361
365
362 keyList = list(self.configurations.keys())
366 keyList = list(self.configurations.keys())
363 keyList.sort()
367 keyList.sort()
364
368
365 n = 1
369 n = 1
366 new_confs = {}
370 new_confs = {}
367
371
368 for procKey in keyList:
372 for procKey in keyList:
369
373
370 conf = self.configurations[procKey]
374 conf = self.configurations[procKey]
371 idProcUnit = str(int(self.id) * 10 + n)
375 idProcUnit = str(int(self.id) * 10 + n)
372 conf.updateId(idProcUnit)
376 conf.updateId(idProcUnit)
373 new_confs[idProcUnit] = conf
377 new_confs[idProcUnit] = conf
374 n += 1
378 n += 1
375
379
376 self.configurations = new_confs
380 self.configurations = new_confs
377
381
378 def setup(self, id=1, name='', description='', email=None, alarm=[]):
382 def setup(self, id=1, name='', description='', email=None, alarm=[]):
379
383
380 self.id = str(id)
384 self.id = str(id)
381 self.description = description
385 self.description = description
382 self.email = email
386 self.email = email
383 self.alarm = alarm
387 self.alarm = alarm
384 if name:
388 if name:
385 self.name = '{} ({})'.format(Process.__name__, name)
389 self.name = '{} ({})'.format(Process.__name__, name)
386
390
387 def update(self, **kwargs):
391 def update(self, **kwargs):
388
392
389 for key, value in kwargs.items():
393 for key, value in kwargs.items():
390 setattr(self, key, value)
394 setattr(self, key, value)
391
395
392 def clone(self):
396 def clone(self):
393
397
394 p = Project()
398 p = Project()
395 p.id = self.id
399 p.id = self.id
396 p.name = self.name
400 p.name = self.name
397 p.description = self.description
401 p.description = self.description
398 p.configurations = self.configurations.copy()
402 p.configurations = self.configurations.copy()
399
403
400 return p
404 return p
401
405
402 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
406 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
403
407
404 '''
408 '''
405 '''
409 '''
406
410
407 if id is None:
411 if id is None:
408 idReadUnit = self.getNewId()
412 idReadUnit = self.getNewId()
409 else:
413 else:
410 idReadUnit = str(id)
414 idReadUnit = str(id)
411
415
412 conf = ReadUnitConf()
416 conf = ReadUnitConf()
413 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
417 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
414 self.configurations[conf.id] = conf
418 self.configurations[conf.id] = conf
415
419
416 return conf
420 return conf
417
421
418 def addProcUnit(self, id=None, inputId='0', datatype=None, name=None):
422 def addProcUnit(self, id=None, inputId='0', datatype=None, name=None):
419
423
420 '''
424 '''
421 '''
425 '''
422
426
423 if id is None:
427 if id is None:
424 idProcUnit = self.getNewId()
428 idProcUnit = self.getNewId()
425 else:
429 else:
426 idProcUnit = id
430 idProcUnit = id
427
431
428 conf = ProcUnitConf()
432 conf = ProcUnitConf()
429 conf.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue)
433 conf.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue)
430 self.configurations[conf.id] = conf
434 self.configurations[conf.id] = conf
431
435
432 return conf
436 return conf
433
437
434 def removeProcUnit(self, id):
438 def removeProcUnit(self, id):
435
439
436 if id in self.configurations:
440 if id in self.configurations:
437 self.configurations.pop(id)
441 self.configurations.pop(id)
438
442
439 def getReadUnit(self):
443 def getReadUnit(self):
440
444
441 for obj in list(self.configurations.values()):
445 for obj in list(self.configurations.values()):
442 if obj.ELEMENTNAME == 'ReadUnit':
446 if obj.ELEMENTNAME == 'ReadUnit':
443 return obj
447 return obj
444
448
445 return None
449 return None
446
450
447 def getProcUnit(self, id):
451 def getProcUnit(self, id):
448
452
449 return self.configurations[id]
453 return self.configurations[id]
450
454
451 def getUnits(self):
455 def getUnits(self):
452
456
453 keys = list(self.configurations)
457 keys = list(self.configurations)
454 keys.sort()
458 keys.sort()
455
459
456 for key in keys:
460 for key in keys:
457 yield self.configurations[key]
461 yield self.configurations[key]
458
462
459 def updateUnit(self, id, **kwargs):
463 def updateUnit(self, id, **kwargs):
460
464
461 conf = self.configurations[id].update(**kwargs)
465 conf = self.configurations[id].update(**kwargs)
462
466
463 def makeXml(self):
467 def makeXml(self):
464
468
465 xml = Element('Project')
469 xml = Element('Project')
466 xml.set('id', str(self.id))
470 xml.set('id', str(self.id))
467 xml.set('name', self.name)
471 xml.set('name', self.name)
468 xml.set('description', self.description)
472 xml.set('description', self.description)
469
473
470 for conf in self.configurations.values():
474 for conf in self.configurations.values():
471 conf.makeXml(xml)
475 conf.makeXml(xml)
472
476
473 self.xml = xml
477 self.xml = xml
474
478
475 def writeXml(self, filename=None):
479 def writeXml(self, filename=None):
476
480
477 if filename == None:
481 if filename == None:
478 if self.filename:
482 if self.filename:
479 filename = self.filename
483 filename = self.filename
480 else:
484 else:
481 filename = 'schain.xml'
485 filename = 'schain.xml'
482
486
483 if not filename:
487 if not filename:
484 print('filename has not been defined. Use setFilename(filename) for do it.')
488 print('filename has not been defined. Use setFilename(filename) for do it.')
485 return 0
489 return 0
486
490
487 abs_file = os.path.abspath(filename)
491 abs_file = os.path.abspath(filename)
488
492
489 if not os.access(os.path.dirname(abs_file), os.W_OK):
493 if not os.access(os.path.dirname(abs_file), os.W_OK):
490 print('No write permission on %s' % os.path.dirname(abs_file))
494 print('No write permission on %s' % os.path.dirname(abs_file))
491 return 0
495 return 0
492
496
493 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
497 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
494 print('File %s already exists and it could not be overwriten' % abs_file)
498 print('File %s already exists and it could not be overwriten' % abs_file)
495 return 0
499 return 0
496
500
497 self.makeXml()
501 self.makeXml()
498
502
499 ElementTree(self.xml).write(abs_file, method='xml')
503 ElementTree(self.xml).write(abs_file, method='xml')
500
504
501 self.filename = abs_file
505 self.filename = abs_file
502
506
503 return 1
507 return 1
504
508
505 def readXml(self, filename):
509 def readXml(self, filename):
506
510
507 abs_file = os.path.abspath(filename)
511 abs_file = os.path.abspath(filename)
508
512
509 self.configurations = {}
513 self.configurations = {}
510
514
511 try:
515 try:
512 self.xml = ElementTree().parse(abs_file)
516 self.xml = ElementTree().parse(abs_file)
513 except:
517 except:
514 log.error('Error reading %s, verify file format' % filename)
518 log.error('Error reading %s, verify file format' % filename)
515 return 0
519 return 0
516
520
517 self.id = self.xml.get('id')
521 self.id = self.xml.get('id')
518 self.name = self.xml.get('name')
522 self.name = self.xml.get('name')
519 self.description = self.xml.get('description')
523 self.description = self.xml.get('description')
520
524
521 for element in self.xml:
525 for element in self.xml:
522 if element.tag == 'ReadUnit':
526 if element.tag == 'ReadUnit':
523 conf = ReadUnitConf()
527 conf = ReadUnitConf()
524 conf.readXml(element, self.id, self.err_queue)
528 conf.readXml(element, self.id, self.err_queue)
525 self.configurations[conf.id] = conf
529 self.configurations[conf.id] = conf
526 elif element.tag == 'ProcUnit':
530 elif element.tag == 'ProcUnit':
527 conf = ProcUnitConf()
531 conf = ProcUnitConf()
528 input_proc = self.configurations[element.get('inputId')]
532 input_proc = self.configurations[element.get('inputId')]
529 conf.readXml(element, self.id, self.err_queue)
533 conf.readXml(element, self.id, self.err_queue)
530 self.configurations[conf.id] = conf
534 self.configurations[conf.id] = conf
531
535
532 self.filename = abs_file
536 self.filename = abs_file
533
537
534 return 1
538 return 1
535
539
536 def __str__(self):
540 def __str__(self):
537
541
538 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
542 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
539 self.id,
543 self.id,
540 self.name,
544 self.name,
541 self.description,
545 self.description,
542 )
546 )
543
547
544 for conf in self.configurations.values():
548 for conf in self.configurations.values():
545 text += '{}'.format(conf)
549 text += '{}'.format(conf)
546
550
547 return text
551 return text
548
552
549 def createObjects(self):
553 def createObjects(self):
550
554
551 keys = list(self.configurations.keys())
555 keys = list(self.configurations.keys())
552 keys.sort()
556 keys.sort()
553 for key in keys:
557 for key in keys:
554 conf = self.configurations[key]
558 conf = self.configurations[key]
555 conf.createObjects()
559 conf.createObjects()
560 if 'Reader' in str(conf):
561 reader = conf.object
562 else:
563 conf.object.reader = reader
556 if conf.inputId is not None:
564 if conf.inputId is not None:
557 if isinstance(conf.inputId, list):
565 if isinstance(conf.inputId, list):
558 conf.object.setInput([self.configurations[x].object for x in conf.inputId])
566 conf.object.setInput([self.configurations[x].object for x in conf.inputId])
559 else:
567 else:
560 conf.object.setInput([self.configurations[conf.inputId].object])
568 conf.object.setInput([self.configurations[conf.inputId].object])
561
569
562 def monitor(self):
570 def monitor(self):
563
571
564 t = Thread(target=self._monitor, args=(self.err_queue, self.ctx))
572 t = Thread(target=self._monitor, args=(self.err_queue, self.ctx))
565 t.start()
573 t.start()
566
574
567 def _monitor(self, queue, ctx):
575 def _monitor(self, queue, ctx):
568
576
569 import socket
577 import socket
570
578
571 procs = 0
579 procs = 0
572 err_msg = ''
580 err_msg = ''
573
581
574 while True:
582 while True:
575 msg = queue.get()
583 msg = queue.get()
576 if '#_start_#' in msg:
584 if '#_start_#' in msg:
577 procs += 1
585 procs += 1
578 elif '#_end_#' in msg:
586 elif '#_end_#' in msg:
579 procs -= 1
587 procs -= 1
580 else:
588 else:
581 err_msg = msg
589 err_msg = msg
582
590
583 if procs == 0 or 'Traceback' in err_msg:
591 if procs == 0 or 'Traceback' in err_msg:
584 break
592 break
585 time.sleep(0.1)
593 time.sleep(0.1)
586
594
587 if '|' in err_msg:
595 if '|' in err_msg:
588 name, err = err_msg.split('|')
596 name, err = err_msg.split('|')
589 if 'SchainWarning' in err:
597 if 'SchainWarning' in err:
590 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
598 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
591 elif 'SchainError' in err:
599 elif 'SchainError' in err:
592 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
600 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
593 else:
601 else:
594 log.error(err, name)
602 log.error(err, name)
595 else:
603 else:
596 name, err = self.name, err_msg
604 name, err = self.name, err_msg
597
605
598 time.sleep(1)
606 time.sleep(1)
599
607
600 ctx.term()
608 ctx.term()
601
609
602 message = ''.join(err)
610 message = ''.join(err)
603
611
604 if err_msg:
612 if err_msg:
605 subject = 'SChain v%s: Error running %s\n' % (
613 subject = 'SChain v%s: Error running %s\n' % (
606 schainpy.__version__, self.name)
614 schainpy.__version__, self.name)
607
615
608 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
616 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
609 socket.gethostname())
617 socket.gethostname())
610 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
618 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
611 subtitle += 'Configuration file: %s\n' % self.filename
619 subtitle += 'Configuration file: %s\n' % self.filename
612 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
620 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
613
621
614 readUnitConfObj = self.getReadUnit()
622 readUnitConfObj = self.getReadUnit()
615 if readUnitConfObj:
623 if readUnitConfObj:
616 subtitle += '\nInput parameters:\n'
624 subtitle += '\nInput parameters:\n'
617 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
625 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
618 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
626 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
619 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
627 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
620 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
628 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
621 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
629 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
622
630
623 a = Alarm(
631 a = Alarm(
624 modes=self.alarm,
632 modes=self.alarm,
625 email=self.email,
633 email=self.email,
626 message=message,
634 message=message,
627 subject=subject,
635 subject=subject,
628 subtitle=subtitle,
636 subtitle=subtitle,
629 filename=self.filename
637 filename=self.filename
630 )
638 )
631
639
632 a.start()
640 a.start()
633
641
634 def setFilename(self, filename):
642 def setFilename(self, filename):
635
643
636 self.filename = filename
644 self.filename = filename
637
645
638 def runProcs(self):
646 def runProcs(self):
639
647
640 err = False
648 err = False
641 n = len(self.configurations)
649 n = len(self.configurations)
642 #print(n)
650 #print(n)
643
651
644 while not err:
652 while not err:
645 #print(self.getUnits())
653 #print(self.getUnits())
646 for conf in self.getUnits():
654 for conf in self.getUnits():
647 #print(conf)
655 #print(conf)
648 ok = conf.run()
656 ok = conf.run()
649 #print("ok", ok)
657 #print("ok", ok)
650 if ok == 'Error':
658 if ok == 'Error':
651 n -= 1
659 n -= 1
652 continue
660 continue
653 elif not ok:
661 elif not ok:
654 break
662 break
655 #print("****************************************************end")
663 #print("****************************************************end")
656 #exit(1)
664 #exit(1)
657 if n == 0:
665 if n == 0:
658 err = True
666 err = True
659
667
660 def run(self):
668 def run(self):
661
669
662 log.success('\nStarting Project {} [id={}]'.format(self.name, self.id), tag='')
670 log.success('\nStarting Project {} [id={}]'.format(self.name, self.id), tag='')
663 self.started = True
671 self.started = True
664 self.start_time = time.time()
672 self.start_time = time.time()
665 self.createObjects()
673 self.createObjects()
666 self.runProcs()
674 self.runProcs()
667 log.success('{} Done (Time: {:4.2f}s)'.format(
675 log.success('{} Done (Time: {:4.2f}s)'.format(
668 self.name,
676 self.name,
669 time.time() - self.start_time), '')
677 time.time() - self.start_time), '')
@@ -1,1082 +1,1093
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Definition of diferent Data objects for different types of data
5 """Definition of diferent Data objects for different types of data
6
6
7 Here you will find the diferent data objects for the different types
7 Here you will find the diferent data objects for the different types
8 of data, this data objects must be used as dataIn or dataOut objects in
8 of data, this data objects must be used as dataIn or dataOut objects in
9 processing units and operations. Currently the supported data objects are:
9 processing units and operations. Currently the supported data objects are:
10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
11 """
11 """
12
12
13 import copy
13 import copy
14 import numpy
14 import numpy
15 import datetime
15 import datetime
16 import json
16 import json
17
17
18 import schainpy.admin
18 import schainpy.admin
19 from schainpy.utils import log
19 from schainpy.utils import log
20 from .jroheaderIO import SystemHeader, RadarControllerHeader
20 from .jroheaderIO import SystemHeader, RadarControllerHeader
21 from schainpy.model.data import _noise
21 from schainpy.model.data import _noise
22
22
23
23
24 def getNumpyDtype(dataTypeCode):
24 def getNumpyDtype(dataTypeCode):
25
25
26 if dataTypeCode == 0:
26 if dataTypeCode == 0:
27 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
27 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
28 elif dataTypeCode == 1:
28 elif dataTypeCode == 1:
29 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
29 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
30 elif dataTypeCode == 2:
30 elif dataTypeCode == 2:
31 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
31 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
32 elif dataTypeCode == 3:
32 elif dataTypeCode == 3:
33 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
33 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
34 elif dataTypeCode == 4:
34 elif dataTypeCode == 4:
35 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
35 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
36 elif dataTypeCode == 5:
36 elif dataTypeCode == 5:
37 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
37 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
38 else:
38 else:
39 raise ValueError('dataTypeCode was not defined')
39 raise ValueError('dataTypeCode was not defined')
40
40
41 return numpyDtype
41 return numpyDtype
42
42
43
43
44 def getDataTypeCode(numpyDtype):
44 def getDataTypeCode(numpyDtype):
45
45
46 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
46 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
47 datatype = 0
47 datatype = 0
48 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
48 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
49 datatype = 1
49 datatype = 1
50 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
50 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
51 datatype = 2
51 datatype = 2
52 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
52 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
53 datatype = 3
53 datatype = 3
54 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
54 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
55 datatype = 4
55 datatype = 4
56 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
56 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
57 datatype = 5
57 datatype = 5
58 else:
58 else:
59 datatype = None
59 datatype = None
60
60
61 return datatype
61 return datatype
62
62
63
63
64 def hildebrand_sekhon(data, navg):
64 def hildebrand_sekhon(data, navg):
65 """
65 """
66 This method is for the objective determination of the noise level in Doppler spectra. This
66 This method is for the objective determination of the noise level in Doppler spectra. This
67 implementation technique is based on the fact that the standard deviation of the spectral
67 implementation technique is based on the fact that the standard deviation of the spectral
68 densities is equal to the mean spectral density for white Gaussian noise
68 densities is equal to the mean spectral density for white Gaussian noise
69
69
70 Inputs:
70 Inputs:
71 Data : heights
71 Data : heights
72 navg : numbers of averages
72 navg : numbers of averages
73
73
74 Return:
74 Return:
75 mean : noise's level
75 mean : noise's level
76 """
76 """
77
77
78 sortdata = numpy.sort(data, axis=None)
78 sortdata = numpy.sort(data, axis=None)
79 #print(numpy.shape(data))
79 #print(numpy.shape(data))
80 #exit()
80 #exit()
81 '''
81 '''
82 lenOfData = len(sortdata)
82 lenOfData = len(sortdata)
83 nums_min = lenOfData*0.2
83 nums_min = lenOfData*0.2
84
84
85 if nums_min <= 5:
85 if nums_min <= 5:
86
86
87 nums_min = 5
87 nums_min = 5
88
88
89 sump = 0.
89 sump = 0.
90 sumq = 0.
90 sumq = 0.
91
91
92 j = 0
92 j = 0
93 cont = 1
93 cont = 1
94
94
95 while((cont == 1)and(j < lenOfData)):
95 while((cont == 1)and(j < lenOfData)):
96
96
97 sump += sortdata[j]
97 sump += sortdata[j]
98 sumq += sortdata[j]**2
98 sumq += sortdata[j]**2
99
99
100 if j > nums_min:
100 if j > nums_min:
101 rtest = float(j)/(j-1) + 1.0/navg
101 rtest = float(j)/(j-1) + 1.0/navg
102 if ((sumq*j) > (rtest*sump**2)):
102 if ((sumq*j) > (rtest*sump**2)):
103 j = j - 1
103 j = j - 1
104 sump = sump - sortdata[j]
104 sump = sump - sortdata[j]
105 sumq = sumq - sortdata[j]**2
105 sumq = sumq - sortdata[j]**2
106 cont = 0
106 cont = 0
107
107
108 j += 1
108 j += 1
109
109
110 lnoise = sump / j
110 lnoise = sump / j
111
111
112 return lnoise
112 return lnoise
113 '''
113 '''
114 return _noise.hildebrand_sekhon(sortdata, navg)
114 return _noise.hildebrand_sekhon(sortdata, navg)
115
115
116
116
117 class Beam:
117 class Beam:
118
118
119 def __init__(self):
119 def __init__(self):
120 self.codeList = []
120 self.codeList = []
121 self.azimuthList = []
121 self.azimuthList = []
122 self.zenithList = []
122 self.zenithList = []
123
123
124
124
125 class GenericData(object):
125 class GenericData(object):
126
126
127 flagNoData = True
127 flagNoData = True
128 blockReader = False
128
129
129 def copy(self, inputObj=None):
130 def copy(self, inputObj=None):
130
131
131 if inputObj == None:
132 if inputObj == None:
132 return copy.deepcopy(self)
133 return copy.deepcopy(self)
133
134
134 for key in list(inputObj.__dict__.keys()):
135 for key in list(inputObj.__dict__.keys()):
135
136
136 attribute = inputObj.__dict__[key]
137 attribute = inputObj.__dict__[key]
137
138
138 # If this attribute is a tuple or list
139 # If this attribute is a tuple or list
139 if type(inputObj.__dict__[key]) in (tuple, list):
140 if type(inputObj.__dict__[key]) in (tuple, list):
140 self.__dict__[key] = attribute[:]
141 self.__dict__[key] = attribute[:]
141 continue
142 continue
142
143
143 # If this attribute is another object or instance
144 # If this attribute is another object or instance
144 if hasattr(attribute, '__dict__'):
145 if hasattr(attribute, '__dict__'):
145 self.__dict__[key] = attribute.copy()
146 self.__dict__[key] = attribute.copy()
146 continue
147 continue
147
148
148 self.__dict__[key] = inputObj.__dict__[key]
149 self.__dict__[key] = inputObj.__dict__[key]
149
150
150 def deepcopy(self):
151 def deepcopy(self):
151
152
152 return copy.deepcopy(self)
153 return copy.deepcopy(self)
153
154
154 def isEmpty(self):
155 def isEmpty(self):
155
156
156 return self.flagNoData
157 return self.flagNoData
157
158
158 def isReady(self):
159 def isReady(self):
159
160
160 return not self.flagNoData
161 return not self.flagNoData
161
162
162
163
163 class JROData(GenericData):
164 class JROData(GenericData):
164
165
165 systemHeaderObj = SystemHeader()
166 systemHeaderObj = SystemHeader()
166 radarControllerHeaderObj = RadarControllerHeader()
167 radarControllerHeaderObj = RadarControllerHeader()
167 type = None
168 type = None
168 datatype = None # dtype but in string
169 datatype = None # dtype but in string
169 nProfiles = None
170 nProfiles = None
170 heightList = None
171 heightList = None
171 channelList = None
172 channelList = None
172 flagDiscontinuousBlock = False
173 flagDiscontinuousBlock = False
173 useLocalTime = False
174 useLocalTime = False
174 utctime = None
175 utctime = None
175 timeZone = None
176 timeZone = None
176 dstFlag = None
177 dstFlag = None
177 errorCount = None
178 errorCount = None
178 blocksize = None
179 blocksize = None
179 flagDecodeData = False # asumo q la data no esta decodificada
180 flagDecodeData = False # asumo q la data no esta decodificada
180 flagDeflipData = False # asumo q la data no esta sin flip
181 flagDeflipData = False # asumo q la data no esta sin flip
181 flagShiftFFT = False
182 flagShiftFFT = False
182 nCohInt = None
183 nCohInt = None
183 windowOfFilter = 1
184 windowOfFilter = 1
184 C = 3e8
185 C = 3e8
185 frequency = 49.92e6
186 frequency = 49.92e6
186 realtime = False
187 realtime = False
187 beacon_heiIndexList = None
188 beacon_heiIndexList = None
188 last_block = None
189 last_block = None
189 blocknow = None
190 blocknow = None
190 azimuth = None
191 azimuth = None
191 zenith = None
192 zenith = None
192 beam = Beam()
193 beam = Beam()
193 profileIndex = None
194 profileIndex = None
194 error = None
195 error = None
195 data = None
196 data = None
196 nmodes = None
197 nmodes = None
197 metadata_list = ['heightList', 'timeZone', 'type']
198 metadata_list = ['heightList', 'timeZone', 'type']
198
199
199 def __str__(self):
200 def __str__(self):
200
201
201 return '{} - {}'.format(self.type, self.datatime())
202 try:
203 dt = self.datatime
204 except:
205 dt = 'None'
206 return '{} - {}'.format(self.type, dt)
202
207
203 def getNoise(self):
208 def getNoise(self):
204
209
205 raise NotImplementedError
210 raise NotImplementedError
206
211
207 @property
212 @property
208 def nChannels(self):
213 def nChannels(self):
209
214
210 return len(self.channelList)
215 return len(self.channelList)
211
216
212 @property
217 @property
213 def channelIndexList(self):
218 def channelIndexList(self):
214
219
215 return list(range(self.nChannels))
220 return list(range(self.nChannels))
216
221
217 @property
222 @property
218 def nHeights(self):
223 def nHeights(self):
219
224
220 return len(self.heightList)
225 return len(self.heightList)
221
226
222 def getDeltaH(self):
227 def getDeltaH(self):
223
228
224 return self.heightList[1] - self.heightList[0]
229 return self.heightList[1] - self.heightList[0]
225
230
226 @property
231 @property
227 def ltctime(self):
232 def ltctime(self):
228
233
229 if self.useLocalTime:
234 if self.useLocalTime:
230 return self.utctime - self.timeZone * 60
235 return self.utctime - self.timeZone * 60
231
236
232 return self.utctime
237 return self.utctime
233
238
234 @property
239 @property
235 def datatime(self):
240 def datatime(self):
236
241
237 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
242 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
238 return datatimeValue
243 return datatimeValue
239
244
240 def getTimeRange(self):
245 def getTimeRange(self):
241
246
242 datatime = []
247 datatime = []
243
248
244 datatime.append(self.ltctime)
249 datatime.append(self.ltctime)
245 datatime.append(self.ltctime + self.timeInterval + 1)
250 datatime.append(self.ltctime + self.timeInterval + 1)
246
251
247 datatime = numpy.array(datatime)
252 datatime = numpy.array(datatime)
248
253
249 return datatime
254 return datatime
250
255
251 def getFmaxTimeResponse(self):
256 def getFmaxTimeResponse(self):
252
257
253 period = (10**-6) * self.getDeltaH() / (0.15)
258 period = (10**-6) * self.getDeltaH() / (0.15)
254
259
255 PRF = 1. / (period * self.nCohInt)
260 PRF = 1. / (period * self.nCohInt)
256
261
257 fmax = PRF
262 fmax = PRF
258
263
259 return fmax
264 return fmax
260
265
261 def getFmax(self):
266 def getFmax(self):
262 PRF = 1. / (self.ippSeconds * self.nCohInt)
267 PRF = 1. / (self.ippSeconds * self.nCohInt)
263 #print("ippsec",self.ippSeconds)
268 #print("ippsec",self.ippSeconds)
264 fmax = PRF
269 fmax = PRF
265 return fmax
270 return fmax
266
271
267 def getVmax(self):
272 def getVmax(self):
268
273
269 _lambda = self.C / self.frequency
274 _lambda = self.C / self.frequency
270
275
271 vmax = self.getFmax() * _lambda / 2
276 vmax = self.getFmax() * _lambda / 2
272
277
273 return vmax
278 return vmax
274
279
275 @property
280 @property
276 def ippSeconds(self):
281 def ippSeconds(self):
277 '''
282 '''
278 '''
283 '''
279 return self.radarControllerHeaderObj.ippSeconds
284 return self.radarControllerHeaderObj.ippSeconds
280
285
281 @ippSeconds.setter
286 @ippSeconds.setter
282 def ippSeconds(self, ippSeconds):
287 def ippSeconds(self, ippSeconds):
283 '''
288 '''
284 '''
289 '''
285 self.radarControllerHeaderObj.ippSeconds = ippSeconds
290 self.radarControllerHeaderObj.ippSeconds = ippSeconds
286
291
287 @property
292 @property
288 def code(self):
293 def code(self):
289 '''
294 '''
290 '''
295 '''
291 return self.radarControllerHeaderObj.code
296 return self.radarControllerHeaderObj.code
292
297
293 @code.setter
298 @code.setter
294 def code(self, code):
299 def code(self, code):
295 '''
300 '''
296 '''
301 '''
297 self.radarControllerHeaderObj.code = code
302 self.radarControllerHeaderObj.code = code
298
303
299 @property
304 @property
300 def nCode(self):
305 def nCode(self):
301 '''
306 '''
302 '''
307 '''
303 return self.radarControllerHeaderObj.nCode
308 return self.radarControllerHeaderObj.nCode
304
309
305 @nCode.setter
310 @nCode.setter
306 def nCode(self, ncode):
311 def nCode(self, ncode):
307 '''
312 '''
308 '''
313 '''
309 self.radarControllerHeaderObj.nCode = ncode
314 self.radarControllerHeaderObj.nCode = ncode
310
315
311 @property
316 @property
312 def nBaud(self):
317 def nBaud(self):
313 '''
318 '''
314 '''
319 '''
315 return self.radarControllerHeaderObj.nBaud
320 return self.radarControllerHeaderObj.nBaud
316
321
317 @nBaud.setter
322 @nBaud.setter
318 def nBaud(self, nbaud):
323 def nBaud(self, nbaud):
319 '''
324 '''
320 '''
325 '''
321 self.radarControllerHeaderObj.nBaud = nbaud
326 self.radarControllerHeaderObj.nBaud = nbaud
322
327
323 @property
328 @property
324 def ipp(self):
329 def ipp(self):
325 '''
330 '''
326 '''
331 '''
327 return self.radarControllerHeaderObj.ipp
332 return self.radarControllerHeaderObj.ipp
328
333
329 @ipp.setter
334 @ipp.setter
330 def ipp(self, ipp):
335 def ipp(self, ipp):
331 '''
336 '''
332 '''
337 '''
333 self.radarControllerHeaderObj.ipp = ipp
338 self.radarControllerHeaderObj.ipp = ipp
334
339
335 @property
340 @property
336 def metadata(self):
341 def metadata(self):
337 '''
342 '''
338 '''
343 '''
339
344
340 return {attr: getattr(self, attr) for attr in self.metadata_list}
345 return {attr: getattr(self, attr) for attr in self.metadata_list}
341
346
342
347
343 class Voltage(JROData):
348 class Voltage(JROData):
344
349
345 dataPP_POW = None
350 dataPP_POW = None
346 dataPP_DOP = None
351 dataPP_DOP = None
347 dataPP_WIDTH = None
352 dataPP_WIDTH = None
348 dataPP_SNR = None
353 dataPP_SNR = None
349
354
350 def __init__(self):
355 def __init__(self):
351 '''
356 '''
352 Constructor
357 Constructor
353 '''
358 '''
354
359
355 self.useLocalTime = True
360 self.useLocalTime = True
356 self.radarControllerHeaderObj = RadarControllerHeader()
361 self.radarControllerHeaderObj = RadarControllerHeader()
357 self.systemHeaderObj = SystemHeader()
362 self.systemHeaderObj = SystemHeader()
358 self.type = "Voltage"
363 self.type = "Voltage"
359 self.data = None
364 self.data = None
360 self.nProfiles = None
365 self.nProfiles = None
361 self.heightList = None
366 self.heightList = None
362 self.channelList = None
367 self.channelList = None
363 self.flagNoData = True
368 self.flagNoData = True
364 self.flagDiscontinuousBlock = False
369 self.flagDiscontinuousBlock = False
365 self.utctime = None
370 self.utctime = None
366 self.timeZone = 0
371 self.timeZone = 0
367 self.dstFlag = None
372 self.dstFlag = None
368 self.errorCount = None
373 self.errorCount = None
369 self.nCohInt = None
374 self.nCohInt = None
370 self.blocksize = None
375 self.blocksize = None
371 self.flagCohInt = False
376 self.flagCohInt = False
372 self.flagDecodeData = False # asumo q la data no esta decodificada
377 self.flagDecodeData = False # asumo q la data no esta decodificada
373 self.flagDeflipData = False # asumo q la data no esta sin flip
378 self.flagDeflipData = False # asumo q la data no esta sin flip
374 self.flagShiftFFT = False
379 self.flagShiftFFT = False
375 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
380 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
376 self.profileIndex = 0
381 self.profileIndex = 0
377 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
382 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
378 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
383 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
379
384
380 def getNoisebyHildebrand(self, channel=None, Profmin_index=None, Profmax_index=None):
385 def getNoisebyHildebrand(self, channel=None, Profmin_index=None, Profmax_index=None):
381 """
386 """
382 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
387 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
383
388
384 Return:
389 Return:
385 noiselevel
390 noiselevel
386 """
391 """
387
392
388 if channel != None:
393 if channel != None:
389 data = self.data[channel]
394 data = self.data[channel]
390 nChannels = 1
395 nChannels = 1
391 else:
396 else:
392 data = self.data
397 data = self.data
393 nChannels = self.nChannels
398 nChannels = self.nChannels
394
399
395 noise = numpy.zeros(nChannels)
400 noise = numpy.zeros(nChannels)
396 power = data * numpy.conjugate(data)
401 power = data * numpy.conjugate(data)
397
402
398 for thisChannel in range(nChannels):
403 for thisChannel in range(nChannels):
399 if nChannels == 1:
404 if nChannels == 1:
400 daux = power[:].real
405 daux = power[:].real
401 else:
406 else:
402 #print(power.shape)
407 #print(power.shape)
403 daux = power[thisChannel, Profmin_index:Profmax_index, :].real
408 daux = power[thisChannel, Profmin_index:Profmax_index, :].real
404 #print(daux.shape)
409 #print(daux.shape)
405 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
410 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
406
411
407 return noise
412 return noise
408
413
409 def getNoise(self, type=1, channel=None, Profmin_index=None, Profmax_index=None):
414 def getNoise(self, type=1, channel=None, Profmin_index=None, Profmax_index=None):
410
415
411 if type == 1:
416 if type == 1:
412 noise = self.getNoisebyHildebrand(channel, Profmin_index, Profmax_index)
417 noise = self.getNoisebyHildebrand(channel, Profmin_index, Profmax_index)
413
418
414 return noise
419 return noise
415
420
416 def getPower(self, channel=None):
421 def getPower(self, channel=None):
417
422
418 if channel != None:
423 if channel != None:
419 data = self.data[channel]
424 data = self.data[channel]
420 else:
425 else:
421 data = self.data
426 data = self.data
422
427
423 power = data * numpy.conjugate(data)
428 power = data * numpy.conjugate(data)
424 powerdB = 10 * numpy.log10(power.real)
429 powerdB = 10 * numpy.log10(power.real)
425 powerdB = numpy.squeeze(powerdB)
430 powerdB = numpy.squeeze(powerdB)
426
431
427 return powerdB
432 return powerdB
428
433
429 @property
434 @property
430 def timeInterval(self):
435 def timeInterval(self):
431
436
432 return self.ippSeconds * self.nCohInt
437 return self.ippSeconds * self.nCohInt
433
438
434 noise = property(getNoise, "I'm the 'nHeights' property.")
439 noise = property(getNoise, "I'm the 'nHeights' property.")
435
440
436
441
437 class Spectra(JROData):
442 class Spectra(JROData):
438
443
439 def __init__(self):
444 def __init__(self):
440 '''
445 '''
441 Constructor
446 Constructor
442 '''
447 '''
443
448
444 self.data_dc = None
449 self.data_dc = None
445 self.data_spc = None
450 self.data_spc = None
446 self.data_cspc = None
451 self.data_cspc = None
447 self.useLocalTime = True
452 self.useLocalTime = True
448 self.radarControllerHeaderObj = RadarControllerHeader()
453 self.radarControllerHeaderObj = RadarControllerHeader()
449 self.systemHeaderObj = SystemHeader()
454 self.systemHeaderObj = SystemHeader()
450 self.type = "Spectra"
455 self.type = "Spectra"
451 self.timeZone = 0
456 self.timeZone = 0
452 self.nProfiles = None
457 self.nProfiles = None
453 self.heightList = None
458 self.heightList = None
454 self.channelList = None
459 self.channelList = None
455 self.pairsList = None
460 self.pairsList = None
456 self.flagNoData = True
461 self.flagNoData = True
457 self.flagDiscontinuousBlock = False
462 self.flagDiscontinuousBlock = False
458 self.utctime = None
463 self.utctime = None
459 self.nCohInt = None
464 self.nCohInt = None
460 self.nIncohInt = None
465 self.nIncohInt = None
461 self.blocksize = None
466 self.blocksize = None
462 self.nFFTPoints = None
467 self.nFFTPoints = None
463 self.wavelength = None
468 self.wavelength = None
464 self.flagDecodeData = False # asumo q la data no esta decodificada
469 self.flagDecodeData = False # asumo q la data no esta decodificada
465 self.flagDeflipData = False # asumo q la data no esta sin flip
470 self.flagDeflipData = False # asumo q la data no esta sin flip
466 self.flagShiftFFT = False
471 self.flagShiftFFT = False
467 self.ippFactor = 1
472 self.ippFactor = 1
468 self.beacon_heiIndexList = []
473 self.beacon_heiIndexList = []
469 self.noise_estimation = None
474 self.noise_estimation = None
475 self.spc_noise = None
470 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
476 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
471 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp','nIncohInt', 'nFFTPoints', 'nProfiles']
477 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp', 'nIncohInt', 'nFFTPoints', 'nProfiles', 'flagDecodeData']
472
478
473 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
479 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
474 """
480 """
475 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
481 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
476
482
477 Return:
483 Return:
478 noiselevel
484 noiselevel
479 """
485 """
480
486
481 noise = numpy.zeros(self.nChannels)
487 noise = numpy.zeros(self.nChannels)
482
488
483 for channel in range(self.nChannels):
489 for channel in range(self.nChannels):
484 #print(self.data_spc[0])
490 #print(self.data_spc[0])
485 #exit(1)
491 #exit(1)
486 daux = self.data_spc[channel,
492 daux = self.data_spc[channel,
487 xmin_index:xmax_index, ymin_index:ymax_index]
493 xmin_index:xmax_index, ymin_index:ymax_index]
488 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
494 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
489
495
490 return noise
496 return noise
491
497
492 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
498 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
493
499
494 if self.noise_estimation is not None:
500 if self.spc_noise is not None:
501 # this was estimated by getNoise Operation defined in jroproc_parameters.py
502 return self.spc_noise
503 elif self.noise_estimation is not None:
495 # this was estimated by getNoise Operation defined in jroproc_spectra.py
504 # this was estimated by getNoise Operation defined in jroproc_spectra.py
496 return self.noise_estimation
505 return self.noise_estimation
497 else:
506 else:
498
507
499 noise = self.getNoisebyHildebrand(
508 noise = self.getNoisebyHildebrand(
500 xmin_index, xmax_index, ymin_index, ymax_index)
509 xmin_index, xmax_index, ymin_index, ymax_index)
501 return noise
510 return noise
502
511
503 def getFreqRangeTimeResponse(self, extrapoints=0):
512 def getFreqRangeTimeResponse(self, extrapoints=0):
504
513
505 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
514 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
506 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
515 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
507
516
508 return freqrange
517 return freqrange
509
518
510 def getAcfRange(self, extrapoints=0):
519 def getAcfRange(self, extrapoints=0):
511
520
512 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
521 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
513 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
522 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
514
523
515 return freqrange
524 return freqrange
516
525
517 def getFreqRange(self, extrapoints=0):
526 def getFreqRange(self, extrapoints=0):
518
527
519 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
528 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
520 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
529 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
521
530
522 return freqrange
531 return freqrange
523
532
524 def getVelRange(self, extrapoints=0):
533 def getVelRange(self, extrapoints=0):
525
534
526 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
535 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
527 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
536 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
528
537
529 if self.nmodes:
538 if self.nmodes:
530 return velrange/self.nmodes
539 return velrange/self.nmodes
531 else:
540 else:
532 return velrange
541 return velrange
533
542
534 @property
543 @property
535 def nPairs(self):
544 def nPairs(self):
536
545
537 return len(self.pairsList)
546 return len(self.pairsList)
538
547
539 @property
548 @property
540 def pairsIndexList(self):
549 def pairsIndexList(self):
541
550
542 return list(range(self.nPairs))
551 return list(range(self.nPairs))
543
552
544 @property
553 @property
545 def normFactor(self):
554 def normFactor(self):
546
555
547 pwcode = 1
556 pwcode = 1
548
557
549 if self.flagDecodeData:
558 if self.flagDecodeData:
550 pwcode = numpy.sum(self.code[0]**2)
559 pwcode = numpy.sum(self.code[0]**2)
551 #pwcode = 64
560 #pwcode = 64
552 #print("pwcode: ", pwcode)
561 #print("pwcode: ", pwcode)
553 #exit(1)
562 #exit(1)
554 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
563 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
555 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
564 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
556
565
557 return normFactor
566 return normFactor
558
567
559 @property
568 @property
560 def flag_cspc(self):
569 def flag_cspc(self):
561
570
562 if self.data_cspc is None:
571 if self.data_cspc is None:
563 return True
572 return True
564
573
565 return False
574 return False
566
575
567 @property
576 @property
568 def flag_dc(self):
577 def flag_dc(self):
569
578
570 if self.data_dc is None:
579 if self.data_dc is None:
571 return True
580 return True
572
581
573 return False
582 return False
574
583
575 @property
584 @property
576 def timeInterval(self):
585 def timeInterval(self):
577
586
578 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
587 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
579 if self.nmodes:
588 if self.nmodes:
580 return self.nmodes*timeInterval
589 return self.nmodes*timeInterval
581 else:
590 else:
582 return timeInterval
591 return timeInterval
583
592
584 def getPower(self):
593 def getPower(self):
585
594
586 factor = self.normFactor
595 factor = self.normFactor
587 z = self.data_spc / factor
596 z = self.data_spc / factor
588 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
597 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
589 avg = numpy.average(z, axis=1)
598 avg = numpy.average(z, axis=1)
590
599
591 return 10 * numpy.log10(avg)
600 return 10 * numpy.log10(avg)
592
601
593 def getCoherence(self, pairsList=None, phase=False):
602 def getCoherence(self, pairsList=None, phase=False):
594
603
595 z = []
604 z = []
596 if pairsList is None:
605 if pairsList is None:
597 pairsIndexList = self.pairsIndexList
606 pairsIndexList = self.pairsIndexList
598 else:
607 else:
599 pairsIndexList = []
608 pairsIndexList = []
600 for pair in pairsList:
609 for pair in pairsList:
601 if pair not in self.pairsList:
610 if pair not in self.pairsList:
602 raise ValueError("Pair %s is not in dataOut.pairsList" % (
611 raise ValueError("Pair %s is not in dataOut.pairsList" % (
603 pair))
612 pair))
604 pairsIndexList.append(self.pairsList.index(pair))
613 pairsIndexList.append(self.pairsList.index(pair))
605 for i in range(len(pairsIndexList)):
614 for i in range(len(pairsIndexList)):
606 pair = self.pairsList[pairsIndexList[i]]
615 pair = self.pairsList[pairsIndexList[i]]
607 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
616 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
608 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
617 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
609 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
618 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
610 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
619 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
611 if phase:
620 if phase:
612 data = numpy.arctan2(avgcoherenceComplex.imag,
621 data = numpy.arctan2(avgcoherenceComplex.imag,
613 avgcoherenceComplex.real) * 180 / numpy.pi
622 avgcoherenceComplex.real) * 180 / numpy.pi
614 else:
623 else:
615 data = numpy.abs(avgcoherenceComplex)
624 data = numpy.abs(avgcoherenceComplex)
616
625
617 z.append(data)
626 z.append(data)
618
627
619 return numpy.array(z)
628 return numpy.array(z)
620
629
621 def setValue(self, value):
630 def setValue(self, value):
622
631
623 print("This property should not be initialized")
632 print("This property should not be initialized")
624
633
625 return
634 return
626
635
627 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
636 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
628
637
629
638
630 class SpectraHeis(Spectra):
639 class SpectraHeis(Spectra):
631
640
632 def __init__(self):
641 def __init__(self):
633
642
634 self.radarControllerHeaderObj = RadarControllerHeader()
643 self.radarControllerHeaderObj = RadarControllerHeader()
635 self.systemHeaderObj = SystemHeader()
644 self.systemHeaderObj = SystemHeader()
636 self.type = "SpectraHeis"
645 self.type = "SpectraHeis"
637 self.nProfiles = None
646 self.nProfiles = None
638 self.heightList = None
647 self.heightList = None
639 self.channelList = None
648 self.channelList = None
640 self.flagNoData = True
649 self.flagNoData = True
641 self.flagDiscontinuousBlock = False
650 self.flagDiscontinuousBlock = False
642 self.utctime = None
651 self.utctime = None
643 self.blocksize = None
652 self.blocksize = None
644 self.profileIndex = 0
653 self.profileIndex = 0
645 self.nCohInt = 1
654 self.nCohInt = 1
646 self.nIncohInt = 1
655 self.nIncohInt = 1
647
656
648 @property
657 @property
649 def normFactor(self):
658 def normFactor(self):
650 pwcode = 1
659 pwcode = 1
651 if self.flagDecodeData:
660 if self.flagDecodeData:
652 pwcode = numpy.sum(self.code[0]**2)
661 pwcode = numpy.sum(self.code[0]**2)
653
662
654 normFactor = self.nIncohInt * self.nCohInt * pwcode
663 normFactor = self.nIncohInt * self.nCohInt * pwcode
655
664
656 return normFactor
665 return normFactor
657
666
658 @property
667 @property
659 def timeInterval(self):
668 def timeInterval(self):
660
669
661 return self.ippSeconds * self.nCohInt * self.nIncohInt
670 return self.ippSeconds * self.nCohInt * self.nIncohInt
662
671
663
672
664 class Fits(JROData):
673 class Fits(JROData):
665
674
666 def __init__(self):
675 def __init__(self):
667
676
668 self.type = "Fits"
677 self.type = "Fits"
669 self.nProfiles = None
678 self.nProfiles = None
670 self.heightList = None
679 self.heightList = None
671 self.channelList = None
680 self.channelList = None
672 self.flagNoData = True
681 self.flagNoData = True
673 self.utctime = None
682 self.utctime = None
674 self.nCohInt = 1
683 self.nCohInt = 1
675 self.nIncohInt = 1
684 self.nIncohInt = 1
676 self.useLocalTime = True
685 self.useLocalTime = True
677 self.profileIndex = 0
686 self.profileIndex = 0
678 self.timeZone = 0
687 self.timeZone = 0
679
688
680 def getTimeRange(self):
689 def getTimeRange(self):
681
690
682 datatime = []
691 datatime = []
683
692
684 datatime.append(self.ltctime)
693 datatime.append(self.ltctime)
685 datatime.append(self.ltctime + self.timeInterval)
694 datatime.append(self.ltctime + self.timeInterval)
686
695
687 datatime = numpy.array(datatime)
696 datatime = numpy.array(datatime)
688
697
689 return datatime
698 return datatime
690
699
691 def getChannelIndexList(self):
700 def getChannelIndexList(self):
692
701
693 return list(range(self.nChannels))
702 return list(range(self.nChannels))
694
703
695 def getNoise(self, type=1):
704 def getNoise(self, type=1):
696
705
697
706
698 if type == 1:
707 if type == 1:
699 noise = self.getNoisebyHildebrand()
708 noise = self.getNoisebyHildebrand()
700
709
701 if type == 2:
710 if type == 2:
702 noise = self.getNoisebySort()
711 noise = self.getNoisebySort()
703
712
704 if type == 3:
713 if type == 3:
705 noise = self.getNoisebyWindow()
714 noise = self.getNoisebyWindow()
706
715
707 return noise
716 return noise
708
717
709 @property
718 @property
710 def timeInterval(self):
719 def timeInterval(self):
711
720
712 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
721 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
713
722
714 return timeInterval
723 return timeInterval
715
724
716 @property
725 @property
717 def ippSeconds(self):
726 def ippSeconds(self):
718 '''
727 '''
719 '''
728 '''
720 return self.ipp_sec
729 return self.ipp_sec
721
730
722 noise = property(getNoise, "I'm the 'nHeights' property.")
731 noise = property(getNoise, "I'm the 'nHeights' property.")
723
732
724
733
725 class Correlation(JROData):
734 class Correlation(JROData):
726
735
727 def __init__(self):
736 def __init__(self):
728 '''
737 '''
729 Constructor
738 Constructor
730 '''
739 '''
731 self.radarControllerHeaderObj = RadarControllerHeader()
740 self.radarControllerHeaderObj = RadarControllerHeader()
732 self.systemHeaderObj = SystemHeader()
741 self.systemHeaderObj = SystemHeader()
733 self.type = "Correlation"
742 self.type = "Correlation"
734 self.data = None
743 self.data = None
735 self.dtype = None
744 self.dtype = None
736 self.nProfiles = None
745 self.nProfiles = None
737 self.heightList = None
746 self.heightList = None
738 self.channelList = None
747 self.channelList = None
739 self.flagNoData = True
748 self.flagNoData = True
740 self.flagDiscontinuousBlock = False
749 self.flagDiscontinuousBlock = False
741 self.utctime = None
750 self.utctime = None
742 self.timeZone = 0
751 self.timeZone = 0
743 self.dstFlag = None
752 self.dstFlag = None
744 self.errorCount = None
753 self.errorCount = None
745 self.blocksize = None
754 self.blocksize = None
746 self.flagDecodeData = False # asumo q la data no esta decodificada
755 self.flagDecodeData = False # asumo q la data no esta decodificada
747 self.flagDeflipData = False # asumo q la data no esta sin flip
756 self.flagDeflipData = False # asumo q la data no esta sin flip
748 self.pairsList = None
757 self.pairsList = None
749 self.nPoints = None
758 self.nPoints = None
750
759
751 def getPairsList(self):
760 def getPairsList(self):
752
761
753 return self.pairsList
762 return self.pairsList
754
763
755 def getNoise(self, mode=2):
764 def getNoise(self, mode=2):
756
765
757 indR = numpy.where(self.lagR == 0)[0][0]
766 indR = numpy.where(self.lagR == 0)[0][0]
758 indT = numpy.where(self.lagT == 0)[0][0]
767 indT = numpy.where(self.lagT == 0)[0][0]
759
768
760 jspectra0 = self.data_corr[:, :, indR, :]
769 jspectra0 = self.data_corr[:, :, indR, :]
761 jspectra = copy.copy(jspectra0)
770 jspectra = copy.copy(jspectra0)
762
771
763 num_chan = jspectra.shape[0]
772 num_chan = jspectra.shape[0]
764 num_hei = jspectra.shape[2]
773 num_hei = jspectra.shape[2]
765
774
766 freq_dc = jspectra.shape[1] / 2
775 freq_dc = jspectra.shape[1] / 2
767 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
776 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
768
777
769 if ind_vel[0] < 0:
778 if ind_vel[0] < 0:
770 ind_vel[list(range(0, 1))] = ind_vel[list(
779 ind_vel[list(range(0, 1))] = ind_vel[list(
771 range(0, 1))] + self.num_prof
780 range(0, 1))] + self.num_prof
772
781
773 if mode == 1:
782 if mode == 1:
774 jspectra[:, freq_dc, :] = (
783 jspectra[:, freq_dc, :] = (
775 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
784 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
776
785
777 if mode == 2:
786 if mode == 2:
778
787
779 vel = numpy.array([-2, -1, 1, 2])
788 vel = numpy.array([-2, -1, 1, 2])
780 xx = numpy.zeros([4, 4])
789 xx = numpy.zeros([4, 4])
781
790
782 for fil in range(4):
791 for fil in range(4):
783 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
792 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
784
793
785 xx_inv = numpy.linalg.inv(xx)
794 xx_inv = numpy.linalg.inv(xx)
786 xx_aux = xx_inv[0, :]
795 xx_aux = xx_inv[0, :]
787
796
788 for ich in range(num_chan):
797 for ich in range(num_chan):
789 yy = jspectra[ich, ind_vel, :]
798 yy = jspectra[ich, ind_vel, :]
790 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
799 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
791
800
792 junkid = jspectra[ich, freq_dc, :] <= 0
801 junkid = jspectra[ich, freq_dc, :] <= 0
793 cjunkid = sum(junkid)
802 cjunkid = sum(junkid)
794
803
795 if cjunkid.any():
804 if cjunkid.any():
796 jspectra[ich, freq_dc, junkid.nonzero()] = (
805 jspectra[ich, freq_dc, junkid.nonzero()] = (
797 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
806 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
798
807
799 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
808 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
800
809
801 return noise
810 return noise
802
811
803 @property
812 @property
804 def timeInterval(self):
813 def timeInterval(self):
805
814
806 return self.ippSeconds * self.nCohInt * self.nProfiles
815 return self.ippSeconds * self.nCohInt * self.nProfiles
807
816
808 def splitFunctions(self):
817 def splitFunctions(self):
809
818
810 pairsList = self.pairsList
819 pairsList = self.pairsList
811 ccf_pairs = []
820 ccf_pairs = []
812 acf_pairs = []
821 acf_pairs = []
813 ccf_ind = []
822 ccf_ind = []
814 acf_ind = []
823 acf_ind = []
815 for l in range(len(pairsList)):
824 for l in range(len(pairsList)):
816 chan0 = pairsList[l][0]
825 chan0 = pairsList[l][0]
817 chan1 = pairsList[l][1]
826 chan1 = pairsList[l][1]
818
827
819 # Obteniendo pares de Autocorrelacion
828 # Obteniendo pares de Autocorrelacion
820 if chan0 == chan1:
829 if chan0 == chan1:
821 acf_pairs.append(chan0)
830 acf_pairs.append(chan0)
822 acf_ind.append(l)
831 acf_ind.append(l)
823 else:
832 else:
824 ccf_pairs.append(pairsList[l])
833 ccf_pairs.append(pairsList[l])
825 ccf_ind.append(l)
834 ccf_ind.append(l)
826
835
827 data_acf = self.data_cf[acf_ind]
836 data_acf = self.data_cf[acf_ind]
828 data_ccf = self.data_cf[ccf_ind]
837 data_ccf = self.data_cf[ccf_ind]
829
838
830 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
839 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
831
840
832 @property
841 @property
833 def normFactor(self):
842 def normFactor(self):
834 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
843 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
835 acf_pairs = numpy.array(acf_pairs)
844 acf_pairs = numpy.array(acf_pairs)
836 normFactor = numpy.zeros((self.nPairs, self.nHeights))
845 normFactor = numpy.zeros((self.nPairs, self.nHeights))
837
846
838 for p in range(self.nPairs):
847 for p in range(self.nPairs):
839 pair = self.pairsList[p]
848 pair = self.pairsList[p]
840
849
841 ch0 = pair[0]
850 ch0 = pair[0]
842 ch1 = pair[1]
851 ch1 = pair[1]
843
852
844 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
853 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
845 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
854 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
846 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
855 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
847
856
848 return normFactor
857 return normFactor
849
858
850
859
851 class Parameters(Spectra):
860 class Parameters(Spectra):
852
861
853 groupList = None # List of Pairs, Groups, etc
862 groupList = None # List of Pairs, Groups, etc
854 data_param = None # Parameters obtained
863 data_param = None # Parameters obtained
855 data_pre = None # Data Pre Parametrization
864 data_pre = None # Data Pre Parametrization
856 data_SNR = None # Signal to Noise Ratio
865 data_SNR = None # Signal to Noise Ratio
857 abscissaList = None # Abscissa, can be velocities, lags or time
866 abscissaList = None # Abscissa, can be velocities, lags or time
858 utctimeInit = None # Initial UTC time
867 utctimeInit = None # Initial UTC time
859 paramInterval = None # Time interval to calculate Parameters in seconds
868 paramInterval = None # Time interval to calculate Parameters in seconds
860 useLocalTime = True
869 useLocalTime = True
861 # Fitting
870 # Fitting
862 data_error = None # Error of the estimation
871 data_error = None # Error of the estimation
863 constants = None
872 constants = None
864 library = None
873 library = None
865 # Output signal
874 # Output signal
866 outputInterval = None # Time interval to calculate output signal in seconds
875 outputInterval = None # Time interval to calculate output signal in seconds
867 data_output = None # Out signal
876 data_output = None # Out signal
868 nAvg = None
877 nAvg = None
869 noise_estimation = None
878 noise_estimation = None
870 GauSPC = None # Fit gaussian SPC
879 GauSPC = None # Fit gaussian SPC
880 spc_noise = None
871
881
872 def __init__(self):
882 def __init__(self):
873 '''
883 '''
874 Constructor
884 Constructor
875 '''
885 '''
876 self.radarControllerHeaderObj = RadarControllerHeader()
886 self.radarControllerHeaderObj = RadarControllerHeader()
877 self.systemHeaderObj = SystemHeader()
887 self.systemHeaderObj = SystemHeader()
878 self.type = "Parameters"
888 self.type = "Parameters"
879 self.timeZone = 0
889 self.timeZone = 0
890 self.ippFactor = 1
880
891
881 def getTimeRange1(self, interval):
892 def getTimeRange1(self, interval):
882
893
883 datatime = []
894 datatime = []
884
895
885 if self.useLocalTime:
896 if self.useLocalTime:
886 time1 = self.utctimeInit - self.timeZone * 60
897 time1 = self.utctimeInit - self.timeZone * 60
887 else:
898 else:
888 time1 = self.utctimeInit
899 time1 = self.utctimeInit
889
900
890 datatime.append(time1)
901 datatime.append(time1)
891 datatime.append(time1 + interval)
902 datatime.append(time1 + interval)
892 datatime = numpy.array(datatime)
903 datatime = numpy.array(datatime)
893
904
894 return datatime
905 return datatime
895
906
896 @property
907 @property
897 def timeInterval(self):
908 def timeInterval(self):
898
909
899 if hasattr(self, 'timeInterval1'):
910 if hasattr(self, 'timeInterval1'):
900 return self.timeInterval1
911 return self.timeInterval1
901 else:
912 else:
902 return self.paramInterval
913 return self.paramInterval
903
914
904
915
905 def setValue(self, value):
916 def setValue(self, value):
906
917
907 print("This property should not be initialized")
918 print("This property should not be initialized")
908
919
909 return
920 return
910
921
911 def getNoise(self):
922 def getNoise(self):
912
923
913 return self.spc_noise
924 return self.spc_noise
914
925
915 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
926 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
916
927
917
928
918 class PlotterData(object):
929 class PlotterData(object):
919 '''
930 '''
920 Object to hold data to be plotted
931 Object to hold data to be plotted
921 '''
932 '''
922
933
923 MAXNUMX = 200
934 MAXNUMX = 200
924 MAXNUMY = 200
935 MAXNUMY = 200
925
936
926 def __init__(self, code, exp_code, localtime=True):
937 def __init__(self, code, exp_code, localtime=True):
927
938
928 self.key = code
939 self.key = code
929 self.exp_code = exp_code
940 self.exp_code = exp_code
930 self.ready = False
941 self.ready = False
931 self.flagNoData = False
942 self.flagNoData = False
932 self.localtime = localtime
943 self.localtime = localtime
933 self.data = {}
944 self.data = {}
934 self.meta = {}
945 self.meta = {}
935 self.__heights = []
946 self.__heights = []
936
947
937 def __str__(self):
948 def __str__(self):
938 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
949 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
939 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
950 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
940
951
941 def __len__(self):
952 def __len__(self):
942 return len(self.data)
953 return len(self.data)
943
954
944 def __getitem__(self, key):
955 def __getitem__(self, key):
945 if isinstance(key, int):
956 if isinstance(key, int):
946 return self.data[self.times[key]]
957 return self.data[self.times[key]]
947 elif isinstance(key, str):
958 elif isinstance(key, str):
948 ret = numpy.array([self.data[x][key] for x in self.times])
959 ret = numpy.array([self.data[x][key] for x in self.times])
949 if ret.ndim > 1:
960 if ret.ndim > 1:
950 ret = numpy.swapaxes(ret, 0, 1)
961 ret = numpy.swapaxes(ret, 0, 1)
951 return ret
962 return ret
952
963
953 def __contains__(self, key):
964 def __contains__(self, key):
954 return key in self.data[self.min_time]
965 return key in self.data[self.min_time]
955
966
956 def setup(self):
967 def setup(self):
957 '''
968 '''
958 Configure object
969 Configure object
959 '''
970 '''
960 self.type = ''
971 self.type = ''
961 self.ready = False
972 self.ready = False
962 del self.data
973 del self.data
963 self.data = {}
974 self.data = {}
964 self.__heights = []
975 self.__heights = []
965 self.__all_heights = set()
976 self.__all_heights = set()
966
977
967 def shape(self, key):
978 def shape(self, key):
968 '''
979 '''
969 Get the shape of the one-element data for the given key
980 Get the shape of the one-element data for the given key
970 '''
981 '''
971
982
972 if len(self.data[self.min_time][key]):
983 if len(self.data[self.min_time][key]):
973 return self.data[self.min_time][key].shape
984 return self.data[self.min_time][key].shape
974 return (0,)
985 return (0,)
975
986
976 def update(self, data, tm, meta={}):
987 def update(self, data, tm, meta={}):
977 '''
988 '''
978 Update data object with new dataOut
989 Update data object with new dataOut
979 '''
990 '''
980
991
981 self.data[tm] = data
992 self.data[tm] = data
982
993
983 for key, value in meta.items():
994 for key, value in meta.items():
984 setattr(self, key, value)
995 setattr(self, key, value)
985
996
986 def normalize_heights(self):
997 def normalize_heights(self):
987 '''
998 '''
988 Ensure same-dimension of the data for different heighList
999 Ensure same-dimension of the data for different heighList
989 '''
1000 '''
990
1001
991 H = numpy.array(list(self.__all_heights))
1002 H = numpy.array(list(self.__all_heights))
992 H.sort()
1003 H.sort()
993 for key in self.data:
1004 for key in self.data:
994 shape = self.shape(key)[:-1] + H.shape
1005 shape = self.shape(key)[:-1] + H.shape
995 for tm, obj in list(self.data[key].items()):
1006 for tm, obj in list(self.data[key].items()):
996 h = self.__heights[self.times.tolist().index(tm)]
1007 h = self.__heights[self.times.tolist().index(tm)]
997 if H.size == h.size:
1008 if H.size == h.size:
998 continue
1009 continue
999 index = numpy.where(numpy.in1d(H, h))[0]
1010 index = numpy.where(numpy.in1d(H, h))[0]
1000 dummy = numpy.zeros(shape) + numpy.nan
1011 dummy = numpy.zeros(shape) + numpy.nan
1001 if len(shape) == 2:
1012 if len(shape) == 2:
1002 dummy[:, index] = obj
1013 dummy[:, index] = obj
1003 else:
1014 else:
1004 dummy[index] = obj
1015 dummy[index] = obj
1005 self.data[key][tm] = dummy
1016 self.data[key][tm] = dummy
1006
1017
1007 self.__heights = [H for tm in self.times]
1018 self.__heights = [H for tm in self.times]
1008
1019
1009 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1020 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1010 '''
1021 '''
1011 Convert data to json
1022 Convert data to json
1012 '''
1023 '''
1013
1024
1014 meta = {}
1025 meta = {}
1015 meta['xrange'] = []
1026 meta['xrange'] = []
1016 dy = int(len(self.yrange)/self.MAXNUMY) + 1
1027 dy = int(len(self.yrange)/self.MAXNUMY) + 1
1017 tmp = self.data[tm][self.key]
1028 tmp = self.data[tm][self.key]
1018 shape = tmp.shape
1029 shape = tmp.shape
1019 if len(shape) == 2:
1030 if len(shape) == 2:
1020 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1031 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1021 elif len(shape) == 3:
1032 elif len(shape) == 3:
1022 dx = int(self.data[tm][self.key].shape[1]/self.MAXNUMX) + 1
1033 dx = int(self.data[tm][self.key].shape[1]/self.MAXNUMX) + 1
1023 data = self.roundFloats(
1034 data = self.roundFloats(
1024 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1035 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1025 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1036 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1026 else:
1037 else:
1027 data = self.roundFloats(self.data[tm][self.key].tolist())
1038 data = self.roundFloats(self.data[tm][self.key].tolist())
1028
1039
1029 ret = {
1040 ret = {
1030 'plot': plot_name,
1041 'plot': plot_name,
1031 'code': self.exp_code,
1042 'code': self.exp_code,
1032 'time': float(tm),
1043 'time': float(tm),
1033 'data': data,
1044 'data': data,
1034 }
1045 }
1035 meta['type'] = plot_type
1046 meta['type'] = plot_type
1036 meta['interval'] = float(self.interval)
1047 meta['interval'] = float(self.interval)
1037 meta['localtime'] = self.localtime
1048 meta['localtime'] = self.localtime
1038 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1049 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1039 meta.update(self.meta)
1050 meta.update(self.meta)
1040 ret['metadata'] = meta
1051 ret['metadata'] = meta
1041 return json.dumps(ret)
1052 return json.dumps(ret)
1042
1053
1043 @property
1054 @property
1044 def times(self):
1055 def times(self):
1045 '''
1056 '''
1046 Return the list of times of the current data
1057 Return the list of times of the current data
1047 '''
1058 '''
1048
1059
1049 ret = [t for t in self.data]
1060 ret = [t for t in self.data]
1050 ret.sort()
1061 ret.sort()
1051 return numpy.array(ret)
1062 return numpy.array(ret)
1052
1063
1053 @property
1064 @property
1054 def min_time(self):
1065 def min_time(self):
1055 '''
1066 '''
1056 Return the minimun time value
1067 Return the minimun time value
1057 '''
1068 '''
1058
1069
1059 return self.times[0]
1070 return self.times[0]
1060
1071
1061 @property
1072 @property
1062 def max_time(self):
1073 def max_time(self):
1063 '''
1074 '''
1064 Return the maximun time value
1075 Return the maximun time value
1065 '''
1076 '''
1066
1077
1067 return self.times[-1]
1078 return self.times[-1]
1068
1079
1069 # @property
1080 # @property
1070 # def heights(self):
1081 # def heights(self):
1071 # '''
1082 # '''
1072 # Return the list of heights of the current data
1083 # Return the list of heights of the current data
1073 # '''
1084 # '''
1074
1085
1075 # return numpy.array(self.__heights[-1])
1086 # return numpy.array(self.__heights[-1])
1076
1087
1077 @staticmethod
1088 @staticmethod
1078 def roundFloats(obj):
1089 def roundFloats(obj):
1079 if isinstance(obj, list):
1090 if isinstance(obj, list):
1080 return list(map(PlotterData.roundFloats, obj))
1091 return list(map(PlotterData.roundFloats, obj))
1081 elif isinstance(obj, float):
1092 elif isinstance(obj, float):
1082 return round(obj, 2)
1093 return round(obj, 2)
@@ -1,704 +1,705
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Base class to create plot operations
5 """Base class to create plot operations
6
6
7 """
7 """
8
8
9 import os
9 import os
10 import sys
10 import sys
11 import zmq
11 import zmq
12 import time
12 import time
13 import numpy
13 import numpy
14 import datetime
14 import datetime
15 from collections import deque
15 from collections import deque
16 from functools import wraps
16 from functools import wraps
17 from threading import Thread
17 from threading import Thread
18 import matplotlib
18 import matplotlib
19
19
20 if 'BACKEND' in os.environ:
20 if 'BACKEND' in os.environ:
21 matplotlib.use(os.environ['BACKEND'])
21 matplotlib.use(os.environ['BACKEND'])
22 elif 'linux' in sys.platform:
22 elif 'linux' in sys.platform:
23 matplotlib.use("TkAgg")
23 matplotlib.use("TkAgg")
24 elif 'darwin' in sys.platform:
24 elif 'darwin' in sys.platform:
25 matplotlib.use('MacOSX')
25 matplotlib.use('MacOSX')
26 else:
26 else:
27 from schainpy.utils import log
27 from schainpy.utils import log
28 log.warning('Using default Backend="Agg"', 'INFO')
28 log.warning('Using default Backend="Agg"', 'INFO')
29 matplotlib.use('Agg')
29 matplotlib.use('Agg')
30
30
31 import matplotlib.pyplot as plt
31 import matplotlib.pyplot as plt
32 from matplotlib.patches import Polygon
32 from matplotlib.patches import Polygon
33 from mpl_toolkits.axes_grid1 import make_axes_locatable
33 from mpl_toolkits.axes_grid1 import make_axes_locatable
34 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
34 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
35
35
36 from schainpy.model.data.jrodata import PlotterData
36 from schainpy.model.data.jrodata import PlotterData
37 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
37 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
38 from schainpy.utils import log
38 from schainpy.utils import log
39
39
40 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
40 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
41 blu_values = matplotlib.pyplot.get_cmap(
41 blu_values = matplotlib.pyplot.get_cmap(
42 'seismic_r', 20)(numpy.arange(20))[10:15]
42 'seismic_r', 20)(numpy.arange(20))[10:15]
43 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
43 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
44 'jro', numpy.vstack((blu_values, jet_values)))
44 'jro', numpy.vstack((blu_values, jet_values)))
45 matplotlib.pyplot.register_cmap(cmap=ncmap)
45 matplotlib.pyplot.register_cmap(cmap=ncmap)
46
46
47 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
47 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
48 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
48 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
49
49
50 EARTH_RADIUS = 6.3710e3
50 EARTH_RADIUS = 6.3710e3
51
51
52 def ll2xy(lat1, lon1, lat2, lon2):
52 def ll2xy(lat1, lon1, lat2, lon2):
53
53
54 p = 0.017453292519943295
54 p = 0.017453292519943295
55 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
55 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
56 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
56 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
57 r = 12742 * numpy.arcsin(numpy.sqrt(a))
57 r = 12742 * numpy.arcsin(numpy.sqrt(a))
58 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
58 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
59 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
59 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
60 theta = -theta + numpy.pi/2
60 theta = -theta + numpy.pi/2
61 return r*numpy.cos(theta), r*numpy.sin(theta)
61 return r*numpy.cos(theta), r*numpy.sin(theta)
62
62
63
63
64 def km2deg(km):
64 def km2deg(km):
65 '''
65 '''
66 Convert distance in km to degrees
66 Convert distance in km to degrees
67 '''
67 '''
68
68
69 return numpy.rad2deg(km/EARTH_RADIUS)
69 return numpy.rad2deg(km/EARTH_RADIUS)
70
70
71
71
72 def figpause(interval):
72 def figpause(interval):
73 backend = plt.rcParams['backend']
73 backend = plt.rcParams['backend']
74 if backend in matplotlib.rcsetup.interactive_bk:
74 if backend in matplotlib.rcsetup.interactive_bk:
75 figManager = matplotlib._pylab_helpers.Gcf.get_active()
75 figManager = matplotlib._pylab_helpers.Gcf.get_active()
76 if figManager is not None:
76 if figManager is not None:
77 canvas = figManager.canvas
77 canvas = figManager.canvas
78 if canvas.figure.stale:
78 if canvas.figure.stale:
79 canvas.draw()
79 canvas.draw()
80 try:
80 try:
81 canvas.start_event_loop(interval)
81 canvas.start_event_loop(interval)
82 except:
82 except:
83 pass
83 pass
84 return
84 return
85
85
86 def popup(message):
86 def popup(message):
87 '''
87 '''
88 '''
88 '''
89
89
90 fig = plt.figure(figsize=(12, 8), facecolor='r')
90 fig = plt.figure(figsize=(12, 8), facecolor='r')
91 text = '\n'.join([s.strip() for s in message.split(':')])
91 text = '\n'.join([s.strip() for s in message.split(':')])
92 fig.text(0.01, 0.5, text, ha='left', va='center',
92 fig.text(0.01, 0.5, text, ha='left', va='center',
93 size='20', weight='heavy', color='w')
93 size='20', weight='heavy', color='w')
94 fig.show()
94 fig.show()
95 figpause(1000)
95 figpause(1000)
96
96
97
97
98 class Throttle(object):
98 class Throttle(object):
99 '''
99 '''
100 Decorator that prevents a function from being called more than once every
100 Decorator that prevents a function from being called more than once every
101 time period.
101 time period.
102 To create a function that cannot be called more than once a minute, but
102 To create a function that cannot be called more than once a minute, but
103 will sleep until it can be called:
103 will sleep until it can be called:
104 @Throttle(minutes=1)
104 @Throttle(minutes=1)
105 def foo():
105 def foo():
106 pass
106 pass
107
107
108 for i in range(10):
108 for i in range(10):
109 foo()
109 foo()
110 print "This function has run %s times." % i
110 print "This function has run %s times." % i
111 '''
111 '''
112
112
113 def __init__(self, seconds=0, minutes=0, hours=0):
113 def __init__(self, seconds=0, minutes=0, hours=0):
114 self.throttle_period = datetime.timedelta(
114 self.throttle_period = datetime.timedelta(
115 seconds=seconds, minutes=minutes, hours=hours
115 seconds=seconds, minutes=minutes, hours=hours
116 )
116 )
117
117
118 self.time_of_last_call = datetime.datetime.min
118 self.time_of_last_call = datetime.datetime.min
119
119
120 def __call__(self, fn):
120 def __call__(self, fn):
121 @wraps(fn)
121 @wraps(fn)
122 def wrapper(*args, **kwargs):
122 def wrapper(*args, **kwargs):
123 coerce = kwargs.pop('coerce', None)
123 coerce = kwargs.pop('coerce', None)
124 if coerce:
124 if coerce:
125 self.time_of_last_call = datetime.datetime.now()
125 self.time_of_last_call = datetime.datetime.now()
126 return fn(*args, **kwargs)
126 return fn(*args, **kwargs)
127 else:
127 else:
128 now = datetime.datetime.now()
128 now = datetime.datetime.now()
129 time_since_last_call = now - self.time_of_last_call
129 time_since_last_call = now - self.time_of_last_call
130 time_left = self.throttle_period - time_since_last_call
130 time_left = self.throttle_period - time_since_last_call
131
131
132 if time_left > datetime.timedelta(seconds=0):
132 if time_left > datetime.timedelta(seconds=0):
133 return
133 return
134
134
135 self.time_of_last_call = datetime.datetime.now()
135 self.time_of_last_call = datetime.datetime.now()
136 return fn(*args, **kwargs)
136 return fn(*args, **kwargs)
137
137
138 return wrapper
138 return wrapper
139
139
140 def apply_throttle(value):
140 def apply_throttle(value):
141
141
142 @Throttle(seconds=value)
142 @Throttle(seconds=value)
143 def fnThrottled(fn):
143 def fnThrottled(fn):
144 fn()
144 fn()
145
145
146 return fnThrottled
146 return fnThrottled
147
147
148
148
149 @MPDecorator
149 @MPDecorator
150 class Plot(Operation):
150 class Plot(Operation):
151 """Base class for Schain plotting operations
151 """Base class for Schain plotting operations
152
152
153 This class should never be use directtly you must subclass a new operation,
153 This class should never be use directtly you must subclass a new operation,
154 children classes must be defined as follow:
154 children classes must be defined as follow:
155
155
156 ExamplePlot(Plot):
156 ExamplePlot(Plot):
157
157
158 CODE = 'code'
158 CODE = 'code'
159 colormap = 'jet'
159 colormap = 'jet'
160 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
160 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
161
161
162 def setup(self):
162 def setup(self):
163 pass
163 pass
164
164
165 def plot(self):
165 def plot(self):
166 pass
166 pass
167
167
168 """
168 """
169
169
170 CODE = 'Figure'
170 CODE = 'Figure'
171 colormap = 'jet'
171 colormap = 'jet'
172 bgcolor = 'white'
172 bgcolor = 'white'
173 buffering = True
173 buffering = True
174 __missing = 1E30
174 __missing = 1E30
175
175
176 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
176 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
177 'showprofile']
177 'showprofile']
178
178
179 def __init__(self):
179 def __init__(self):
180
180
181 Operation.__init__(self)
181 Operation.__init__(self)
182 self.isConfig = False
182 self.isConfig = False
183 self.isPlotConfig = False
183 self.isPlotConfig = False
184 self.save_time = 0
184 self.save_time = 0
185 self.sender_time = 0
185 self.sender_time = 0
186 self.data = None
186 self.data = None
187 self.firsttime = True
187 self.firsttime = True
188 self.sender_queue = deque(maxlen=10)
188 self.sender_queue = deque(maxlen=10)
189 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
189 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
190
190
191 def __fmtTime(self, x, pos):
191 def __fmtTime(self, x, pos):
192 '''
192 '''
193 '''
193 '''
194
194
195 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
195 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
196
196
197 def __setup(self, **kwargs):
197 def __setup(self, **kwargs):
198 '''
198 '''
199 Initialize variables
199 Initialize variables
200 '''
200 '''
201
201
202 self.figures = []
202 self.figures = []
203 self.axes = []
203 self.axes = []
204 self.cb_axes = []
204 self.cb_axes = []
205 self.localtime = kwargs.pop('localtime', True)
205 self.localtime = kwargs.pop('localtime', True)
206 self.show = kwargs.get('show', True)
206 self.show = kwargs.get('show', True)
207 self.save = kwargs.get('save', False)
207 self.save = kwargs.get('save', False)
208 self.save_period = kwargs.get('save_period', 0)
208 self.save_period = kwargs.get('save_period', 0)
209 self.colormap = kwargs.get('colormap', self.colormap)
209 self.colormap = kwargs.get('colormap', self.colormap)
210 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
210 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
211 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
211 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
212 self.colormaps = kwargs.get('colormaps', None)
212 self.colormaps = kwargs.get('colormaps', None)
213 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
213 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
214 self.showprofile = kwargs.get('showprofile', False)
214 self.showprofile = kwargs.get('showprofile', False)
215 self.title = kwargs.get('wintitle', self.CODE.upper())
215 self.title = kwargs.get('wintitle', self.CODE.upper())
216 self.cb_label = kwargs.get('cb_label', None)
216 self.cb_label = kwargs.get('cb_label', None)
217 self.cb_labels = kwargs.get('cb_labels', None)
217 self.cb_labels = kwargs.get('cb_labels', None)
218 self.labels = kwargs.get('labels', None)
218 self.labels = kwargs.get('labels', None)
219 self.xaxis = kwargs.get('xaxis', 'frequency')
219 self.xaxis = kwargs.get('xaxis', 'frequency')
220 self.zmin = kwargs.get('zmin', None)
220 self.zmin = kwargs.get('zmin', None)
221 self.zmax = kwargs.get('zmax', None)
221 self.zmax = kwargs.get('zmax', None)
222 self.zlimits = kwargs.get('zlimits', None)
222 self.zlimits = kwargs.get('zlimits', None)
223 self.xlimits = kwargs.get('xlimits', None)
223 self.xlimits = kwargs.get('xlimits', None)
224 self.xstep_given = kwargs.get('xstep_given', None)
224 self.xstep_given = kwargs.get('xstep_given', None)
225 self.ystep_given = kwargs.get('ystep_given', None)
225 self.ystep_given = kwargs.get('ystep_given', None)
226 self.autoxticks = kwargs.get('autoxticks', True)
226 self.autoxticks = kwargs.get('autoxticks', True)
227 self.xmin = kwargs.get('xmin', None)
227 self.xmin = kwargs.get('xmin', None)
228 self.xmax = kwargs.get('xmax', None)
228 self.xmax = kwargs.get('xmax', None)
229 self.xrange = kwargs.get('xrange', 12)
229 self.xrange = kwargs.get('xrange', 12)
230 self.xscale = kwargs.get('xscale', None)
230 self.xscale = kwargs.get('xscale', None)
231 self.ymin = kwargs.get('ymin', None)
231 self.ymin = kwargs.get('ymin', None)
232 self.ymax = kwargs.get('ymax', None)
232 self.ymax = kwargs.get('ymax', None)
233 self.yscale = kwargs.get('yscale', None)
233 self.yscale = kwargs.get('yscale', None)
234 self.xlabel = kwargs.get('xlabel', None)
234 self.xlabel = kwargs.get('xlabel', None)
235 self.attr_time = kwargs.get('attr_time', 'utctime')
235 self.attr_time = kwargs.get('attr_time', 'utctime')
236 self.attr_data = kwargs.get('attr_data', 'data_param')
236 self.attr_data = kwargs.get('attr_data', 'data_param')
237 self.decimation = kwargs.get('decimation', None)
237 self.decimation = kwargs.get('decimation', None)
238 self.oneFigure = kwargs.get('oneFigure', True)
238 self.oneFigure = kwargs.get('oneFigure', True)
239 self.width = kwargs.get('width', None)
239 self.width = kwargs.get('width', None)
240 self.height = kwargs.get('height', None)
240 self.height = kwargs.get('height', None)
241 self.colorbar = kwargs.get('colorbar', True)
241 self.colorbar = kwargs.get('colorbar', True)
242 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
242 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
243 self.channels = kwargs.get('channels', None)
243 self.channels = kwargs.get('channels', None)
244 self.titles = kwargs.get('titles', [])
244 self.titles = kwargs.get('titles', [])
245 self.polar = False
245 self.polar = False
246 self.type = kwargs.get('type', 'iq')
246 self.type = kwargs.get('type', 'iq')
247 self.grid = kwargs.get('grid', False)
247 self.grid = kwargs.get('grid', False)
248 self.pause = kwargs.get('pause', False)
248 self.pause = kwargs.get('pause', False)
249 self.save_code = kwargs.get('save_code', self.CODE)
249 self.save_code = kwargs.get('save_code', self.CODE)
250 self.throttle = kwargs.get('throttle', 0)
250 self.throttle = kwargs.get('throttle', 0)
251 self.exp_code = kwargs.get('exp_code', None)
251 self.exp_code = kwargs.get('exp_code', None)
252 self.server = kwargs.get('server', False)
252 self.server = kwargs.get('server', False)
253 self.sender_period = kwargs.get('sender_period', 60)
253 self.sender_period = kwargs.get('sender_period', 60)
254 self.tag = kwargs.get('tag', '')
254 self.tag = kwargs.get('tag', '')
255 self.height_index = kwargs.get('height_index', None)
255 self.height_index = kwargs.get('height_index', None)
256 self.__throttle_plot = apply_throttle(self.throttle)
256 self.__throttle_plot = apply_throttle(self.throttle)
257 code = self.attr_data if self.attr_data else self.CODE
257 code = self.attr_data if self.attr_data else self.CODE
258 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
258 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
259 #self.EEJtype = kwargs.get('EEJtype', 2)
259 #self.EEJtype = kwargs.get('EEJtype', 2)
260
260
261 if self.server:
261 if self.server:
262 if not self.server.startswith('tcp://'):
262 if not self.server.startswith('tcp://'):
263 self.server = 'tcp://{}'.format(self.server)
263 self.server = 'tcp://{}'.format(self.server)
264 log.success(
264 log.success(
265 'Sending to server: {}'.format(self.server),
265 'Sending to server: {}'.format(self.server),
266 self.name
266 self.name
267 )
267 )
268
268
269 if isinstance(self.attr_data, str):
269 if isinstance(self.attr_data, str):
270 self.attr_data = [self.attr_data]
270 self.attr_data = [self.attr_data]
271
271
272 def __setup_plot(self):
272 def __setup_plot(self):
273 '''
273 '''
274 Common setup for all figures, here figures and axes are created
274 Common setup for all figures, here figures and axes are created
275 '''
275 '''
276
276
277 self.setup()
277 self.setup()
278
278
279 self.time_label = 'LT' if self.localtime else 'UTC'
279 self.time_label = 'LT' if self.localtime else 'UTC'
280
280
281 if self.width is None:
281 if self.width is None:
282 self.width = 8
282 self.width = 8
283
283
284 self.figures = []
284 self.figures = []
285 self.axes = []
285 self.axes = []
286 self.cb_axes = []
286 self.cb_axes = []
287 self.pf_axes = []
287 self.pf_axes = []
288 self.cmaps = []
288 self.cmaps = []
289
289
290 size = '15%' if self.ncols == 1 else '30%'
290 size = '15%' if self.ncols == 1 else '30%'
291 pad = '4%' if self.ncols == 1 else '8%'
291 pad = '4%' if self.ncols == 1 else '8%'
292
292
293 if self.oneFigure:
293 if self.oneFigure:
294 if self.height is None:
294 if self.height is None:
295 self.height = 1.4 * self.nrows + 1
295 self.height = 1.4 * self.nrows + 1
296 fig = plt.figure(figsize=(self.width, self.height),
296 fig = plt.figure(figsize=(self.width, self.height),
297 edgecolor='k',
297 edgecolor='k',
298 facecolor='w')
298 facecolor='w')
299 self.figures.append(fig)
299 self.figures.append(fig)
300 for n in range(self.nplots):
300 for n in range(self.nplots):
301 ax = fig.add_subplot(self.nrows, self.ncols,
301 ax = fig.add_subplot(self.nrows, self.ncols,
302 n + 1, polar=self.polar)
302 n + 1, polar=self.polar)
303 ax.tick_params(labelsize=8)
303 ax.tick_params(labelsize=8)
304 ax.firsttime = True
304 ax.firsttime = True
305 ax.index = 0
305 ax.index = 0
306 ax.press = None
306 ax.press = None
307 ax.cbar = None
307 self.axes.append(ax)
308 self.axes.append(ax)
308 if self.showprofile:
309 if self.showprofile:
309 cax = self.__add_axes(ax, size=size, pad=pad)
310 cax = self.__add_axes(ax, size=size, pad=pad)
310 cax.tick_params(labelsize=8)
311 cax.tick_params(labelsize=8)
311 self.pf_axes.append(cax)
312 self.pf_axes.append(cax)
312 else:
313 else:
313 if self.height is None:
314 if self.height is None:
314 self.height = 3
315 self.height = 3
315 for n in range(self.nplots):
316 for n in range(self.nplots):
316 fig = plt.figure(figsize=(self.width, self.height),
317 fig = plt.figure(figsize=(self.width, self.height),
317 edgecolor='k',
318 edgecolor='k',
318 facecolor='w')
319 facecolor='w')
319 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
320 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
320 ax.tick_params(labelsize=8)
321 ax.tick_params(labelsize=8)
321 ax.firsttime = True
322 ax.firsttime = True
322 ax.index = 0
323 ax.index = 0
323 ax.press = None
324 ax.press = None
324 self.figures.append(fig)
325 self.figures.append(fig)
325 self.axes.append(ax)
326 self.axes.append(ax)
326 if self.showprofile:
327 if self.showprofile:
327 cax = self.__add_axes(ax, size=size, pad=pad)
328 cax = self.__add_axes(ax, size=size, pad=pad)
328 cax.tick_params(labelsize=8)
329 cax.tick_params(labelsize=8)
329 self.pf_axes.append(cax)
330 self.pf_axes.append(cax)
330
331
331 for n in range(self.nrows):
332 for n in range(self.nrows):
332 if self.colormaps is not None:
333 if self.colormaps is not None:
333 cmap = plt.get_cmap(self.colormaps[n])
334 cmap = plt.get_cmap(self.colormaps[n])
334 else:
335 else:
335 cmap = plt.get_cmap(self.colormap)
336 cmap = plt.get_cmap(self.colormap)
336 cmap.set_bad(self.bgcolor, 1.)
337 cmap.set_bad(self.bgcolor, 1.)
337 self.cmaps.append(cmap)
338 self.cmaps.append(cmap)
338
339
339 def __add_axes(self, ax, size='30%', pad='8%'):
340 def __add_axes(self, ax, size='30%', pad='8%'):
340 '''
341 '''
341 Add new axes to the given figure
342 Add new axes to the given figure
342 '''
343 '''
343 divider = make_axes_locatable(ax)
344 divider = make_axes_locatable(ax)
344 nax = divider.new_horizontal(size=size, pad=pad)
345 nax = divider.new_horizontal(size=size, pad=pad)
345 ax.figure.add_axes(nax)
346 ax.figure.add_axes(nax)
346 return nax
347 return nax
347
348
348 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
349 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
349 '''
350 '''
350 Create a masked array for missing data
351 Create a masked array for missing data
351 '''
352 '''
352 if x_buffer.shape[0] < 2:
353 if x_buffer.shape[0] < 2:
353 return x_buffer, y_buffer, z_buffer
354 return x_buffer, y_buffer, z_buffer
354
355
355 deltas = x_buffer[1:] - x_buffer[0:-1]
356 deltas = x_buffer[1:] - x_buffer[0:-1]
356 x_median = numpy.median(deltas)
357 x_median = numpy.median(deltas)
357
358
358 index = numpy.where(deltas > 5 * x_median)
359 index = numpy.where(deltas > 5 * x_median)
359
360
360 if len(index[0]) != 0:
361 if len(index[0]) != 0:
361 z_buffer[::, index[0], ::] = self.__missing
362 z_buffer[::, index[0], ::] = self.__missing
362 z_buffer = numpy.ma.masked_inside(z_buffer,
363 z_buffer = numpy.ma.masked_inside(z_buffer,
363 0.99 * self.__missing,
364 0.99 * self.__missing,
364 1.01 * self.__missing)
365 1.01 * self.__missing)
365
366
366 return x_buffer, y_buffer, z_buffer
367 return x_buffer, y_buffer, z_buffer
367
368
368 def decimate(self):
369 def decimate(self):
369
370
370 # dx = int(len(self.x)/self.__MAXNUMX) + 1
371 # dx = int(len(self.x)/self.__MAXNUMX) + 1
371 dy = int(len(self.y) / self.decimation) + 1
372 dy = int(len(self.y) / self.decimation) + 1
372
373
373 # x = self.x[::dx]
374 # x = self.x[::dx]
374 x = self.x
375 x = self.x
375 y = self.y[::dy]
376 y = self.y[::dy]
376 z = self.z[::, ::, ::dy]
377 z = self.z[::, ::, ::dy]
377
378
378 return x, y, z
379 return x, y, z
379
380
380 def format(self):
381 def format(self):
381 '''
382 '''
382 Set min and max values, labels, ticks and titles
383 Set min and max values, labels, ticks and titles
383 '''
384 '''
384
385
385 for n, ax in enumerate(self.axes):
386 for n, ax in enumerate(self.axes):
386 if ax.firsttime:
387 if ax.firsttime:
387 if self.xaxis != 'time':
388 if self.xaxis != 'time':
388 xmin = self.xmin
389 xmin = self.xmin
389 xmax = self.xmax
390 xmax = self.xmax
390 else:
391 else:
391 xmin = self.tmin
392 xmin = self.tmin
392 xmax = self.tmin + self.xrange*60*60
393 xmax = self.tmin + self.xrange*60*60
393 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
394 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
394 ax.xaxis.set_major_locator(LinearLocator(9))
395 ax.xaxis.set_major_locator(LinearLocator(9))
395 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
396 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
396 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
397 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
397 ax.set_facecolor(self.bgcolor)
398 ax.set_facecolor(self.bgcolor)
398 if self.xscale:
399 if self.xscale:
399 ax.xaxis.set_major_formatter(FuncFormatter(
400 ax.xaxis.set_major_formatter(FuncFormatter(
400 lambda x, pos: '{0:g}'.format(x*self.xscale)))
401 lambda x, pos: '{0:g}'.format(x*self.xscale)))
401 if self.yscale:
402 if self.yscale:
402 ax.yaxis.set_major_formatter(FuncFormatter(
403 ax.yaxis.set_major_formatter(FuncFormatter(
403 lambda x, pos: '{0:g}'.format(x*self.yscale)))
404 lambda x, pos: '{0:g}'.format(x*self.yscale)))
404 if self.xlabel is not None:
405 if self.xlabel is not None:
405 ax.set_xlabel(self.xlabel)
406 ax.set_xlabel(self.xlabel)
406 if self.ylabel is not None:
407 if self.ylabel is not None:
407 ax.set_ylabel(self.ylabel)
408 ax.set_ylabel(self.ylabel)
408 if self.showprofile:
409 if self.showprofile:
409 if self.zlimits is not None:
410 if self.zlimits is not None:
410 self.zmin, self.zmax = self.zlimits[n]
411 self.zmin, self.zmax = self.zlimits[n]
411 self.pf_axes[n].set_ylim(ymin, ymax)
412 self.pf_axes[n].set_ylim(ymin, ymax)
412 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
413 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
413 self.pf_axes[n].set_xlabel('dB')
414 self.pf_axes[n].set_xlabel('dB')
414 self.pf_axes[n].grid(b=True, axis='x')
415 self.pf_axes[n].grid(b=True, axis='x')
415 [tick.set_visible(False)
416 [tick.set_visible(False)
416 for tick in self.pf_axes[n].get_yticklabels()]
417 for tick in self.pf_axes[n].get_yticklabels()]
417 if self.colorbar:
418 if self.colorbar and ax.cbar == None:
418 ax.cbar = plt.colorbar(
419 ax.cbar = plt.colorbar(
419 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
420 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
420 ax.cbar.ax.tick_params(labelsize=8)
421 ax.cbar.ax.tick_params(labelsize=8)
421 ax.cbar.ax.press = None
422 ax.cbar.ax.press = None
422 if self.cb_label:
423 if self.cb_label:
423 ax.cbar.set_label(self.cb_label, size=8)
424 ax.cbar.set_label(self.cb_label, size=8)
424 elif self.cb_labels:
425 elif self.cb_labels:
425 ax.cbar.set_label(self.cb_labels[n], size=8)
426 ax.cbar.set_label(self.cb_labels[n], size=8)
426 else:
427 else:
427 ax.cbar = None
428 ax.cbar = None
428 ax.set_xlim(xmin, xmax)
429 ax.set_xlim(xmin, xmax)
429 ax.set_ylim(ymin, ymax)
430 ax.set_ylim(ymin, ymax)
430 ax.firsttime = False
431 ax.firsttime = False
431 if self.grid:
432 if self.grid:
432 ax.grid(True)
433 ax.grid(True)
433 if not self.polar:
434 if not self.polar:
434 ax.set_title('{} {} {}'.format(
435 ax.set_title('{} {} {}'.format(
435 self.titles[n],
436 self.titles[n],
436 self.getDateTime(self.data.max_time).strftime(
437 self.getDateTime(self.data.max_time).strftime(
437 '%Y-%m-%d %H:%M:%S'),
438 '%Y-%m-%d %H:%M:%S'),
438 self.time_label),
439 self.time_label),
439 size=8)
440 size=8)
440 else:
441 else:
441 ax.set_title('{}'.format(self.titles[n]), size=8)
442 ax.set_title('{}'.format(self.titles[n]), size=8)
442 ax.set_ylim(0, 90)
443 ax.set_ylim(0, 90)
443 ax.set_yticks(numpy.arange(0, 90, 20))
444 ax.set_yticks(numpy.arange(0, 90, 20))
444 ax.yaxis.labelpad = 40
445 ax.yaxis.labelpad = 40
445
446
446 if self.firsttime:
447 if self.firsttime:
447 for n, fig in enumerate(self.figures):
448 for n, fig in enumerate(self.figures):
448 fig.subplots_adjust(**self.plots_adjust)
449 fig.subplots_adjust(**self.plots_adjust)
449 self.firsttime = False
450 self.firsttime = False
450
451
451 def clear_figures(self):
452 def clear_figures(self):
452 '''
453 '''
453 Reset axes for redraw plots
454 Reset axes for redraw plots
454 '''
455 '''
455
456
456 for ax in self.axes+self.pf_axes+self.cb_axes:
457 for ax in self.axes+self.pf_axes+self.cb_axes:
457 ax.clear()
458 ax.clear()
458 ax.firsttime = True
459 ax.firsttime = True
459 if hasattr(ax, 'cbar') and ax.cbar:
460 if hasattr(ax, 'cbar') and ax.cbar:
460 ax.cbar.remove()
461 ax.cbar.remove()
461
462
462 def __plot(self):
463 def __plot(self):
463 '''
464 '''
464 Main function to plot, format and save figures
465 Main function to plot, format and save figures
465 '''
466 '''
466
467
467 self.plot()
468 self.plot()
468 self.format()
469 self.format()
469
470
470 for n, fig in enumerate(self.figures):
471 for n, fig in enumerate(self.figures):
471 if self.nrows == 0 or self.nplots == 0:
472 if self.nrows == 0 or self.nplots == 0:
472 log.warning('No data', self.name)
473 log.warning('No data', self.name)
473 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
474 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
474 fig.canvas.manager.set_window_title(self.CODE)
475 fig.canvas.manager.set_window_title(self.CODE)
475 continue
476 continue
476
477
477 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
478 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
478 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
479 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
479 fig.canvas.draw()
480 fig.canvas.draw()
480 if self.show:
481 if self.show:
481 fig.show()
482 fig.show()
482 figpause(0.01)
483 figpause(0.01)
483
484
484 if self.save:
485 if self.save:
485 self.save_figure(n)
486 self.save_figure(n)
486
487
487 if self.server:
488 if self.server:
488 self.send_to_server()
489 self.send_to_server()
489
490
490 def __update(self, dataOut, timestamp):
491 def __update(self, dataOut, timestamp):
491 '''
492 '''
492 '''
493 '''
493
494
494 metadata = {
495 metadata = {
495 'yrange': dataOut.heightList,
496 'yrange': dataOut.heightList,
496 'interval': dataOut.timeInterval,
497 'interval': dataOut.timeInterval,
497 'channels': dataOut.channelList
498 'channels': dataOut.channelList
498 }
499 }
499
500
500 data, meta = self.update(dataOut)
501 data, meta = self.update(dataOut)
501 metadata.update(meta)
502 metadata.update(meta)
502 self.data.update(data, timestamp, metadata)
503 self.data.update(data, timestamp, metadata)
503
504
504 def save_figure(self, n):
505 def save_figure(self, n):
505 '''
506 '''
506 '''
507 '''
507
508
508 if (self.data.max_time - self.save_time) <= self.save_period:
509 if (self.data.max_time - self.save_time) <= self.save_period:
509 return
510 return
510
511
511 self.save_time = self.data.max_time
512 self.save_time = self.data.max_time
512
513
513 fig = self.figures[n]
514 fig = self.figures[n]
514
515
515 if self.throttle == 0:
516 if self.throttle == 0:
516 figname = os.path.join(
517 figname = os.path.join(
517 self.save,
518 self.save,
518 self.save_code,
519 self.save_code,
519 '{}_{}.png'.format(
520 '{}_{}.png'.format(
520 self.save_code,
521 self.save_code,
521 self.getDateTime(self.data.max_time).strftime(
522 self.getDateTime(self.data.max_time).strftime(
522 '%Y%m%d_%H%M%S'
523 '%Y%m%d_%H%M%S'
523 ),
524 ),
524 )
525 )
525 )
526 )
526 log.log('Saving figure: {}'.format(figname), self.name)
527 log.log('Saving figure: {}'.format(figname), self.name)
527 if not os.path.isdir(os.path.dirname(figname)):
528 if not os.path.isdir(os.path.dirname(figname)):
528 os.makedirs(os.path.dirname(figname))
529 os.makedirs(os.path.dirname(figname))
529 fig.savefig(figname)
530 fig.savefig(figname)
530
531
531 figname = os.path.join(
532 figname = os.path.join(
532 self.save,
533 self.save,
533 #self.save_code,
534 #self.save_code,
534 '{}_{}.png'.format(
535 '{}_{}.png'.format(
535 self.save_code,
536 self.save_code,
536 self.getDateTime(self.data.min_time).strftime(
537 self.getDateTime(self.data.min_time).strftime(
537 '%Y%m%d'
538 '%Y%m%d'
538 ),
539 ),
539 )
540 )
540 )
541 )
541 log.log('Saving figure: {}'.format(figname), self.name)
542 log.log('Saving figure: {}'.format(figname), self.name)
542 if not os.path.isdir(os.path.dirname(figname)):
543 if not os.path.isdir(os.path.dirname(figname)):
543 os.makedirs(os.path.dirname(figname))
544 os.makedirs(os.path.dirname(figname))
544 fig.savefig(figname)
545 fig.savefig(figname)
545
546
546 def send_to_server(self):
547 def send_to_server(self):
547 '''
548 '''
548 '''
549 '''
549
550
550 if self.exp_code == None:
551 if self.exp_code == None:
551 log.warning('Missing `exp_code` skipping sending to server...')
552 log.warning('Missing `exp_code` skipping sending to server...')
552
553
553 last_time = self.data.max_time
554 last_time = self.data.max_time
554 interval = last_time - self.sender_time
555 interval = last_time - self.sender_time
555 if interval < self.sender_period:
556 if interval < self.sender_period:
556 return
557 return
557
558
558 self.sender_time = last_time
559 self.sender_time = last_time
559
560
560 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax', 'zlimits']
561 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax', 'zlimits']
561 for attr in attrs:
562 for attr in attrs:
562 value = getattr(self, attr)
563 value = getattr(self, attr)
563 if value:
564 if value:
564 if isinstance(value, (numpy.float32, numpy.float64)):
565 if isinstance(value, (numpy.float32, numpy.float64)):
565 value = round(float(value), 2)
566 value = round(float(value), 2)
566 self.data.meta[attr] = value
567 self.data.meta[attr] = value
567 if self.colormap == 'jet':
568 if self.colormap == 'jet':
568 self.data.meta['colormap'] = 'Jet'
569 self.data.meta['colormap'] = 'Jet'
569 elif 'RdBu' in self.colormap:
570 elif 'RdBu' in self.colormap:
570 self.data.meta['colormap'] = 'RdBu'
571 self.data.meta['colormap'] = 'RdBu'
571 else:
572 else:
572 self.data.meta['colormap'] = 'Viridis'
573 self.data.meta['colormap'] = 'Viridis'
573 self.data.meta['interval'] = int(interval)
574 self.data.meta['interval'] = int(interval)
574 #print(last_time)
575 #print(last_time)
575 #print(time.time())
576 #print(time.time())
576 #exit(1)
577 #exit(1)
577 self.sender_queue.append(last_time)
578 self.sender_queue.append(last_time)
578
579
579 while True:
580 while True:
580 try:
581 try:
581 tm = self.sender_queue.popleft()
582 tm = self.sender_queue.popleft()
582 except IndexError:
583 except IndexError:
583 break
584 break
584 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
585 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
585 self.socket.send_string(msg)
586 self.socket.send_string(msg)
586 socks = dict(self.poll.poll(2000))
587 socks = dict(self.poll.poll(2000))
587 if socks.get(self.socket) == zmq.POLLIN:
588 if socks.get(self.socket) == zmq.POLLIN:
588 reply = self.socket.recv_string()
589 reply = self.socket.recv_string()
589 if reply == 'ok':
590 if reply == 'ok':
590 log.log("Response from server ok", self.name)
591 log.log("Response from server ok", self.name)
591 time.sleep(0.1)
592 time.sleep(0.1)
592 continue
593 continue
593 else:
594 else:
594 log.warning(
595 log.warning(
595 "Malformed reply from server: {}".format(reply), self.name)
596 "Malformed reply from server: {}".format(reply), self.name)
596 else:
597 else:
597 log.warning(
598 log.warning(
598 "No response from server, retrying...", self.name)
599 "No response from server, retrying...", self.name)
599 self.sender_queue.appendleft(tm)
600 self.sender_queue.appendleft(tm)
600 self.socket.setsockopt(zmq.LINGER, 0)
601 self.socket.setsockopt(zmq.LINGER, 0)
601 self.socket.close()
602 self.socket.close()
602 self.poll.unregister(self.socket)
603 self.poll.unregister(self.socket)
603 self.socket = self.context.socket(zmq.REQ)
604 self.socket = self.context.socket(zmq.REQ)
604 self.socket.connect(self.server)
605 self.socket.connect(self.server)
605 self.poll.register(self.socket, zmq.POLLIN)
606 self.poll.register(self.socket, zmq.POLLIN)
606 break
607 break
607
608
608 def setup(self):
609 def setup(self):
609 '''
610 '''
610 This method should be implemented in the child class, the following
611 This method should be implemented in the child class, the following
611 attributes should be set:
612 attributes should be set:
612
613
613 self.nrows: number of rows
614 self.nrows: number of rows
614 self.ncols: number of cols
615 self.ncols: number of cols
615 self.nplots: number of plots (channels or pairs)
616 self.nplots: number of plots (channels or pairs)
616 self.ylabel: label for Y axes
617 self.ylabel: label for Y axes
617 self.titles: list of axes title
618 self.titles: list of axes title
618
619
619 '''
620 '''
620 raise NotImplementedError
621 raise NotImplementedError
621
622
622 def plot(self):
623 def plot(self):
623 '''
624 '''
624 Must be defined in the child class, the actual plotting method
625 Must be defined in the child class, the actual plotting method
625 '''
626 '''
626 raise NotImplementedError
627 raise NotImplementedError
627
628
628 def update(self, dataOut):
629 def update(self, dataOut):
629 '''
630 '''
630 Must be defined in the child class, update self.data with new data
631 Must be defined in the child class, update self.data with new data
631 '''
632 '''
632
633
633 data = {
634 data = {
634 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
635 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
635 }
636 }
636 meta = {}
637 meta = {}
637
638
638 return data, meta
639 return data, meta
639
640
640 def run(self, dataOut, **kwargs):
641 def run(self, dataOut, **kwargs):
641 '''
642 '''
642 Main plotting routine
643 Main plotting routine
643 '''
644 '''
644
645
645 if self.isConfig is False:
646 if self.isConfig is False:
646 self.__setup(**kwargs)
647 self.__setup(**kwargs)
647
648
648 if self.localtime:
649 if self.localtime:
649 self.getDateTime = datetime.datetime.fromtimestamp
650 self.getDateTime = datetime.datetime.fromtimestamp
650 else:
651 else:
651 self.getDateTime = datetime.datetime.utcfromtimestamp
652 self.getDateTime = datetime.datetime.utcfromtimestamp
652
653
653 self.data.setup()
654 self.data.setup()
654 self.isConfig = True
655 self.isConfig = True
655 if self.server:
656 if self.server:
656 self.context = zmq.Context()
657 self.context = zmq.Context()
657 self.socket = self.context.socket(zmq.REQ)
658 self.socket = self.context.socket(zmq.REQ)
658 self.socket.connect(self.server)
659 self.socket.connect(self.server)
659 self.poll = zmq.Poller()
660 self.poll = zmq.Poller()
660 self.poll.register(self.socket, zmq.POLLIN)
661 self.poll.register(self.socket, zmq.POLLIN)
661
662
662 tm = getattr(dataOut, self.attr_time)
663 tm = getattr(dataOut, self.attr_time)
663 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
664 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
664 self.save_time = tm
665 self.save_time = tm
665 self.__plot()
666 self.__plot()
666 #self.tmin += self.xrange*60*60 #Modified by R. Flores
667 #self.tmin += self.xrange*60*60 #Modified by R. Flores
667 self.tmin += 24*60*60 #Modified by R. Flores
668 self.tmin += 24*60*60 #Modified by R. Flores
668
669
669 self.data.setup()
670 self.data.setup()
670 self.clear_figures()
671 self.clear_figures()
671
672
672 self.__update(dataOut, tm)
673 self.__update(dataOut, tm)
673
674
674 if self.isPlotConfig is False:
675 if self.isPlotConfig is False:
675 self.__setup_plot()
676 self.__setup_plot()
676 self.isPlotConfig = True
677 self.isPlotConfig = True
677 if self.xaxis == 'time':
678 if self.xaxis == 'time':
678 dt = self.getDateTime(tm)
679 dt = self.getDateTime(tm)
679
680
680 if self.xmin is None:
681 if self.xmin is None:
681 self.tmin = tm
682 self.tmin = tm
682 self.xmin = dt.hour
683 self.xmin = dt.hour
683 minutes = (self.xmin-int(self.xmin)) * 60
684 minutes = (self.xmin-int(self.xmin)) * 60
684 seconds = (minutes - int(minutes)) * 60
685 seconds = (minutes - int(minutes)) * 60
685 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
686 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
686 datetime.datetime(1970, 1, 1)).total_seconds()
687 datetime.datetime(1970, 1, 1)).total_seconds()
687 if self.localtime:
688 if self.localtime:
688 self.tmin += time.timezone
689 self.tmin += time.timezone
689
690
690 if self.xmin is not None and self.xmax is not None:
691 if self.xmin is not None and self.xmax is not None:
691 self.xrange = self.xmax - self.xmin
692 self.xrange = self.xmax - self.xmin
692
693
693 if self.throttle == 0:
694 if self.throttle == 0:
694 self.__plot()
695 self.__plot()
695 else:
696 else:
696 self.__throttle_plot(self.__plot)#, coerce=coerce)
697 self.__throttle_plot(self.__plot)#, coerce=coerce)
697
698
698 def close(self):
699 def close(self):
699
700
700 if self.data and not self.data.flagNoData:
701 if self.data and not self.data.flagNoData:
701 self.save_time = 0
702 self.save_time = 0
702 self.__plot()
703 self.__plot()
703 if self.data and not self.data.flagNoData and self.pause:
704 if self.data and not self.data.flagNoData and self.pause:
704 figpause(10)
705 figpause(10)
@@ -1,494 +1,494
1 import os
1 import os
2 import datetime
2 import datetime
3 import numpy
3 import numpy
4
4
5 from schainpy.model.graphics.jroplot_base import Plot, plt
5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
7 from schainpy.utils import log
7 from schainpy.utils import log
8
8
9 EARTH_RADIUS = 6.3710e3
9 EARTH_RADIUS = 6.3710e3
10
10
11
11
12 def ll2xy(lat1, lon1, lat2, lon2):
12 def ll2xy(lat1, lon1, lat2, lon2):
13
13
14 p = 0.017453292519943295
14 p = 0.017453292519943295
15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
20 theta = -theta + numpy.pi/2
20 theta = -theta + numpy.pi/2
21 return r*numpy.cos(theta), r*numpy.sin(theta)
21 return r*numpy.cos(theta), r*numpy.sin(theta)
22
22
23
23
24 def km2deg(km):
24 def km2deg(km):
25 '''
25 '''
26 Convert distance in km to degrees
26 Convert distance in km to degrees
27 '''
27 '''
28
28
29 return numpy.rad2deg(km/EARTH_RADIUS)
29 return numpy.rad2deg(km/EARTH_RADIUS)
30
30
31
31
32
32
33 class SpectralMomentsPlot(SpectraPlot):
33 class SpectralMomentsPlot(SpectraPlot):
34 '''
34 '''
35 Plot for Spectral Moments
35 Plot for Spectral Moments
36 '''
36 '''
37 CODE = 'spc_moments'
37 CODE = 'spc_moments'
38 # colormap = 'jet'
38 # colormap = 'jet'
39 # plot_type = 'pcolor'
39 # plot_type = 'pcolor'
40
40
41 class DobleGaussianPlot(SpectraPlot):
41 class DobleGaussianPlot(SpectraPlot):
42 '''
42 '''
43 Plot for Double Gaussian Plot
43 Plot for Double Gaussian Plot
44 '''
44 '''
45 CODE = 'gaussian_fit'
45 CODE = 'gaussian_fit'
46 # colormap = 'jet'
46 # colormap = 'jet'
47 # plot_type = 'pcolor'
47 # plot_type = 'pcolor'
48
48
49
49
50 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
50 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
51 '''
51 '''
52 Plot SpectraCut with Double Gaussian Fit
52 Plot SpectraCut with Double Gaussian Fit
53 '''
53 '''
54 CODE = 'cut_gaussian_fit'
54 CODE = 'cut_gaussian_fit'
55
55
56
56
57 class SpectralFitObliquePlot(SpectraPlot):
57 class SpectralFitObliquePlot(SpectraPlot):
58 '''
58 '''
59 Plot for Spectral Oblique
59 Plot for Spectral Oblique
60 '''
60 '''
61 CODE = 'spc_moments'
61 CODE = 'spc_moments'
62 colormap = 'jet'
62 colormap = 'jet'
63 plot_type = 'pcolor'
63 plot_type = 'pcolor'
64
64
65
65
66
66
67 class SnrPlot(RTIPlot):
67 class SnrPlot(RTIPlot):
68 '''
68 '''
69 Plot for SNR Data
69 Plot for SNR Data
70 '''
70 '''
71
71
72 CODE = 'snr'
72 CODE = 'snr'
73 colormap = 'jet'
73 colormap = 'jet'
74
74
75 def update(self, dataOut):
75 def update(self, dataOut):
76
76
77 data = {
77 data = {
78 'snr': 10*numpy.log10(dataOut.data_snr)
78 'snr': 10*numpy.log10(dataOut.data_snr)
79 }
79 }
80
80
81 return data, {}
81 return data, {}
82
82
83 class DopplerPlot(RTIPlot):
83 class DopplerPlot(RTIPlot):
84 '''
84 '''
85 Plot for DOPPLER Data (1st moment)
85 Plot for DOPPLER Data (1st moment)
86 '''
86 '''
87
87
88 CODE = 'dop'
88 CODE = 'dop'
89 colormap = 'jet'
89 colormap = 'jet'
90
90
91 def update(self, dataOut):
91 def update(self, dataOut):
92
92
93 data = {
93 data = {
94 'dop': 10*numpy.log10(dataOut.data_dop)
94 'dop': 10*numpy.log10(dataOut.data_dop)
95 }
95 }
96
96
97 return data, {}
97 return data, {}
98
98
99 class DopplerEEJPlot_V0(RTIPlot):
99 class DopplerEEJPlot_V0(RTIPlot):
100 '''
100 '''
101 Written by R. Flores
101 Written by R. Flores
102 '''
102 '''
103 '''
103 '''
104 Plot for EEJ
104 Plot for EEJ
105 '''
105 '''
106
106
107 CODE = 'dop'
107 CODE = 'dop'
108 colormap = 'RdBu_r'
108 colormap = 'RdBu_r'
109 colormap = 'jet'
109 colormap = 'jet'
110
110
111 def setup(self):
111 def setup(self):
112
112
113 self.xaxis = 'time'
113 self.xaxis = 'time'
114 self.ncols = 1
114 self.ncols = 1
115 self.nrows = len(self.data.channels)
115 self.nrows = len(self.data.channels)
116 self.nplots = len(self.data.channels)
116 self.nplots = len(self.data.channels)
117 self.ylabel = 'Range [km]'
117 self.ylabel = 'Range [km]'
118 self.xlabel = 'Time'
118 self.xlabel = 'Time'
119 self.cb_label = '(m/s)'
119 self.cb_label = '(m/s)'
120 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
120 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
121 self.titles = ['{} Channel {}'.format(
121 self.titles = ['{} Channel {}'.format(
122 self.CODE.upper(), x) for x in range(self.nrows)]
122 self.CODE.upper(), x) for x in range(self.nrows)]
123
123
124 def update(self, dataOut):
124 def update(self, dataOut):
125 #print(self.EEJtype)
125 #print(self.EEJtype)
126
126
127 if self.EEJtype == 1:
127 if self.EEJtype == 1:
128 data = {
128 data = {
129 'dop': dataOut.Oblique_params[:,-2,:]
129 'dop': dataOut.Oblique_params[:,-2,:]
130 }
130 }
131 elif self.EEJtype == 2:
131 elif self.EEJtype == 2:
132 data = {
132 data = {
133 'dop': dataOut.Oblique_params[:,-1,:]
133 'dop': dataOut.Oblique_params[:,-1,:]
134 }
134 }
135
135
136 return data, {}
136 return data, {}
137
137
138 class DopplerEEJPlot(RTIPlot):
138 class DopplerEEJPlot(RTIPlot):
139 '''
139 '''
140 Written by R. Flores
140 Written by R. Flores
141 '''
141 '''
142 '''
142 '''
143 Plot for Doppler Shift EEJ
143 Plot for Doppler Shift EEJ
144 '''
144 '''
145
145
146 CODE = 'dop'
146 CODE = 'dop'
147 colormap = 'RdBu_r'
147 colormap = 'RdBu_r'
148 #colormap = 'jet'
148 #colormap = 'jet'
149
149
150 def setup(self):
150 def setup(self):
151
151
152 self.xaxis = 'time'
152 self.xaxis = 'time'
153 self.ncols = 1
153 self.ncols = 1
154 self.nrows = 2
154 self.nrows = 2
155 self.nplots = 2
155 self.nplots = 2
156 self.ylabel = 'Range [km]'
156 self.ylabel = 'Range [km]'
157 self.xlabel = 'Time'
157 self.xlabel = 'Time'
158 self.cb_label = '(m/s)'
158 self.cb_label = '(m/s)'
159 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
159 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
160 self.titles = ['{} EJJ Type {} /'.format(
160 self.titles = ['{} EJJ Type {} /'.format(
161 self.CODE.upper(), x) for x in range(1,1+self.nrows)]
161 self.CODE.upper(), x) for x in range(1,1+self.nrows)]
162
162
163 def update(self, dataOut):
163 def update(self, dataOut):
164
164
165 if dataOut.mode == 11: #Double Gaussian
165 if dataOut.mode == 11: #Double Gaussian
166 doppler = numpy.append(dataOut.Oblique_params[:,1,:],dataOut.Oblique_params[:,4,:],axis=0)
166 doppler = numpy.append(dataOut.Oblique_params[:,1,:],dataOut.Oblique_params[:,4,:],axis=0)
167 elif dataOut.mode == 9: #Double Skew Gaussian
167 elif dataOut.mode == 9: #Double Skew Gaussian
168 doppler = numpy.append(dataOut.Oblique_params[:,-2,:],dataOut.Oblique_params[:,-1,:],axis=0)
168 doppler = numpy.append(dataOut.Oblique_params[:,-2,:],dataOut.Oblique_params[:,-1,:],axis=0)
169 data = {
169 data = {
170 'dop': doppler
170 'dop': doppler
171 }
171 }
172
172
173 return data, {}
173 return data, {}
174
174
175 class SpcWidthEEJPlot(RTIPlot):
175 class SpcWidthEEJPlot(RTIPlot):
176 '''
176 '''
177 Written by R. Flores
177 Written by R. Flores
178 '''
178 '''
179 '''
179 '''
180 Plot for EEJ Spectral Width
180 Plot for EEJ Spectral Width
181 '''
181 '''
182
182
183 CODE = 'width'
183 CODE = 'width'
184 colormap = 'RdBu_r'
184 colormap = 'RdBu_r'
185 colormap = 'jet'
185 colormap = 'jet'
186
186
187 def setup(self):
187 def setup(self):
188
188
189 self.xaxis = 'time'
189 self.xaxis = 'time'
190 self.ncols = 1
190 self.ncols = 1
191 self.nrows = 2
191 self.nrows = 2
192 self.nplots = 2
192 self.nplots = 2
193 self.ylabel = 'Range [km]'
193 self.ylabel = 'Range [km]'
194 self.xlabel = 'Time'
194 self.xlabel = 'Time'
195 self.cb_label = '(m/s)'
195 self.cb_label = '(m/s)'
196 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
196 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
197 self.titles = ['{} EJJ Type {} /'.format(
197 self.titles = ['{} EJJ Type {} /'.format(
198 self.CODE.upper(), x) for x in range(1,1+self.nrows)]
198 self.CODE.upper(), x) for x in range(1,1+self.nrows)]
199
199
200 def update(self, dataOut):
200 def update(self, dataOut):
201
201
202 if dataOut.mode == 11: #Double Gaussian
202 if dataOut.mode == 11: #Double Gaussian
203 width = numpy.append(dataOut.Oblique_params[:,2,:],dataOut.Oblique_params[:,5,:],axis=0)
203 width = numpy.append(dataOut.Oblique_params[:,2,:],dataOut.Oblique_params[:,5,:],axis=0)
204 elif dataOut.mode == 9: #Double Skew Gaussian
204 elif dataOut.mode == 9: #Double Skew Gaussian
205 width = numpy.append(dataOut.Oblique_params[:,2,:],dataOut.Oblique_params[:,6,:],axis=0)
205 width = numpy.append(dataOut.Oblique_params[:,2,:],dataOut.Oblique_params[:,6,:],axis=0)
206 data = {
206 data = {
207 'width': width
207 'width': width
208 }
208 }
209
209
210 return data, {}
210 return data, {}
211
211
212 class PowerPlot(RTIPlot):
212 class PowerPlot(RTIPlot):
213 '''
213 '''
214 Plot for Power Data (0 moment)
214 Plot for Power Data (0 moment)
215 '''
215 '''
216
216
217 CODE = 'pow'
217 CODE = 'pow'
218 colormap = 'jet'
218 colormap = 'jet'
219
219
220 def update(self, dataOut):
220 def update(self, dataOut):
221
221
222 data = {
222 data = {
223 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
223 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
224 }
224 }
225
225
226 return data, {}
226 return data, {}
227
227
228 class SpectralWidthPlot(RTIPlot):
228 class SpectralWidthPlot(RTIPlot):
229 '''
229 '''
230 Plot for Spectral Width Data (2nd moment)
230 Plot for Spectral Width Data (2nd moment)
231 '''
231 '''
232
232
233 CODE = 'width'
233 CODE = 'width'
234 colormap = 'jet'
234 colormap = 'jet'
235
235
236 def update(self, dataOut):
236 def update(self, dataOut):
237
237
238 data = {
238 data = {
239 'width': dataOut.data_width
239 'width': dataOut.data_width
240 }
240 }
241
241
242 return data, {}
242 return data, {}
243
243
244 class SkyMapPlot(Plot):
244 class SkyMapPlot(Plot):
245 '''
245 '''
246 Plot for meteors detection data
246 Plot for meteors detection data
247 '''
247 '''
248
248
249 CODE = 'param'
249 CODE = 'param'
250
250
251 def setup(self):
251 def setup(self):
252
252
253 self.ncols = 1
253 self.ncols = 1
254 self.nrows = 1
254 self.nrows = 1
255 self.width = 7.2
255 self.width = 7.2
256 self.height = 7.2
256 self.height = 7.2
257 self.nplots = 1
257 self.nplots = 1
258 self.xlabel = 'Zonal Zenith Angle (deg)'
258 self.xlabel = 'Zonal Zenith Angle (deg)'
259 self.ylabel = 'Meridional Zenith Angle (deg)'
259 self.ylabel = 'Meridional Zenith Angle (deg)'
260 self.polar = True
260 self.polar = True
261 self.ymin = -180
261 self.ymin = -180
262 self.ymax = 180
262 self.ymax = 180
263 self.colorbar = False
263 self.colorbar = False
264
264
265 def plot(self):
265 def plot(self):
266
266
267 arrayParameters = numpy.concatenate(self.data['param'])
267 arrayParameters = numpy.concatenate(self.data['param'])
268 error = arrayParameters[:, -1]
268 error = arrayParameters[:, -1]
269 indValid = numpy.where(error == 0)[0]
269 indValid = numpy.where(error == 0)[0]
270 finalMeteor = arrayParameters[indValid, :]
270 finalMeteor = arrayParameters[indValid, :]
271 finalAzimuth = finalMeteor[:, 3]
271 finalAzimuth = finalMeteor[:, 3]
272 finalZenith = finalMeteor[:, 4]
272 finalZenith = finalMeteor[:, 4]
273
273
274 x = finalAzimuth * numpy.pi / 180
274 x = finalAzimuth * numpy.pi / 180
275 y = finalZenith
275 y = finalZenith
276
276
277 ax = self.axes[0]
277 ax = self.axes[0]
278
278
279 if ax.firsttime:
279 if ax.firsttime:
280 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
280 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
281 else:
281 else:
282 ax.plot.set_data(x, y)
282 ax.plot.set_data(x, y)
283
283
284 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
284 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
285 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
285 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
286 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
286 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
287 dt2,
287 dt2,
288 len(x))
288 len(x))
289 self.titles[0] = title
289 self.titles[0] = title
290
290
291
291
292 class GenericRTIPlot(Plot):
292 class GenericRTIPlot(Plot):
293 '''
293 '''
294 Plot for data_xxxx object
294 Plot for data_xxxx object
295 '''
295 '''
296
296
297 CODE = 'param'
297 CODE = 'param'
298 colormap = 'viridis'
298 colormap = 'viridis'
299 plot_type = 'pcolorbuffer'
299 plot_type = 'pcolorbuffer'
300
300
301 def setup(self):
301 def setup(self):
302 self.xaxis = 'time'
302 self.xaxis = 'time'
303 self.ncols = 1
303 self.ncols = 1
304 self.nrows = self.data.shape('param')[0]
304 self.nrows = self.data.shape('param')[0]
305 self.nplots = self.nrows
305 self.nplots = self.nrows
306 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
306 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
307
307
308 if not self.xlabel:
308 if not self.xlabel:
309 self.xlabel = 'Time'
309 self.xlabel = 'Time'
310
310
311 self.ylabel = 'Range [km]'
311 self.ylabel = 'Range [km]'
312 if not self.titles:
312 if not self.titles:
313 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
313 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
314
314
315 def update(self, dataOut):
315 def update(self, dataOut):
316
316
317 data = {
317 data = {
318 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
318 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
319 }
319 }
320
320
321 meta = {}
321 meta = {}
322
322
323 return data, meta
323 return data, meta
324
324
325 def plot(self):
325 def plot(self):
326 # self.data.normalize_heights()
326 # self.data.normalize_heights()
327 self.x = self.data.times
327 self.x = self.data.times
328 self.y = self.data.yrange
328 self.y = self.data.yrange
329 self.z = self.data['param']
329 self.z = self.data['param']
330
330
331 self.z = numpy.ma.masked_invalid(self.z)
331 self.z = numpy.ma.masked_invalid(self.z)
332
332
333 if self.decimation is None:
333 if self.decimation is None:
334 x, y, z = self.fill_gaps(self.x, self.y, self.z)
334 x, y, z = self.fill_gaps(self.x, self.y, self.z)
335 else:
335 else:
336 x, y, z = self.fill_gaps(*self.decimate())
336 x, y, z = self.fill_gaps(*self.decimate())
337
337
338 for n, ax in enumerate(self.axes):
338 for n, ax in enumerate(self.axes):
339
339
340 self.zmax = self.zmax if self.zmax is not None else numpy.max(
340 self.zmax = self.zmax if self.zmax is not None else numpy.max(
341 self.z[n])
341 self.z[n])
342 self.zmin = self.zmin if self.zmin is not None else numpy.min(
342 self.zmin = self.zmin if self.zmin is not None else numpy.min(
343 self.z[n])
343 self.z[n])
344
344
345 if ax.firsttime:
345 if ax.firsttime:
346 if self.zlimits is not None:
346 if self.zlimits is not None:
347 self.zmin, self.zmax = self.zlimits[n]
347 self.zmin, self.zmax = self.zlimits[n]
348
348
349 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
349 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
350 vmin=self.zmin,
350 vmin=self.zmin,
351 vmax=self.zmax,
351 vmax=self.zmax,
352 cmap=self.cmaps[n]
352 cmap=self.cmaps[n]
353 )
353 )
354 else:
354 else:
355 if self.zlimits is not None:
355 if self.zlimits is not None:
356 self.zmin, self.zmax = self.zlimits[n]
356 self.zmin, self.zmax = self.zlimits[n]
357 ax.collections.remove(ax.collections[0])
357 ax.plt.remove()
358 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
358 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
359 vmin=self.zmin,
359 vmin=self.zmin,
360 vmax=self.zmax,
360 vmax=self.zmax,
361 cmap=self.cmaps[n]
361 cmap=self.cmaps[n]
362 )
362 )
363
363
364
364
365 class PolarMapPlot(Plot):
365 class PolarMapPlot(Plot):
366 '''
366 '''
367 Plot for weather radar
367 Plot for weather radar
368 '''
368 '''
369
369
370 CODE = 'param'
370 CODE = 'param'
371 colormap = 'seismic'
371 colormap = 'seismic'
372
372
373 def setup(self):
373 def setup(self):
374 self.ncols = 1
374 self.ncols = 1
375 self.nrows = 1
375 self.nrows = 1
376 self.width = 9
376 self.width = 9
377 self.height = 8
377 self.height = 8
378 self.mode = self.data.meta['mode']
378 self.mode = self.data.meta['mode']
379 if self.channels is not None:
379 if self.channels is not None:
380 self.nplots = len(self.channels)
380 self.nplots = len(self.channels)
381 self.nrows = len(self.channels)
381 self.nrows = len(self.channels)
382 else:
382 else:
383 self.nplots = self.data.shape(self.CODE)[0]
383 self.nplots = self.data.shape(self.CODE)[0]
384 self.nrows = self.nplots
384 self.nrows = self.nplots
385 self.channels = list(range(self.nplots))
385 self.channels = list(range(self.nplots))
386 if self.mode == 'E':
386 if self.mode == 'E':
387 self.xlabel = 'Longitude'
387 self.xlabel = 'Longitude'
388 self.ylabel = 'Latitude'
388 self.ylabel = 'Latitude'
389 else:
389 else:
390 self.xlabel = 'Range (km)'
390 self.xlabel = 'Range (km)'
391 self.ylabel = 'Height (km)'
391 self.ylabel = 'Height (km)'
392 self.bgcolor = 'white'
392 self.bgcolor = 'white'
393 self.cb_labels = self.data.meta['units']
393 self.cb_labels = self.data.meta['units']
394 self.lat = self.data.meta['latitude']
394 self.lat = self.data.meta['latitude']
395 self.lon = self.data.meta['longitude']
395 self.lon = self.data.meta['longitude']
396 self.xmin, self.xmax = float(
396 self.xmin, self.xmax = float(
397 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
397 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
398 self.ymin, self.ymax = float(
398 self.ymin, self.ymax = float(
399 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
399 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
400 # self.polar = True
400 # self.polar = True
401
401
402 def plot(self):
402 def plot(self):
403
403
404 for n, ax in enumerate(self.axes):
404 for n, ax in enumerate(self.axes):
405 data = self.data['param'][self.channels[n]]
405 data = self.data['param'][self.channels[n]]
406
406
407 zeniths = numpy.linspace(
407 zeniths = numpy.linspace(
408 0, self.data.meta['max_range'], data.shape[1])
408 0, self.data.meta['max_range'], data.shape[1])
409 if self.mode == 'E':
409 if self.mode == 'E':
410 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
410 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
411 r, theta = numpy.meshgrid(zeniths, azimuths)
411 r, theta = numpy.meshgrid(zeniths, azimuths)
412 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
412 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
413 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
413 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
414 x = km2deg(x) + self.lon
414 x = km2deg(x) + self.lon
415 y = km2deg(y) + self.lat
415 y = km2deg(y) + self.lat
416 else:
416 else:
417 azimuths = numpy.radians(self.data.yrange)
417 azimuths = numpy.radians(self.data.yrange)
418 r, theta = numpy.meshgrid(zeniths, azimuths)
418 r, theta = numpy.meshgrid(zeniths, azimuths)
419 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
419 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
420 self.y = zeniths
420 self.y = zeniths
421
421
422 if ax.firsttime:
422 if ax.firsttime:
423 if self.zlimits is not None:
423 if self.zlimits is not None:
424 self.zmin, self.zmax = self.zlimits[n]
424 self.zmin, self.zmax = self.zlimits[n]
425 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
425 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
426 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
426 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
427 vmin=self.zmin,
427 vmin=self.zmin,
428 vmax=self.zmax,
428 vmax=self.zmax,
429 cmap=self.cmaps[n])
429 cmap=self.cmaps[n])
430 else:
430 else:
431 if self.zlimits is not None:
431 if self.zlimits is not None:
432 self.zmin, self.zmax = self.zlimits[n]
432 self.zmin, self.zmax = self.zlimits[n]
433 ax.collections.remove(ax.collections[0])
433 ax.plt.remove()
434 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
434 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
435 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
435 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
436 vmin=self.zmin,
436 vmin=self.zmin,
437 vmax=self.zmax,
437 vmax=self.zmax,
438 cmap=self.cmaps[n])
438 cmap=self.cmaps[n])
439
439
440 if self.mode == 'A':
440 if self.mode == 'A':
441 continue
441 continue
442
442
443 # plot district names
443 # plot district names
444 f = open('/data/workspace/schain_scripts/distrito.csv')
444 f = open('/data/workspace/schain_scripts/distrito.csv')
445 for line in f:
445 for line in f:
446 label, lon, lat = [s.strip() for s in line.split(',') if s]
446 label, lon, lat = [s.strip() for s in line.split(',') if s]
447 lat = float(lat)
447 lat = float(lat)
448 lon = float(lon)
448 lon = float(lon)
449 # ax.plot(lon, lat, '.b', ms=2)
449 # ax.plot(lon, lat, '.b', ms=2)
450 ax.text(lon, lat, label.decode('utf8'), ha='center',
450 ax.text(lon, lat, label.decode('utf8'), ha='center',
451 va='bottom', size='8', color='black')
451 va='bottom', size='8', color='black')
452
452
453 # plot limites
453 # plot limites
454 limites = []
454 limites = []
455 tmp = []
455 tmp = []
456 for line in open('/data/workspace/schain_scripts/lima.csv'):
456 for line in open('/data/workspace/schain_scripts/lima.csv'):
457 if '#' in line:
457 if '#' in line:
458 if tmp:
458 if tmp:
459 limites.append(tmp)
459 limites.append(tmp)
460 tmp = []
460 tmp = []
461 continue
461 continue
462 values = line.strip().split(',')
462 values = line.strip().split(',')
463 tmp.append((float(values[0]), float(values[1])))
463 tmp.append((float(values[0]), float(values[1])))
464 for points in limites:
464 for points in limites:
465 ax.add_patch(
465 ax.add_patch(
466 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
466 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
467
467
468 # plot Cuencas
468 # plot Cuencas
469 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
469 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
470 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
470 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
471 values = [line.strip().split(',') for line in f]
471 values = [line.strip().split(',') for line in f]
472 points = [(float(s[0]), float(s[1])) for s in values]
472 points = [(float(s[0]), float(s[1])) for s in values]
473 ax.add_patch(Polygon(points, ec='b', fc='none'))
473 ax.add_patch(Polygon(points, ec='b', fc='none'))
474
474
475 # plot grid
475 # plot grid
476 for r in (15, 30, 45, 60):
476 for r in (15, 30, 45, 60):
477 ax.add_artist(plt.Circle((self.lon, self.lat),
477 ax.add_artist(plt.Circle((self.lon, self.lat),
478 km2deg(r), color='0.6', fill=False, lw=0.2))
478 km2deg(r), color='0.6', fill=False, lw=0.2))
479 ax.text(
479 ax.text(
480 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
480 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
481 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
481 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
482 '{}km'.format(r),
482 '{}km'.format(r),
483 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
483 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
484
484
485 if self.mode == 'E':
485 if self.mode == 'E':
486 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
486 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
487 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
487 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
488 else:
488 else:
489 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
489 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
490 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
490 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
491
491
492 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
492 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
493 self.titles = ['{} {}'.format(
493 self.titles = ['{} {}'.format(
494 self.data.parameters[x], title) for x in self.channels]
494 self.data.parameters[x], title) for x in self.channels]
@@ -1,1349 +1,1349
1 # Copyright (c) 2012-2021 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2021 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Classes to plot Spectra data
5 """Classes to plot Spectra data
6
6
7 """
7 """
8
8
9 import os
9 import os
10 import numpy
10 import numpy
11 #import collections.abc
11 #import collections.abc
12
12
13 from schainpy.model.graphics.jroplot_base import Plot, plt, log
13 from schainpy.model.graphics.jroplot_base import Plot, plt, log
14
14
15 class SpectraPlot(Plot):
15 class SpectraPlot(Plot):
16 '''
16 '''
17 Plot for Spectra data
17 Plot for Spectra data
18 '''
18 '''
19
19
20 CODE = 'spc'
20 CODE = 'spc'
21 colormap = 'jet'
21 colormap = 'jet'
22 plot_type = 'pcolor'
22 plot_type = 'pcolor'
23 buffering = False
23 buffering = False
24
24
25 def setup(self):
25 def setup(self):
26
26
27 self.nplots = len(self.data.channels)
27 self.nplots = len(self.data.channels)
28 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
28 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
29 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
29 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
30 self.height = 2.6 * self.nrows
30 self.height = 2.6 * self.nrows
31 self.cb_label = 'dB'
31 self.cb_label = 'dB'
32 if self.showprofile:
32 if self.showprofile:
33 self.width = 4 * self.ncols
33 self.width = 4 * self.ncols
34 else:
34 else:
35 self.width = 3.5 * self.ncols
35 self.width = 3.5 * self.ncols
36 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
36 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
37 self.ylabel = 'Range [km]'
37 self.ylabel = 'Range [km]'
38
38
39 def update(self, dataOut):
39 def update(self, dataOut):
40
40
41 data = {}
41 data = {}
42 meta = {}
42 meta = {}
43
43
44 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
44 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
45 #print("dataOut.normFactor: ", dataOut.normFactor)
45 #print("dataOut.normFactor: ", dataOut.normFactor)
46 #print("spc: ", dataOut.data_spc[0,0,0])
46 #print("spc: ", dataOut.data_spc[0,0,0])
47 #spc = 10*numpy.log10(dataOut.data_spc)
47 #spc = 10*numpy.log10(dataOut.data_spc)
48 #print("Spc: ",spc[0])
48 #print("Spc: ",spc[0])
49 #exit(1)
49 #exit(1)
50 data['spc'] = spc
50 data['spc'] = spc
51 data['rti'] = dataOut.getPower()
51 data['rti'] = dataOut.getPower()
52 #print(data['rti'][0])
52 #print(data['rti'][0])
53 #exit(1)
53 #exit(1)
54 #print("NormFactor: ",dataOut.normFactor)
54 #print("NormFactor: ",dataOut.normFactor)
55 #data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
55 #data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
56 if hasattr(dataOut, 'LagPlot'): #Double Pulse
56 if hasattr(dataOut, 'LagPlot'): #Double Pulse
57 max_hei_id = dataOut.nHeights - 2*dataOut.LagPlot
57 max_hei_id = dataOut.nHeights - 2*dataOut.LagPlot
58 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=46,ymax_index=max_hei_id)/dataOut.normFactor)
58 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=46,ymax_index=max_hei_id)/dataOut.normFactor)
59 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=40,ymax_index=max_hei_id)/dataOut.normFactor)
59 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=40,ymax_index=max_hei_id)/dataOut.normFactor)
60 data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=53,ymax_index=max_hei_id)/dataOut.normFactor)
60 data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=53,ymax_index=max_hei_id)/dataOut.normFactor)
61 data['noise'][0] = 10*numpy.log10(dataOut.getNoise(ymin_index=53)[0]/dataOut.normFactor)
61 data['noise'][0] = 10*numpy.log10(dataOut.getNoise(ymin_index=53)[0]/dataOut.normFactor)
62 #data['noise'][1] = 22.035507
62 #data['noise'][1] = 22.035507
63 else:
63 else:
64 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
64 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
65 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=26,ymax_index=44)/dataOut.normFactor)
65 #data['noise'] = 10*numpy.log10(dataOut.getNoise(ymin_index=26,ymax_index=44)/dataOut.normFactor)
66 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
66 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
67
67
68 if self.CODE == 'spc_moments':
68 if self.CODE == 'spc_moments':
69 data['moments'] = dataOut.moments
69 data['moments'] = dataOut.moments
70 if self.CODE == 'gaussian_fit':
70 if self.CODE == 'gaussian_fit':
71 data['gaussfit'] = dataOut.DGauFitParams
71 data['gaussfit'] = dataOut.DGauFitParams
72
72
73 return data, meta
73 return data, meta
74
74
75 def plot(self):
75 def plot(self):
76
76
77 if self.xaxis == "frequency":
77 if self.xaxis == "frequency":
78 x = self.data.xrange[0]
78 x = self.data.xrange[0]
79 self.xlabel = "Frequency (kHz)"
79 self.xlabel = "Frequency (kHz)"
80 elif self.xaxis == "time":
80 elif self.xaxis == "time":
81 x = self.data.xrange[1]
81 x = self.data.xrange[1]
82 self.xlabel = "Time (ms)"
82 self.xlabel = "Time (ms)"
83 else:
83 else:
84 x = self.data.xrange[2]
84 x = self.data.xrange[2]
85 self.xlabel = "Velocity (m/s)"
85 self.xlabel = "Velocity (m/s)"
86
86
87 if (self.CODE == 'spc_moments') | (self.CODE == 'gaussian_fit'):
87 if (self.CODE == 'spc_moments') | (self.CODE == 'gaussian_fit'):
88 x = self.data.xrange[2]
88 x = self.data.xrange[2]
89 self.xlabel = "Velocity (m/s)"
89 self.xlabel = "Velocity (m/s)"
90
90
91 self.titles = []
91 self.titles = []
92
92
93 y = self.data.yrange
93 y = self.data.yrange
94 self.y = y
94 self.y = y
95
95
96 data = self.data[-1]
96 data = self.data[-1]
97 z = data['spc']
97 z = data['spc']
98
98
99 self.CODE2 = 'spc_oblique'
99 self.CODE2 = 'spc_oblique'
100
100
101 for n, ax in enumerate(self.axes):
101 for n, ax in enumerate(self.axes):
102 noise = data['noise'][n]
102 noise = data['noise'][n]
103 if self.CODE == 'spc_moments':
103 if self.CODE == 'spc_moments':
104 mean = data['moments'][n, 1]
104 mean = data['moments'][n, 1]
105 if self.CODE == 'gaussian_fit':
105 if self.CODE == 'gaussian_fit':
106 gau0 = data['gaussfit'][n][2,:,0]
106 gau0 = data['gaussfit'][n][2,:,0]
107 gau1 = data['gaussfit'][n][2,:,1]
107 gau1 = data['gaussfit'][n][2,:,1]
108 if ax.firsttime:
108 if ax.firsttime:
109 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
109 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
110 self.xmin = self.xmin if self.xmin else numpy.nanmin(x)#-self.xmax
110 self.xmin = self.xmin if self.xmin else numpy.nanmin(x)#-self.xmax
111 #self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
111 #self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
112 #self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
112 #self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
113 if self.zlimits is not None:
113 if self.zlimits is not None:
114 self.zmin, self.zmax = self.zlimits[n]
114 self.zmin, self.zmax = self.zlimits[n]
115
115
116 ax.plt = ax.pcolormesh(x, y, z[n].T,
116 ax.plt = ax.pcolormesh(x, y, z[n].T,
117 vmin=self.zmin,
117 vmin=self.zmin,
118 vmax=self.zmax,
118 vmax=self.zmax,
119 cmap=plt.get_cmap(self.colormap),
119 cmap=plt.get_cmap(self.colormap),
120 )
120 )
121
121
122 if self.showprofile:
122 if self.showprofile:
123 ax.plt_profile = self.pf_axes[n].plot(
123 ax.plt_profile = self.pf_axes[n].plot(
124 data['rti'][n], y)[0]
124 data['rti'][n], y)[0]
125 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
125 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
126 color="k", linestyle="dashed", lw=1)[0]
126 color="k", linestyle="dashed", lw=1)[0]
127 if self.CODE == 'spc_moments':
127 if self.CODE == 'spc_moments':
128 ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
128 ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
129 if self.CODE == 'gaussian_fit':
129 if self.CODE == 'gaussian_fit':
130 ax.plt_gau0 = ax.plot(gau0, y, color='r', lw=1)[0]
130 ax.plt_gau0 = ax.plot(gau0, y, color='r', lw=1)[0]
131 ax.plt_gau1 = ax.plot(gau1, y, color='y', lw=1)[0]
131 ax.plt_gau1 = ax.plot(gau1, y, color='y', lw=1)[0]
132 else:
132 else:
133 if self.zlimits is not None:
133 if self.zlimits is not None:
134 self.zmin, self.zmax = self.zlimits[n]
134 self.zmin, self.zmax = self.zlimits[n]
135 ax.plt.set_array(z[n].T.ravel())
135 ax.plt.set_array(z[n].T.ravel())
136 if self.showprofile:
136 if self.showprofile:
137 ax.plt_profile.set_data(data['rti'][n], y)
137 ax.plt_profile.set_data(data['rti'][n], y)
138 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
138 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
139 if self.CODE == 'spc_moments':
139 if self.CODE == 'spc_moments':
140 ax.plt_mean.set_data(mean, y)
140 ax.plt_mean.set_data(mean, y)
141 if self.CODE == 'gaussian_fit':
141 if self.CODE == 'gaussian_fit':
142 ax.plt_gau0.set_data(gau0, y)
142 ax.plt_gau0.set_data(gau0, y)
143 ax.plt_gau1.set_data(gau1, y)
143 ax.plt_gau1.set_data(gau1, y)
144 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
144 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
145
145
146 class SpectraObliquePlot(Plot):
146 class SpectraObliquePlot(Plot):
147 '''
147 '''
148 Plot for Spectra data
148 Plot for Spectra data
149 '''
149 '''
150
150
151 CODE = 'spc_oblique'
151 CODE = 'spc_oblique'
152 colormap = 'jet'
152 colormap = 'jet'
153 plot_type = 'pcolor'
153 plot_type = 'pcolor'
154
154
155 def setup(self):
155 def setup(self):
156 self.xaxis = "oblique"
156 self.xaxis = "oblique"
157 self.nplots = len(self.data.channels)
157 self.nplots = len(self.data.channels)
158 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
158 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
159 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
159 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
160 self.height = 2.6 * self.nrows
160 self.height = 2.6 * self.nrows
161 self.cb_label = 'dB'
161 self.cb_label = 'dB'
162 if self.showprofile:
162 if self.showprofile:
163 self.width = 4 * self.ncols
163 self.width = 4 * self.ncols
164 else:
164 else:
165 self.width = 3.5 * self.ncols
165 self.width = 3.5 * self.ncols
166 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
166 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
167 self.ylabel = 'Range [km]'
167 self.ylabel = 'Range [km]'
168
168
169 def update(self, dataOut):
169 def update(self, dataOut):
170
170
171 data = {}
171 data = {}
172 meta = {}
172 meta = {}
173
173
174 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
174 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
175 data['spc'] = spc
175 data['spc'] = spc
176 data['rti'] = dataOut.getPower()
176 data['rti'] = dataOut.getPower()
177 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
177 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
178 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
178 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
179 '''
179 '''
180 data['shift1'] = dataOut.Oblique_params[0,-2,:]
180 data['shift1'] = dataOut.Oblique_params[0,-2,:]
181 data['shift2'] = dataOut.Oblique_params[0,-1,:]
181 data['shift2'] = dataOut.Oblique_params[0,-1,:]
182 data['shift1_error'] = dataOut.Oblique_param_errors[0,-2,:]
182 data['shift1_error'] = dataOut.Oblique_param_errors[0,-2,:]
183 data['shift2_error'] = dataOut.Oblique_param_errors[0,-1,:]
183 data['shift2_error'] = dataOut.Oblique_param_errors[0,-1,:]
184 '''
184 '''
185 '''
185 '''
186 data['shift1'] = dataOut.Oblique_params[0,1,:]
186 data['shift1'] = dataOut.Oblique_params[0,1,:]
187 data['shift2'] = dataOut.Oblique_params[0,4,:]
187 data['shift2'] = dataOut.Oblique_params[0,4,:]
188 data['shift1_error'] = dataOut.Oblique_param_errors[0,1,:]
188 data['shift1_error'] = dataOut.Oblique_param_errors[0,1,:]
189 data['shift2_error'] = dataOut.Oblique_param_errors[0,4,:]
189 data['shift2_error'] = dataOut.Oblique_param_errors[0,4,:]
190 '''
190 '''
191 data['shift1'] = dataOut.Dop_EEJ_T1[0]
191 data['shift1'] = dataOut.Dop_EEJ_T1[0]
192 data['shift2'] = dataOut.Dop_EEJ_T2[0]
192 data['shift2'] = dataOut.Dop_EEJ_T2[0]
193 data['max_val_2'] = dataOut.Oblique_params[0,-1,:]
193 data['max_val_2'] = dataOut.Oblique_params[0,-1,:]
194 data['shift1_error'] = dataOut.Err_Dop_EEJ_T1[0]
194 data['shift1_error'] = dataOut.Err_Dop_EEJ_T1[0]
195 data['shift2_error'] = dataOut.Err_Dop_EEJ_T2[0]
195 data['shift2_error'] = dataOut.Err_Dop_EEJ_T2[0]
196
196
197 return data, meta
197 return data, meta
198
198
199 def plot(self):
199 def plot(self):
200
200
201 if self.xaxis == "frequency":
201 if self.xaxis == "frequency":
202 x = self.data.xrange[0]
202 x = self.data.xrange[0]
203 self.xlabel = "Frequency (kHz)"
203 self.xlabel = "Frequency (kHz)"
204 elif self.xaxis == "time":
204 elif self.xaxis == "time":
205 x = self.data.xrange[1]
205 x = self.data.xrange[1]
206 self.xlabel = "Time (ms)"
206 self.xlabel = "Time (ms)"
207 else:
207 else:
208 x = self.data.xrange[2]
208 x = self.data.xrange[2]
209 self.xlabel = "Velocity (m/s)"
209 self.xlabel = "Velocity (m/s)"
210
210
211 self.titles = []
211 self.titles = []
212
212
213 y = self.data.yrange
213 y = self.data.yrange
214 self.y = y
214 self.y = y
215
215
216 data = self.data[-1]
216 data = self.data[-1]
217 z = data['spc']
217 z = data['spc']
218
218
219 for n, ax in enumerate(self.axes):
219 for n, ax in enumerate(self.axes):
220 noise = self.data['noise'][n][-1]
220 noise = self.data['noise'][n][-1]
221 shift1 = data['shift1']
221 shift1 = data['shift1']
222 #print(shift1)
222 #print(shift1)
223 shift2 = data['shift2']
223 shift2 = data['shift2']
224 max_val_2 = data['max_val_2']
224 max_val_2 = data['max_val_2']
225 err1 = data['shift1_error']
225 err1 = data['shift1_error']
226 err2 = data['shift2_error']
226 err2 = data['shift2_error']
227 if ax.firsttime:
227 if ax.firsttime:
228
228
229 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
229 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
230 self.xmin = self.xmin if self.xmin else -self.xmax
230 self.xmin = self.xmin if self.xmin else -self.xmax
231 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
231 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
232 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
232 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
233 ax.plt = ax.pcolormesh(x, y, z[n].T,
233 ax.plt = ax.pcolormesh(x, y, z[n].T,
234 vmin=self.zmin,
234 vmin=self.zmin,
235 vmax=self.zmax,
235 vmax=self.zmax,
236 cmap=plt.get_cmap(self.colormap)
236 cmap=plt.get_cmap(self.colormap)
237 )
237 )
238
238
239 if self.showprofile:
239 if self.showprofile:
240 ax.plt_profile = self.pf_axes[n].plot(
240 ax.plt_profile = self.pf_axes[n].plot(
241 self.data['rti'][n][-1], y)[0]
241 self.data['rti'][n][-1], y)[0]
242 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
242 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
243 color="k", linestyle="dashed", lw=1)[0]
243 color="k", linestyle="dashed", lw=1)[0]
244
244
245 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
245 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
246 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
246 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
247 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
247 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
248
248
249 #print("plotter1: ", self.ploterr1,shift1)
249 #print("plotter1: ", self.ploterr1,shift1)
250
250
251 else:
251 else:
252 #print("else plotter1: ", self.ploterr1,shift1)
252 #print("else plotter1: ", self.ploterr1,shift1)
253 self.ploterr1.remove()
253 self.ploterr1.remove()
254 self.ploterr2.remove()
254 self.ploterr2.remove()
255 self.ploterr3.remove()
255 self.ploterr3.remove()
256 ax.plt.set_array(z[n].T.ravel())
256 ax.plt.set_array(z[n].T.ravel())
257 if self.showprofile:
257 if self.showprofile:
258 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
258 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
259 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
259 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
260 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
260 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
261 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
261 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
262 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
262 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
263
263
264 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
264 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
265
265
266
266
267 class CrossSpectraPlot(Plot):
267 class CrossSpectraPlot(Plot):
268
268
269 CODE = 'cspc'
269 CODE = 'cspc'
270 colormap = 'jet'
270 colormap = 'jet'
271 plot_type = 'pcolor'
271 plot_type = 'pcolor'
272 zmin_coh = None
272 zmin_coh = None
273 zmax_coh = None
273 zmax_coh = None
274 zmin_phase = None
274 zmin_phase = None
275 zmax_phase = None
275 zmax_phase = None
276
276
277 def setup(self):
277 def setup(self):
278
278
279 self.ncols = 4
279 self.ncols = 4
280 self.nplots = len(self.data.pairs) * 2
280 self.nplots = len(self.data.pairs) * 2
281 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
281 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
282 self.width = 3.1 * self.ncols
282 self.width = 3.1 * self.ncols
283 self.height = 5 * self.nrows
283 self.height = 5 * self.nrows
284 self.ylabel = 'Range [km]'
284 self.ylabel = 'Range [km]'
285 self.showprofile = False
285 self.showprofile = False
286 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
286 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
287
287
288 def update(self, dataOut):
288 def update(self, dataOut):
289
289
290 data = {}
290 data = {}
291 meta = {}
291 meta = {}
292
292
293 spc = dataOut.data_spc
293 spc = dataOut.data_spc
294 cspc = dataOut.data_cspc
294 cspc = dataOut.data_cspc
295 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
295 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
296 meta['pairs'] = dataOut.pairsList
296 meta['pairs'] = dataOut.pairsList
297
297
298 tmp = []
298 tmp = []
299
299
300 for n, pair in enumerate(meta['pairs']):
300 for n, pair in enumerate(meta['pairs']):
301 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
301 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
302 coh = numpy.abs(out)
302 coh = numpy.abs(out)
303 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
303 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
304 tmp.append(coh)
304 tmp.append(coh)
305 tmp.append(phase)
305 tmp.append(phase)
306
306
307 data['cspc'] = numpy.array(tmp)
307 data['cspc'] = numpy.array(tmp)
308
308
309 return data, meta
309 return data, meta
310
310
311 def plot(self):
311 def plot(self):
312
312
313 if self.xaxis == "frequency":
313 if self.xaxis == "frequency":
314 x = self.data.xrange[0]
314 x = self.data.xrange[0]
315 self.xlabel = "Frequency (kHz)"
315 self.xlabel = "Frequency (kHz)"
316 elif self.xaxis == "time":
316 elif self.xaxis == "time":
317 x = self.data.xrange[1]
317 x = self.data.xrange[1]
318 self.xlabel = "Time (ms)"
318 self.xlabel = "Time (ms)"
319 else:
319 else:
320 x = self.data.xrange[2]
320 x = self.data.xrange[2]
321 self.xlabel = "Velocity (m/s)"
321 self.xlabel = "Velocity (m/s)"
322
322
323 self.titles = []
323 self.titles = []
324
324
325 y = self.data.yrange
325 y = self.data.yrange
326 self.y = y
326 self.y = y
327
327
328 data = self.data[-1]
328 data = self.data[-1]
329 cspc = data['cspc']
329 cspc = data['cspc']
330
330
331 for n in range(len(self.data.pairs)):
331 for n in range(len(self.data.pairs)):
332 pair = self.data.pairs[n]
332 pair = self.data.pairs[n]
333 coh = cspc[n*2]
333 coh = cspc[n*2]
334 phase = cspc[n*2+1]
334 phase = cspc[n*2+1]
335 ax = self.axes[2 * n]
335 ax = self.axes[2 * n]
336 if ax.firsttime:
336 if ax.firsttime:
337 ax.plt = ax.pcolormesh(x, y, coh.T,
337 ax.plt = ax.pcolormesh(x, y, coh.T,
338 vmin=0,
338 vmin=0,
339 vmax=1,
339 vmax=1,
340 cmap=plt.get_cmap(self.colormap_coh)
340 cmap=plt.get_cmap(self.colormap_coh)
341 )
341 )
342 else:
342 else:
343 ax.plt.set_array(coh.T.ravel())
343 ax.plt.set_array(coh.T.ravel())
344 self.titles.append(
344 self.titles.append(
345 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
345 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
346
346
347 ax = self.axes[2 * n + 1]
347 ax = self.axes[2 * n + 1]
348 if ax.firsttime:
348 if ax.firsttime:
349 ax.plt = ax.pcolormesh(x, y, phase.T,
349 ax.plt = ax.pcolormesh(x, y, phase.T,
350 vmin=-180,
350 vmin=-180,
351 vmax=180,
351 vmax=180,
352 cmap=plt.get_cmap(self.colormap_phase)
352 cmap=plt.get_cmap(self.colormap_phase)
353 )
353 )
354 else:
354 else:
355 ax.plt.set_array(phase.T.ravel())
355 ax.plt.set_array(phase.T.ravel())
356 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
356 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
357
357
358
358
359 class CrossSpectra4Plot(Plot):
359 class CrossSpectra4Plot(Plot):
360
360
361 CODE = 'cspc'
361 CODE = 'cspc'
362 colormap = 'jet'
362 colormap = 'jet'
363 plot_type = 'pcolor'
363 plot_type = 'pcolor'
364 zmin_coh = None
364 zmin_coh = None
365 zmax_coh = None
365 zmax_coh = None
366 zmin_phase = None
366 zmin_phase = None
367 zmax_phase = None
367 zmax_phase = None
368
368
369 def setup(self):
369 def setup(self):
370
370
371 self.ncols = 4
371 self.ncols = 4
372 self.nrows = len(self.data.pairs)
372 self.nrows = len(self.data.pairs)
373 self.nplots = self.nrows * 4
373 self.nplots = self.nrows * 4
374 self.width = 3.1 * self.ncols
374 self.width = 3.1 * self.ncols
375 self.height = 5 * self.nrows
375 self.height = 5 * self.nrows
376 self.ylabel = 'Range [km]'
376 self.ylabel = 'Range [km]'
377 self.showprofile = False
377 self.showprofile = False
378 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
378 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
379
379
380 def plot(self):
380 def plot(self):
381
381
382 if self.xaxis == "frequency":
382 if self.xaxis == "frequency":
383 x = self.data.xrange[0]
383 x = self.data.xrange[0]
384 self.xlabel = "Frequency (kHz)"
384 self.xlabel = "Frequency (kHz)"
385 elif self.xaxis == "time":
385 elif self.xaxis == "time":
386 x = self.data.xrange[1]
386 x = self.data.xrange[1]
387 self.xlabel = "Time (ms)"
387 self.xlabel = "Time (ms)"
388 else:
388 else:
389 x = self.data.xrange[2]
389 x = self.data.xrange[2]
390 self.xlabel = "Velocity (m/s)"
390 self.xlabel = "Velocity (m/s)"
391
391
392 self.titles = []
392 self.titles = []
393
393
394
394
395 y = self.data.heights
395 y = self.data.heights
396 self.y = y
396 self.y = y
397 nspc = self.data['spc']
397 nspc = self.data['spc']
398 #print(numpy.shape(self.data['spc']))
398 #print(numpy.shape(self.data['spc']))
399 spc = self.data['cspc'][0]
399 spc = self.data['cspc'][0]
400 #print(numpy.shape(nspc))
400 #print(numpy.shape(nspc))
401 #exit()
401 #exit()
402 #nspc[1,:,:] = numpy.flip(nspc[1,:,:],axis=0)
402 #nspc[1,:,:] = numpy.flip(nspc[1,:,:],axis=0)
403 #print(numpy.shape(spc))
403 #print(numpy.shape(spc))
404 #exit()
404 #exit()
405 cspc = self.data['cspc'][1]
405 cspc = self.data['cspc'][1]
406
406
407 #xflip=numpy.flip(x)
407 #xflip=numpy.flip(x)
408 #print(numpy.shape(cspc))
408 #print(numpy.shape(cspc))
409 #exit()
409 #exit()
410
410
411 for n in range(self.nrows):
411 for n in range(self.nrows):
412 noise = self.data['noise'][:,-1]
412 noise = self.data['noise'][:,-1]
413 pair = self.data.pairs[n]
413 pair = self.data.pairs[n]
414 #print(pair)
414 #print(pair)
415 #exit()
415 #exit()
416 ax = self.axes[4 * n]
416 ax = self.axes[4 * n]
417 if ax.firsttime:
417 if ax.firsttime:
418 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
418 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
419 self.xmin = self.xmin if self.xmin else -self.xmax
419 self.xmin = self.xmin if self.xmin else -self.xmax
420 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
420 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
421 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
421 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
422 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
422 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
423 vmin=self.zmin,
423 vmin=self.zmin,
424 vmax=self.zmax,
424 vmax=self.zmax,
425 cmap=plt.get_cmap(self.colormap)
425 cmap=plt.get_cmap(self.colormap)
426 )
426 )
427 else:
427 else:
428 #print(numpy.shape(nspc[pair[0]].T))
428 #print(numpy.shape(nspc[pair[0]].T))
429 #exit()
429 #exit()
430 ax.plt.set_array(nspc[pair[0]].T.ravel())
430 ax.plt.set_array(nspc[pair[0]].T.ravel())
431 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
431 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
432
432
433 ax = self.axes[4 * n + 1]
433 ax = self.axes[4 * n + 1]
434
434
435 if ax.firsttime:
435 if ax.firsttime:
436 ax.plt = ax.pcolormesh(x , y, numpy.flip(nspc[pair[1]],axis=0).T,
436 ax.plt = ax.pcolormesh(x , y, numpy.flip(nspc[pair[1]],axis=0).T,
437 vmin=self.zmin,
437 vmin=self.zmin,
438 vmax=self.zmax,
438 vmax=self.zmax,
439 cmap=plt.get_cmap(self.colormap)
439 cmap=plt.get_cmap(self.colormap)
440 )
440 )
441 else:
441 else:
442
442
443 ax.plt.set_array(numpy.flip(nspc[pair[1]],axis=0).T.ravel())
443 ax.plt.set_array(numpy.flip(nspc[pair[1]],axis=0).T.ravel())
444 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
444 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
445
445
446 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
446 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
447 coh = numpy.abs(out)
447 coh = numpy.abs(out)
448 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
448 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
449
449
450 ax = self.axes[4 * n + 2]
450 ax = self.axes[4 * n + 2]
451 if ax.firsttime:
451 if ax.firsttime:
452 ax.plt = ax.pcolormesh(x, y, numpy.flip(coh,axis=0).T,
452 ax.plt = ax.pcolormesh(x, y, numpy.flip(coh,axis=0).T,
453 vmin=0,
453 vmin=0,
454 vmax=1,
454 vmax=1,
455 cmap=plt.get_cmap(self.colormap_coh)
455 cmap=plt.get_cmap(self.colormap_coh)
456 )
456 )
457 else:
457 else:
458 ax.plt.set_array(numpy.flip(coh,axis=0).T.ravel())
458 ax.plt.set_array(numpy.flip(coh,axis=0).T.ravel())
459 self.titles.append(
459 self.titles.append(
460 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
460 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
461
461
462 ax = self.axes[4 * n + 3]
462 ax = self.axes[4 * n + 3]
463 if ax.firsttime:
463 if ax.firsttime:
464 ax.plt = ax.pcolormesh(x, y, numpy.flip(phase,axis=0).T,
464 ax.plt = ax.pcolormesh(x, y, numpy.flip(phase,axis=0).T,
465 vmin=-180,
465 vmin=-180,
466 vmax=180,
466 vmax=180,
467 cmap=plt.get_cmap(self.colormap_phase)
467 cmap=plt.get_cmap(self.colormap_phase)
468 )
468 )
469 else:
469 else:
470 ax.plt.set_array(numpy.flip(phase,axis=0).T.ravel())
470 ax.plt.set_array(numpy.flip(phase,axis=0).T.ravel())
471 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
471 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
472
472
473
473
474 class CrossSpectra2Plot(Plot):
474 class CrossSpectra2Plot(Plot):
475
475
476 CODE = 'cspc'
476 CODE = 'cspc'
477 colormap = 'jet'
477 colormap = 'jet'
478 plot_type = 'pcolor'
478 plot_type = 'pcolor'
479 zmin_coh = None
479 zmin_coh = None
480 zmax_coh = None
480 zmax_coh = None
481 zmin_phase = None
481 zmin_phase = None
482 zmax_phase = None
482 zmax_phase = None
483
483
484 def setup(self):
484 def setup(self):
485
485
486 self.ncols = 1
486 self.ncols = 1
487 self.nrows = len(self.data.pairs)
487 self.nrows = len(self.data.pairs)
488 self.nplots = self.nrows * 1
488 self.nplots = self.nrows * 1
489 self.width = 3.1 * self.ncols
489 self.width = 3.1 * self.ncols
490 self.height = 5 * self.nrows
490 self.height = 5 * self.nrows
491 self.ylabel = 'Range [km]'
491 self.ylabel = 'Range [km]'
492 self.showprofile = False
492 self.showprofile = False
493 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
493 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
494
494
495 def plot(self):
495 def plot(self):
496
496
497 if self.xaxis == "frequency":
497 if self.xaxis == "frequency":
498 x = self.data.xrange[0]
498 x = self.data.xrange[0]
499 self.xlabel = "Frequency (kHz)"
499 self.xlabel = "Frequency (kHz)"
500 elif self.xaxis == "time":
500 elif self.xaxis == "time":
501 x = self.data.xrange[1]
501 x = self.data.xrange[1]
502 self.xlabel = "Time (ms)"
502 self.xlabel = "Time (ms)"
503 else:
503 else:
504 x = self.data.xrange[2]
504 x = self.data.xrange[2]
505 self.xlabel = "Velocity (m/s)"
505 self.xlabel = "Velocity (m/s)"
506
506
507 self.titles = []
507 self.titles = []
508
508
509
509
510 y = self.data.heights
510 y = self.data.heights
511 self.y = y
511 self.y = y
512 #nspc = self.data['spc']
512 #nspc = self.data['spc']
513 #print(numpy.shape(self.data['spc']))
513 #print(numpy.shape(self.data['spc']))
514 #spc = self.data['cspc'][0]
514 #spc = self.data['cspc'][0]
515 #print(numpy.shape(spc))
515 #print(numpy.shape(spc))
516 #exit()
516 #exit()
517 cspc = self.data['cspc'][1]
517 cspc = self.data['cspc'][1]
518 #print(numpy.shape(cspc))
518 #print(numpy.shape(cspc))
519 #exit()
519 #exit()
520
520
521 for n in range(self.nrows):
521 for n in range(self.nrows):
522 noise = self.data['noise'][:,-1]
522 noise = self.data['noise'][:,-1]
523 pair = self.data.pairs[n]
523 pair = self.data.pairs[n]
524 #print(pair) #exit()
524 #print(pair) #exit()
525
525
526
526
527
527
528 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
528 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
529
529
530 #print(out[:,53])
530 #print(out[:,53])
531 #exit()
531 #exit()
532 cross = numpy.abs(out)
532 cross = numpy.abs(out)
533 z = cross/self.data.nFactor
533 z = cross/self.data.nFactor
534 #print("here")
534 #print("here")
535 #print(dataOut.data_spc[0,0,0])
535 #print(dataOut.data_spc[0,0,0])
536 #exit()
536 #exit()
537
537
538 cross = 10*numpy.log10(z)
538 cross = 10*numpy.log10(z)
539 #print(numpy.shape(cross))
539 #print(numpy.shape(cross))
540 #print(cross[0,:])
540 #print(cross[0,:])
541 #print(self.data.nFactor)
541 #print(self.data.nFactor)
542 #exit()
542 #exit()
543 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
543 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
544
544
545 ax = self.axes[1 * n]
545 ax = self.axes[1 * n]
546 if ax.firsttime:
546 if ax.firsttime:
547 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
547 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
548 self.xmin = self.xmin if self.xmin else -self.xmax
548 self.xmin = self.xmin if self.xmin else -self.xmax
549 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
549 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
550 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
550 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
551 ax.plt = ax.pcolormesh(x, y, cross.T,
551 ax.plt = ax.pcolormesh(x, y, cross.T,
552 vmin=self.zmin,
552 vmin=self.zmin,
553 vmax=self.zmax,
553 vmax=self.zmax,
554 cmap=plt.get_cmap(self.colormap)
554 cmap=plt.get_cmap(self.colormap)
555 )
555 )
556 else:
556 else:
557 ax.plt.set_array(cross.T.ravel())
557 ax.plt.set_array(cross.T.ravel())
558 self.titles.append(
558 self.titles.append(
559 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
559 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
560
560
561
561
562 class CrossSpectra3Plot(Plot):
562 class CrossSpectra3Plot(Plot):
563
563
564 CODE = 'cspc'
564 CODE = 'cspc'
565 colormap = 'jet'
565 colormap = 'jet'
566 plot_type = 'pcolor'
566 plot_type = 'pcolor'
567 zmin_coh = None
567 zmin_coh = None
568 zmax_coh = None
568 zmax_coh = None
569 zmin_phase = None
569 zmin_phase = None
570 zmax_phase = None
570 zmax_phase = None
571
571
572 def setup(self):
572 def setup(self):
573
573
574 self.ncols = 3
574 self.ncols = 3
575 self.nrows = len(self.data.pairs)
575 self.nrows = len(self.data.pairs)
576 self.nplots = self.nrows * 3
576 self.nplots = self.nrows * 3
577 self.width = 3.1 * self.ncols
577 self.width = 3.1 * self.ncols
578 self.height = 5 * self.nrows
578 self.height = 5 * self.nrows
579 self.ylabel = 'Range [km]'
579 self.ylabel = 'Range [km]'
580 self.showprofile = False
580 self.showprofile = False
581 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
581 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
582
582
583 def plot(self):
583 def plot(self):
584
584
585 if self.xaxis == "frequency":
585 if self.xaxis == "frequency":
586 x = self.data.xrange[0]
586 x = self.data.xrange[0]
587 self.xlabel = "Frequency (kHz)"
587 self.xlabel = "Frequency (kHz)"
588 elif self.xaxis == "time":
588 elif self.xaxis == "time":
589 x = self.data.xrange[1]
589 x = self.data.xrange[1]
590 self.xlabel = "Time (ms)"
590 self.xlabel = "Time (ms)"
591 else:
591 else:
592 x = self.data.xrange[2]
592 x = self.data.xrange[2]
593 self.xlabel = "Velocity (m/s)"
593 self.xlabel = "Velocity (m/s)"
594
594
595 self.titles = []
595 self.titles = []
596
596
597
597
598 y = self.data.heights
598 y = self.data.heights
599 self.y = y
599 self.y = y
600 #nspc = self.data['spc']
600 #nspc = self.data['spc']
601 #print(numpy.shape(self.data['spc']))
601 #print(numpy.shape(self.data['spc']))
602 #spc = self.data['cspc'][0]
602 #spc = self.data['cspc'][0]
603 #print(numpy.shape(spc))
603 #print(numpy.shape(spc))
604 #exit()
604 #exit()
605 cspc = self.data['cspc'][1]
605 cspc = self.data['cspc'][1]
606 #print(numpy.shape(cspc))
606 #print(numpy.shape(cspc))
607 #exit()
607 #exit()
608
608
609 for n in range(self.nrows):
609 for n in range(self.nrows):
610 noise = self.data['noise'][:,-1]
610 noise = self.data['noise'][:,-1]
611 pair = self.data.pairs[n]
611 pair = self.data.pairs[n]
612 #print(pair) #exit()
612 #print(pair) #exit()
613
613
614
614
615
615
616 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
616 out = cspc[n]# / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
617
617
618 #print(out[:,53])
618 #print(out[:,53])
619 #exit()
619 #exit()
620 cross = numpy.abs(out)
620 cross = numpy.abs(out)
621 z = cross/self.data.nFactor
621 z = cross/self.data.nFactor
622 cross = 10*numpy.log10(z)
622 cross = 10*numpy.log10(z)
623
623
624 out_r= out.real/self.data.nFactor
624 out_r= out.real/self.data.nFactor
625 #out_r = 10*numpy.log10(out_r)
625 #out_r = 10*numpy.log10(out_r)
626
626
627 out_i= out.imag/self.data.nFactor
627 out_i= out.imag/self.data.nFactor
628 #out_i = 10*numpy.log10(out_i)
628 #out_i = 10*numpy.log10(out_i)
629 #print(numpy.shape(cross))
629 #print(numpy.shape(cross))
630 #print(cross[0,:])
630 #print(cross[0,:])
631 #print(self.data.nFactor)
631 #print(self.data.nFactor)
632 #exit()
632 #exit()
633 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
633 #phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
634
634
635 ax = self.axes[3 * n]
635 ax = self.axes[3 * n]
636 if ax.firsttime:
636 if ax.firsttime:
637 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
637 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
638 self.xmin = self.xmin if self.xmin else -self.xmax
638 self.xmin = self.xmin if self.xmin else -self.xmax
639 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
639 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
640 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
640 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
641 ax.plt = ax.pcolormesh(x, y, cross.T,
641 ax.plt = ax.pcolormesh(x, y, cross.T,
642 vmin=self.zmin,
642 vmin=self.zmin,
643 vmax=self.zmax,
643 vmax=self.zmax,
644 cmap=plt.get_cmap(self.colormap)
644 cmap=plt.get_cmap(self.colormap)
645 )
645 )
646 else:
646 else:
647 ax.plt.set_array(cross.T.ravel())
647 ax.plt.set_array(cross.T.ravel())
648 self.titles.append(
648 self.titles.append(
649 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
649 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
650
650
651 ax = self.axes[3 * n + 1]
651 ax = self.axes[3 * n + 1]
652 if ax.firsttime:
652 if ax.firsttime:
653 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
653 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
654 self.xmin = self.xmin if self.xmin else -self.xmax
654 self.xmin = self.xmin if self.xmin else -self.xmax
655 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
655 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
656 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
656 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
657 ax.plt = ax.pcolormesh(x, y, out_r.T,
657 ax.plt = ax.pcolormesh(x, y, out_r.T,
658 vmin=-1.e6,
658 vmin=-1.e6,
659 vmax=0,
659 vmax=0,
660 cmap=plt.get_cmap(self.colormap)
660 cmap=plt.get_cmap(self.colormap)
661 )
661 )
662 else:
662 else:
663 ax.plt.set_array(out_r.T.ravel())
663 ax.plt.set_array(out_r.T.ravel())
664 self.titles.append(
664 self.titles.append(
665 'Cross Spectra Real Ch{} * Ch{}'.format(pair[0], pair[1]))
665 'Cross Spectra Real Ch{} * Ch{}'.format(pair[0], pair[1]))
666
666
667 ax = self.axes[3 * n + 2]
667 ax = self.axes[3 * n + 2]
668
668
669
669
670 if ax.firsttime:
670 if ax.firsttime:
671 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
671 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
672 self.xmin = self.xmin if self.xmin else -self.xmax
672 self.xmin = self.xmin if self.xmin else -self.xmax
673 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
673 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
674 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
674 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
675 ax.plt = ax.pcolormesh(x, y, out_i.T,
675 ax.plt = ax.pcolormesh(x, y, out_i.T,
676 vmin=-1.e6,
676 vmin=-1.e6,
677 vmax=1.e6,
677 vmax=1.e6,
678 cmap=plt.get_cmap(self.colormap)
678 cmap=plt.get_cmap(self.colormap)
679 )
679 )
680 else:
680 else:
681 ax.plt.set_array(out_i.T.ravel())
681 ax.plt.set_array(out_i.T.ravel())
682 self.titles.append(
682 self.titles.append(
683 'Cross Spectra Imag Ch{} * Ch{}'.format(pair[0], pair[1]))
683 'Cross Spectra Imag Ch{} * Ch{}'.format(pair[0], pair[1]))
684
684
685 class RTIPlot(Plot):
685 class RTIPlot(Plot):
686 '''
686 '''
687 Plot for RTI data
687 Plot for RTI data
688 '''
688 '''
689
689
690 CODE = 'rti'
690 CODE = 'rti'
691 colormap = 'jet'
691 colormap = 'jet'
692 plot_type = 'pcolorbuffer'
692 plot_type = 'pcolorbuffer'
693
693
694 def setup(self):
694 def setup(self):
695 self.xaxis = 'time'
695 self.xaxis = 'time'
696 self.ncols = 1
696 self.ncols = 1
697 self.nrows = len(self.data.channels)
697 self.nrows = len(self.data.channels)
698 self.nplots = len(self.data.channels)
698 self.nplots = len(self.data.channels)
699 self.ylabel = 'Range [km]'
699 self.ylabel = 'Range [km]'
700 self.xlabel = 'Time'
700 self.xlabel = 'Time'
701 self.cb_label = 'dB'
701 self.cb_label = 'dB'
702 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
702 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
703 self.titles = ['{} Channel {}'.format(
703 self.titles = ['{} Channel {}'.format(
704 self.CODE.upper(), x) for x in range(self.nrows)]
704 self.CODE.upper(), x) for x in range(self.nrows)]
705
705
706 def update(self, dataOut):
706 def update(self, dataOut):
707
707
708 data = {}
708 data = {}
709 meta = {}
709 meta = {}
710 data['rti'] = dataOut.getPower()
710 data['rti'] = dataOut.getPower()
711 #print(numpy.shape(data['rti']))
711 #print(numpy.shape(data['rti']))
712
712
713 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
713 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
714
714
715 return data, meta
715 return data, meta
716
716
717 def plot(self):
717 def plot(self):
718
718
719 self.x = self.data.times
719 self.x = self.data.times
720 self.y = self.data.yrange
720 self.y = self.data.yrange
721 self.z = self.data[self.CODE]
721 self.z = self.data[self.CODE]
722 #print("Inside RTI: ", self.z)
722 #print("Inside RTI: ", self.z)
723 self.z = numpy.ma.masked_invalid(self.z)
723 self.z = numpy.ma.masked_invalid(self.z)
724
724
725 if self.decimation is None:
725 if self.decimation is None:
726 x, y, z = self.fill_gaps(self.x, self.y, self.z)
726 x, y, z = self.fill_gaps(self.x, self.y, self.z)
727 else:
727 else:
728 x, y, z = self.fill_gaps(*self.decimate())
728 x, y, z = self.fill_gaps(*self.decimate())
729 #print("self.z: ", self.z)
729 #print("self.z: ", self.z)
730 #exit(1)
730 #exit(1)
731 '''
731 '''
732 if not isinstance(self.zmin, collections.abc.Sequence):
732 if not isinstance(self.zmin, collections.abc.Sequence):
733 if not self.zmin:
733 if not self.zmin:
734 self.zmin = [numpy.min(self.z)]*len(self.axes)
734 self.zmin = [numpy.min(self.z)]*len(self.axes)
735 else:
735 else:
736 self.zmin = [self.zmin]*len(self.axes)
736 self.zmin = [self.zmin]*len(self.axes)
737
737
738 if not isinstance(self.zmax, collections.abc.Sequence):
738 if not isinstance(self.zmax, collections.abc.Sequence):
739 if not self.zmax:
739 if not self.zmax:
740 self.zmax = [numpy.max(self.z)]*len(self.axes)
740 self.zmax = [numpy.max(self.z)]*len(self.axes)
741 else:
741 else:
742 self.zmax = [self.zmax]*len(self.axes)
742 self.zmax = [self.zmax]*len(self.axes)
743 '''
743 '''
744 for n, ax in enumerate(self.axes):
744 for n, ax in enumerate(self.axes):
745
745
746 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
746 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
747 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
747 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
748
748
749 if ax.firsttime:
749 if ax.firsttime:
750 if self.zlimits is not None:
750 if self.zlimits is not None:
751 self.zmin, self.zmax = self.zlimits[n]
751 self.zmin, self.zmax = self.zlimits[n]
752 ax.plt = ax.pcolormesh(x, y, z[n].T,
752 ax.plt = ax.pcolormesh(x, y, z[n].T,
753 vmin=self.zmin,
753 vmin=self.zmin,
754 vmax=self.zmax,
754 vmax=self.zmax,
755 cmap=plt.get_cmap(self.colormap)
755 cmap=plt.get_cmap(self.colormap)
756 )
756 )
757 if self.showprofile:
757 if self.showprofile:
758 ax.plot_profile = self.pf_axes[n].plot(
758 ax.plot_profile = self.pf_axes[n].plot(
759 self.data['rti'][n][-1], self.y)[0]
759 self.data['rti'][n][-1], self.y)[0]
760 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
760 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
761 color="k", linestyle="dashed", lw=1)[0]
761 color="k", linestyle="dashed", lw=1)[0]
762 else:
762 else:
763 if self.zlimits is not None:
763 if self.zlimits is not None:
764 self.zmin, self.zmax = self.zlimits[n]
764 self.zmin, self.zmax = self.zlimits[n]
765 ax.collections.remove(ax.collections[0])
765 ax.plt.remove()
766 ax.plt = ax.pcolormesh(x, y, z[n].T,
766 ax.plt = ax.pcolormesh(x, y, z[n].T,
767 vmin=self.zmin,
767 vmin=self.zmin,
768 vmax=self.zmax,
768 vmax=self.zmax,
769 cmap=plt.get_cmap(self.colormap)
769 cmap=plt.get_cmap(self.colormap)
770 )
770 )
771 if self.showprofile:
771 if self.showprofile:
772 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
772 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
773 ax.plot_noise.set_data(numpy.repeat(
773 ax.plot_noise.set_data(numpy.repeat(
774 self.data['noise'][n][-1], len(self.y)), self.y)
774 self.data['noise'][n][-1], len(self.y)), self.y)
775
775
776
776
777 class SpectrogramPlot(Plot):
777 class SpectrogramPlot(Plot):
778 '''
778 '''
779 Plot for Spectrogram data
779 Plot for Spectrogram data
780 '''
780 '''
781
781
782 CODE = 'Spectrogram_Profile'
782 CODE = 'Spectrogram_Profile'
783 colormap = 'binary'
783 colormap = 'binary'
784 plot_type = 'pcolorbuffer'
784 plot_type = 'pcolorbuffer'
785
785
786 def setup(self):
786 def setup(self):
787 self.xaxis = 'time'
787 self.xaxis = 'time'
788 self.ncols = 1
788 self.ncols = 1
789 self.nrows = len(self.data.channels)
789 self.nrows = len(self.data.channels)
790 self.nplots = len(self.data.channels)
790 self.nplots = len(self.data.channels)
791 self.xlabel = 'Time'
791 self.xlabel = 'Time'
792 #self.cb_label = 'dB'
792 #self.cb_label = 'dB'
793 self.plots_adjust.update({'hspace':1.2, 'left': 0.1, 'bottom': 0.12, 'right':0.95})
793 self.plots_adjust.update({'hspace':1.2, 'left': 0.1, 'bottom': 0.12, 'right':0.95})
794 self.titles = []
794 self.titles = []
795
795
796 #self.titles = ['{} Channel {} \n H = {} km ({} - {})'.format(
796 #self.titles = ['{} Channel {} \n H = {} km ({} - {})'.format(
797 #self.CODE.upper(), x, self.data.heightList[self.data.hei], self.data.heightList[self.data.hei],self.data.heightList[self.data.hei]+(self.data.DH*self.data.nProfiles)) for x in range(self.nrows)]
797 #self.CODE.upper(), x, self.data.heightList[self.data.hei], self.data.heightList[self.data.hei],self.data.heightList[self.data.hei]+(self.data.DH*self.data.nProfiles)) for x in range(self.nrows)]
798
798
799 self.titles = ['{} Channel {}'.format(
799 self.titles = ['{} Channel {}'.format(
800 self.CODE.upper(), x) for x in range(self.nrows)]
800 self.CODE.upper(), x) for x in range(self.nrows)]
801
801
802
802
803 def update(self, dataOut):
803 def update(self, dataOut):
804 data = {}
804 data = {}
805 meta = {}
805 meta = {}
806
806
807 maxHei = 1620#+12000
807 maxHei = 1620#+12000
808 maxHei = 1180
808 maxHei = 1180
809 indb = numpy.where(dataOut.heightList <= maxHei)
809 indb = numpy.where(dataOut.heightList <= maxHei)
810 hei = indb[0][-1]
810 hei = indb[0][-1]
811 #print(dataOut.heightList)
811 #print(dataOut.heightList)
812
812
813 factor = dataOut.nIncohInt
813 factor = dataOut.nIncohInt
814 z = dataOut.data_spc[:,:,hei] / factor
814 z = dataOut.data_spc[:,:,hei] / factor
815 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
815 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
816 #buffer = 10 * numpy.log10(z)
816 #buffer = 10 * numpy.log10(z)
817
817
818 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
818 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
819
819
820
820
821 #self.hei = hei
821 #self.hei = hei
822 #self.heightList = dataOut.heightList
822 #self.heightList = dataOut.heightList
823 #self.DH = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
823 #self.DH = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
824 #self.nProfiles = dataOut.nProfiles
824 #self.nProfiles = dataOut.nProfiles
825
825
826 data['Spectrogram_Profile'] = 10 * numpy.log10(z)
826 data['Spectrogram_Profile'] = 10 * numpy.log10(z)
827
827
828 data['hei'] = hei
828 data['hei'] = hei
829 data['DH'] = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
829 data['DH'] = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
830 data['nProfiles'] = dataOut.nProfiles
830 data['nProfiles'] = dataOut.nProfiles
831 #meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
831 #meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
832 '''
832 '''
833 import matplotlib.pyplot as plt
833 import matplotlib.pyplot as plt
834 plt.plot(10 * numpy.log10(z[0,:]))
834 plt.plot(10 * numpy.log10(z[0,:]))
835 plt.show()
835 plt.show()
836
836
837 from time import sleep
837 from time import sleep
838 sleep(10)
838 sleep(10)
839 '''
839 '''
840 return data, meta
840 return data, meta
841
841
842 def plot(self):
842 def plot(self):
843
843
844 self.x = self.data.times
844 self.x = self.data.times
845 self.z = self.data[self.CODE]
845 self.z = self.data[self.CODE]
846 self.y = self.data.xrange[0]
846 self.y = self.data.xrange[0]
847
847
848 hei = self.data['hei'][-1]
848 hei = self.data['hei'][-1]
849 DH = self.data['DH'][-1]
849 DH = self.data['DH'][-1]
850 nProfiles = self.data['nProfiles'][-1]
850 nProfiles = self.data['nProfiles'][-1]
851
851
852 self.ylabel = "Frequency (kHz)"
852 self.ylabel = "Frequency (kHz)"
853
853
854 self.z = numpy.ma.masked_invalid(self.z)
854 self.z = numpy.ma.masked_invalid(self.z)
855
855
856 if self.decimation is None:
856 if self.decimation is None:
857 x, y, z = self.fill_gaps(self.x, self.y, self.z)
857 x, y, z = self.fill_gaps(self.x, self.y, self.z)
858 else:
858 else:
859 x, y, z = self.fill_gaps(*self.decimate())
859 x, y, z = self.fill_gaps(*self.decimate())
860
860
861 for n, ax in enumerate(self.axes):
861 for n, ax in enumerate(self.axes):
862 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
862 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
863 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
863 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
864 data = self.data[-1]
864 data = self.data[-1]
865 if ax.firsttime:
865 if ax.firsttime:
866 ax.plt = ax.pcolormesh(x, y, z[n].T,
866 ax.plt = ax.pcolormesh(x, y, z[n].T,
867 vmin=self.zmin,
867 vmin=self.zmin,
868 vmax=self.zmax,
868 vmax=self.zmax,
869 cmap=plt.get_cmap(self.colormap)
869 cmap=plt.get_cmap(self.colormap)
870 )
870 )
871 else:
871 else:
872 ax.collections.remove(ax.collections[0])
872 ax.plt.remove()
873 ax.plt = ax.pcolormesh(x, y, z[n].T,
873 ax.plt = ax.pcolormesh(x, y, z[n].T,
874 vmin=self.zmin,
874 vmin=self.zmin,
875 vmax=self.zmax,
875 vmax=self.zmax,
876 cmap=plt.get_cmap(self.colormap)
876 cmap=plt.get_cmap(self.colormap)
877 )
877 )
878
878
879 #self.titles.append('Spectrogram')
879 #self.titles.append('Spectrogram')
880
880
881 #self.titles.append('{} Channel {} \n H = {} km ({} - {})'.format(
881 #self.titles.append('{} Channel {} \n H = {} km ({} - {})'.format(
882 #self.CODE.upper(), x, y[hei], y[hei],y[hei]+(DH*nProfiles)))
882 #self.CODE.upper(), x, y[hei], y[hei],y[hei]+(DH*nProfiles)))
883
883
884
884
885
885
886
886
887 class CoherencePlot(RTIPlot):
887 class CoherencePlot(RTIPlot):
888 '''
888 '''
889 Plot for Coherence data
889 Plot for Coherence data
890 '''
890 '''
891
891
892 CODE = 'coh'
892 CODE = 'coh'
893
893
894 def setup(self):
894 def setup(self):
895 self.xaxis = 'time'
895 self.xaxis = 'time'
896 self.ncols = 1
896 self.ncols = 1
897 self.nrows = len(self.data.pairs)
897 self.nrows = len(self.data.pairs)
898 self.nplots = len(self.data.pairs)
898 self.nplots = len(self.data.pairs)
899 self.ylabel = 'Range [km]'
899 self.ylabel = 'Range [km]'
900 self.xlabel = 'Time'
900 self.xlabel = 'Time'
901 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
901 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
902 if self.CODE == 'coh':
902 if self.CODE == 'coh':
903 self.cb_label = ''
903 self.cb_label = ''
904 self.titles = [
904 self.titles = [
905 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
905 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
906 else:
906 else:
907 self.cb_label = 'Degrees'
907 self.cb_label = 'Degrees'
908 self.titles = [
908 self.titles = [
909 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
909 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
910
910
911 def update(self, dataOut):
911 def update(self, dataOut):
912
912
913 data = {}
913 data = {}
914 meta = {}
914 meta = {}
915 data['coh'] = dataOut.getCoherence()
915 data['coh'] = dataOut.getCoherence()
916 meta['pairs'] = dataOut.pairsList
916 meta['pairs'] = dataOut.pairsList
917
917
918 return data, meta
918 return data, meta
919
919
920 class PhasePlot(CoherencePlot):
920 class PhasePlot(CoherencePlot):
921 '''
921 '''
922 Plot for Phase map data
922 Plot for Phase map data
923 '''
923 '''
924
924
925 CODE = 'phase'
925 CODE = 'phase'
926 colormap = 'seismic'
926 colormap = 'seismic'
927
927
928 def update(self, dataOut):
928 def update(self, dataOut):
929
929
930 data = {}
930 data = {}
931 meta = {}
931 meta = {}
932 data['phase'] = dataOut.getCoherence(phase=True)
932 data['phase'] = dataOut.getCoherence(phase=True)
933 meta['pairs'] = dataOut.pairsList
933 meta['pairs'] = dataOut.pairsList
934
934
935 return data, meta
935 return data, meta
936
936
937 class NoisePlot(Plot):
937 class NoisePlot(Plot):
938 '''
938 '''
939 Plot for noise
939 Plot for noise
940 '''
940 '''
941
941
942 CODE = 'noise'
942 CODE = 'noise'
943 plot_type = 'scatterbuffer'
943 plot_type = 'scatterbuffer'
944
944
945 def setup(self):
945 def setup(self):
946 self.xaxis = 'time'
946 self.xaxis = 'time'
947 self.ncols = 1
947 self.ncols = 1
948 self.nrows = 1
948 self.nrows = 1
949 self.nplots = 1
949 self.nplots = 1
950 self.ylabel = 'Intensity [dB]'
950 self.ylabel = 'Intensity [dB]'
951 self.xlabel = 'Time'
951 self.xlabel = 'Time'
952 self.titles = ['Noise']
952 self.titles = ['Noise']
953 self.colorbar = False
953 self.colorbar = False
954 self.plots_adjust.update({'right': 0.85 })
954 self.plots_adjust.update({'right': 0.85 })
955
955
956 def update(self, dataOut):
956 def update(self, dataOut):
957
957
958 data = {}
958 data = {}
959 meta = {}
959 meta = {}
960 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
960 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
961 meta['yrange'] = numpy.array([])
961 meta['yrange'] = numpy.array([])
962
962
963 return data, meta
963 return data, meta
964
964
965 def plot(self):
965 def plot(self):
966
966
967 x = self.data.times
967 x = self.data.times
968 xmin = self.data.min_time
968 xmin = self.data.min_time
969 xmax = xmin + self.xrange * 60 * 60
969 xmax = xmin + self.xrange * 60 * 60
970 Y = self.data['noise']
970 Y = self.data['noise']
971
971
972 if self.axes[0].firsttime:
972 if self.axes[0].firsttime:
973 self.ymin = numpy.nanmin(Y) - 5
973 self.ymin = numpy.nanmin(Y) - 5
974 self.ymax = numpy.nanmax(Y) + 5
974 self.ymax = numpy.nanmax(Y) + 5
975 for ch in self.data.channels:
975 for ch in self.data.channels:
976 y = Y[ch]
976 y = Y[ch]
977 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
977 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
978 plt.legend(bbox_to_anchor=(1.18, 1.0))
978 plt.legend(bbox_to_anchor=(1.18, 1.0))
979 else:
979 else:
980 for ch in self.data.channels:
980 for ch in self.data.channels:
981 y = Y[ch]
981 y = Y[ch]
982 self.axes[0].lines[ch].set_data(x, y)
982 self.axes[0].lines[ch].set_data(x, y)
983
983
984 self.ymin = numpy.nanmin(Y) - 5
984 self.ymin = numpy.nanmin(Y) - 5
985 self.ymax = numpy.nanmax(Y) + 10
985 self.ymax = numpy.nanmax(Y) + 10
986
986
987
987
988 class PowerProfilePlot(Plot):
988 class PowerProfilePlot(Plot):
989
989
990 CODE = 'pow_profile'
990 CODE = 'pow_profile'
991 plot_type = 'scatter'
991 plot_type = 'scatter'
992
992
993 def setup(self):
993 def setup(self):
994
994
995 self.ncols = 1
995 self.ncols = 1
996 self.nrows = 1
996 self.nrows = 1
997 self.nplots = 1
997 self.nplots = 1
998 self.height = 4
998 self.height = 4
999 self.width = 3
999 self.width = 3
1000 self.ylabel = 'Range [km]'
1000 self.ylabel = 'Range [km]'
1001 self.xlabel = 'Intensity [dB]'
1001 self.xlabel = 'Intensity [dB]'
1002 self.titles = ['Power Profile']
1002 self.titles = ['Power Profile']
1003 self.colorbar = False
1003 self.colorbar = False
1004
1004
1005 def update(self, dataOut):
1005 def update(self, dataOut):
1006
1006
1007 data = {}
1007 data = {}
1008 meta = {}
1008 meta = {}
1009 data[self.CODE] = dataOut.getPower()
1009 data[self.CODE] = dataOut.getPower()
1010
1010
1011 return data, meta
1011 return data, meta
1012
1012
1013 def plot(self):
1013 def plot(self):
1014
1014
1015 y = self.data.yrange
1015 y = self.data.yrange
1016 self.y = y
1016 self.y = y
1017
1017
1018 x = self.data[-1][self.CODE]
1018 x = self.data[-1][self.CODE]
1019
1019
1020 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
1020 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
1021 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
1021 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
1022
1022
1023 if self.axes[0].firsttime:
1023 if self.axes[0].firsttime:
1024 for ch in self.data.channels:
1024 for ch in self.data.channels:
1025 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
1025 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
1026 plt.legend()
1026 plt.legend()
1027 else:
1027 else:
1028 for ch in self.data.channels:
1028 for ch in self.data.channels:
1029 self.axes[0].lines[ch].set_data(x[ch], y)
1029 self.axes[0].lines[ch].set_data(x[ch], y)
1030
1030
1031
1031
1032 class SpectraCutPlot(Plot):
1032 class SpectraCutPlot(Plot):
1033
1033
1034 CODE = 'spc_cut'
1034 CODE = 'spc_cut'
1035 plot_type = 'scatter'
1035 plot_type = 'scatter'
1036 buffering = False
1036 buffering = False
1037
1037
1038 def setup(self):
1038 def setup(self):
1039
1039
1040 self.nplots = len(self.data.channels)
1040 self.nplots = len(self.data.channels)
1041 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
1041 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
1042 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
1042 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
1043 self.width = 3.4 * self.ncols + 1.5
1043 self.width = 3.4 * self.ncols + 1.5
1044 self.height = 3 * self.nrows
1044 self.height = 3 * self.nrows
1045 self.ylabel = 'Power [dB]'
1045 self.ylabel = 'Power [dB]'
1046 self.colorbar = False
1046 self.colorbar = False
1047 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
1047 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
1048
1048
1049 def update(self, dataOut):
1049 def update(self, dataOut):
1050
1050
1051 data = {}
1051 data = {}
1052 meta = {}
1052 meta = {}
1053 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
1053 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
1054 data['spc'] = spc
1054 data['spc'] = spc
1055 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
1055 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
1056 if self.CODE == 'cut_gaussian_fit':
1056 if self.CODE == 'cut_gaussian_fit':
1057 data['gauss_fit0'] = 10*numpy.log10(dataOut.GaussFit0/dataOut.normFactor)
1057 data['gauss_fit0'] = 10*numpy.log10(dataOut.GaussFit0/dataOut.normFactor)
1058 data['gauss_fit1'] = 10*numpy.log10(dataOut.GaussFit1/dataOut.normFactor)
1058 data['gauss_fit1'] = 10*numpy.log10(dataOut.GaussFit1/dataOut.normFactor)
1059 return data, meta
1059 return data, meta
1060
1060
1061 def plot(self):
1061 def plot(self):
1062 if self.xaxis == "frequency":
1062 if self.xaxis == "frequency":
1063 x = self.data.xrange[0][1:]
1063 x = self.data.xrange[0][1:]
1064 self.xlabel = "Frequency (kHz)"
1064 self.xlabel = "Frequency (kHz)"
1065 elif self.xaxis == "time":
1065 elif self.xaxis == "time":
1066 x = self.data.xrange[1]
1066 x = self.data.xrange[1]
1067 self.xlabel = "Time (ms)"
1067 self.xlabel = "Time (ms)"
1068 else:
1068 else:
1069 x = self.data.xrange[2][:-1]
1069 x = self.data.xrange[2][:-1]
1070 self.xlabel = "Velocity (m/s)"
1070 self.xlabel = "Velocity (m/s)"
1071
1071
1072 if self.CODE == 'cut_gaussian_fit':
1072 if self.CODE == 'cut_gaussian_fit':
1073 x = self.data.xrange[2][:-1]
1073 x = self.data.xrange[2][:-1]
1074 self.xlabel = "Velocity (m/s)"
1074 self.xlabel = "Velocity (m/s)"
1075
1075
1076 self.titles = []
1076 self.titles = []
1077
1077
1078 y = self.data.yrange
1078 y = self.data.yrange
1079 data = self.data[-1]
1079 data = self.data[-1]
1080 z = data['spc']
1080 z = data['spc']
1081
1081
1082 if self.height_index:
1082 if self.height_index:
1083 index = numpy.array(self.height_index)
1083 index = numpy.array(self.height_index)
1084 else:
1084 else:
1085 index = numpy.arange(0, len(y), int((len(y))/9))
1085 index = numpy.arange(0, len(y), int((len(y))/9))
1086
1086
1087 for n, ax in enumerate(self.axes):
1087 for n, ax in enumerate(self.axes):
1088 if self.CODE == 'cut_gaussian_fit':
1088 if self.CODE == 'cut_gaussian_fit':
1089 gau0 = data['gauss_fit0']
1089 gau0 = data['gauss_fit0']
1090 gau1 = data['gauss_fit1']
1090 gau1 = data['gauss_fit1']
1091 if ax.firsttime:
1091 if ax.firsttime:
1092 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
1092 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
1093 self.xmin = self.xmin if self.xmin else -self.xmax
1093 self.xmin = self.xmin if self.xmin else -self.xmax
1094 self.ymin = self.ymin if self.ymin else numpy.nanmin(z[:,:,index])
1094 self.ymin = self.ymin if self.ymin else numpy.nanmin(z[:,:,index])
1095 self.ymax = self.ymax if self.ymax else numpy.nanmax(z[:,:,index])
1095 self.ymax = self.ymax if self.ymax else numpy.nanmax(z[:,:,index])
1096 #print(self.ymax)
1096 #print(self.ymax)
1097 #print(z[n, :, index])
1097 #print(z[n, :, index])
1098 ax.plt = ax.plot(x, z[n, :, index].T, lw=0.25)
1098 ax.plt = ax.plot(x, z[n, :, index].T, lw=0.25)
1099 if self.CODE == 'cut_gaussian_fit':
1099 if self.CODE == 'cut_gaussian_fit':
1100 ax.plt_gau0 = ax.plot(x, gau0[n, :, index].T, lw=1, linestyle='-.')
1100 ax.plt_gau0 = ax.plot(x, gau0[n, :, index].T, lw=1, linestyle='-.')
1101 for i, line in enumerate(ax.plt_gau0):
1101 for i, line in enumerate(ax.plt_gau0):
1102 line.set_color(ax.plt[i].get_color())
1102 line.set_color(ax.plt[i].get_color())
1103 ax.plt_gau1 = ax.plot(x, gau1[n, :, index].T, lw=1, linestyle='--')
1103 ax.plt_gau1 = ax.plot(x, gau1[n, :, index].T, lw=1, linestyle='--')
1104 for i, line in enumerate(ax.plt_gau1):
1104 for i, line in enumerate(ax.plt_gau1):
1105 line.set_color(ax.plt[i].get_color())
1105 line.set_color(ax.plt[i].get_color())
1106 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
1106 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
1107 self.figures[0].legend(ax.plt, labels, loc='center right')
1107 self.figures[0].legend(ax.plt, labels, loc='center right')
1108 else:
1108 else:
1109 for i, line in enumerate(ax.plt):
1109 for i, line in enumerate(ax.plt):
1110 line.set_data(x, z[n, :, index[i]].T)
1110 line.set_data(x, z[n, :, index[i]].T)
1111 for i, line in enumerate(ax.plt_gau0):
1111 for i, line in enumerate(ax.plt_gau0):
1112 line.set_data(x, gau0[n, :, index[i]].T)
1112 line.set_data(x, gau0[n, :, index[i]].T)
1113 line.set_color(ax.plt[i].get_color())
1113 line.set_color(ax.plt[i].get_color())
1114 for i, line in enumerate(ax.plt_gau1):
1114 for i, line in enumerate(ax.plt_gau1):
1115 line.set_data(x, gau1[n, :, index[i]].T)
1115 line.set_data(x, gau1[n, :, index[i]].T)
1116 line.set_color(ax.plt[i].get_color())
1116 line.set_color(ax.plt[i].get_color())
1117 self.titles.append('CH {}'.format(n))
1117 self.titles.append('CH {}'.format(n))
1118
1118
1119
1119
1120 class BeaconPhase(Plot):
1120 class BeaconPhase(Plot):
1121
1121
1122 __isConfig = None
1122 __isConfig = None
1123 __nsubplots = None
1123 __nsubplots = None
1124
1124
1125 PREFIX = 'beacon_phase'
1125 PREFIX = 'beacon_phase'
1126
1126
1127 def __init__(self):
1127 def __init__(self):
1128 Plot.__init__(self)
1128 Plot.__init__(self)
1129 self.timerange = 24*60*60
1129 self.timerange = 24*60*60
1130 self.isConfig = False
1130 self.isConfig = False
1131 self.__nsubplots = 1
1131 self.__nsubplots = 1
1132 self.counter_imagwr = 0
1132 self.counter_imagwr = 0
1133 self.WIDTH = 800
1133 self.WIDTH = 800
1134 self.HEIGHT = 400
1134 self.HEIGHT = 400
1135 self.WIDTHPROF = 120
1135 self.WIDTHPROF = 120
1136 self.HEIGHTPROF = 0
1136 self.HEIGHTPROF = 0
1137 self.xdata = None
1137 self.xdata = None
1138 self.ydata = None
1138 self.ydata = None
1139
1139
1140 self.PLOT_CODE = BEACON_CODE
1140 self.PLOT_CODE = BEACON_CODE
1141
1141
1142 self.FTP_WEI = None
1142 self.FTP_WEI = None
1143 self.EXP_CODE = None
1143 self.EXP_CODE = None
1144 self.SUB_EXP_CODE = None
1144 self.SUB_EXP_CODE = None
1145 self.PLOT_POS = None
1145 self.PLOT_POS = None
1146
1146
1147 self.filename_phase = None
1147 self.filename_phase = None
1148
1148
1149 self.figfile = None
1149 self.figfile = None
1150
1150
1151 self.xmin = None
1151 self.xmin = None
1152 self.xmax = None
1152 self.xmax = None
1153
1153
1154 def getSubplots(self):
1154 def getSubplots(self):
1155
1155
1156 ncol = 1
1156 ncol = 1
1157 nrow = 1
1157 nrow = 1
1158
1158
1159 return nrow, ncol
1159 return nrow, ncol
1160
1160
1161 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1161 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1162
1162
1163 self.__showprofile = showprofile
1163 self.__showprofile = showprofile
1164 self.nplots = nplots
1164 self.nplots = nplots
1165
1165
1166 ncolspan = 7
1166 ncolspan = 7
1167 colspan = 6
1167 colspan = 6
1168 self.__nsubplots = 2
1168 self.__nsubplots = 2
1169
1169
1170 self.createFigure(id = id,
1170 self.createFigure(id = id,
1171 wintitle = wintitle,
1171 wintitle = wintitle,
1172 widthplot = self.WIDTH+self.WIDTHPROF,
1172 widthplot = self.WIDTH+self.WIDTHPROF,
1173 heightplot = self.HEIGHT+self.HEIGHTPROF,
1173 heightplot = self.HEIGHT+self.HEIGHTPROF,
1174 show=show)
1174 show=show)
1175
1175
1176 nrow, ncol = self.getSubplots()
1176 nrow, ncol = self.getSubplots()
1177
1177
1178 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1178 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1179
1179
1180 def save_phase(self, filename_phase):
1180 def save_phase(self, filename_phase):
1181 f = open(filename_phase,'w+')
1181 f = open(filename_phase,'w+')
1182 f.write('\n\n')
1182 f.write('\n\n')
1183 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
1183 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
1184 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
1184 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
1185 f.close()
1185 f.close()
1186
1186
1187 def save_data(self, filename_phase, data, data_datetime):
1187 def save_data(self, filename_phase, data, data_datetime):
1188 f=open(filename_phase,'a')
1188 f=open(filename_phase,'a')
1189 timetuple_data = data_datetime.timetuple()
1189 timetuple_data = data_datetime.timetuple()
1190 day = str(timetuple_data.tm_mday)
1190 day = str(timetuple_data.tm_mday)
1191 month = str(timetuple_data.tm_mon)
1191 month = str(timetuple_data.tm_mon)
1192 year = str(timetuple_data.tm_year)
1192 year = str(timetuple_data.tm_year)
1193 hour = str(timetuple_data.tm_hour)
1193 hour = str(timetuple_data.tm_hour)
1194 minute = str(timetuple_data.tm_min)
1194 minute = str(timetuple_data.tm_min)
1195 second = str(timetuple_data.tm_sec)
1195 second = str(timetuple_data.tm_sec)
1196 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
1196 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
1197 f.close()
1197 f.close()
1198
1198
1199 def plot(self):
1199 def plot(self):
1200 log.warning('TODO: Not yet implemented...')
1200 log.warning('TODO: Not yet implemented...')
1201
1201
1202 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1202 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1203 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
1203 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
1204 timerange=None,
1204 timerange=None,
1205 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1205 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1206 server=None, folder=None, username=None, password=None,
1206 server=None, folder=None, username=None, password=None,
1207 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1207 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1208
1208
1209 if dataOut.flagNoData:
1209 if dataOut.flagNoData:
1210 return dataOut
1210 return dataOut
1211
1211
1212 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1212 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1213 return
1213 return
1214
1214
1215 if pairsList == None:
1215 if pairsList == None:
1216 pairsIndexList = dataOut.pairsIndexList[:10]
1216 pairsIndexList = dataOut.pairsIndexList[:10]
1217 else:
1217 else:
1218 pairsIndexList = []
1218 pairsIndexList = []
1219 for pair in pairsList:
1219 for pair in pairsList:
1220 if pair not in dataOut.pairsList:
1220 if pair not in dataOut.pairsList:
1221 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
1221 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
1222 pairsIndexList.append(dataOut.pairsList.index(pair))
1222 pairsIndexList.append(dataOut.pairsList.index(pair))
1223
1223
1224 if pairsIndexList == []:
1224 if pairsIndexList == []:
1225 return
1225 return
1226
1226
1227 # if len(pairsIndexList) > 4:
1227 # if len(pairsIndexList) > 4:
1228 # pairsIndexList = pairsIndexList[0:4]
1228 # pairsIndexList = pairsIndexList[0:4]
1229
1229
1230 hmin_index = None
1230 hmin_index = None
1231 hmax_index = None
1231 hmax_index = None
1232
1232
1233 if hmin != None and hmax != None:
1233 if hmin != None and hmax != None:
1234 indexes = numpy.arange(dataOut.nHeights)
1234 indexes = numpy.arange(dataOut.nHeights)
1235 hmin_list = indexes[dataOut.heightList >= hmin]
1235 hmin_list = indexes[dataOut.heightList >= hmin]
1236 hmax_list = indexes[dataOut.heightList <= hmax]
1236 hmax_list = indexes[dataOut.heightList <= hmax]
1237
1237
1238 if hmin_list.any():
1238 if hmin_list.any():
1239 hmin_index = hmin_list[0]
1239 hmin_index = hmin_list[0]
1240
1240
1241 if hmax_list.any():
1241 if hmax_list.any():
1242 hmax_index = hmax_list[-1]+1
1242 hmax_index = hmax_list[-1]+1
1243
1243
1244 x = dataOut.getTimeRange()
1244 x = dataOut.getTimeRange()
1245
1245
1246 thisDatetime = dataOut.datatime
1246 thisDatetime = dataOut.datatime
1247
1247
1248 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1248 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1249 xlabel = "Local Time"
1249 xlabel = "Local Time"
1250 ylabel = "Phase (degrees)"
1250 ylabel = "Phase (degrees)"
1251
1251
1252 update_figfile = False
1252 update_figfile = False
1253
1253
1254 nplots = len(pairsIndexList)
1254 nplots = len(pairsIndexList)
1255 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1255 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
1256 phase_beacon = numpy.zeros(len(pairsIndexList))
1256 phase_beacon = numpy.zeros(len(pairsIndexList))
1257 for i in range(nplots):
1257 for i in range(nplots):
1258 pair = dataOut.pairsList[pairsIndexList[i]]
1258 pair = dataOut.pairsList[pairsIndexList[i]]
1259 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
1259 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
1260 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
1260 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
1261 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
1261 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
1262 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
1262 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
1263 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
1263 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
1264
1264
1265 if dataOut.beacon_heiIndexList:
1265 if dataOut.beacon_heiIndexList:
1266 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
1266 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
1267 else:
1267 else:
1268 phase_beacon[i] = numpy.average(phase)
1268 phase_beacon[i] = numpy.average(phase)
1269
1269
1270 if not self.isConfig:
1270 if not self.isConfig:
1271
1271
1272 nplots = len(pairsIndexList)
1272 nplots = len(pairsIndexList)
1273
1273
1274 self.setup(id=id,
1274 self.setup(id=id,
1275 nplots=nplots,
1275 nplots=nplots,
1276 wintitle=wintitle,
1276 wintitle=wintitle,
1277 showprofile=showprofile,
1277 showprofile=showprofile,
1278 show=show)
1278 show=show)
1279
1279
1280 if timerange != None:
1280 if timerange != None:
1281 self.timerange = timerange
1281 self.timerange = timerange
1282
1282
1283 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1283 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1284
1284
1285 if ymin == None: ymin = 0
1285 if ymin == None: ymin = 0
1286 if ymax == None: ymax = 360
1286 if ymax == None: ymax = 360
1287
1287
1288 self.FTP_WEI = ftp_wei
1288 self.FTP_WEI = ftp_wei
1289 self.EXP_CODE = exp_code
1289 self.EXP_CODE = exp_code
1290 self.SUB_EXP_CODE = sub_exp_code
1290 self.SUB_EXP_CODE = sub_exp_code
1291 self.PLOT_POS = plot_pos
1291 self.PLOT_POS = plot_pos
1292
1292
1293 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1293 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1294 self.isConfig = True
1294 self.isConfig = True
1295 self.figfile = figfile
1295 self.figfile = figfile
1296 self.xdata = numpy.array([])
1296 self.xdata = numpy.array([])
1297 self.ydata = numpy.array([])
1297 self.ydata = numpy.array([])
1298
1298
1299 update_figfile = True
1299 update_figfile = True
1300
1300
1301 #open file beacon phase
1301 #open file beacon phase
1302 path = '%s%03d' %(self.PREFIX, self.id)
1302 path = '%s%03d' %(self.PREFIX, self.id)
1303 beacon_file = os.path.join(path,'%s.txt'%self.name)
1303 beacon_file = os.path.join(path,'%s.txt'%self.name)
1304 self.filename_phase = os.path.join(figpath,beacon_file)
1304 self.filename_phase = os.path.join(figpath,beacon_file)
1305 #self.save_phase(self.filename_phase)
1305 #self.save_phase(self.filename_phase)
1306
1306
1307
1307
1308 #store data beacon phase
1308 #store data beacon phase
1309 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1309 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
1310
1310
1311 self.setWinTitle(title)
1311 self.setWinTitle(title)
1312
1312
1313
1313
1314 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1314 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1315
1315
1316 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
1316 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
1317
1317
1318 axes = self.axesList[0]
1318 axes = self.axesList[0]
1319
1319
1320 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1320 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1321
1321
1322 if len(self.ydata)==0:
1322 if len(self.ydata)==0:
1323 self.ydata = phase_beacon.reshape(-1,1)
1323 self.ydata = phase_beacon.reshape(-1,1)
1324 else:
1324 else:
1325 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1325 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1326
1326
1327
1327
1328 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1328 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1329 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1329 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1330 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1330 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1331 XAxisAsTime=True, grid='both'
1331 XAxisAsTime=True, grid='both'
1332 )
1332 )
1333
1333
1334 self.draw()
1334 self.draw()
1335
1335
1336 if dataOut.ltctime >= self.xmax:
1336 if dataOut.ltctime >= self.xmax:
1337 self.counter_imagwr = wr_period
1337 self.counter_imagwr = wr_period
1338 self.isConfig = False
1338 self.isConfig = False
1339 update_figfile = True
1339 update_figfile = True
1340
1340
1341 self.save(figpath=figpath,
1341 self.save(figpath=figpath,
1342 figfile=figfile,
1342 figfile=figfile,
1343 save=save,
1343 save=save,
1344 ftp=ftp,
1344 ftp=ftp,
1345 wr_period=wr_period,
1345 wr_period=wr_period,
1346 thisDatetime=thisDatetime,
1346 thisDatetime=thisDatetime,
1347 update_figfile=update_figfile)
1347 update_figfile=update_figfile)
1348
1348
1349 return dataOut
1349 return dataOut
@@ -1,1428 +1,1428
1
1
2 import os
2 import os
3 import time
3 import time
4 import math
4 import math
5 import datetime
5 import datetime
6 import numpy
6 import numpy
7
7
8 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator #YONG
8 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator #YONG
9
9
10 from .jroplot_spectra import RTIPlot, NoisePlot
10 from .jroplot_spectra import RTIPlot, NoisePlot
11
11
12 from schainpy.utils import log
12 from schainpy.utils import log
13 from .plotting_codes import *
13 from .plotting_codes import *
14
14
15 from schainpy.model.graphics.jroplot_base import Plot, plt
15 from schainpy.model.graphics.jroplot_base import Plot, plt
16
16
17 import matplotlib.pyplot as plt
17 import matplotlib.pyplot as plt
18 import matplotlib.colors as colors
18 import matplotlib.colors as colors
19 from matplotlib.ticker import MultipleLocator, LogLocator, NullFormatter
19 from matplotlib.ticker import MultipleLocator, LogLocator, NullFormatter
20
20
21 class RTIDPPlot(RTIPlot):
21 class RTIDPPlot(RTIPlot):
22 '''
22 '''
23 Written by R. Flores
23 Written by R. Flores
24 '''
24 '''
25 '''Plot for RTI Double Pulse Experiment Using Cross Products Analysis
25 '''Plot for RTI Double Pulse Experiment Using Cross Products Analysis
26 '''
26 '''
27
27
28 CODE = 'RTIDP'
28 CODE = 'RTIDP'
29 colormap = 'jet'
29 colormap = 'jet'
30 plot_name = 'RTI'
30 plot_name = 'RTI'
31 plot_type = 'pcolorbuffer'
31 plot_type = 'pcolorbuffer'
32
32
33 def setup(self):
33 def setup(self):
34 self.xaxis = 'time'
34 self.xaxis = 'time'
35 self.ncols = 1
35 self.ncols = 1
36 self.nrows = 3
36 self.nrows = 3
37 self.nplots = self.nrows
37 self.nplots = self.nrows
38
38
39 self.ylabel = 'Range [km]'
39 self.ylabel = 'Range [km]'
40 self.xlabel = 'Time (LT)'
40 self.xlabel = 'Time (LT)'
41
41
42 self.cb_label = 'Intensity (dB)'
42 self.cb_label = 'Intensity (dB)'
43
43
44 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
44 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
45
45
46 self.titles = ['{} Channel {}'.format(
46 self.titles = ['{} Channel {}'.format(
47 self.plot_name.upper(), '0x1'),'{} Channel {}'.format(
47 self.plot_name.upper(), '0x1'),'{} Channel {}'.format(
48 self.plot_name.upper(), '0'),'{} Channel {}'.format(
48 self.plot_name.upper(), '0'),'{} Channel {}'.format(
49 self.plot_name.upper(), '1')]
49 self.plot_name.upper(), '1')]
50
50
51 def update(self, dataOut):
51 def update(self, dataOut):
52
52
53 data = {}
53 data = {}
54 meta = {}
54 meta = {}
55 data['rti'] = dataOut.data_for_RTI_DP
55 data['rti'] = dataOut.data_for_RTI_DP
56 data['NDP'] = dataOut.NDP
56 data['NDP'] = dataOut.NDP
57
57
58 return data, meta
58 return data, meta
59
59
60 def plot(self):
60 def plot(self):
61
61
62 NDP = self.data['NDP'][-1]
62 NDP = self.data['NDP'][-1]
63 self.x = self.data.times
63 self.x = self.data.times
64 self.y = self.data.yrange[0:NDP]
64 self.y = self.data.yrange[0:NDP]
65 self.z = self.data['rti']
65 self.z = self.data['rti']
66 self.z = numpy.ma.masked_invalid(self.z)
66 self.z = numpy.ma.masked_invalid(self.z)
67
67
68 if self.decimation is None:
68 if self.decimation is None:
69 x, y, z = self.fill_gaps(self.x, self.y, self.z)
69 x, y, z = self.fill_gaps(self.x, self.y, self.z)
70 else:
70 else:
71 x, y, z = self.fill_gaps(*self.decimate())
71 x, y, z = self.fill_gaps(*self.decimate())
72
72
73 for n, ax in enumerate(self.axes):
73 for n, ax in enumerate(self.axes):
74
74
75 self.zmax = self.zmax if self.zmax is not None else numpy.max(
75 self.zmax = self.zmax if self.zmax is not None else numpy.max(
76 self.z[1][0,12:40])
76 self.z[1][0,12:40])
77 self.zmin = self.zmin if self.zmin is not None else numpy.min(
77 self.zmin = self.zmin if self.zmin is not None else numpy.min(
78 self.z[1][0,12:40])
78 self.z[1][0,12:40])
79
79
80 if ax.firsttime:
80 if ax.firsttime:
81
81
82 if self.zlimits is not None:
82 if self.zlimits is not None:
83 self.zmin, self.zmax = self.zlimits[n]
83 self.zmin, self.zmax = self.zlimits[n]
84
84
85 ax.plt = ax.pcolormesh(x, y, z[n].T,
85 ax.plt = ax.pcolormesh(x, y, z[n].T,
86 vmin=self.zmin,
86 vmin=self.zmin,
87 vmax=self.zmax,
87 vmax=self.zmax,
88 cmap=plt.get_cmap(self.colormap)
88 cmap=plt.get_cmap(self.colormap)
89 )
89 )
90 else:
90 else:
91 #if self.zlimits is not None:
91 #if self.zlimits is not None:
92 #self.zmin, self.zmax = self.zlimits[n]
92 #self.zmin, self.zmax = self.zlimits[n]
93 ax.collections.remove(ax.collections[0])
93 ax.plt.remove()
94 ax.plt = ax.pcolormesh(x, y, z[n].T,
94 ax.plt = ax.pcolormesh(x, y, z[n].T,
95 vmin=self.zmin,
95 vmin=self.zmin,
96 vmax=self.zmax,
96 vmax=self.zmax,
97 cmap=plt.get_cmap(self.colormap)
97 cmap=plt.get_cmap(self.colormap)
98 )
98 )
99
99
100
100
101 class RTILPPlot(RTIPlot):
101 class RTILPPlot(RTIPlot):
102 '''
102 '''
103 Written by R. Flores
103 Written by R. Flores
104 '''
104 '''
105 '''
105 '''
106 Plot for RTI Long Pulse Using Cross Products Analysis
106 Plot for RTI Long Pulse Using Cross Products Analysis
107 '''
107 '''
108
108
109 CODE = 'RTILP'
109 CODE = 'RTILP'
110 colormap = 'jet'
110 colormap = 'jet'
111 plot_name = 'RTI LP'
111 plot_name = 'RTI LP'
112 plot_type = 'pcolorbuffer'
112 plot_type = 'pcolorbuffer'
113
113
114 def setup(self):
114 def setup(self):
115 self.xaxis = 'time'
115 self.xaxis = 'time'
116 self.ncols = 1
116 self.ncols = 1
117 self.nrows = 2
117 self.nrows = 2
118 self.nplots = self.nrows
118 self.nplots = self.nrows
119
119
120 self.ylabel = 'Range [km]'
120 self.ylabel = 'Range [km]'
121 self.xlabel = 'Time (LT)'
121 self.xlabel = 'Time (LT)'
122
122
123 self.cb_label = 'Intensity (dB)'
123 self.cb_label = 'Intensity (dB)'
124
124
125 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
125 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
126
126
127
127
128 self.titles = ['{} Channel {}'.format(
128 self.titles = ['{} Channel {}'.format(
129 self.plot_name.upper(), '0'),'{} Channel {}'.format(
129 self.plot_name.upper(), '0'),'{} Channel {}'.format(
130 self.plot_name.upper(), '1'),'{} Channel {}'.format(
130 self.plot_name.upper(), '1'),'{} Channel {}'.format(
131 self.plot_name.upper(), '2'),'{} Channel {}'.format(
131 self.plot_name.upper(), '2'),'{} Channel {}'.format(
132 self.plot_name.upper(), '3')]
132 self.plot_name.upper(), '3')]
133
133
134
134
135 def update(self, dataOut):
135 def update(self, dataOut):
136
136
137 data = {}
137 data = {}
138 meta = {}
138 meta = {}
139 data['rti'] = dataOut.data_for_RTI_LP
139 data['rti'] = dataOut.data_for_RTI_LP
140 data['NRANGE'] = dataOut.NRANGE
140 data['NRANGE'] = dataOut.NRANGE
141
141
142 return data, meta
142 return data, meta
143
143
144 def plot(self):
144 def plot(self):
145
145
146 NRANGE = self.data['NRANGE'][-1]
146 NRANGE = self.data['NRANGE'][-1]
147 self.x = self.data.times
147 self.x = self.data.times
148 self.y = self.data.yrange[0:NRANGE]
148 self.y = self.data.yrange[0:NRANGE]
149
149
150 self.z = self.data['rti']
150 self.z = self.data['rti']
151
151
152 self.z = numpy.ma.masked_invalid(self.z)
152 self.z = numpy.ma.masked_invalid(self.z)
153
153
154 if self.decimation is None:
154 if self.decimation is None:
155 x, y, z = self.fill_gaps(self.x, self.y, self.z)
155 x, y, z = self.fill_gaps(self.x, self.y, self.z)
156 else:
156 else:
157 x, y, z = self.fill_gaps(*self.decimate())
157 x, y, z = self.fill_gaps(*self.decimate())
158
158
159 for n, ax in enumerate(self.axes):
159 for n, ax in enumerate(self.axes):
160
160
161 self.zmax = self.zmax if self.zmax is not None else numpy.max(
161 self.zmax = self.zmax if self.zmax is not None else numpy.max(
162 self.z[1][0,12:40])
162 self.z[1][0,12:40])
163 self.zmin = self.zmin if self.zmin is not None else numpy.min(
163 self.zmin = self.zmin if self.zmin is not None else numpy.min(
164 self.z[1][0,12:40])
164 self.z[1][0,12:40])
165
165
166 if ax.firsttime:
166 if ax.firsttime:
167
167
168 if self.zlimits is not None:
168 if self.zlimits is not None:
169 self.zmin, self.zmax = self.zlimits[n]
169 self.zmin, self.zmax = self.zlimits[n]
170
170
171
171
172 ax.plt = ax.pcolormesh(x, y, z[n].T,
172 ax.plt = ax.pcolormesh(x, y, z[n].T,
173 vmin=self.zmin,
173 vmin=self.zmin,
174 vmax=self.zmax,
174 vmax=self.zmax,
175 cmap=plt.get_cmap(self.colormap)
175 cmap=plt.get_cmap(self.colormap)
176 )
176 )
177
177
178 else:
178 else:
179 if self.zlimits is not None:
179 if self.zlimits is not None:
180 self.zmin, self.zmax = self.zlimits[n]
180 self.zmin, self.zmax = self.zlimits[n]
181 ax.collections.remove(ax.collections[0])
181 ax.plt.remove()
182 ax.plt = ax.pcolormesh(x, y, z[n].T,
182 ax.plt = ax.pcolormesh(x, y, z[n].T,
183 vmin=self.zmin,
183 vmin=self.zmin,
184 vmax=self.zmax,
184 vmax=self.zmax,
185 cmap=plt.get_cmap(self.colormap)
185 cmap=plt.get_cmap(self.colormap)
186 )
186 )
187
187
188
188
189 class DenRTIPlot(RTIPlot):
189 class DenRTIPlot(RTIPlot):
190 '''
190 '''
191 Written by R. Flores
191 Written by R. Flores
192 '''
192 '''
193 '''
193 '''
194 Plot for Den
194 RTI Plot for Electron Densities
195 '''
195 '''
196
196
197 CODE = 'denrti'
197 CODE = 'denrti'
198 colormap = 'jet'
198 colormap = 'jet'
199
199
200 def setup(self):
200 def setup(self):
201 self.xaxis = 'time'
201 self.xaxis = 'time'
202 self.ncols = 1
202 self.ncols = 1
203 self.nrows = self.data.shape(self.CODE)[0]
203 self.nrows = self.data.shape(self.CODE)[0]
204 self.nplots = self.nrows
204 self.nplots = self.nrows
205
205
206 self.ylabel = 'Range [km]'
206 self.ylabel = 'Range [km]'
207 self.xlabel = 'Time (LT)'
207 self.xlabel = 'Time (LT)'
208
208
209 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
209 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
210
210
211 if self.CODE == 'denrti':
211 if self.CODE == 'denrti':
212 self.cb_label = r'$\mathrm{N_e}$ Electron Density ($\mathrm{1/cm^3}$)'
212 self.cb_label = r'$\mathrm{N_e}$ Electron Density ($\mathrm{1/cm^3}$)'
213
213
214 self.titles = ['Electron Density RTI']
214 self.titles = ['Electron Density RTI']
215
215
216 def update(self, dataOut):
216 def update(self, dataOut):
217
217
218 data = {}
218 data = {}
219 meta = {}
219 meta = {}
220
220
221 data['denrti'] = dataOut.DensityFinal*1.e-6 #To Plot in cm^-3
221 data['denrti'] = dataOut.DensityFinal*1.e-6 #To Plot in cm^-3
222
222
223 return data, meta
223 return data, meta
224
224
225 def plot(self):
225 def plot(self):
226
226
227 self.x = self.data.times
227 self.x = self.data.times
228 self.y = self.data.yrange
228 self.y = self.data.yrange
229
229
230 self.z = self.data[self.CODE]
230 self.z = self.data[self.CODE]
231
231
232 self.z = numpy.ma.masked_invalid(self.z)
232 self.z = numpy.ma.masked_invalid(self.z)
233
233
234 if self.decimation is None:
234 if self.decimation is None:
235 x, y, z = self.fill_gaps(self.x, self.y, self.z)
235 x, y, z = self.fill_gaps(self.x, self.y, self.z)
236 else:
236 else:
237 x, y, z = self.fill_gaps(*self.decimate())
237 x, y, z = self.fill_gaps(*self.decimate())
238
238
239 for n, ax in enumerate(self.axes):
239 for n, ax in enumerate(self.axes):
240
240
241 self.zmax = self.zmax if self.zmax is not None else numpy.max(
241 self.zmax = self.zmax if self.zmax is not None else numpy.max(
242 self.z[n])
242 self.z[n])
243 self.zmin = self.zmin if self.zmin is not None else numpy.min(
243 self.zmin = self.zmin if self.zmin is not None else numpy.min(
244 self.z[n])
244 self.z[n])
245
245
246 if ax.firsttime:
246 if ax.firsttime:
247
247
248 if self.zlimits is not None:
248 if self.zlimits is not None:
249 self.zmin, self.zmax = self.zlimits[n]
249 self.zmin, self.zmax = self.zlimits[n]
250 if numpy.log10(self.zmin)<0:
250 if numpy.log10(self.zmin)<0:
251 self.zmin=1
251 self.zmin=1
252 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
252 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
253 vmin=self.zmin,
253 #vmin=self.zmin,
254 vmax=self.zmax,
254 #vmax=self.zmax,
255 cmap=self.cmaps[n],
255 cmap=self.cmaps[n],
256 norm=colors.LogNorm()
256 norm=colors.LogNorm(vmin=self.zmin,vmax=self.zmax)
257 )
257 )
258
258
259 else:
259 else:
260 if self.zlimits is not None:
260 if self.zlimits is not None:
261 self.zmin, self.zmax = self.zlimits[n]
261 self.zmin, self.zmax = self.zlimits[n]
262 ax.collections.remove(ax.collections[0])
262 ax.plt.remove()
263 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
263 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
264 vmin=self.zmin,
264 #vmin=self.zmin,
265 vmax=self.zmax,
265 #vmax=self.zmax,
266 cmap=self.cmaps[n],
266 cmap=self.cmaps[n],
267 norm=colors.LogNorm()
267 norm=colors.LogNorm(vmin=self.zmin,vmax=self.zmax)
268 )
268 )
269
269
270
270
271 class ETempRTIPlot(RTIPlot):
271 class ETempRTIPlot(RTIPlot):
272 '''
272 '''
273 Written by R. Flores
273 Written by R. Flores
274 '''
274 '''
275 '''
275 '''
276 Plot for Electron Temperature
276 Plot for Electron Temperature
277 '''
277 '''
278
278
279 CODE = 'ETemp'
279 CODE = 'ETemp'
280 colormap = 'jet'
280 colormap = 'jet'
281
281
282 def setup(self):
282 def setup(self):
283 self.xaxis = 'time'
283 self.xaxis = 'time'
284 self.ncols = 1
284 self.ncols = 1
285 self.nrows = self.data.shape(self.CODE)[0]
285 self.nrows = self.data.shape(self.CODE)[0]
286 self.nplots = self.nrows
286 self.nplots = self.nrows
287
287
288 self.ylabel = 'Range [km]'
288 self.ylabel = 'Range [km]'
289 self.xlabel = 'Time (LT)'
289 self.xlabel = 'Time (LT)'
290 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
290 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
291 if self.CODE == 'ETemp':
291 if self.CODE == 'ETemp':
292 self.cb_label = 'Electron Temperature (K)'
292 self.cb_label = 'Electron Temperature (K)'
293 self.titles = ['Electron Temperature RTI']
293 self.titles = ['Electron Temperature RTI']
294 if self.CODE == 'ITemp':
294 if self.CODE == 'ITemp':
295 self.cb_label = 'Ion Temperature (K)'
295 self.cb_label = 'Ion Temperature (K)'
296 self.titles = ['Ion Temperature RTI']
296 self.titles = ['Ion Temperature RTI']
297 if self.CODE == 'HeFracLP':
297 if self.CODE == 'HeFracLP':
298 self.cb_label ='He+ Fraction'
298 self.cb_label ='He+ Fraction'
299 self.titles = ['He+ Fraction RTI']
299 self.titles = ['He+ Fraction RTI']
300 self.zmax=0.16
300 self.zmax=0.16
301 if self.CODE == 'HFracLP':
301 if self.CODE == 'HFracLP':
302 self.cb_label ='H+ Fraction'
302 self.cb_label ='H+ Fraction'
303 self.titles = ['H+ Fraction RTI']
303 self.titles = ['H+ Fraction RTI']
304
304
305 def update(self, dataOut):
305 def update(self, dataOut):
306
306
307 data = {}
307 data = {}
308 meta = {}
308 meta = {}
309
309
310 data['ETemp'] = dataOut.ElecTempFinal
310 data['ETemp'] = dataOut.ElecTempFinal
311
311
312 return data, meta
312 return data, meta
313
313
314 def plot(self):
314 def plot(self):
315
315
316 self.x = self.data.times
316 self.x = self.data.times
317 self.y = self.data.yrange
317 self.y = self.data.yrange
318 self.z = self.data[self.CODE]
318 self.z = self.data[self.CODE]
319
319
320 self.z = numpy.ma.masked_invalid(self.z)
320 self.z = numpy.ma.masked_invalid(self.z)
321
321
322 if self.decimation is None:
322 if self.decimation is None:
323 x, y, z = self.fill_gaps(self.x, self.y, self.z)
323 x, y, z = self.fill_gaps(self.x, self.y, self.z)
324 else:
324 else:
325 x, y, z = self.fill_gaps(*self.decimate())
325 x, y, z = self.fill_gaps(*self.decimate())
326
326
327 for n, ax in enumerate(self.axes):
327 for n, ax in enumerate(self.axes):
328
328
329 self.zmax = self.zmax if self.zmax is not None else numpy.max(
329 self.zmax = self.zmax if self.zmax is not None else numpy.max(
330 self.z[n])
330 self.z[n])
331 self.zmin = self.zmin if self.zmin is not None else numpy.min(
331 self.zmin = self.zmin if self.zmin is not None else numpy.min(
332 self.z[n])
332 self.z[n])
333
333
334 if ax.firsttime:
334 if ax.firsttime:
335
335
336 if self.zlimits is not None:
336 if self.zlimits is not None:
337 self.zmin, self.zmax = self.zlimits[n]
337 self.zmin, self.zmax = self.zlimits[n]
338
338
339 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
339 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
340 vmin=self.zmin,
340 vmin=self.zmin,
341 vmax=self.zmax,
341 vmax=self.zmax,
342 cmap=self.cmaps[n]
342 cmap=self.cmaps[n]
343 )
343 )
344 #plt.tight_layout()
344 #plt.tight_layout()
345
345
346 else:
346 else:
347 if self.zlimits is not None:
347 if self.zlimits is not None:
348 self.zmin, self.zmax = self.zlimits[n]
348 self.zmin, self.zmax = self.zlimits[n]
349 ax.collections.remove(ax.collections[0])
349 ax.plt.remove()
350 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
350 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
351 vmin=self.zmin,
351 vmin=self.zmin,
352 vmax=self.zmax,
352 vmax=self.zmax,
353 cmap=self.cmaps[n]
353 cmap=self.cmaps[n]
354 )
354 )
355
355
356
356
357 class ITempRTIPlot(ETempRTIPlot):
357 class ITempRTIPlot(ETempRTIPlot):
358 '''
358 '''
359 Written by R. Flores
359 Written by R. Flores
360 '''
360 '''
361 '''
361 '''
362 Plot for Ion Temperature
362 Plot for Ion Temperature
363 '''
363 '''
364
364
365 CODE = 'ITemp'
365 CODE = 'ITemp'
366 colormap = 'jet'
366 colormap = 'jet'
367 plot_name = 'Ion Temperature'
367 plot_name = 'Ion Temperature'
368
368
369 def update(self, dataOut):
369 def update(self, dataOut):
370
370
371 data = {}
371 data = {}
372 meta = {}
372 meta = {}
373
373
374 data['ITemp'] = dataOut.IonTempFinal
374 data['ITemp'] = dataOut.IonTempFinal
375
375
376 return data, meta
376 return data, meta
377
377
378
378
379 class HFracRTIPlot(ETempRTIPlot):
379 class HFracRTIPlot(ETempRTIPlot):
380 '''
380 '''
381 Written by R. Flores
381 Written by R. Flores
382 '''
382 '''
383 '''
383 '''
384 Plot for H+ LP
384 Plot for H+ LP
385 '''
385 '''
386
386
387 CODE = 'HFracLP'
387 CODE = 'HFracLP'
388 colormap = 'jet'
388 colormap = 'jet'
389 plot_name = 'H+ Frac'
389 plot_name = 'H+ Frac'
390
390
391 def update(self, dataOut):
391 def update(self, dataOut):
392
392
393 data = {}
393 data = {}
394 meta = {}
394 meta = {}
395 data['HFracLP'] = dataOut.PhyFinal
395 data['HFracLP'] = dataOut.PhyFinal
396
396
397 return data, meta
397 return data, meta
398
398
399
399
400 class HeFracRTIPlot(ETempRTIPlot):
400 class HeFracRTIPlot(ETempRTIPlot):
401 '''
401 '''
402 Written by R. Flores
402 Written by R. Flores
403 '''
403 '''
404 '''
404 '''
405 Plot for He+ LP
405 Plot for He+ LP
406 '''
406 '''
407
407
408 CODE = 'HeFracLP'
408 CODE = 'HeFracLP'
409 colormap = 'jet'
409 colormap = 'jet'
410 plot_name = 'He+ Frac'
410 plot_name = 'He+ Frac'
411
411
412 def update(self, dataOut):
412 def update(self, dataOut):
413
413
414 data = {}
414 data = {}
415 meta = {}
415 meta = {}
416 data['HeFracLP'] = dataOut.PheFinal
416 data['HeFracLP'] = dataOut.PheFinal
417
417
418 return data, meta
418 return data, meta
419
419
420
420
421 class TempsDPPlot(Plot):
421 class TempsDPPlot(Plot):
422 '''
422 '''
423 Written by R. Flores
423 Written by R. Flores
424 '''
424 '''
425 '''
425 '''
426 Plot for Electron - Ion Temperatures
426 Plot for Electron - Ion Temperatures
427 '''
427 '''
428
428
429 CODE = 'tempsDP'
429 CODE = 'tempsDP'
430 #plot_name = 'Temperatures'
430 #plot_name = 'Temperatures'
431 plot_type = 'scatterbuffer'
431 plot_type = 'scatterbuffer'
432
432
433 def setup(self):
433 def setup(self):
434
434
435 self.ncols = 1
435 self.ncols = 1
436 self.nrows = 1
436 self.nrows = 1
437 self.nplots = 1
437 self.nplots = 1
438 self.ylabel = 'Range [km]'
438 self.ylabel = 'Range [km]'
439 self.xlabel = 'Temperature (K)'
439 self.xlabel = 'Temperature (K)'
440 self.titles = ['Electron/Ion Temperatures']
440 self.titles = ['Electron/Ion Temperatures']
441 self.width = 3.5
441 self.width = 3.5
442 self.height = 5.5
442 self.height = 5.5
443 self.colorbar = False
443 self.colorbar = False
444 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
444 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
445
445
446 def update(self, dataOut):
446 def update(self, dataOut):
447 data = {}
447 data = {}
448 meta = {}
448 meta = {}
449
449
450 data['Te'] = dataOut.te2
450 data['Te'] = dataOut.te2
451 data['Ti'] = dataOut.ti2
451 data['Ti'] = dataOut.ti2
452 data['Te_error'] = dataOut.ete2
452 data['Te_error'] = dataOut.ete2
453 data['Ti_error'] = dataOut.eti2
453 data['Ti_error'] = dataOut.eti2
454
454
455 meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
455 meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
456
456
457 return data, meta
457 return data, meta
458
458
459 def plot(self):
459 def plot(self):
460
460
461 y = self.data.yrange
461 y = self.data.yrange
462
462
463 self.xmin = -100
463 self.xmin = -100
464 self.xmax = 5000
464 self.xmax = 5000
465
465
466 ax = self.axes[0]
466 ax = self.axes[0]
467
467
468 data = self.data[-1]
468 data = self.data[-1]
469
469
470 Te = data['Te']
470 Te = data['Te']
471 Ti = data['Ti']
471 Ti = data['Ti']
472 errTe = data['Te_error']
472 errTe = data['Te_error']
473 errTi = data['Ti_error']
473 errTi = data['Ti_error']
474
474
475 if ax.firsttime:
475 if ax.firsttime:
476 ax.errorbar(Te, y, xerr=errTe, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='Te')
476 ax.errorbar(Te, y, xerr=errTe, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='Te')
477 ax.errorbar(Ti, y, fmt='k^', xerr=errTi,elinewidth=1.0,color='b',linewidth=2.0, label='Ti')
477 ax.errorbar(Ti, y, fmt='k^', xerr=errTi,elinewidth=1.0,color='k',linewidth=2.0, label='Ti')
478 plt.legend(loc='lower right')
478 plt.legend(loc='lower right')
479 self.ystep_given = 50
479 self.ystep_given = 50
480 ax.yaxis.set_minor_locator(MultipleLocator(15))
480 ax.yaxis.set_minor_locator(MultipleLocator(15))
481 ax.grid(which='minor')
481 ax.grid(which='minor')
482
482
483 else:
483 else:
484 self.clear_figures()
484 self.clear_figures()
485 ax.errorbar(Te, y, xerr=errTe, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='Te')
485 ax.errorbar(Te, y, xerr=errTe, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='Te')
486 ax.errorbar(Ti, y, fmt='k^', xerr=errTi,elinewidth=1.0,color='b',linewidth=2.0, label='Ti')
486 ax.errorbar(Ti, y, fmt='k^', xerr=errTi,elinewidth=1.0,color='k',linewidth=2.0, label='Ti')
487 plt.legend(loc='lower right')
487 plt.legend(loc='lower right')
488 ax.yaxis.set_minor_locator(MultipleLocator(15))
488 ax.yaxis.set_minor_locator(MultipleLocator(15))
489
489
490
490
491 class TempsHPPlot(Plot):
491 class TempsHPPlot(Plot):
492 '''
492 '''
493 Written by R. Flores
493 Written by R. Flores
494 '''
494 '''
495 '''
495 '''
496 Plot for Temperatures Hybrid Experiment
496 Plot for Temperatures Hybrid Experiment
497 '''
497 '''
498
498
499 CODE = 'temps_LP'
499 CODE = 'temps_LP'
500 #plot_name = 'Temperatures'
500 #plot_name = 'Temperatures'
501 plot_type = 'scatterbuffer'
501 plot_type = 'scatterbuffer'
502
502
503
503
504 def setup(self):
504 def setup(self):
505
505
506 self.ncols = 1
506 self.ncols = 1
507 self.nrows = 1
507 self.nrows = 1
508 self.nplots = 1
508 self.nplots = 1
509 self.ylabel = 'Range [km]'
509 self.ylabel = 'Range [km]'
510 self.xlabel = 'Temperature (K)'
510 self.xlabel = 'Temperature (K)'
511 self.titles = ['Electron/Ion Temperatures']
511 self.titles = ['Electron/Ion Temperatures']
512 self.width = 3.5
512 self.width = 3.5
513 self.height = 6.5
513 self.height = 6.5
514 self.colorbar = False
514 self.colorbar = False
515 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
515 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
516
516
517 def update(self, dataOut):
517 def update(self, dataOut):
518 data = {}
518 data = {}
519 meta = {}
519 meta = {}
520
520
521
521
522 data['Te'] = numpy.concatenate((dataOut.te2[:dataOut.cut],dataOut.te[dataOut.cut:]))
522 data['Te'] = numpy.concatenate((dataOut.te2[:dataOut.cut],dataOut.te[dataOut.cut:]))
523 data['Ti'] = numpy.concatenate((dataOut.ti2[:dataOut.cut],dataOut.ti[dataOut.cut:]))
523 data['Ti'] = numpy.concatenate((dataOut.ti2[:dataOut.cut],dataOut.ti[dataOut.cut:]))
524 data['Te_error'] = numpy.concatenate((dataOut.ete2[:dataOut.cut],dataOut.ete[dataOut.cut:]))
524 data['Te_error'] = numpy.concatenate((dataOut.ete2[:dataOut.cut],dataOut.ete[dataOut.cut:]))
525 data['Ti_error'] = numpy.concatenate((dataOut.eti2[:dataOut.cut],dataOut.eti[dataOut.cut:]))
525 data['Ti_error'] = numpy.concatenate((dataOut.eti2[:dataOut.cut],dataOut.eti[dataOut.cut:]))
526
526
527 meta['yrange'] = dataOut.heightList[0:dataOut.NACF]
527 meta['yrange'] = dataOut.heightList[0:dataOut.NACF]
528
528
529 return data, meta
529 return data, meta
530
530
531 def plot(self):
531 def plot(self):
532
532
533
533
534 self.y = self.data.yrange
534 self.y = self.data.yrange
535 self.xmin = -100
535 self.xmin = -100
536 self.xmax = 4500
536 self.xmax = 4500
537 ax = self.axes[0]
537 ax = self.axes[0]
538
538
539 data = self.data[-1]
539 data = self.data[-1]
540
540
541 Te = data['Te']
541 Te = data['Te']
542 Ti = data['Ti']
542 Ti = data['Ti']
543 errTe = data['Te_error']
543 errTe = data['Te_error']
544 errTi = data['Ti_error']
544 errTi = data['Ti_error']
545
545
546 if ax.firsttime:
546 if ax.firsttime:
547
547
548 ax.errorbar(Te, self.y, xerr=errTe, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='Te')
548 ax.errorbar(Te, self.y, xerr=errTe, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='Te')
549 ax.errorbar(Ti, self.y, fmt='k^', xerr=errTi,elinewidth=1.0,color='b',linewidth=2.0, label='Ti')
549 ax.errorbar(Ti, self.y, fmt='k^', xerr=errTi,elinewidth=1.0,color='',linewidth=2.0, label='Ti')
550 plt.legend(loc='lower right')
550 plt.legend(loc='lower right')
551 self.ystep_given = 200
551 self.ystep_given = 200
552 ax.yaxis.set_minor_locator(MultipleLocator(15))
552 ax.yaxis.set_minor_locator(MultipleLocator(15))
553 ax.grid(which='minor')
553 ax.grid(which='minor')
554
554
555 else:
555 else:
556 self.clear_figures()
556 self.clear_figures()
557 ax.errorbar(Te, self.y, xerr=errTe, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='Te')
557 ax.errorbar(Te, self.y, xerr=errTe, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='Te')
558 ax.errorbar(Ti, self.y, fmt='k^', xerr=errTi,elinewidth=1.0,color='b',linewidth=2.0, label='Ti')
558 ax.errorbar(Ti, self.y, fmt='k^', xerr=errTi,elinewidth=1.0,color='k',linewidth=2.0, label='Ti')
559 plt.legend(loc='lower right')
559 plt.legend(loc='lower right')
560 ax.yaxis.set_minor_locator(MultipleLocator(15))
560 ax.yaxis.set_minor_locator(MultipleLocator(15))
561 ax.grid(which='minor')
561 ax.grid(which='minor')
562
562
563
563
564 class FracsHPPlot(Plot):
564 class FracsHPPlot(Plot):
565 '''
565 '''
566 Written by R. Flores
566 Written by R. Flores
567 '''
567 '''
568 '''
568 '''
569 Plot for Composition LP
569 Plot for Composition LP
570 '''
570 '''
571
571
572 CODE = 'fracs_LP'
572 CODE = 'fracs_LP'
573 plot_type = 'scatterbuffer'
573 plot_type = 'scatterbuffer'
574
574
575
575
576 def setup(self):
576 def setup(self):
577
577
578 self.ncols = 1
578 self.ncols = 1
579 self.nrows = 1
579 self.nrows = 1
580 self.nplots = 1
580 self.nplots = 1
581 self.ylabel = 'Range [km]'
581 self.ylabel = 'Range [km]'
582 self.xlabel = 'Frac'
582 self.xlabel = 'Frac'
583 self.titles = ['Composition']
583 self.titles = ['Composition']
584 self.width = 3.5
584 self.width = 3.5
585 self.height = 6.5
585 self.height = 6.5
586 self.colorbar = False
586 self.colorbar = False
587 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
587 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
588
588
589 def update(self, dataOut):
589 def update(self, dataOut):
590 data = {}
590 data = {}
591 meta = {}
591 meta = {}
592
592
593 #aux_nan=numpy.zeros(dataOut.cut,'float32')
593 #aux_nan=numpy.zeros(dataOut.cut,'float32')
594 #aux_nan[:]=numpy.nan
594 #aux_nan[:]=numpy.nan
595 #data['ph'] = numpy.concatenate((aux_nan,dataOut.ph[dataOut.cut:]))
595 #data['ph'] = numpy.concatenate((aux_nan,dataOut.ph[dataOut.cut:]))
596 #data['eph'] = numpy.concatenate((aux_nan,dataOut.eph[dataOut.cut:]))
596 #data['eph'] = numpy.concatenate((aux_nan,dataOut.eph[dataOut.cut:]))
597
597
598 data['ph'] = dataOut.ph[dataOut.cut:]
598 data['ph'] = dataOut.ph[dataOut.cut:]
599 data['eph'] = dataOut.eph[dataOut.cut:]
599 data['eph'] = dataOut.eph[dataOut.cut:]
600 data['phe'] = dataOut.phe[dataOut.cut:]
600 data['phe'] = dataOut.phe[dataOut.cut:]
601 data['ephe'] = dataOut.ephe[dataOut.cut:]
601 data['ephe'] = dataOut.ephe[dataOut.cut:]
602
602
603 data['cut'] = dataOut.cut
603 data['cut'] = dataOut.cut
604
604
605 meta['yrange'] = dataOut.heightList[0:dataOut.NACF]
605 meta['yrange'] = dataOut.heightList[0:dataOut.NACF]
606
606
607
607
608 return data, meta
608 return data, meta
609
609
610 def plot(self):
610 def plot(self):
611
611
612 data = self.data[-1]
612 data = self.data[-1]
613
613
614 ph = data['ph']
614 ph = data['ph']
615 eph = data['eph']
615 eph = data['eph']
616 phe = data['phe']
616 phe = data['phe']
617 ephe = data['ephe']
617 ephe = data['ephe']
618 cut = data['cut']
618 cut = data['cut']
619 self.y = self.data.yrange
619 self.y = self.data.yrange
620
620
621 self.xmin = 0
621 self.xmin = 0
622 self.xmax = 1
622 self.xmax = 1
623 ax = self.axes[0]
623 ax = self.axes[0]
624
624
625 if ax.firsttime:
625 if ax.firsttime:
626
626
627 ax.errorbar(ph, self.y[cut:], xerr=eph, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='H+')
627 ax.errorbar(ph, self.y[cut:], xerr=eph, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='H+')
628 ax.errorbar(phe, self.y[cut:], fmt='k^', xerr=ephe,elinewidth=1.0,color='b',linewidth=2.0, label='He+')
628 ax.errorbar(phe, self.y[cut:], fmt='k^', xerr=ephe,elinewidth=1.0,color='k',linewidth=2.0, label='He+')
629 plt.legend(loc='lower right')
629 plt.legend(loc='lower right')
630 self.xstep_given = 0.2
630 self.xstep_given = 0.2
631 self.ystep_given = 200
631 self.ystep_given = 200
632 ax.yaxis.set_minor_locator(MultipleLocator(15))
632 ax.yaxis.set_minor_locator(MultipleLocator(15))
633 ax.grid(which='minor')
633 ax.grid(which='minor')
634
634
635 else:
635 else:
636 self.clear_figures()
636 self.clear_figures()
637 ax.errorbar(ph, self.y[cut:], xerr=eph, fmt='r^',elinewidth=1.0,color='b',linewidth=2.0, label='H+')
637 ax.errorbar(ph, self.y[cut:], xerr=eph, fmt='r^',elinewidth=1.0,color='r',linewidth=2.0, label='H+')
638 ax.errorbar(phe, self.y[cut:], fmt='k^', xerr=ephe,elinewidth=1.0,color='b',linewidth=2.0, label='He+')
638 ax.errorbar(phe, self.y[cut:], fmt='k^', xerr=ephe,elinewidth=1.0,color='k',linewidth=2.0, label='He+')
639 plt.legend(loc='lower right')
639 plt.legend(loc='lower right')
640 ax.yaxis.set_minor_locator(MultipleLocator(15))
640 ax.yaxis.set_minor_locator(MultipleLocator(15))
641 ax.grid(which='minor')
641 ax.grid(which='minor')
642
642
643 class EDensityPlot(Plot):
643 class EDensityPlot(Plot):
644 '''
644 '''
645 Written by R. Flores
645 Written by R. Flores
646 '''
646 '''
647 '''
647 '''
648 Plot for electron density
648 Plot for electron density
649 '''
649 '''
650
650
651 CODE = 'den'
651 CODE = 'den'
652 #plot_name = 'Electron Density'
652 #plot_name = 'Electron Density'
653 plot_type = 'scatterbuffer'
653 plot_type = 'scatterbuffer'
654
654
655 def setup(self):
655 def setup(self):
656
656
657 self.ncols = 1
657 self.ncols = 1
658 self.nrows = 1
658 self.nrows = 1
659 self.nplots = 1
659 self.nplots = 1
660 self.ylabel = 'Range [km]'
660 self.ylabel = 'Range [km]'
661 self.xlabel = r'$\mathrm{N_e}$ Electron Density ($\mathrm{1/cm^3}$)'
661 self.xlabel = r'$\mathrm{N_e}$ Electron Density ($\mathrm{1/cm^3}$)'
662 self.titles = ['Electron Density']
662 self.titles = ['Electron Density']
663 self.width = 3.5
663 self.width = 3.5
664 self.height = 5.5
664 self.height = 5.5
665 self.colorbar = False
665 self.colorbar = False
666 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
666 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
667
667
668 def update(self, dataOut):
668 def update(self, dataOut):
669 data = {}
669 data = {}
670 meta = {}
670 meta = {}
671
671
672 data['den_power'] = dataOut.ph2[:dataOut.NSHTS]
672 data['den_power'] = dataOut.ph2[:dataOut.NSHTS]
673 data['den_Faraday'] = dataOut.dphi[:dataOut.NSHTS]
673 data['den_Faraday'] = dataOut.dphi[:dataOut.NSHTS]
674 data['den_error'] = dataOut.sdp2[:dataOut.NSHTS]
674 data['den_error'] = dataOut.sdp2[:dataOut.NSHTS]
675 #data['err_Faraday'] = dataOut.sdn1[:dataOut.NSHTS]
675 #data['err_Faraday'] = dataOut.sdn1[:dataOut.NSHTS]
676 #print(numpy.shape(data['den_power']))
676 #print(numpy.shape(data['den_power']))
677 #print(numpy.shape(data['den_Faraday']))
677 #print(numpy.shape(data['den_Faraday']))
678 #print(numpy.shape(data['den_error']))
678 #print(numpy.shape(data['den_error']))
679
679
680 data['NSHTS'] = dataOut.NSHTS
680 data['NSHTS'] = dataOut.NSHTS
681
681
682 meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
682 meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
683
683
684 return data, meta
684 return data, meta
685
685
686 def plot(self):
686 def plot(self):
687
687
688 y = self.data.yrange
688 y = self.data.yrange
689
689
690 #self.xmin = 1e3
690 #self.xmin = 1e3
691 #self.xmax = 1e7
691 #self.xmax = 1e7
692
692
693 ax = self.axes[0]
693 ax = self.axes[0]
694
694
695 data = self.data[-1]
695 data = self.data[-1]
696
696
697 DenPow = data['den_power']
697 DenPow = data['den_power']
698 DenFar = data['den_Faraday']
698 DenFar = data['den_Faraday']
699 errDenPow = data['den_error']
699 errDenPow = data['den_error']
700 #errFaraday = data['err_Faraday']
700 #errFaraday = data['err_Faraday']
701
701
702 NSHTS = data['NSHTS']
702 NSHTS = data['NSHTS']
703
703
704 if self.CODE == 'denLP':
704 if self.CODE == 'denLP':
705 DenPowLP = data['den_LP']
705 DenPowLP = data['den_LP']
706 errDenPowLP = data['den_LP_error']
706 errDenPowLP = data['den_LP_error']
707 cut = data['cut']
707 cut = data['cut']
708
708
709 if ax.firsttime:
709 if ax.firsttime:
710 self.autoxticks=False
710 self.autoxticks=False
711 #ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
711 #ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
712 ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday',markersize=2,linestyle='-')
712 ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday',markersize=2,linestyle='-')
713 #ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
713 #ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
714 ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power',markersize=2,linestyle='-')
714 ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='k',linewidth=1.0, label='Power',markersize=2,linestyle='-')
715
715
716 if self.CODE=='denLP':
716 if self.CODE=='denLP':
717 ax.errorbar(DenPowLP[cut:], y[cut:], xerr=errDenPowLP[cut:], fmt='r^-',elinewidth=1.0,color='r',linewidth=1.0, label='LP Profile',markersize=2)
717 ax.errorbar(DenPowLP[cut:], y[cut:], xerr=errDenPowLP[cut:], fmt='r^-',elinewidth=1.0,color='r',linewidth=1.0, label='LP Profile',markersize=2)
718
718
719 plt.legend(loc='upper left',fontsize=8.5)
719 plt.legend(loc='upper left',fontsize=8.5)
720 #plt.legend(loc='lower left',fontsize=8.5)
720 #plt.legend(loc='lower left',fontsize=8.5)
721 ax.set_xscale("log", nonposx='clip')
721 ax.set_xscale("log")#, nonposx='clip')
722 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
722 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
723 self.ystep_given=100
723 self.ystep_given=100
724 if self.CODE=='denLP':
724 if self.CODE=='denLP':
725 self.ystep_given=200
725 self.ystep_given=200
726 ax.set_yticks(grid_y_ticks,minor=True)
726 ax.set_yticks(grid_y_ticks,minor=True)
727 locmaj = LogLocator(base=10,numticks=12)
727 locmaj = LogLocator(base=10,numticks=12)
728 ax.xaxis.set_major_locator(locmaj)
728 ax.xaxis.set_major_locator(locmaj)
729 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
729 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
730 ax.xaxis.set_minor_locator(locmin)
730 ax.xaxis.set_minor_locator(locmin)
731 ax.xaxis.set_minor_formatter(NullFormatter())
731 ax.xaxis.set_minor_formatter(NullFormatter())
732 ax.grid(which='minor')
732 ax.grid(which='minor')
733
733
734 else:
734 else:
735 dataBefore = self.data[-2]
735 dataBefore = self.data[-2]
736 DenPowBefore = dataBefore['den_power']
736 DenPowBefore = dataBefore['den_power']
737 self.clear_figures()
737 self.clear_figures()
738 #ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
738 #ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday Profile',markersize=2)
739 ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday',markersize=2,linestyle='-')
739 ax.errorbar(DenFar, y[:NSHTS], xerr=1, fmt='h-',elinewidth=1.0,color='g',linewidth=1.0, label='Faraday',markersize=2,linestyle='-')
740 #ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
740 #ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power Profile',markersize=2)
741 ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power',markersize=2,linestyle='-')
741 ax.errorbar(DenPow, y[:NSHTS], fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='k',linewidth=1.0, label='Power',markersize=2,linestyle='-')
742 ax.errorbar(DenPowBefore, y[:NSHTS], elinewidth=1.0,color='r',linewidth=0.5,linestyle="dashed")
742 ax.errorbar(DenPowBefore, y[:NSHTS], elinewidth=1.0,color='r',linewidth=0.5,linestyle="dashed")
743
743
744 if self.CODE=='denLP':
744 if self.CODE=='denLP':
745 ax.errorbar(DenPowLP[cut:], y[cut:], fmt='r^-', xerr=errDenPowLP[cut:],elinewidth=1.0,color='r',linewidth=1.0, label='LP Profile',markersize=2)
745 ax.errorbar(DenPowLP[cut:], y[cut:], fmt='r^-', xerr=errDenPowLP[cut:],elinewidth=1.0,color='r',linewidth=1.0, label='LP Profile',markersize=2)
746
746
747 ax.set_xscale("log", nonposx='clip')
747 ax.set_xscale("log")#, nonposx='clip')
748 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
748 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
749 ax.set_yticks(grid_y_ticks,minor=True)
749 ax.set_yticks(grid_y_ticks,minor=True)
750 locmaj = LogLocator(base=10,numticks=12)
750 locmaj = LogLocator(base=10,numticks=12)
751 ax.xaxis.set_major_locator(locmaj)
751 ax.xaxis.set_major_locator(locmaj)
752 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
752 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
753 ax.xaxis.set_minor_locator(locmin)
753 ax.xaxis.set_minor_locator(locmin)
754 ax.xaxis.set_minor_formatter(NullFormatter())
754 ax.xaxis.set_minor_formatter(NullFormatter())
755 ax.grid(which='minor')
755 ax.grid(which='minor')
756 plt.legend(loc='upper left',fontsize=8.5)
756 plt.legend(loc='upper left',fontsize=8.5)
757 #plt.legend(loc='lower left',fontsize=8.5)
757 #plt.legend(loc='lower left',fontsize=8.5)
758
758
759 class RelativeDenPlot(Plot):
759 class RelativeDenPlot(Plot):
760 '''
760 '''
761 Written by R. Flores
761 Written by R. Flores
762 '''
762 '''
763 '''
763 '''
764 Plot for electron density
764 Plot for electron density
765 '''
765 '''
766
766
767 CODE = 'den'
767 CODE = 'den'
768 #plot_name = 'Electron Density'
768 #plot_name = 'Electron Density'
769 plot_type = 'scatterbuffer'
769 plot_type = 'scatterbuffer'
770
770
771 def setup(self):
771 def setup(self):
772
772
773 self.ncols = 1
773 self.ncols = 1
774 self.nrows = 1
774 self.nrows = 1
775 self.nplots = 1
775 self.nplots = 1
776 self.ylabel = 'Range [km]'
776 self.ylabel = 'Range [km]'
777 self.xlabel = r'$\mathrm{N_e}$ Relative Electron Density ($\mathrm{1/cm^3}$)'
777 self.xlabel = r'$\mathrm{N_e}$ Relative Electron Density ($\mathrm{1/cm^3}$)'
778 self.titles = ['Electron Density']
778 self.titles = ['Electron Density']
779 self.width = 3.5
779 self.width = 3.5
780 self.height = 5.5
780 self.height = 5.5
781 self.colorbar = False
781 self.colorbar = False
782 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
782 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
783
783
784 def update(self, dataOut):
784 def update(self, dataOut):
785 data = {}
785 data = {}
786 meta = {}
786 meta = {}
787
787
788 data['den_power'] = dataOut.ph2
788 data['den_power'] = dataOut.ph2
789 data['den_error'] = dataOut.sdp2
789 data['den_error'] = dataOut.sdp2
790
790
791 meta['yrange'] = dataOut.heightList
791 meta['yrange'] = dataOut.heightList
792
792
793 return data, meta
793 return data, meta
794
794
795 def plot(self):
795 def plot(self):
796
796
797 y = self.data.yrange
797 y = self.data.yrange
798
798
799 ax = self.axes[0]
799 ax = self.axes[0]
800
800
801 data = self.data[-1]
801 data = self.data[-1]
802
802
803 DenPow = data['den_power']
803 DenPow = data['den_power']
804 errDenPow = data['den_error']
804 errDenPow = data['den_error']
805
805
806 if ax.firsttime:
806 if ax.firsttime:
807 self.autoxticks=False
807 self.autoxticks=False
808 ax.errorbar(DenPow, y, fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power',markersize=2,linestyle='-')
808 ax.errorbar(DenPow, y, fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='k',linewidth=1.0, label='Power',markersize=2,linestyle='-')
809
809
810 plt.legend(loc='upper left',fontsize=8.5)
810 plt.legend(loc='upper left',fontsize=8.5)
811 #plt.legend(loc='lower left',fontsize=8.5)
811 #plt.legend(loc='lower left',fontsize=8.5)
812 ax.set_xscale("log", nonposx='clip')
812 ax.set_xscale("log")#, nonposx='clip')
813 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
813 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
814 self.ystep_given=100
814 self.ystep_given=100
815 ax.set_yticks(grid_y_ticks,minor=True)
815 ax.set_yticks(grid_y_ticks,minor=True)
816 locmaj = LogLocator(base=10,numticks=12)
816 locmaj = LogLocator(base=10,numticks=12)
817 ax.xaxis.set_major_locator(locmaj)
817 ax.xaxis.set_major_locator(locmaj)
818 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
818 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
819 ax.xaxis.set_minor_locator(locmin)
819 ax.xaxis.set_minor_locator(locmin)
820 ax.xaxis.set_minor_formatter(NullFormatter())
820 ax.xaxis.set_minor_formatter(NullFormatter())
821 ax.grid(which='minor')
821 ax.grid(which='minor')
822
822
823 else:
823 else:
824 dataBefore = self.data[-2]
824 dataBefore = self.data[-2]
825 DenPowBefore = dataBefore['den_power']
825 DenPowBefore = dataBefore['den_power']
826 self.clear_figures()
826 self.clear_figures()
827 ax.errorbar(DenPow, y, fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='b',linewidth=1.0, label='Power',markersize=2,linestyle='-')
827 ax.errorbar(DenPow, y, fmt='k^-', xerr=errDenPow,elinewidth=1.0,color='k',linewidth=1.0, label='Power',markersize=2,linestyle='-')
828 ax.errorbar(DenPowBefore, y, elinewidth=1.0,color='r',linewidth=0.5,linestyle="dashed")
828 ax.errorbar(DenPowBefore, y, elinewidth=1.0,color='r',linewidth=0.5,linestyle="dashed")
829
829
830 ax.set_xscale("log", nonposx='clip')
830 ax.set_xscale("log")#, nonposx='clip')
831 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
831 grid_y_ticks=numpy.arange(numpy.nanmin(y),numpy.nanmax(y),50)
832 ax.set_yticks(grid_y_ticks,minor=True)
832 ax.set_yticks(grid_y_ticks,minor=True)
833 locmaj = LogLocator(base=10,numticks=12)
833 locmaj = LogLocator(base=10,numticks=12)
834 ax.xaxis.set_major_locator(locmaj)
834 ax.xaxis.set_major_locator(locmaj)
835 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
835 locmin = LogLocator(base=10.0,subs=(0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9),numticks=12)
836 ax.xaxis.set_minor_locator(locmin)
836 ax.xaxis.set_minor_locator(locmin)
837 ax.xaxis.set_minor_formatter(NullFormatter())
837 ax.xaxis.set_minor_formatter(NullFormatter())
838 ax.grid(which='minor')
838 ax.grid(which='minor')
839 plt.legend(loc='upper left',fontsize=8.5)
839 plt.legend(loc='upper left',fontsize=8.5)
840 #plt.legend(loc='lower left',fontsize=8.5)
840 #plt.legend(loc='lower left',fontsize=8.5)
841
841
842 class FaradayAnglePlot(Plot):
842 class FaradayAnglePlot(Plot):
843 '''
843 '''
844 Written by R. Flores
844 Written by R. Flores
845 '''
845 '''
846 '''
846 '''
847 Plot for electron density
847 Plot for electron density
848 '''
848 '''
849
849
850 CODE = 'angle'
850 CODE = 'angle'
851 plot_name = 'Faraday Angle'
851 plot_name = 'Faraday Angle'
852 plot_type = 'scatterbuffer'
852 plot_type = 'scatterbuffer'
853
853
854 def setup(self):
854 def setup(self):
855
855
856 self.ncols = 1
856 self.ncols = 1
857 self.nrows = 1
857 self.nrows = 1
858 self.nplots = 1
858 self.nplots = 1
859 self.ylabel = 'Range [km]'
859 self.ylabel = 'Range [km]'
860 self.xlabel = 'Faraday Angle (º)'
860 self.xlabel = 'Faraday Angle (º)'
861 self.titles = ['Electron Density']
861 self.titles = ['Electron Density']
862 self.width = 3.5
862 self.width = 3.5
863 self.height = 5.5
863 self.height = 5.5
864 self.colorbar = False
864 self.colorbar = False
865 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
865 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
866
866
867 def update(self, dataOut):
867 def update(self, dataOut):
868 data = {}
868 data = {}
869 meta = {}
869 meta = {}
870
870
871 data['angle'] = numpy.degrees(dataOut.phi)
871 data['angle'] = numpy.degrees(dataOut.phi)
872 #'''
872 #'''
873 #print(dataOut.phi_uwrp)
873 #print(dataOut.phi_uwrp)
874 #print(data['angle'])
874 #print(data['angle'])
875 #exit(1)
875 #exit(1)
876 #'''
876 #'''
877 data['dphi'] = dataOut.dphi_uc*10
877 data['dphi'] = dataOut.dphi_uc*10
878 #print(dataOut.dphi)
878 #print(dataOut.dphi)
879
879
880 #data['NSHTS'] = dataOut.NSHTS
880 #data['NSHTS'] = dataOut.NSHTS
881
881
882 #meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
882 #meta['yrange'] = dataOut.heightList[0:dataOut.NSHTS]
883
883
884 return data, meta
884 return data, meta
885
885
886 def plot(self):
886 def plot(self):
887
887
888 data = self.data[-1]
888 data = self.data[-1]
889 self.x = data[self.CODE]
889 self.x = data[self.CODE]
890 dphi = data['dphi']
890 dphi = data['dphi']
891 self.y = self.data.yrange
891 self.y = self.data.yrange
892 self.xmin = -360#-180
892 self.xmin = -360#-180
893 self.xmax = 360#180
893 self.xmax = 360#180
894 ax = self.axes[0]
894 ax = self.axes[0]
895
895
896 if ax.firsttime:
896 if ax.firsttime:
897 self.autoxticks=False
897 self.autoxticks=False
898 #if self.CODE=='den':
898 #if self.CODE=='den':
899 ax.plot(self.x, self.y,marker='o',color='g',linewidth=1.0,markersize=2)
899 ax.plot(self.x, self.y,marker='o',color='g',linewidth=1.0,markersize=2)
900 ax.plot(dphi, self.y,marker='o',color='blue',linewidth=1.0,markersize=2)
900 ax.plot(dphi, self.y,marker='o',color='blue',linewidth=1.0,markersize=2)
901
901
902 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
902 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
903 self.ystep_given=100
903 self.ystep_given=100
904 if self.CODE=='denLP':
904 if self.CODE=='denLP':
905 self.ystep_given=200
905 self.ystep_given=200
906 ax.set_yticks(grid_y_ticks,minor=True)
906 ax.set_yticks(grid_y_ticks,minor=True)
907 ax.grid(which='minor')
907 ax.grid(which='minor')
908 #plt.tight_layout()
908 #plt.tight_layout()
909 else:
909 else:
910
910
911 self.clear_figures()
911 self.clear_figures()
912 #if self.CODE=='den':
912 #if self.CODE=='den':
913 #print(numpy.shape(self.x))
913 #print(numpy.shape(self.x))
914 ax.plot(self.x, self.y, marker='o',color='g',linewidth=1.0, markersize=2)
914 ax.plot(self.x, self.y, marker='o',color='g',linewidth=1.0, markersize=2)
915 ax.plot(dphi, self.y,marker='o',color='blue',linewidth=1.0,markersize=2)
915 ax.plot(dphi, self.y,marker='o',color='blue',linewidth=1.0,markersize=2)
916
916
917 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
917 grid_y_ticks=numpy.arange(numpy.nanmin(self.y),numpy.nanmax(self.y),50)
918 ax.set_yticks(grid_y_ticks,minor=True)
918 ax.set_yticks(grid_y_ticks,minor=True)
919 ax.grid(which='minor')
919 ax.grid(which='minor')
920
920
921 class EDensityHPPlot(EDensityPlot):
921 class EDensityHPPlot(EDensityPlot):
922 '''
922 '''
923 Written by R. Flores
923 Written by R. Flores
924 '''
924 '''
925 '''
925 '''
926 Plot for Electron Density Hybrid Experiment
926 Plot for Electron Density Hybrid Experiment
927 '''
927 '''
928
928
929 CODE = 'denLP'
929 CODE = 'denLP'
930 plot_name = 'Electron Density'
930 plot_name = 'Electron Density'
931 plot_type = 'scatterbuffer'
931 plot_type = 'scatterbuffer'
932
932
933 def update(self, dataOut):
933 def update(self, dataOut):
934 data = {}
934 data = {}
935 meta = {}
935 meta = {}
936
936
937 data['den_power'] = dataOut.ph2[:dataOut.NSHTS]
937 data['den_power'] = dataOut.ph2[:dataOut.NSHTS]
938 data['den_Faraday']=dataOut.dphi[:dataOut.NSHTS]
938 data['den_Faraday']=dataOut.dphi[:dataOut.NSHTS]
939 data['den_error']=dataOut.sdp2[:dataOut.NSHTS]
939 data['den_error']=dataOut.sdp2[:dataOut.NSHTS]
940 data['den_LP']=dataOut.ne[:dataOut.NACF]
940 data['den_LP']=dataOut.ne[:dataOut.NACF]
941 data['den_LP_error']=dataOut.ene[:dataOut.NACF]*dataOut.ne[:dataOut.NACF]*0.434
941 data['den_LP_error']=dataOut.ene[:dataOut.NACF]*dataOut.ne[:dataOut.NACF]*0.434
942 #self.ene=10**dataOut.ene[:dataOut.NACF]
942 #self.ene=10**dataOut.ene[:dataOut.NACF]
943 data['NSHTS']=dataOut.NSHTS
943 data['NSHTS']=dataOut.NSHTS
944 data['cut']=dataOut.cut
944 data['cut']=dataOut.cut
945
945
946 return data, meta
946 return data, meta
947
947
948
948
949 class ACFsPlot(Plot):
949 class ACFsPlot(Plot):
950 '''
950 '''
951 Written by R. Flores
951 Written by R. Flores
952 '''
952 '''
953 '''
953 '''
954 Plot for ACFs Double Pulse Experiment
954 Plot for ACFs Double Pulse Experiment
955 '''
955 '''
956
956
957 CODE = 'acfs'
957 CODE = 'acfs'
958 #plot_name = 'ACF'
958 #plot_name = 'ACF'
959 plot_type = 'scatterbuffer'
959 plot_type = 'scatterbuffer'
960
960
961
961
962 def setup(self):
962 def setup(self):
963 self.ncols = 1
963 self.ncols = 1
964 self.nrows = 1
964 self.nrows = 1
965 self.nplots = 1
965 self.nplots = 1
966 self.ylabel = 'Range [km]'
966 self.ylabel = 'Range [km]'
967 self.xlabel = 'Lag (ms)'
967 self.xlabel = 'Lag (ms)'
968 self.titles = ['ACFs']
968 self.titles = ['ACFs']
969 self.width = 3.5
969 self.width = 3.5
970 self.height = 5.5
970 self.height = 5.5
971 self.colorbar = False
971 self.colorbar = False
972 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
972 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
973
973
974 def update(self, dataOut):
974 def update(self, dataOut):
975 data = {}
975 data = {}
976 meta = {}
976 meta = {}
977
977
978 data['ACFs'] = dataOut.acfs_to_plot
978 data['ACFs'] = dataOut.acfs_to_plot
979 data['ACFs_error'] = dataOut.acfs_error_to_plot
979 data['ACFs_error'] = dataOut.acfs_error_to_plot
980 data['lags'] = dataOut.lags_to_plot
980 data['lags'] = dataOut.lags_to_plot
981 data['Lag_contaminated_1'] = dataOut.x_igcej_to_plot
981 data['Lag_contaminated_1'] = dataOut.x_igcej_to_plot
982 data['Lag_contaminated_2'] = dataOut.x_ibad_to_plot
982 data['Lag_contaminated_2'] = dataOut.x_ibad_to_plot
983 data['Height_contaminated_1'] = dataOut.y_igcej_to_plot
983 data['Height_contaminated_1'] = dataOut.y_igcej_to_plot
984 data['Height_contaminated_2'] = dataOut.y_ibad_to_plot
984 data['Height_contaminated_2'] = dataOut.y_ibad_to_plot
985
985
986 meta['yrange'] = numpy.array([])
986 meta['yrange'] = numpy.array([])
987 #meta['NSHTS'] = dataOut.NSHTS
987 #meta['NSHTS'] = dataOut.NSHTS
988 #meta['DPL'] = dataOut.DPL
988 #meta['DPL'] = dataOut.DPL
989 data['NSHTS'] = dataOut.NSHTS #This is metadata
989 data['NSHTS'] = dataOut.NSHTS #This is metadata
990 data['DPL'] = dataOut.DPL #This is metadata
990 data['DPL'] = dataOut.DPL #This is metadata
991
991
992 return data, meta
992 return data, meta
993
993
994 def plot(self):
994 def plot(self):
995
995
996 data = self.data[-1]
996 data = self.data[-1]
997 #NSHTS = self.meta['NSHTS']
997 #NSHTS = self.meta['NSHTS']
998 #DPL = self.meta['DPL']
998 #DPL = self.meta['DPL']
999 NSHTS = data['NSHTS'] #This is metadata
999 NSHTS = data['NSHTS'] #This is metadata
1000 DPL = data['DPL'] #This is metadata
1000 DPL = data['DPL'] #This is metadata
1001
1001
1002 lags = data['lags']
1002 lags = data['lags']
1003 ACFs = data['ACFs']
1003 ACFs = data['ACFs']
1004 errACFs = data['ACFs_error']
1004 errACFs = data['ACFs_error']
1005 BadLag1 = data['Lag_contaminated_1']
1005 BadLag1 = data['Lag_contaminated_1']
1006 BadLag2 = data['Lag_contaminated_2']
1006 BadLag2 = data['Lag_contaminated_2']
1007 BadHei1 = data['Height_contaminated_1']
1007 BadHei1 = data['Height_contaminated_1']
1008 BadHei2 = data['Height_contaminated_2']
1008 BadHei2 = data['Height_contaminated_2']
1009
1009
1010 self.xmin = 0.0
1010 self.xmin = 0.0
1011 self.xmax = 2.0
1011 self.xmax = 2.0
1012 self.y = ACFs
1012 self.y = ACFs
1013
1013
1014 ax = self.axes[0]
1014 ax = self.axes[0]
1015
1015
1016 if ax.firsttime:
1016 if ax.firsttime:
1017
1017
1018 for i in range(NSHTS):
1018 for i in range(NSHTS):
1019 x_aux = numpy.isfinite(lags[i,:])
1019 x_aux = numpy.isfinite(lags[i,:])
1020 y_aux = numpy.isfinite(ACFs[i,:])
1020 y_aux = numpy.isfinite(ACFs[i,:])
1021 yerr_aux = numpy.isfinite(errACFs[i,:])
1021 yerr_aux = numpy.isfinite(errACFs[i,:])
1022 x_igcej_aux = numpy.isfinite(BadLag1[i,:])
1022 x_igcej_aux = numpy.isfinite(BadLag1[i,:])
1023 y_igcej_aux = numpy.isfinite(BadHei1[i,:])
1023 y_igcej_aux = numpy.isfinite(BadHei1[i,:])
1024 x_ibad_aux = numpy.isfinite(BadLag2[i,:])
1024 x_ibad_aux = numpy.isfinite(BadLag2[i,:])
1025 y_ibad_aux = numpy.isfinite(BadHei2[i,:])
1025 y_ibad_aux = numpy.isfinite(BadHei2[i,:])
1026 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1026 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1027 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',marker='o',linewidth=1.0,markersize=2)
1027 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',marker='o',linewidth=1.0,markersize=2)
1028 ax.plot(BadLag1[i,x_igcej_aux],BadHei1[i,y_igcej_aux],'x',color='red',markersize=2)
1028 ax.plot(BadLag1[i,x_igcej_aux],BadHei1[i,y_igcej_aux],'x',color='red',markersize=2)
1029 ax.plot(BadLag2[i,x_ibad_aux],BadHei2[i,y_ibad_aux],'X',color='red',markersize=2)
1029 ax.plot(BadLag2[i,x_ibad_aux],BadHei2[i,y_ibad_aux],'X',color='red',markersize=2)
1030
1030
1031 self.xstep_given = (self.xmax-self.xmin)/(DPL-1)
1031 self.xstep_given = (self.xmax-self.xmin)/(DPL-1)
1032 self.ystep_given = 50
1032 self.ystep_given = 50
1033 ax.yaxis.set_minor_locator(MultipleLocator(15))
1033 ax.yaxis.set_minor_locator(MultipleLocator(15))
1034 ax.grid(which='minor')
1034 ax.grid(which='minor')
1035
1035
1036 else:
1036 else:
1037 self.clear_figures()
1037 self.clear_figures()
1038 for i in range(NSHTS):
1038 for i in range(NSHTS):
1039 x_aux = numpy.isfinite(lags[i,:])
1039 x_aux = numpy.isfinite(lags[i,:])
1040 y_aux = numpy.isfinite(ACFs[i,:])
1040 y_aux = numpy.isfinite(ACFs[i,:])
1041 yerr_aux = numpy.isfinite(errACFs[i,:])
1041 yerr_aux = numpy.isfinite(errACFs[i,:])
1042 x_igcej_aux = numpy.isfinite(BadLag1[i,:])
1042 x_igcej_aux = numpy.isfinite(BadLag1[i,:])
1043 y_igcej_aux = numpy.isfinite(BadHei1[i,:])
1043 y_igcej_aux = numpy.isfinite(BadHei1[i,:])
1044 x_ibad_aux = numpy.isfinite(BadLag2[i,:])
1044 x_ibad_aux = numpy.isfinite(BadLag2[i,:])
1045 y_ibad_aux = numpy.isfinite(BadHei2[i,:])
1045 y_ibad_aux = numpy.isfinite(BadHei2[i,:])
1046 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1046 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1047 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],linewidth=1.0,markersize=2,color='b',marker='o')
1047 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],linewidth=1.0,markersize=2,color='b',marker='o')
1048 ax.plot(BadLag1[i,x_igcej_aux],BadHei1[i,y_igcej_aux],'x',color='red',markersize=2)
1048 ax.plot(BadLag1[i,x_igcej_aux],BadHei1[i,y_igcej_aux],'x',color='red',markersize=2)
1049 ax.plot(BadLag2[i,x_ibad_aux],BadHei2[i,y_ibad_aux],'X',color='red',markersize=2)
1049 ax.plot(BadLag2[i,x_ibad_aux],BadHei2[i,y_ibad_aux],'X',color='red',markersize=2)
1050 ax.yaxis.set_minor_locator(MultipleLocator(15))
1050 ax.yaxis.set_minor_locator(MultipleLocator(15))
1051
1051
1052 class ACFsLPPlot(Plot):
1052 class ACFsLPPlot(Plot):
1053 '''
1053 '''
1054 Written by R. Flores
1054 Written by R. Flores
1055 '''
1055 '''
1056 '''
1056 '''
1057 Plot for ACFs Double Pulse Experiment
1057 Plot for ACFs Double Pulse Experiment
1058 '''
1058 '''
1059
1059
1060 CODE = 'acfs_LP'
1060 CODE = 'acfs_LP'
1061 #plot_name = 'ACF'
1061 #plot_name = 'ACF'
1062 plot_type = 'scatterbuffer'
1062 plot_type = 'scatterbuffer'
1063
1063
1064
1064
1065 def setup(self):
1065 def setup(self):
1066 self.ncols = 1
1066 self.ncols = 1
1067 self.nrows = 1
1067 self.nrows = 1
1068 self.nplots = 1
1068 self.nplots = 1
1069 self.ylabel = 'Range [km]'
1069 self.ylabel = 'Range [km]'
1070 self.xlabel = 'Lag (ms)'
1070 self.xlabel = 'Lag (ms)'
1071 self.titles = ['ACFs']
1071 self.titles = ['ACFs']
1072 self.width = 3.5
1072 self.width = 3.5
1073 self.height = 5.5
1073 self.height = 5.5
1074 self.colorbar = False
1074 self.colorbar = False
1075 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1075 self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1076
1076
1077 def update(self, dataOut):
1077 def update(self, dataOut):
1078 data = {}
1078 data = {}
1079 meta = {}
1079 meta = {}
1080
1080
1081 aux=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1081 aux=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1082 errors=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1082 errors=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1083 lags_LP_to_plot=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1083 lags_LP_to_plot=numpy.zeros((dataOut.NACF,dataOut.IBITS),'float32')
1084
1084
1085 for i in range(dataOut.NACF):
1085 for i in range(dataOut.NACF):
1086 for j in range(dataOut.IBITS):
1086 for j in range(dataOut.IBITS):
1087 if numpy.abs(dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0])<1.0:
1087 if numpy.abs(dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0])<1.0:
1088 aux[i,j]=dataOut.output_LP_integrated.real[j,i,0]/dataOut.output_LP_integrated.real[0,i,0]
1088 aux[i,j]=dataOut.output_LP_integrated.real[j,i,0]/dataOut.output_LP_integrated.real[0,i,0]
1089 aux[i,j]=max(min(aux[i,j],1.0),-1.0)*dataOut.DH+dataOut.heightList[i]
1089 aux[i,j]=max(min(aux[i,j],1.0),-1.0)*dataOut.DH+dataOut.heightList[i]
1090 lags_LP_to_plot[i,j]=dataOut.lags_LP[j]
1090 lags_LP_to_plot[i,j]=dataOut.lags_LP[j]
1091 errors[i,j]=dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0]*dataOut.DH
1091 errors[i,j]=dataOut.errors[j,i]/dataOut.output_LP_integrated.real[0,i,0]*dataOut.DH
1092 else:
1092 else:
1093 aux[i,j]=numpy.nan
1093 aux[i,j]=numpy.nan
1094 lags_LP_to_plot[i,j]=numpy.nan
1094 lags_LP_to_plot[i,j]=numpy.nan
1095 errors[i,j]=numpy.nan
1095 errors[i,j]=numpy.nan
1096
1096
1097 data['ACFs'] = aux
1097 data['ACFs'] = aux
1098 data['ACFs_error'] = errors
1098 data['ACFs_error'] = errors
1099 data['lags'] = lags_LP_to_plot
1099 data['lags'] = lags_LP_to_plot
1100
1100
1101 meta['yrange'] = numpy.array([])
1101 meta['yrange'] = numpy.array([])
1102 #meta['NACF'] = dataOut.NACF
1102 #meta['NACF'] = dataOut.NACF
1103 #meta['NLAG'] = dataOut.NLAG
1103 #meta['NLAG'] = dataOut.NLAG
1104 data['NACF'] = dataOut.NACF #This is metadata
1104 data['NACF'] = dataOut.NACF #This is metadata
1105 data['NLAG'] = dataOut.NLAG #This is metadata
1105 data['NLAG'] = dataOut.NLAG #This is metadata
1106
1106
1107 return data, meta
1107 return data, meta
1108
1108
1109 def plot(self):
1109 def plot(self):
1110
1110
1111 data = self.data[-1]
1111 data = self.data[-1]
1112 #NACF = self.meta['NACF']
1112 #NACF = self.meta['NACF']
1113 #NLAG = self.meta['NLAG']
1113 #NLAG = self.meta['NLAG']
1114 NACF = data['NACF'] #This is metadata
1114 NACF = data['NACF'] #This is metadata
1115 NLAG = data['NLAG'] #This is metadata
1115 NLAG = data['NLAG'] #This is metadata
1116
1116
1117 lags = data['lags']
1117 lags = data['lags']
1118 ACFs = data['ACFs']
1118 ACFs = data['ACFs']
1119 errACFs = data['ACFs_error']
1119 errACFs = data['ACFs_error']
1120
1120
1121 self.xmin = 0.0
1121 self.xmin = 0.0
1122 self.xmax = 1.5
1122 self.xmax = 1.5
1123
1123
1124 self.y = ACFs
1124 self.y = ACFs
1125
1125
1126 ax = self.axes[0]
1126 ax = self.axes[0]
1127
1127
1128 if ax.firsttime:
1128 if ax.firsttime:
1129
1129
1130 for i in range(NACF):
1130 for i in range(NACF):
1131 x_aux = numpy.isfinite(lags[i,:])
1131 x_aux = numpy.isfinite(lags[i,:])
1132 y_aux = numpy.isfinite(ACFs[i,:])
1132 y_aux = numpy.isfinite(ACFs[i,:])
1133 yerr_aux = numpy.isfinite(errACFs[i,:])
1133 yerr_aux = numpy.isfinite(errACFs[i,:])
1134
1134
1135 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1135 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1136 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',linewidth=1.0,markersize=2,ecolor='r')
1136 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',linewidth=1.0,markersize=2,ecolor='r')
1137
1137
1138 #self.xstep_given = (self.xmax-self.xmin)/(self.data.NLAG-1)
1138 #self.xstep_given = (self.xmax-self.xmin)/(self.data.NLAG-1)
1139 self.xstep_given=0.3
1139 self.xstep_given=0.3
1140 self.ystep_given = 200
1140 self.ystep_given = 200
1141 ax.yaxis.set_minor_locator(MultipleLocator(15))
1141 ax.yaxis.set_minor_locator(MultipleLocator(15))
1142 ax.grid(which='minor')
1142 ax.grid(which='minor')
1143
1143
1144 else:
1144 else:
1145 self.clear_figures()
1145 self.clear_figures()
1146
1146
1147 for i in range(NACF):
1147 for i in range(NACF):
1148 x_aux = numpy.isfinite(lags[i,:])
1148 x_aux = numpy.isfinite(lags[i,:])
1149 y_aux = numpy.isfinite(ACFs[i,:])
1149 y_aux = numpy.isfinite(ACFs[i,:])
1150 yerr_aux = numpy.isfinite(errACFs[i,:])
1150 yerr_aux = numpy.isfinite(errACFs[i,:])
1151
1151
1152 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1152 if lags[i,:][~numpy.isnan(lags[i,:])].shape[0]>2:
1153 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',linewidth=1.0,markersize=2,ecolor='r')
1153 ax.errorbar(lags[i,x_aux], ACFs[i,y_aux], yerr=errACFs[i,x_aux],color='b',linewidth=1.0,markersize=2,ecolor='r')
1154
1154
1155 ax.yaxis.set_minor_locator(MultipleLocator(15))
1155 ax.yaxis.set_minor_locator(MultipleLocator(15))
1156
1156
1157
1157
1158 class CrossProductsPlot(Plot):
1158 class CrossProductsPlot(Plot):
1159 '''
1159 '''
1160 Written by R. Flores
1160 Written by R. Flores
1161 '''
1161 '''
1162 '''
1162 '''
1163 Plot for cross products
1163 Plot for cross products
1164 '''
1164 '''
1165
1165
1166 CODE = 'crossprod'
1166 CODE = 'crossprod'
1167 plot_name = 'Cross Products'
1167 plot_name = 'Cross Products'
1168 plot_type = 'scatterbuffer'
1168 plot_type = 'scatterbuffer'
1169
1169
1170 def setup(self):
1170 def setup(self):
1171
1171
1172 self.ncols = 3
1172 self.ncols = 3
1173 self.nrows = 1
1173 self.nrows = 1
1174 self.nplots = 3
1174 self.nplots = 3
1175 self.ylabel = 'Range [km]'
1175 self.ylabel = 'Range [km]'
1176 self.titles = []
1176 self.titles = []
1177 self.width = 3.5*self.nplots
1177 self.width = 3.5*self.nplots
1178 self.height = 5.5
1178 self.height = 5.5
1179 self.colorbar = False
1179 self.colorbar = False
1180 self.plots_adjust.update({'wspace':.3, 'left': 0.12, 'right': 0.92, 'bottom': 0.1})
1180 self.plots_adjust.update({'wspace':.3, 'left': 0.12, 'right': 0.92, 'bottom': 0.1})
1181
1181
1182
1182
1183 def update(self, dataOut):
1183 def update(self, dataOut):
1184
1184
1185 data = {}
1185 data = {}
1186 meta = {}
1186 meta = {}
1187
1187
1188 data['crossprod'] = dataOut.crossprods
1188 data['crossprod'] = dataOut.crossprods
1189 data['NDP'] = dataOut.NDP
1189 data['NDP'] = dataOut.NDP
1190
1190
1191 return data, meta
1191 return data, meta
1192
1192
1193 def plot(self):
1193 def plot(self):
1194
1194
1195 NDP = self.data['NDP'][-1]
1195 NDP = self.data['NDP'][-1]
1196 x = self.data['crossprod'][:,-1,:,:,:,:]
1196 x = self.data['crossprod'][:,-1,:,:,:,:]
1197 y = self.data.yrange[0:NDP]
1197 y = self.data.yrange[0:NDP]
1198
1198
1199 for n, ax in enumerate(self.axes):
1199 for n, ax in enumerate(self.axes):
1200
1200
1201 self.xmin=numpy.min(numpy.concatenate((x[n][0,20:30,0,0],x[n][1,20:30,0,0],x[n][2,20:30,0,0],x[n][3,20:30,0,0])))
1201 self.xmin=numpy.min(numpy.concatenate((x[n][0,20:30,0,0],x[n][1,20:30,0,0],x[n][2,20:30,0,0],x[n][3,20:30,0,0])))
1202 self.xmax=numpy.max(numpy.concatenate((x[n][0,20:30,0,0],x[n][1,20:30,0,0],x[n][2,20:30,0,0],x[n][3,20:30,0,0])))
1202 self.xmax=numpy.max(numpy.concatenate((x[n][0,20:30,0,0],x[n][1,20:30,0,0],x[n][2,20:30,0,0],x[n][3,20:30,0,0])))
1203
1203
1204 if ax.firsttime:
1204 if ax.firsttime:
1205
1205
1206 self.autoxticks=False
1206 self.autoxticks=False
1207 if n==0:
1207 if n==0:
1208 label1='kax'
1208 label1='kax'
1209 label2='kay'
1209 label2='kay'
1210 label3='kbx'
1210 label3='kbx'
1211 label4='kby'
1211 label4='kby'
1212 self.xlimits=[(self.xmin,self.xmax)]
1212 self.xlimits=[(self.xmin,self.xmax)]
1213 elif n==1:
1213 elif n==1:
1214 label1='kax2'
1214 label1='kax2'
1215 label2='kay2'
1215 label2='kay2'
1216 label3='kbx2'
1216 label3='kbx2'
1217 label4='kby2'
1217 label4='kby2'
1218 self.xlimits.append((self.xmin,self.xmax))
1218 self.xlimits.append((self.xmin,self.xmax))
1219 elif n==2:
1219 elif n==2:
1220 label1='kaxay'
1220 label1='kaxay'
1221 label2='kbxby'
1221 label2='kbxby'
1222 label3='kaxbx'
1222 label3='kaxbx'
1223 label4='kaxby'
1223 label4='kaxby'
1224 self.xlimits.append((self.xmin,self.xmax))
1224 self.xlimits.append((self.xmin,self.xmax))
1225
1225
1226 ax.plotline1 = ax.plot(x[n][0,:,0,0], y, color='r',linewidth=2.0, label=label1)
1226 ax.plotline1 = ax.plot(x[n][0,:,0,0], y, color='r',linewidth=2.0, label=label1)
1227 ax.plotline2 = ax.plot(x[n][1,:,0,0], y, color='k',linewidth=2.0, label=label2)
1227 ax.plotline2 = ax.plot(x[n][1,:,0,0], y, color='k',linewidth=2.0, label=label2)
1228 ax.plotline3 = ax.plot(x[n][2,:,0,0], y, color='b',linewidth=2.0, label=label3)
1228 ax.plotline3 = ax.plot(x[n][2,:,0,0], y, color='b',linewidth=2.0, label=label3)
1229 ax.plotline4 = ax.plot(x[n][3,:,0,0], y, color='m',linewidth=2.0, label=label4)
1229 ax.plotline4 = ax.plot(x[n][3,:,0,0], y, color='m',linewidth=2.0, label=label4)
1230 ax.legend(loc='upper right')
1230 ax.legend(loc='upper right')
1231 ax.set_xlim(self.xmin, self.xmax)
1231 ax.set_xlim(self.xmin, self.xmax)
1232 self.titles.append('{}'.format(self.plot_name.upper()))
1232 self.titles.append('{}'.format(self.plot_name.upper()))
1233
1233
1234 else:
1234 else:
1235
1235
1236 if n==0:
1236 if n==0:
1237 self.xlimits=[(self.xmin,self.xmax)]
1237 self.xlimits=[(self.xmin,self.xmax)]
1238 else:
1238 else:
1239 self.xlimits.append((self.xmin,self.xmax))
1239 self.xlimits.append((self.xmin,self.xmax))
1240
1240
1241 ax.set_xlim(self.xmin, self.xmax)
1241 ax.set_xlim(self.xmin, self.xmax)
1242
1242
1243 ax.plotline1[0].set_data(x[n][0,:,0,0],y)
1243 ax.plotline1[0].set_data(x[n][0,:,0,0],y)
1244 ax.plotline2[0].set_data(x[n][1,:,0,0],y)
1244 ax.plotline2[0].set_data(x[n][1,:,0,0],y)
1245 ax.plotline3[0].set_data(x[n][2,:,0,0],y)
1245 ax.plotline3[0].set_data(x[n][2,:,0,0],y)
1246 ax.plotline4[0].set_data(x[n][3,:,0,0],y)
1246 ax.plotline4[0].set_data(x[n][3,:,0,0],y)
1247 self.titles.append('{}'.format(self.plot_name.upper()))
1247 self.titles.append('{}'.format(self.plot_name.upper()))
1248
1248
1249
1249
1250 class CrossProductsLPPlot(Plot):
1250 class CrossProductsLPPlot(Plot):
1251 '''
1251 '''
1252 Written by R. Flores
1252 Written by R. Flores
1253 '''
1253 '''
1254 '''
1254 '''
1255 Plot for cross products LP
1255 Plot for cross products LP
1256 '''
1256 '''
1257
1257
1258 CODE = 'crossprodslp'
1258 CODE = 'crossprodslp'
1259 plot_name = 'Cross Products LP'
1259 plot_name = 'Cross Products LP'
1260 plot_type = 'scatterbuffer'
1260 plot_type = 'scatterbuffer'
1261
1261
1262
1262
1263 def setup(self):
1263 def setup(self):
1264
1264
1265 self.ncols = 2
1265 self.ncols = 2
1266 self.nrows = 1
1266 self.nrows = 1
1267 self.nplots = 2
1267 self.nplots = 2
1268 self.ylabel = 'Range [km]'
1268 self.ylabel = 'Range [km]'
1269 self.xlabel = 'dB'
1269 self.xlabel = 'dB'
1270 self.width = 3.5*self.nplots
1270 self.width = 3.5*self.nplots
1271 self.height = 5.5
1271 self.height = 5.5
1272 self.colorbar = False
1272 self.colorbar = False
1273 self.titles = []
1273 self.titles = []
1274 self.plots_adjust.update({'wspace': .8 ,'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1274 self.plots_adjust.update({'wspace': .8 ,'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1275
1275
1276 def update(self, dataOut):
1276 def update(self, dataOut):
1277 data = {}
1277 data = {}
1278 meta = {}
1278 meta = {}
1279
1279
1280 data['crossprodslp'] = 10*numpy.log10(numpy.abs(dataOut.output_LP))
1280 data['crossprodslp'] = 10*numpy.log10(numpy.abs(dataOut.output_LP))
1281
1281
1282 data['NRANGE'] = dataOut.NRANGE #This is metadata
1282 data['NRANGE'] = dataOut.NRANGE #This is metadata
1283 data['NLAG'] = dataOut.NLAG #This is metadata
1283 data['NLAG'] = dataOut.NLAG #This is metadata
1284
1284
1285 return data, meta
1285 return data, meta
1286
1286
1287 def plot(self):
1287 def plot(self):
1288
1288
1289 NRANGE = self.data['NRANGE'][-1]
1289 NRANGE = self.data['NRANGE'][-1]
1290 NLAG = self.data['NLAG'][-1]
1290 NLAG = self.data['NLAG'][-1]
1291
1291
1292 x = self.data[self.CODE][:,-1,:,:]
1292 x = self.data[self.CODE][:,-1,:,:]
1293 self.y = self.data.yrange[0:NRANGE]
1293 self.y = self.data.yrange[0:NRANGE]
1294
1294
1295 label_array=numpy.array(['lag '+ str(x) for x in range(NLAG)])
1295 label_array=numpy.array(['lag '+ str(x) for x in range(NLAG)])
1296 color_array=['r','k','g','b','c','m','y','orange','steelblue','purple','peru','darksalmon','grey','limegreen','olive','midnightblue']
1296 color_array=['r','k','g','b','c','m','y','orange','steelblue','purple','peru','darksalmon','grey','limegreen','olive','midnightblue']
1297
1297
1298
1298
1299 for n, ax in enumerate(self.axes):
1299 for n, ax in enumerate(self.axes):
1300
1300
1301 self.xmin=28#30
1301 self.xmin=28#30
1302 self.xmax=70#70
1302 self.xmax=70#70
1303 #self.xmin=numpy.min(numpy.concatenate((self.x[0,:,n],self.x[1,:,n])))
1303 #self.xmin=numpy.min(numpy.concatenate((self.x[0,:,n],self.x[1,:,n])))
1304 #self.xmax=numpy.max(numpy.concatenate((self.x[0,:,n],self.x[1,:,n])))
1304 #self.xmax=numpy.max(numpy.concatenate((self.x[0,:,n],self.x[1,:,n])))
1305
1305
1306 if ax.firsttime:
1306 if ax.firsttime:
1307
1307
1308 self.autoxticks=False
1308 self.autoxticks=False
1309 if n == 0:
1309 if n == 0:
1310 self.plotline_array=numpy.zeros((2,NLAG),dtype=object)
1310 self.plotline_array=numpy.zeros((2,NLAG),dtype=object)
1311
1311
1312 for i in range(NLAG):
1312 for i in range(NLAG):
1313 self.plotline_array[n,i], = ax.plot(x[i,:,n], self.y, color=color_array[i],linewidth=1.0, label=label_array[i])
1313 self.plotline_array[n,i], = ax.plot(x[i,:,n], self.y, color=color_array[i],linewidth=1.0, label=label_array[i])
1314
1314
1315 ax.legend(loc='upper right')
1315 ax.legend(loc='upper right')
1316 ax.set_xlim(self.xmin, self.xmax)
1316 ax.set_xlim(self.xmin, self.xmax)
1317 if n==0:
1317 if n==0:
1318 self.titles.append('{} CH0'.format(self.plot_name.upper()))
1318 self.titles.append('{} CH0'.format(self.plot_name.upper()))
1319 if n==1:
1319 if n==1:
1320 self.titles.append('{} CH1'.format(self.plot_name.upper()))
1320 self.titles.append('{} CH1'.format(self.plot_name.upper()))
1321 else:
1321 else:
1322 for i in range(NLAG):
1322 for i in range(NLAG):
1323 self.plotline_array[n,i].set_data(x[i,:,n],self.y)
1323 self.plotline_array[n,i].set_data(x[i,:,n],self.y)
1324
1324
1325 if n==0:
1325 if n==0:
1326 self.titles.append('{} CH0'.format(self.plot_name.upper()))
1326 self.titles.append('{} CH0'.format(self.plot_name.upper()))
1327 if n==1:
1327 if n==1:
1328 self.titles.append('{} CH1'.format(self.plot_name.upper()))
1328 self.titles.append('{} CH1'.format(self.plot_name.upper()))
1329
1329
1330
1330
1331 class NoiseDPPlot(NoisePlot):
1331 class NoiseDPPlot(NoisePlot):
1332 '''
1332 '''
1333 Written by R. Flores
1333 Written by R. Flores
1334 '''
1334 '''
1335 '''
1335 '''
1336 Plot for noise Double Pulse
1336 Plot for noise Double Pulse
1337 '''
1337 '''
1338
1338
1339 CODE = 'noise'
1339 CODE = 'noise'
1340 #plot_name = 'Noise'
1340 #plot_name = 'Noise'
1341 #plot_type = 'scatterbuffer'
1341 #plot_type = 'scatterbuffer'
1342
1342
1343 def update(self, dataOut):
1343 def update(self, dataOut):
1344
1344
1345 data = {}
1345 data = {}
1346 meta = {}
1346 meta = {}
1347 data['noise'] = 10*numpy.log10(dataOut.noise_final)
1347 data['noise'] = 10*numpy.log10(dataOut.noise_final)
1348
1348
1349 return data, meta
1349 return data, meta
1350
1350
1351
1351
1352 class XmitWaveformPlot(Plot):
1352 class XmitWaveformPlot(Plot):
1353 '''
1353 '''
1354 Written by R. Flores
1354 Written by R. Flores
1355 '''
1355 '''
1356 '''
1356 '''
1357 Plot for xmit waveform
1357 Plot for xmit waveform
1358 '''
1358 '''
1359
1359
1360 CODE = 'xmit'
1360 CODE = 'xmit'
1361 plot_name = 'Xmit Waveform'
1361 plot_name = 'Xmit Waveform'
1362 plot_type = 'scatterbuffer'
1362 plot_type = 'scatterbuffer'
1363
1363
1364
1364
1365 def setup(self):
1365 def setup(self):
1366
1366
1367 self.ncols = 1
1367 self.ncols = 1
1368 self.nrows = 1
1368 self.nrows = 1
1369 self.nplots = 1
1369 self.nplots = 1
1370 self.ylabel = ''
1370 self.ylabel = ''
1371 self.xlabel = 'Number of Lag'
1371 self.xlabel = 'Number of Lag'
1372 self.width = 5.5
1372 self.width = 5.5
1373 self.height = 3.5
1373 self.height = 3.5
1374 self.colorbar = False
1374 self.colorbar = False
1375 self.plots_adjust.update({'right': 0.85 })
1375 self.plots_adjust.update({'right': 0.85 })
1376 self.titles = [self.plot_name]
1376 self.titles = [self.plot_name]
1377 #self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1377 #self.plots_adjust.update({'left': 0.17, 'right': 0.88, 'bottom': 0.1})
1378
1378
1379 #if not self.titles:
1379 #if not self.titles:
1380 #self.titles = self.data.parameters \
1380 #self.titles = self.data.parameters \
1381 #if self.data.parameters else ['{}'.format(self.plot_name.upper())]
1381 #if self.data.parameters else ['{}'.format(self.plot_name.upper())]
1382
1382
1383 def update(self, dataOut):
1383 def update(self, dataOut):
1384
1384
1385 data = {}
1385 data = {}
1386 meta = {}
1386 meta = {}
1387
1387
1388 y_1=numpy.arctan2(dataOut.output_LP[:,0,2].imag,dataOut.output_LP[:,0,2].real)* 180 / (numpy.pi*10)
1388 y_1=numpy.arctan2(dataOut.output_LP[:,0,2].imag,dataOut.output_LP[:,0,2].real)* 180 / (numpy.pi*10)
1389 y_2=numpy.abs(dataOut.output_LP[:,0,2])
1389 y_2=numpy.abs(dataOut.output_LP[:,0,2])
1390 norm=numpy.max(y_2)
1390 norm=numpy.max(y_2)
1391 norm=max(norm,0.1)
1391 norm=max(norm,0.1)
1392 y_2=y_2/norm
1392 y_2=y_2/norm
1393
1393
1394 meta['yrange'] = numpy.array([])
1394 meta['yrange'] = numpy.array([])
1395
1395
1396 data['xmit'] = numpy.vstack((y_1,y_2))
1396 data['xmit'] = numpy.vstack((y_1,y_2))
1397 data['NLAG'] = dataOut.NLAG
1397 data['NLAG'] = dataOut.NLAG
1398
1398
1399 return data, meta
1399 return data, meta
1400
1400
1401 def plot(self):
1401 def plot(self):
1402
1402
1403 data = self.data[-1]
1403 data = self.data[-1]
1404 NLAG = data['NLAG']
1404 NLAG = data['NLAG']
1405 x = numpy.arange(0,NLAG,1,'float32')
1405 x = numpy.arange(0,NLAG,1,'float32')
1406 y = data['xmit']
1406 y = data['xmit']
1407
1407
1408 self.xmin = 0
1408 self.xmin = 0
1409 self.xmax = NLAG-1
1409 self.xmax = NLAG-1
1410 self.ymin = -1.0
1410 self.ymin = -1.0
1411 self.ymax = 1.0
1411 self.ymax = 1.0
1412 ax = self.axes[0]
1412 ax = self.axes[0]
1413
1413
1414 if ax.firsttime:
1414 if ax.firsttime:
1415 ax.plotline0=ax.plot(x,y[0,:],color='blue')
1415 ax.plotline0=ax.plot(x,y[0,:],color='blue')
1416 ax.plotline1=ax.plot(x,y[1,:],color='red')
1416 ax.plotline1=ax.plot(x,y[1,:],color='red')
1417 secax=ax.secondary_xaxis(location=0.5)
1417 secax=ax.secondary_xaxis(location=0.5)
1418 secax.xaxis.tick_bottom()
1418 secax.xaxis.tick_bottom()
1419 secax.tick_params( labelleft=False, labeltop=False,
1419 secax.tick_params( labelleft=False, labeltop=False,
1420 labelright=False, labelbottom=False)
1420 labelright=False, labelbottom=False)
1421
1421
1422 self.xstep_given = 3
1422 self.xstep_given = 3
1423 self.ystep_given = .25
1423 self.ystep_given = .25
1424 secax.set_xticks(numpy.linspace(self.xmin, self.xmax, 6)) #only works on matplotlib.version>3.2
1424 secax.set_xticks(numpy.linspace(self.xmin, self.xmax, 6)) #only works on matplotlib.version>3.2
1425
1425
1426 else:
1426 else:
1427 ax.plotline0[0].set_data(x,y[0,:])
1427 ax.plotline0[0].set_data(x,y[0,:])
1428 ax.plotline1[0].set_data(x,y[1,:])
1428 ax.plotline1[0].set_data(x,y[1,:])
@@ -1,355 +1,361
1 '''
1 '''
2 Created on Nov 9, 2016
2 Created on Nov 9, 2016
3
3
4 @author: roj- LouVD
4 @author: roj- LouVD
5 '''
5 '''
6
6
7
7
8 import os
8 import os
9 import sys
9 import sys
10 import time
10 import time
11 import glob
11 import glob
12 import datetime
12 import datetime
13
13
14 import numpy
14 import numpy
15
15
16 import schainpy.admin
16 import schainpy.admin
17 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator
17 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator
18 from schainpy.model.data.jrodata import Parameters
18 from schainpy.model.data.jrodata import Parameters
19 from schainpy.model.io.jroIO_base import Reader
19 from schainpy.model.io.jroIO_base import Reader
20 from schainpy.utils import log
20 from schainpy.utils import log
21
21
22 FILE_HEADER_STRUCTURE = numpy.dtype([
22 FILE_HEADER_STRUCTURE = numpy.dtype([
23 ('FMN', '<u4'),
23 ('FMN', '<u4'),
24 ('nrec', '<u4'),
24 ('nrec', '<u4'),
25 ('fr_offset', '<u4'),
25 ('fr_offset', '<u4'),
26 ('id', '<u4'),
26 ('id', '<u4'),
27 ('site', 'u1', (32,))
27 ('site', 'u1', (32,))
28 ])
28 ])
29
29
30 REC_HEADER_STRUCTURE = numpy.dtype([
30 REC_HEADER_STRUCTURE = numpy.dtype([
31 ('rmn', '<u4'),
31 ('rmn', '<u4'),
32 ('rcounter', '<u4'),
32 ('rcounter', '<u4'),
33 ('nr_offset', '<u4'),
33 ('nr_offset', '<u4'),
34 ('tr_offset', '<u4'),
34 ('tr_offset', '<u4'),
35 ('time', '<u4'),
35 ('time', '<u4'),
36 ('time_msec', '<u4'),
36 ('time_msec', '<u4'),
37 ('tag', 'u1', (32,)),
37 ('tag', 'u1', (32,)),
38 ('comments', 'u1', (32,)),
38 ('comments', 'u1', (32,)),
39 ('lat', '<f4'),
39 ('lat', '<f4'),
40 ('lon', '<f4'),
40 ('lon', '<f4'),
41 ('gps_status', '<u4'),
41 ('gps_status', '<u4'),
42 ('freq', '<u4'),
42 ('freq', '<u4'),
43 ('freq0', '<u4'),
43 ('freq0', '<u4'),
44 ('nchan', '<u4'),
44 ('nchan', '<u4'),
45 ('delta_r', '<u4'),
45 ('delta_r', '<u4'),
46 ('nranges', '<u4'),
46 ('nranges', '<u4'),
47 ('r0', '<u4'),
47 ('r0', '<u4'),
48 ('prf', '<u4'),
48 ('prf', '<u4'),
49 ('ncoh', '<u4'),
49 ('ncoh', '<u4'),
50 ('npoints', '<u4'),
50 ('npoints', '<u4'),
51 ('polarization', '<i4'),
51 ('polarization', '<i4'),
52 ('rx_filter', '<u4'),
52 ('rx_filter', '<u4'),
53 ('nmodes', '<u4'),
53 ('nmodes', '<u4'),
54 ('dmode_index', '<u4'),
54 ('dmode_index', '<u4'),
55 ('dmode_rngcorr', '<u4'),
55 ('dmode_rngcorr', '<u4'),
56 ('nrxs', '<u4'),
56 ('nrxs', '<u4'),
57 ('acf_length', '<u4'),
57 ('acf_length', '<u4'),
58 ('acf_lags', '<u4'),
58 ('acf_lags', '<u4'),
59 ('sea_to_atmos', '<f4'),
59 ('sea_to_atmos', '<f4'),
60 ('sea_notch', '<u4'),
60 ('sea_notch', '<u4'),
61 ('lh_sea', '<u4'),
61 ('lh_sea', '<u4'),
62 ('hh_sea', '<u4'),
62 ('hh_sea', '<u4'),
63 ('nbins_sea', '<u4'),
63 ('nbins_sea', '<u4'),
64 ('min_snr', '<f4'),
64 ('min_snr', '<f4'),
65 ('min_cc', '<f4'),
65 ('min_cc', '<f4'),
66 ('max_time_diff', '<f4')
66 ('max_time_diff', '<f4')
67 ])
67 ])
68
68
69 DATA_STRUCTURE = numpy.dtype([
69 DATA_STRUCTURE = numpy.dtype([
70 ('range', '<u4'),
70 ('range', '<u4'),
71 ('status', '<u4'),
71 ('status', '<u4'),
72 ('zonal', '<f4'),
72 ('zonal', '<f4'),
73 ('meridional', '<f4'),
73 ('meridional', '<f4'),
74 ('vertical', '<f4'),
74 ('vertical', '<f4'),
75 ('zonal_a', '<f4'),
75 ('zonal_a', '<f4'),
76 ('meridional_a', '<f4'),
76 ('meridional_a', '<f4'),
77 ('corrected_fading', '<f4'), # seconds
77 ('corrected_fading', '<f4'), # seconds
78 ('uncorrected_fading', '<f4'), # seconds
78 ('uncorrected_fading', '<f4'), # seconds
79 ('time_diff', '<f4'),
79 ('time_diff', '<f4'),
80 ('major_axis', '<f4'),
80 ('major_axis', '<f4'),
81 ('axial_ratio', '<f4'),
81 ('axial_ratio', '<f4'),
82 ('orientation', '<f4'),
82 ('orientation', '<f4'),
83 ('sea_power', '<u4'),
83 ('sea_power', '<u4'),
84 ('sea_algorithm', '<u4')
84 ('sea_algorithm', '<u4')
85 ])
85 ])
86
86
87
87
88 class BLTRParamReader(Reader, ProcessingUnit):
88 class BLTRParamReader(Reader, ProcessingUnit):
89 '''
89 '''
90 Boundary Layer and Tropospheric Radar (BLTR) reader, Wind velocities and SNR
90 Boundary Layer and Tropospheric Radar (BLTR) reader, Wind velocities and SNR
91 from *.sswma files
91 from *.sswma files
92 '''
92 '''
93
93
94 ext = '.sswma'
94 ext = '.sswma'
95
95
96 def __init__(self):
96 def __init__(self):
97
97
98 ProcessingUnit.__init__(self)
98 ProcessingUnit.__init__(self)
99
99
100 self.dataOut = Parameters()
100 self.dataOut = Parameters()
101 self.dataOut.timezone = 300
101 self.dataOut.timezone = 300
102 self.counter_records = 0
102 self.counter_records = 0
103 self.flagNoMoreFiles = 0
103 self.flagNoMoreFiles = 0
104 self.isConfig = False
104 self.isConfig = False
105 self.filename = None
105 self.filename = None
106 self.status_value = 0
106 self.status_value = 0
107 self.datatime = datetime.datetime(1900,1,1)
107 self.datatime = datetime.datetime(1900,1,1)
108 self.filefmt = "*********%Y%m%d******"
108 self.filefmt = "*********%Y%m%d******"
109
109
110 def setup(self, **kwargs):
110 def setup(self, **kwargs):
111
111
112 self.set_kwargs(**kwargs)
112 self.set_kwargs(**kwargs)
113
113
114 if self.path is None:
114 if self.path is None:
115 raise ValueError("The path is not valid")
115 raise ValueError("The path is not valid")
116
116
117 if self.online:
117 if self.online:
118 log.log("Searching files in online mode...", self.name)
118 log.log("Searching files in online mode...", self.name)
119
119
120 for nTries in range(self.nTries):
120 for nTries in range(self.nTries):
121 fullpath = self.searchFilesOnLine(self.path, self.startDate,
121 fullpath = self.searchFilesOnLine(self.path, self.startDate,
122 self.endDate, self.expLabel, self.ext, self.walk,
122 self.endDate, self.expLabel, self.ext, self.walk,
123 self.filefmt, self.folderfmt)
123 self.filefmt, self.folderfmt)
124 try:
124 try:
125 fullpath = next(fullpath)
125 fullpath = next(fullpath)
126 except:
126 except:
127 fullpath = None
127 fullpath = None
128
128
129 if fullpath:
129 if fullpath:
130 self.fileSize = os.path.getsize(fullpath)
130 self.fileSize = os.path.getsize(fullpath)
131 self.filename = fullpath
131 self.filename = fullpath
132 self.flagIsNewFile = 1
132 self.flagIsNewFile = 1
133 if self.fp != None:
133 if self.fp != None:
134 self.fp.close()
134 self.fp.close()
135 self.fp = self.open_file(fullpath, self.open_mode)
135 self.fp = self.open_file(fullpath, self.open_mode)
136 self.flagNoMoreFiles = 0
136 self.flagNoMoreFiles = 0
137 break
137 break
138
138
139 log.warning(
139 log.warning(
140 'Waiting {} sec for a valid file in {}: try {} ...'.format(
140 'Waiting {} sec for a valid file in {}: try {} ...'.format(
141 self.delay, self.path, nTries + 1),
141 self.delay, self.path, nTries + 1),
142 self.name)
142 self.name)
143 time.sleep(self.delay)
143 time.sleep(self.delay)
144
144
145 if not(fullpath):
145 if not(fullpath):
146 raise schainpy.admin.SchainError(
146 raise schainpy.admin.SchainError(
147 'There isn\'t any valid file in {}'.format(self.path))
147 'There isn\'t any valid file in {}'.format(self.path))
148 self.readFirstHeader()
148 self.readFirstHeader()
149 else:
149 else:
150 log.log("Searching files in {}".format(self.path), self.name)
150 log.log("Searching files in {}".format(self.path), self.name)
151 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
151 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
152 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
152 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
153 self.setNextFile()
153 self.setNextFile()
154
154
155 def checkForRealPath(self, nextFile, nextDay):
155 def checkForRealPath(self, nextFile, nextDay):
156 '''
156 '''
157 '''
157 '''
158
158
159 dt = self.datatime + datetime.timedelta(1)
159 dt = self.datatime + datetime.timedelta(1)
160 filename = '{}.{}{}'.format(self.siteFile, dt.strftime('%Y%m%d'), self.ext)
160 filename = '{}.{}{}'.format(self.siteFile, dt.strftime('%Y%m%d'), self.ext)
161 fullfilename = os.path.join(self.path, filename)
161 fullfilename = os.path.join(self.path, filename)
162 if os.path.exists(fullfilename):
162 if os.path.exists(fullfilename):
163 return fullfilename, filename
163 return fullfilename, filename
164 return None, filename
164 return None, filename
165
165
166
166
167 def readFirstHeader(self):
167 def readFirstHeader(self):
168 '''
168 '''
169 '''
169 '''
170
170
171 # 'peru2' ---> Piura - 'peru1' ---> Huancayo or Porcuya
171 # 'peru2' ---> Piura - 'peru1' ---> Huancayo or Porcuya
172 self.siteFile = self.filename.split('/')[-1].split('.')[0]
172 self.siteFile = self.filename.split('/')[-1].split('.')[0]
173 self.header_file = numpy.fromfile(self.fp, FILE_HEADER_STRUCTURE, 1)
173 self.header_file = numpy.fromfile(self.fp, FILE_HEADER_STRUCTURE, 1)
174 self.nrecords = self.header_file['nrec'][0]
174 self.nrecords = self.header_file['nrec'][0]
175 self.counter_records = 0
175 self.counter_records = 0
176 self.flagIsNewFile = 0
176 self.flagIsNewFile = 0
177 self.fileIndex += 1
177 self.fileIndex += 1
178
178
179 def readNextBlock(self):
179 def readNextBlock(self):
180
180
181 while True:
181 while True:
182 if not self.online and self.counter_records == self.nrecords:
182 if not self.online and self.counter_records == self.nrecords:
183 self.flagIsNewFile = 1
183 self.flagIsNewFile = 1
184 if not self.setNextFile():
184 if not self.setNextFile():
185 return 0
185 return 0
186 try:
186 try:
187 pointer = self.fp.tell()
187 if self.online and self.counter_records == 0:
188 pos = int(self.fileSize / (38512))
189 self.counter_records = pos*2 - 2
190 pointer = 38512 * (pos-1) + 48
191 self.fp.seek(pointer)
192 else:
193 pointer = self.fp.tell()
188 self.readBlock()
194 self.readBlock()
189 except:
195 except:
190 if self.online and self.waitDataBlock(pointer, 38512) == 1:
196 if self.online and self.waitDataBlock(pointer, 38512) == 1:
191 continue
197 continue
192 else:
198 else:
193 if not self.setNextFile():
199 if not self.setNextFile():
194 return 0
200 return 0
195
201
196 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
202 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
197 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
203 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
198 log.warning(
204 log.warning(
199 'Reading Record No. {}/{} -> {} [Skipping]'.format(
205 'Reading Record No. {}/{} -> {} [Skipping]'.format(
200 self.counter_records,
206 self.counter_records,
201 self.nrecords,
207 self.nrecords,
202 self.datatime.ctime()),
208 self.datatime.ctime()),
203 'BLTRParamReader')
209 'BLTRParamReader')
204 continue
210 continue
205 break
211 break
206
212
207 log.log('Reading Record No. {} -> {}'.format(
213 log.log('Reading Record No. {} -> {}'.format(
208 self.counter_records,
214 self.counter_records,
209 self.datatime.ctime()), 'BLTRParamReader')
215 self.datatime.ctime()), 'BLTRParamReader')
210
216
211 return 1
217 return 1
212
218
213 def readBlock(self):
219 def readBlock(self):
214
220
215 pointer = self.fp.tell()
221 pointer = self.fp.tell()
216 header_rec = numpy.fromfile(self.fp, REC_HEADER_STRUCTURE, 1)
222 header_rec = numpy.fromfile(self.fp, REC_HEADER_STRUCTURE, 1)
217 self.nchannels = int(header_rec['nchan'][0] / 2)
223 self.nchannels = int(header_rec['nchan'][0] / 2)
218 self.kchan = header_rec['nrxs'][0]
224 self.kchan = header_rec['nrxs'][0]
219 self.nmodes = header_rec['nmodes'][0]
225 self.nmodes = header_rec['nmodes'][0]
220 self.nranges = header_rec['nranges'][0]
226 self.nranges = header_rec['nranges'][0]
221 self.fp.seek(pointer)
227 self.fp.seek(pointer)
222 self.height = numpy.empty((self.nmodes, self.nranges))
228 self.height = numpy.empty((self.nmodes, self.nranges))
223 self.snr = numpy.empty((self.nmodes, int(self.nchannels), self.nranges))
229 self.snr = numpy.empty((self.nmodes, int(self.nchannels), self.nranges))
224 self.buffer = numpy.empty((self.nmodes, 3, self.nranges))
230 self.buffer = numpy.empty((self.nmodes, 3, self.nranges))
225 self.flagDiscontinuousBlock = 0
231 self.flagDiscontinuousBlock = 0
226
232
227 for mode in range(self.nmodes):
233 for mode in range(self.nmodes):
228 self.readHeader()
234 self.readHeader()
229 data = self.readData()
235 data = self.readData()
230 self.height[mode] = (data[0] - self.correction) / 1000.
236 self.height[mode] = (data[0] - self.correction) / 1000.
231 self.buffer[mode] = data[1]
237 self.buffer[mode] = data[1]
232 self.snr[mode] = data[2]
238 self.snr[mode] = data[2]
233
239
234 self.counter_records = self.counter_records + self.nmodes
240 self.counter_records = self.counter_records + self.nmodes
235
241
236 return
242 return
237
243
238 def readHeader(self):
244 def readHeader(self):
239 '''
245 '''
240 RecordHeader of BLTR rawdata file
246 RecordHeader of BLTR rawdata file
241 '''
247 '''
242
248
243 header_structure = numpy.dtype(
249 header_structure = numpy.dtype(
244 REC_HEADER_STRUCTURE.descr + [
250 REC_HEADER_STRUCTURE.descr + [
245 ('antenna_coord', 'f4', (2, int(self.nchannels))),
251 ('antenna_coord', 'f4', (2, int(self.nchannels))),
246 ('rx_gains', 'u4', (int(self.nchannels),)),
252 ('rx_gains', 'u4', (int(self.nchannels),)),
247 ('rx_analysis', 'u4', (int(self.nchannels),))
253 ('rx_analysis', 'u4', (int(self.nchannels),))
248 ]
254 ]
249 )
255 )
250
256
251 self.header_rec = numpy.fromfile(self.fp, header_structure, 1)
257 self.header_rec = numpy.fromfile(self.fp, header_structure, 1)
252 self.lat = self.header_rec['lat'][0]
258 self.lat = self.header_rec['lat'][0]
253 self.lon = self.header_rec['lon'][0]
259 self.lon = self.header_rec['lon'][0]
254 self.delta = self.header_rec['delta_r'][0]
260 self.delta = self.header_rec['delta_r'][0]
255 self.correction = self.header_rec['dmode_rngcorr'][0]
261 self.correction = self.header_rec['dmode_rngcorr'][0]
256 self.imode = self.header_rec['dmode_index'][0]
262 self.imode = self.header_rec['dmode_index'][0]
257 self.antenna = self.header_rec['antenna_coord']
263 self.antenna = self.header_rec['antenna_coord']
258 self.rx_gains = self.header_rec['rx_gains']
264 self.rx_gains = self.header_rec['rx_gains']
259 self.time = self.header_rec['time'][0]
265 self.time = self.header_rec['time'][0]
260 dt = datetime.datetime.utcfromtimestamp(self.time)
266 dt = datetime.datetime.utcfromtimestamp(self.time)
261 if dt.date()>self.datatime.date():
267 if dt.date()>self.datatime.date():
262 self.flagDiscontinuousBlock = 1
268 self.flagDiscontinuousBlock = 1
263 self.datatime = dt
269 self.datatime = dt
264
270
265 def readData(self):
271 def readData(self):
266 '''
272 '''
267 Reading and filtering data block record of BLTR rawdata file,
273 Reading and filtering data block record of BLTR rawdata file,
268 filtering is according to status_value.
274 filtering is according to status_value.
269
275
270 Input:
276 Input:
271 status_value - Array data is set to NAN for values that are not
277 status_value - Array data is set to NAN for values that are not
272 equal to status_value
278 equal to status_value
273
279
274 '''
280 '''
275 self.nchannels = int(self.nchannels)
281 self.nchannels = int(self.nchannels)
276
282
277 data_structure = numpy.dtype(
283 data_structure = numpy.dtype(
278 DATA_STRUCTURE.descr + [
284 DATA_STRUCTURE.descr + [
279 ('rx_saturation', 'u4', (self.nchannels,)),
285 ('rx_saturation', 'u4', (self.nchannels,)),
280 ('chan_offset', 'u4', (2 * self.nchannels,)),
286 ('chan_offset', 'u4', (2 * self.nchannels,)),
281 ('rx_amp', 'u4', (self.nchannels,)),
287 ('rx_amp', 'u4', (self.nchannels,)),
282 ('rx_snr', 'f4', (self.nchannels,)),
288 ('rx_snr', 'f4', (self.nchannels,)),
283 ('cross_snr', 'f4', (self.kchan,)),
289 ('cross_snr', 'f4', (self.kchan,)),
284 ('sea_power_relative', 'f4', (self.kchan,))]
290 ('sea_power_relative', 'f4', (self.kchan,))]
285 )
291 )
286
292
287 data = numpy.fromfile(self.fp, data_structure, self.nranges)
293 data = numpy.fromfile(self.fp, data_structure, self.nranges)
288
294
289 height = data['range']
295 height = data['range']
290 winds = numpy.array(
296 winds = numpy.array(
291 (data['zonal'], data['meridional'], data['vertical']))
297 (data['zonal'], data['meridional'], data['vertical']))
292 snr = data['rx_snr'].T
298 snr = data['rx_snr'].T
293
299
294 winds[numpy.where(winds == -9999.)] = numpy.nan
300 winds[numpy.where(winds == -9999.)] = numpy.nan
295 winds[:, numpy.where(data['status'] != self.status_value)] = numpy.nan
301 winds[:, numpy.where(data['status'] != self.status_value)] = numpy.nan
296 snr[numpy.where(snr == -9999.)] = numpy.nan
302 snr[numpy.where(snr == -9999.)] = numpy.nan
297 snr[:, numpy.where(data['status'] != self.status_value)] = numpy.nan
303 snr[:, numpy.where(data['status'] != self.status_value)] = numpy.nan
298 snr = numpy.power(10, snr / 10)
304 snr = numpy.power(10, snr / 10)
299
305
300 return height, winds, snr
306 return height, winds, snr
301
307
302 def set_output(self):
308 def set_output(self):
303 '''
309 '''
304 Storing data from databuffer to dataOut object
310 Storing data from databuffer to dataOut object
305 '''
311 '''
306
312
307 self.dataOut.data_snr = self.snr
313 self.dataOut.data_snr = self.snr
308 self.dataOut.height = self.height
314 self.dataOut.height = self.height
309 self.dataOut.data = self.buffer
315 self.dataOut.data = self.buffer
310 self.dataOut.utctimeInit = self.time
316 self.dataOut.utctimeInit = self.time
311 self.dataOut.utctime = self.dataOut.utctimeInit
317 self.dataOut.utctime = self.dataOut.utctimeInit
312 self.dataOut.useLocalTime = False
318 self.dataOut.useLocalTime = False
313 self.dataOut.paramInterval = 157
319 self.dataOut.paramInterval = 157
314 self.dataOut.site = self.siteFile
320 self.dataOut.site = self.siteFile
315 self.dataOut.nrecords = self.nrecords / self.nmodes
321 self.dataOut.nrecords = self.nrecords / self.nmodes
316 self.dataOut.lat = self.lat
322 self.dataOut.lat = self.lat
317 self.dataOut.lon = self.lon
323 self.dataOut.lon = self.lon
318 self.dataOut.channelList = list(range(self.nchannels))
324 self.dataOut.channelList = list(range(self.nchannels))
319 self.dataOut.kchan = self.kchan
325 self.dataOut.kchan = self.kchan
320 self.dataOut.delta = self.delta
326 self.dataOut.delta = self.delta
321 self.dataOut.correction = self.correction
327 self.dataOut.correction = self.correction
322 self.dataOut.nmodes = self.nmodes
328 self.dataOut.nmodes = self.nmodes
323 self.dataOut.imode = self.imode
329 self.dataOut.imode = self.imode
324 self.dataOut.antenna = self.antenna
330 self.dataOut.antenna = self.antenna
325 self.dataOut.rx_gains = self.rx_gains
331 self.dataOut.rx_gains = self.rx_gains
326 self.dataOut.flagNoData = False
332 self.dataOut.flagNoData = False
327 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
333 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
328
334
329 def getData(self):
335 def getData(self):
330 '''
336 '''
331 Storing data from databuffer to dataOut object
337 Storing data from databuffer to dataOut object
332 '''
338 '''
333 if self.flagNoMoreFiles:
339 if self.flagNoMoreFiles:
334 self.dataOut.flagNoData = True
340 self.dataOut.flagNoData = True
335 return 0
341 return 0
336
342
337 if not self.readNextBlock():
343 if not self.readNextBlock():
338 self.dataOut.flagNoData = True
344 self.dataOut.flagNoData = True
339 return 0
345 return 0
340
346
341 self.set_output()
347 self.set_output()
342
348
343 return 1
349 return 1
344
350
345 def run(self, **kwargs):
351 def run(self, **kwargs):
346 '''
352 '''
347 '''
353 '''
348
354
349 if not(self.isConfig):
355 if not(self.isConfig):
350 self.setup(**kwargs)
356 self.setup(**kwargs)
351 self.isConfig = True
357 self.isConfig = True
352
358
353 self.getData()
359 self.getData()
354
360
355 return No newline at end of file
361 return
@@ -1,1614 +1,1618
1 """
1 """
2 Created on Jul 2, 2014
2 Created on Jul 2, 2014
3
3
4 @author: roj-idl71
4 @author: roj-idl71
5 """
5 """
6 import os
6 import os
7 import sys
7 import sys
8 import glob
8 import glob
9 import time
9 import time
10 import numpy
10 import numpy
11 import fnmatch
11 import fnmatch
12 import inspect
12 import inspect
13 import time
13 import time
14 import datetime
14 import datetime
15 import zmq
15 import zmq
16
16
17 from schainpy.model.proc.jroproc_base import Operation, MPDecorator
17 from schainpy.model.proc.jroproc_base import Operation, MPDecorator
18 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
18 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
19 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
19 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
20 from schainpy.utils import log
20 from schainpy.utils import log
21 import schainpy.admin
21 import schainpy.admin
22
22
23 LOCALTIME = True
23 LOCALTIME = True
24 DT_DIRECTIVES = {
24 DT_DIRECTIVES = {
25 '%Y': 4,
25 '%Y': 4,
26 '%y': 2,
26 '%y': 2,
27 '%m': 2,
27 '%m': 2,
28 '%d': 2,
28 '%d': 2,
29 '%j': 3,
29 '%j': 3,
30 '%H': 2,
30 '%H': 2,
31 '%M': 2,
31 '%M': 2,
32 '%S': 2,
32 '%S': 2,
33 '%f': 6
33 '%f': 6
34 }
34 }
35
35
36
36
37 def isNumber(cad):
37 def isNumber(cad):
38 """
38 """
39 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
39 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
40
40
41 Excepciones:
41 Excepciones:
42 Si un determinado string no puede ser convertido a numero
42 Si un determinado string no puede ser convertido a numero
43 Input:
43 Input:
44 str, string al cual se le analiza para determinar si convertible a un numero o no
44 str, string al cual se le analiza para determinar si convertible a un numero o no
45
45
46 Return:
46 Return:
47 True : si el string es uno numerico
47 True : si el string es uno numerico
48 False : no es un string numerico
48 False : no es un string numerico
49 """
49 """
50 try:
50 try:
51 float(cad)
51 float(cad)
52 return True
52 return True
53 except:
53 except:
54 return False
54 return False
55
55
56
56
57 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
57 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
58 """
58 """
59 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
59 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
60
60
61 Inputs:
61 Inputs:
62 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
62 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
63
63
64 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
64 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
65 segundos contados desde 01/01/1970.
65 segundos contados desde 01/01/1970.
66 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
66 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
67 segundos contados desde 01/01/1970.
67 segundos contados desde 01/01/1970.
68
68
69 Return:
69 Return:
70 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
70 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
71 fecha especificado, de lo contrario retorna False.
71 fecha especificado, de lo contrario retorna False.
72
72
73 Excepciones:
73 Excepciones:
74 Si el archivo no existe o no puede ser abierto
74 Si el archivo no existe o no puede ser abierto
75 Si la cabecera no puede ser leida.
75 Si la cabecera no puede ser leida.
76
76
77 """
77 """
78 basicHeaderObj = BasicHeader(LOCALTIME)
78 basicHeaderObj = BasicHeader(LOCALTIME)
79
79
80 try:
80 try:
81
81
82 fp = open(filename, 'rb')
82 fp = open(filename, 'rb')
83 except IOError:
83 except IOError:
84 print("The file %s can't be opened" % (filename))
84 print("The file %s can't be opened" % (filename))
85 return 0
85 return 0
86
86
87 sts = basicHeaderObj.read(fp)
87 sts = basicHeaderObj.read(fp)
88 fp.close()
88 fp.close()
89
89
90 if not(sts):
90 if not(sts):
91 print("Skipping the file %s because it has not a valid header" % (filename))
91 print("Skipping the file %s because it has not a valid header" % (filename))
92 return 0
92 return 0
93
93
94 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
94 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
95 return 0
95 return 0
96
96
97 return 1
97 return 1
98
98
99
99
100 def isTimeInRange(thisTime, startTime, endTime):
100 def isTimeInRange(thisTime, startTime, endTime):
101 if endTime >= startTime:
101 if endTime >= startTime:
102 if (thisTime < startTime) or (thisTime > endTime):
102 if (thisTime < startTime) or (thisTime > endTime):
103 return 0
103 return 0
104 return 1
104 return 1
105 else:
105 else:
106 if (thisTime < startTime) and (thisTime > endTime):
106 if (thisTime < startTime) and (thisTime > endTime):
107 return 0
107 return 0
108 return 1
108 return 1
109
109
110
110
111 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
111 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
112 """
112 """
113 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
113 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
114
114
115 Inputs:
115 Inputs:
116 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
116 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
117
117
118 startDate : fecha inicial del rango seleccionado en formato datetime.date
118 startDate : fecha inicial del rango seleccionado en formato datetime.date
119
119
120 endDate : fecha final del rango seleccionado en formato datetime.date
120 endDate : fecha final del rango seleccionado en formato datetime.date
121
121
122 startTime : tiempo inicial del rango seleccionado en formato datetime.time
122 startTime : tiempo inicial del rango seleccionado en formato datetime.time
123
123
124 endTime : tiempo final del rango seleccionado en formato datetime.time
124 endTime : tiempo final del rango seleccionado en formato datetime.time
125
125
126 Return:
126 Return:
127 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
127 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
128 fecha especificado, de lo contrario retorna False.
128 fecha especificado, de lo contrario retorna False.
129
129
130 Excepciones:
130 Excepciones:
131 Si el archivo no existe o no puede ser abierto
131 Si el archivo no existe o no puede ser abierto
132 Si la cabecera no puede ser leida.
132 Si la cabecera no puede ser leida.
133
133
134 """
134 """
135
135
136 try:
136 try:
137 fp = open(filename, 'rb')
137 fp = open(filename, 'rb')
138 except IOError:
138 except IOError:
139 print("The file %s can't be opened" % (filename))
139 print("The file %s can't be opened" % (filename))
140 return None
140 return None
141
141
142 firstBasicHeaderObj = BasicHeader(LOCALTIME)
142 firstBasicHeaderObj = BasicHeader(LOCALTIME)
143 systemHeaderObj = SystemHeader()
143 systemHeaderObj = SystemHeader()
144
144
145 radarControllerHeaderObj = RadarControllerHeader()
145 radarControllerHeaderObj = RadarControllerHeader()
146 processingHeaderObj = ProcessingHeader()
146 processingHeaderObj = ProcessingHeader()
147
147
148 lastBasicHeaderObj = BasicHeader(LOCALTIME)
148 lastBasicHeaderObj = BasicHeader(LOCALTIME)
149
149
150 sts = firstBasicHeaderObj.read(fp)
150 sts = firstBasicHeaderObj.read(fp)
151
151
152 if not(sts):
152 if not(sts):
153 print("[Reading] Skipping the file %s because it has not a valid header" % (filename))
153 print("[Reading] Skipping the file %s because it has not a valid header" % (filename))
154 return None
154 return None
155
155
156 if not systemHeaderObj.read(fp):
156 if not systemHeaderObj.read(fp):
157 return None
157 return None
158
158
159 if not radarControllerHeaderObj.read(fp):
159 if not radarControllerHeaderObj.read(fp):
160 return None
160 return None
161
161
162 if not processingHeaderObj.read(fp):
162 if not processingHeaderObj.read(fp):
163 return None
163 return None
164
164
165 filesize = os.path.getsize(filename)
165 filesize = os.path.getsize(filename)
166
166
167 offset = processingHeaderObj.blockSize + 24 # header size
167 offset = processingHeaderObj.blockSize + 24 # header size
168
168
169 if filesize <= offset:
169 if filesize <= offset:
170 print("[Reading] %s: This file has not enough data" % filename)
170 print("[Reading] %s: This file has not enough data" % filename)
171 return None
171 return None
172
172
173 fp.seek(-offset, 2)
173 fp.seek(-offset, 2)
174
174
175 sts = lastBasicHeaderObj.read(fp)
175 sts = lastBasicHeaderObj.read(fp)
176
176
177 fp.close()
177 fp.close()
178
178
179 thisDatetime = lastBasicHeaderObj.datatime
179 thisDatetime = lastBasicHeaderObj.datatime
180 thisTime_last_block = thisDatetime.time()
180 thisTime_last_block = thisDatetime.time()
181
181
182 thisDatetime = firstBasicHeaderObj.datatime
182 thisDatetime = firstBasicHeaderObj.datatime
183 thisDate = thisDatetime.date()
183 thisDate = thisDatetime.date()
184 thisTime_first_block = thisDatetime.time()
184 thisTime_first_block = thisDatetime.time()
185
185
186 # General case
186 # General case
187 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
187 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
188 #-----------o----------------------------o-----------
188 #-----------o----------------------------o-----------
189 # startTime endTime
189 # startTime endTime
190
190
191 if endTime >= startTime:
191 if endTime >= startTime:
192 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
192 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
193 return None
193 return None
194
194
195 return thisDatetime
195 return thisDatetime
196
196
197 # If endTime < startTime then endTime belongs to the next day
197 # If endTime < startTime then endTime belongs to the next day
198
198
199 #<<<<<<<<<<<o o>>>>>>>>>>>
199 #<<<<<<<<<<<o o>>>>>>>>>>>
200 #-----------o----------------------------o-----------
200 #-----------o----------------------------o-----------
201 # endTime startTime
201 # endTime startTime
202
202
203 if (thisDate == startDate) and (thisTime_last_block < startTime):
203 if (thisDate == startDate) and (thisTime_last_block < startTime):
204 return None
204 return None
205
205
206 if (thisDate == endDate) and (thisTime_first_block > endTime):
206 if (thisDate == endDate) and (thisTime_first_block > endTime):
207 return None
207 return None
208
208
209 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
209 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
210 return None
210 return None
211
211
212 return thisDatetime
212 return thisDatetime
213
213
214
214
215 def isFolderInDateRange(folder, startDate=None, endDate=None):
215 def isFolderInDateRange(folder, startDate=None, endDate=None):
216 """
216 """
217 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
217 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
218
218
219 Inputs:
219 Inputs:
220 folder : nombre completo del directorio.
220 folder : nombre completo del directorio.
221 Su formato deberia ser "/path_root/?YYYYDDD"
221 Su formato deberia ser "/path_root/?YYYYDDD"
222
222
223 siendo:
223 siendo:
224 YYYY : Anio (ejemplo 2015)
224 YYYY : Anio (ejemplo 2015)
225 DDD : Dia del anio (ejemplo 305)
225 DDD : Dia del anio (ejemplo 305)
226
226
227 startDate : fecha inicial del rango seleccionado en formato datetime.date
227 startDate : fecha inicial del rango seleccionado en formato datetime.date
228
228
229 endDate : fecha final del rango seleccionado en formato datetime.date
229 endDate : fecha final del rango seleccionado en formato datetime.date
230
230
231 Return:
231 Return:
232 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
232 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
233 fecha especificado, de lo contrario retorna False.
233 fecha especificado, de lo contrario retorna False.
234 Excepciones:
234 Excepciones:
235 Si el directorio no tiene el formato adecuado
235 Si el directorio no tiene el formato adecuado
236 """
236 """
237
237
238 basename = os.path.basename(folder)
238 basename = os.path.basename(folder)
239
239
240 if not isRadarFolder(basename):
240 if not isRadarFolder(basename):
241 print("The folder %s has not the rigth format" % folder)
241 print("The folder %s has not the rigth format" % folder)
242 return 0
242 return 0
243
243
244 if startDate and endDate:
244 if startDate and endDate:
245 thisDate = getDateFromRadarFolder(basename)
245 thisDate = getDateFromRadarFolder(basename)
246
246
247 if thisDate < startDate:
247 if thisDate < startDate:
248 return 0
248 return 0
249
249
250 if thisDate > endDate:
250 if thisDate > endDate:
251 return 0
251 return 0
252
252
253 return 1
253 return 1
254
254
255
255
256 def isFileInDateRange(filename, startDate=None, endDate=None):
256 def isFileInDateRange(filename, startDate=None, endDate=None):
257 """
257 """
258 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
258 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
259
259
260 Inputs:
260 Inputs:
261 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
261 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
262
262
263 Su formato deberia ser "?YYYYDDDsss"
263 Su formato deberia ser "?YYYYDDDsss"
264
264
265 siendo:
265 siendo:
266 YYYY : Anio (ejemplo 2015)
266 YYYY : Anio (ejemplo 2015)
267 DDD : Dia del anio (ejemplo 305)
267 DDD : Dia del anio (ejemplo 305)
268 sss : set
268 sss : set
269
269
270 startDate : fecha inicial del rango seleccionado en formato datetime.date
270 startDate : fecha inicial del rango seleccionado en formato datetime.date
271
271
272 endDate : fecha final del rango seleccionado en formato datetime.date
272 endDate : fecha final del rango seleccionado en formato datetime.date
273
273
274 Return:
274 Return:
275 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
275 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
276 fecha especificado, de lo contrario retorna False.
276 fecha especificado, de lo contrario retorna False.
277 Excepciones:
277 Excepciones:
278 Si el archivo no tiene el formato adecuado
278 Si el archivo no tiene el formato adecuado
279 """
279 """
280
280
281 basename = os.path.basename(filename)
281 basename = os.path.basename(filename)
282
282
283 if not isRadarFile(basename):
283 if not isRadarFile(basename):
284 print("The filename %s has not the rigth format" % filename)
284 print("The filename %s has not the rigth format" % filename)
285 return 0
285 return 0
286
286
287 if startDate and endDate:
287 if startDate and endDate:
288 thisDate = getDateFromRadarFile(basename)
288 thisDate = getDateFromRadarFile(basename)
289
289
290 if thisDate < startDate:
290 if thisDate < startDate:
291 return 0
291 return 0
292
292
293 if thisDate > endDate:
293 if thisDate > endDate:
294 return 0
294 return 0
295
295
296 return 1
296 return 1
297
297
298
298
299 def getFileFromSet(path, ext, set):
299 def getFileFromSet(path, ext, set):
300 validFilelist = []
300 validFilelist = []
301 fileList = os.listdir(path)
301 fileList = os.listdir(path)
302
302
303 # 0 1234 567 89A BCDE
303 # 0 1234 567 89A BCDE
304 # H YYYY DDD SSS .ext
304 # H YYYY DDD SSS .ext
305
305
306 for thisFile in fileList:
306 for thisFile in fileList:
307 try:
307 try:
308 year = int(thisFile[1:5])
308 year = int(thisFile[1:5])
309 doy = int(thisFile[5:8])
309 doy = int(thisFile[5:8])
310 except:
310 except:
311 continue
311 continue
312
312
313 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
313 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
314 continue
314 continue
315
315
316 validFilelist.append(thisFile)
316 validFilelist.append(thisFile)
317
317
318 myfile = fnmatch.filter(
318 myfile = fnmatch.filter(
319 validFilelist, '*%4.4d%3.3d%3.3d*' % (year, doy, set))
319 validFilelist, '*%4.4d%3.3d%3.3d*' % (year, doy, set))
320
320
321 if len(myfile) != 0:
321 if len(myfile) != 0:
322 return myfile[0]
322 return myfile[0]
323 else:
323 else:
324 filename = '*%4.4d%3.3d%3.3d%s' % (year, doy, set, ext.lower())
324 filename = '*%4.4d%3.3d%3.3d%s' % (year, doy, set, ext.lower())
325 print('the filename %s does not exist' % filename)
325 print('the filename %s does not exist' % filename)
326 print('...going to the last file: ')
326 print('...going to the last file: ')
327
327
328 if validFilelist:
328 if validFilelist:
329 validFilelist = sorted(validFilelist, key=str.lower)
329 validFilelist = sorted(validFilelist, key=str.lower)
330 return validFilelist[-1]
330 return validFilelist[-1]
331
331
332 return None
332 return None
333
333
334
334
335 def getlastFileFromPath(path, ext):
335 def getlastFileFromPath(path, ext):
336 """
336 """
337 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
337 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
338 al final de la depuracion devuelve el ultimo file de la lista que quedo.
338 al final de la depuracion devuelve el ultimo file de la lista que quedo.
339
339
340 Input:
340 Input:
341 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
341 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
342 ext : extension de los files contenidos en una carpeta
342 ext : extension de los files contenidos en una carpeta
343
343
344 Return:
344 Return:
345 El ultimo file de una determinada carpeta, no se considera el path.
345 El ultimo file de una determinada carpeta, no se considera el path.
346 """
346 """
347 validFilelist = []
347 validFilelist = []
348 fileList = os.listdir(path)
348 fileList = os.listdir(path)
349
349
350 # 0 1234 567 89A BCDE
350 # 0 1234 567 89A BCDE
351 # H YYYY DDD SSS .ext
351 # H YYYY DDD SSS .ext
352
352
353 for thisFile in fileList:
353 for thisFile in fileList:
354
354
355 year = thisFile[1:5]
355 year = thisFile[1:5]
356 if not isNumber(year):
356 if not isNumber(year):
357 continue
357 continue
358
358
359 doy = thisFile[5:8]
359 doy = thisFile[5:8]
360 if not isNumber(doy):
360 if not isNumber(doy):
361 continue
361 continue
362
362
363 year = int(year)
363 year = int(year)
364 doy = int(doy)
364 doy = int(doy)
365
365
366 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
366 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
367 continue
367 continue
368
368
369 validFilelist.append(thisFile)
369 validFilelist.append(thisFile)
370
370
371 if validFilelist:
371 if validFilelist:
372 validFilelist = sorted(validFilelist, key=str.lower)
372 validFilelist = sorted(validFilelist, key=str.lower)
373 return validFilelist[-1]
373 return validFilelist[-1]
374
374
375 return None
375 return None
376
376
377
377
378 def isRadarFolder(folder):
378 def isRadarFolder(folder):
379 try:
379 try:
380 year = int(folder[1:5])
380 year = int(folder[1:5])
381 doy = int(folder[5:8])
381 doy = int(folder[5:8])
382 except:
382 except:
383 return 0
383 return 0
384
384
385 return 1
385 return 1
386
386
387
387
388 def isRadarFile(file):
388 def isRadarFile(file):
389 try:
389 try:
390 year = int(file[1:5])
390 year = int(file[1:5])
391 doy = int(file[5:8])
391 doy = int(file[5:8])
392 set = int(file[8:11])
392 set = int(file[8:11])
393 except:
393 except:
394 return 0
394 return 0
395
395
396 return 1
396 return 1
397
397
398
398
399 def getDateFromRadarFile(file):
399 def getDateFromRadarFile(file):
400 try:
400 try:
401 year = int(file[1:5])
401 year = int(file[1:5])
402 doy = int(file[5:8])
402 doy = int(file[5:8])
403 set = int(file[8:11])
403 set = int(file[8:11])
404 except:
404 except:
405 return None
405 return None
406
406
407 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
407 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
408 return thisDate
408 return thisDate
409
409
410
410
411 def getDateFromRadarFolder(folder):
411 def getDateFromRadarFolder(folder):
412 try:
412 try:
413 year = int(folder[1:5])
413 year = int(folder[1:5])
414 doy = int(folder[5:8])
414 doy = int(folder[5:8])
415 except:
415 except:
416 return None
416 return None
417
417
418 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
418 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
419 return thisDate
419 return thisDate
420
420
421 def parse_format(s, fmt):
421 def parse_format(s, fmt):
422
422
423 for i in range(fmt.count('%')):
423 for i in range(fmt.count('%')):
424 x = fmt.index('%')
424 x = fmt.index('%')
425 d = DT_DIRECTIVES[fmt[x:x+2]]
425 d = DT_DIRECTIVES[fmt[x:x+2]]
426 fmt = fmt.replace(fmt[x:x+2], s[x:x+d])
426 fmt = fmt.replace(fmt[x:x+2], s[x:x+d])
427 return fmt
427 return fmt
428
428
429 class Reader(object):
429 class Reader(object):
430
430
431 c = 3E8
431 c = 3E8
432 isConfig = False
432 isConfig = False
433 dtype = None
433 dtype = None
434 pathList = []
434 pathList = []
435 filenameList = []
435 filenameList = []
436 datetimeList = []
436 datetimeList = []
437 filename = None
437 filename = None
438 ext = None
438 ext = None
439 flagIsNewFile = 1
439 flagIsNewFile = 1
440 flagDiscontinuousBlock = 0
440 flagDiscontinuousBlock = 0
441 flagIsNewBlock = 0
441 flagIsNewBlock = 0
442 flagNoMoreFiles = 0
442 flagNoMoreFiles = 0
443 fp = None
443 fp = None
444 firstHeaderSize = 0
444 firstHeaderSize = 0
445 basicHeaderSize = 24
445 basicHeaderSize = 24
446 versionFile = 1103
446 versionFile = 1103
447 fileSize = None
447 fileSize = None
448 fileSizeByHeader = None
448 fileSizeByHeader = None
449 fileIndex = -1
449 fileIndex = -1
450 profileIndex = None
450 profileIndex = None
451 blockIndex = 0
451 blockIndex = 0
452 nTotalBlocks = 0
452 nTotalBlocks = 0
453 maxTimeStep = 30
453 maxTimeStep = 30
454 lastUTTime = None
454 lastUTTime = None
455 datablock = None
455 datablock = None
456 dataOut = None
456 dataOut = None
457 getByBlock = False
457 getByBlock = False
458 path = None
458 path = None
459 startDate = None
459 startDate = None
460 endDate = None
460 endDate = None
461 startTime = datetime.time(0, 0, 0)
461 startTime = datetime.time(0, 0, 0)
462 endTime = datetime.time(23, 59, 59)
462 endTime = datetime.time(23, 59, 59)
463 set = None
463 set = None
464 expLabel = ""
464 expLabel = ""
465 online = False
465 online = False
466 delay = 60
466 delay = 60
467 nTries = 3 # quantity tries
467 nTries = 3 # quantity tries
468 nFiles = 3 # number of files for searching
468 nFiles = 3 # number of files for searching
469 walk = True
469 walk = True
470 getblock = False
470 getblock = False
471 nTxs = 1
471 nTxs = 1
472 realtime = False
472 realtime = False
473 blocksize = 0
473 blocksize = 0
474 blocktime = None
474 blocktime = None
475 warnings = True
475 warnings = True
476 verbose = True
476 verbose = True
477 server = None
477 server = None
478 topic = None
478 format = None
479 format = None
479 oneDDict = None
480 oneDDict = None
480 twoDDict = None
481 twoDDict = None
481 independentParam = None
482 independentParam = None
482 filefmt = None
483 filefmt = None
483 folderfmt = None
484 folderfmt = None
484 open_file = open
485 open_file = open
485 open_mode = 'rb'
486 open_mode = 'rb'
486
487
487 def run(self):
488 def run(self):
488
489
489 raise NotImplementedError
490 raise NotImplementedError
490
491
491 def getAllowedArgs(self):
492 def getAllowedArgs(self):
492 if hasattr(self, '__attrs__'):
493 if hasattr(self, '__attrs__'):
493 return self.__attrs__
494 return self.__attrs__
494 else:
495 else:
495 return inspect.getargspec(self.run).args
496 return inspect.getargspec(self.run).args
496
497
497 def set_kwargs(self, **kwargs):
498 def set_kwargs(self, **kwargs):
498
499
499 for key, value in kwargs.items():
500 for key, value in kwargs.items():
500 setattr(self, key, value)
501 setattr(self, key, value)
501
502
502 def find_folders(self, path, startDate, endDate, folderfmt, last=False):
503 def find_folders(self, path, startDate, endDate, folderfmt, last=False):
503
504
504 folders = [x for f in path.split(',')
505 folders = [x for f in path.split(',')
505 for x in os.listdir(f) if os.path.isdir(os.path.join(f, x))]
506 for x in os.listdir(f) if os.path.isdir(os.path.join(f, x))]
506 folders.sort()
507 folders.sort()
507
508
508 if last:
509 if last:
509 folders = [folders[-1]]
510 folders = [folders[-1]]
510
511
511 for folder in folders:
512 for folder in folders:
512 try:
513 try:
513 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
514 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
514 if dt >= startDate and dt <= endDate:
515 if dt >= startDate and dt <= endDate:
515 yield os.path.join(path, folder)
516 yield os.path.join(path, folder)
516 else:
517 else:
517 log.log('Skiping folder {}'.format(folder), self.name)
518 log.log('Skiping folder {}'.format(folder), self.name)
518 except Exception as e:
519 except Exception as e:
519 log.log('Skiping folder {}'.format(folder), self.name)
520 log.log('Skiping folder {}'.format(folder), self.name)
520 continue
521 continue
521 return
522 return
522
523
523 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
524 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
524 expLabel='', last=False):
525 expLabel='', last=False):
525 for path in folders:
526 for path in folders:
526 files = glob.glob1(path+'/'+expLabel, '*{}'.format(ext))
527 files = glob.glob1(path+'/'+expLabel, '*{}'.format(ext))
527 files.sort()
528 files.sort()
528 if last:
529 if last:
529 if files:
530 if files:
530 fo = files[-1]
531 fo = files[-1]
531 try:
532 try:
532 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
533 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
533 yield os.path.join(path, expLabel, fo)
534 yield os.path.join(path, expLabel, fo)
534 except Exception as e:
535 except Exception as e:
535 pass
536 pass
536 return
537 return
537 else:
538 else:
538 return
539 return
539
540
540 for fo in files:
541 for fo in files:
541 try:
542 try:
542 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
543 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
543 #print(dt)
544 #print(dt)
544 #print(startDate)
545 #print(startDate)
545 #print(endDate)
546 #print(endDate)
546 if dt >= startDate and dt <= endDate:
547 if dt >= startDate and dt <= endDate:
547
548
548 yield os.path.join(path, expLabel, fo)
549 yield os.path.join(path, expLabel, fo)
549
550
550 else:
551 else:
551
552
552 log.log('Skiping file {}'.format(fo), self.name)
553 log.log('Skiping file {}'.format(fo), self.name)
553 except Exception as e:
554 except Exception as e:
554 log.log('Skiping file {}'.format(fo), self.name)
555 log.log('Skiping file {}'.format(fo), self.name)
555 continue
556 continue
556
557
557 def searchFilesOffLine(self, path, startDate, endDate,
558 def searchFilesOffLine(self, path, startDate, endDate,
558 expLabel, ext, walk,
559 expLabel, ext, walk,
559 filefmt, folderfmt):
560 filefmt, folderfmt):
560 """Search files in offline mode for the given arguments
561 """Search files in offline mode for the given arguments
561
562
562 Return:
563 Return:
563 Generator of files
564 Generator of files
564 """
565 """
565
566
566 if walk:
567 if walk:
567 folders = self.find_folders(
568 folders = self.find_folders(
568 path, startDate, endDate, folderfmt)
569 path, startDate, endDate, folderfmt)
569 #print("folders: ", folders)
570 #print("folders: ", folders)
570 else:
571 else:
571 folders = path.split(',')
572 folders = path.split(',')
572
573
573 return self.find_files(
574 return self.find_files(
574 folders, ext, filefmt, startDate, endDate, expLabel)
575 folders, ext, filefmt, startDate, endDate, expLabel)
575
576
576 def searchFilesOnLine(self, path, startDate, endDate,
577 def searchFilesOnLine(self, path, startDate, endDate,
577 expLabel, ext, walk,
578 expLabel, ext, walk,
578 filefmt, folderfmt):
579 filefmt, folderfmt):
579 """Search for the last file of the last folder
580 """Search for the last file of the last folder
580
581
581 Arguments:
582 Arguments:
582 path : carpeta donde estan contenidos los files que contiene data
583 path : carpeta donde estan contenidos los files que contiene data
583 expLabel : Nombre del subexperimento (subfolder)
584 expLabel : Nombre del subexperimento (subfolder)
584 ext : extension de los files
585 ext : extension de los files
585 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
586 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
586
587
587 Return:
588 Return:
588 generator with the full path of last filename
589 generator with the full path of last filename
589 """
590 """
590
591
591 if walk:
592 if walk:
592 folders = self.find_folders(
593 folders = self.find_folders(
593 path, startDate, endDate, folderfmt, last=True)
594 path, startDate, endDate, folderfmt, last=True)
594 else:
595 else:
595 folders = path.split(',')
596 folders = path.split(',')
596
597
597 return self.find_files(
598 return self.find_files(
598 folders, ext, filefmt, startDate, endDate, expLabel, last=True)
599 folders, ext, filefmt, startDate, endDate, expLabel, last=True)
599
600
600 def setNextFile(self):
601 def setNextFile(self):
601 """Set the next file to be readed open it and parse de file header"""
602 """Set the next file to be readed open it and parse de file header"""
602
603
603 #print("fp: ",self.fp)
604 #print("fp: ",self.fp)
604 while True:
605 while True:
605
606
606 #print(self.fp)
607 #print(self.fp)
607 if self.fp != None:
608 if self.fp != None:
608 self.fp.close()
609 self.fp.close()
609
610
610 #print("setNextFile")
611 #print("setNextFile")
611 #print("BEFORE OPENING",self.filename)
612 #print("BEFORE OPENING",self.filename)
612 if self.online:
613 if self.online:
613 newFile = self.setNextFileOnline()
614 newFile = self.setNextFileOnline()
614
615
615 else:
616 else:
616
617
617 newFile = self.setNextFileOffline()
618 newFile = self.setNextFileOffline()
618
619
619 #print("newFile: ",newFile)
620 #print("newFile: ",newFile)
620 if not(newFile):
621 if not(newFile):
621
622
622 if self.online:
623 if self.online:
623 raise schainpy.admin.SchainError('Time to wait for new files reach')
624 raise schainpy.admin.SchainError('Time to wait for new files reach')
624 else:
625 else:
625 if self.fileIndex == -1:
626 if self.fileIndex == -1:
626 #print("OKK")
627 #print("OKK")
627 raise schainpy.admin.SchainWarning('No files found in the given path')
628 raise schainpy.admin.SchainWarning('No files found in the given path')
628 else:
629 else:
629
630
630 raise schainpy.admin.SchainWarning('No more files to read')
631 raise schainpy.admin.SchainWarning('No more files to read')
631
632
632 if self.verifyFile(self.filename):
633 if self.verifyFile(self.filename):
633
634
634 break
635 break
635
636
636 ##print("BEFORE OPENING",self.filename)
637 ##print("BEFORE OPENING",self.filename)
637
638
638 log.log('Opening file: %s' % self.filename, self.name)
639 log.log('Opening file: %s' % self.filename, self.name)
639
640
640 self.readFirstHeader()
641 self.readFirstHeader()
641 self.nReadBlocks = 0
642 self.nReadBlocks = 0
642
643
643 def setNextFileOnline(self):
644 def setNextFileOnline(self):
644 """Check for the next file to be readed in online mode.
645 """Check for the next file to be readed in online mode.
645
646
646 Set:
647 Set:
647 self.filename
648 self.filename
648 self.fp
649 self.fp
649 self.filesize
650 self.filesize
650
651
651 Return:
652 Return:
652 boolean
653 boolean
653
654
654 """
655 """
655
656
656 nextFile = True
657 nextFile = True
657 nextDay = False
658 nextDay = False
658
659
659 for nFiles in range(self.nFiles+1):
660 for nFiles in range(self.nFiles+1):
660 for nTries in range(self.nTries):
661 for nTries in range(self.nTries):
661 fullfilename, filename = self.checkForRealPath(nextFile, nextDay)
662 fullfilename, filename = self.checkForRealPath(nextFile, nextDay)
662 if fullfilename is not None:
663 if fullfilename is not None:
663 break
664 break
664 log.warning(
665 log.warning(
665 "Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, filename, nTries + 1),
666 "Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, filename, nTries + 1),
666 self.name)
667 self.name)
667 time.sleep(self.delay)
668 time.sleep(self.delay)
668 nextFile = False
669 nextFile = False
669 continue
670 continue
670
671
671 if fullfilename is not None:
672 if fullfilename is not None:
672 break
673 break
673
674
674 #self.nTries = 1
675 #self.nTries = 1
675 nextFile = True
676 nextFile = True
676
677
677 if nFiles == (self.nFiles - 1):
678 if nFiles == (self.nFiles - 1):
678 log.log('Trying with next day...', self.name)
679 log.log('Trying with next day...', self.name)
679 nextDay = True
680 nextDay = True
680 self.nTries = 3
681 self.nTries = 3
681
682
682 if fullfilename:
683 if fullfilename:
683 self.fileSize = os.path.getsize(fullfilename)
684 self.fileSize = os.path.getsize(fullfilename)
684 self.filename = fullfilename
685 self.filename = fullfilename
685 self.flagIsNewFile = 1
686 self.flagIsNewFile = 1
686 if self.fp != None:
687 if self.fp != None:
687 self.fp.close()
688 self.fp.close()
688 #print(fullfilename)
689 #print(fullfilename)
689 self.fp = self.open_file(fullfilename, self.open_mode)
690 self.fp = self.open_file(fullfilename, self.open_mode)
690
691
691 self.flagNoMoreFiles = 0
692 self.flagNoMoreFiles = 0
692 self.fileIndex += 1
693 self.fileIndex += 1
693 return 1
694 return 1
694 else:
695 else:
695 return 0
696 return 0
696
697
697 def setNextFileOffline(self):
698 def setNextFileOffline(self):
698 """Open the next file to be readed in offline mode"""
699 """Open the next file to be readed in offline mode"""
699
700
700 try:
701 try:
701 filename = next(self.filenameList)
702 filename = next(self.filenameList)
702 self.fileIndex +=1
703 self.fileIndex +=1
703 except StopIteration:
704 except StopIteration:
704 self.flagNoMoreFiles = 1
705 self.flagNoMoreFiles = 1
705 return 0
706 return 0
706 #print(self.fileIndex)
707 #print(self.fileIndex)
707 #print(filename)
708 #print(filename)
708 self.filename = filename
709 self.filename = filename
709 self.fileSize = os.path.getsize(filename)
710 self.fileSize = os.path.getsize(filename)
710 self.fp = self.open_file(filename, self.open_mode)
711 self.fp = self.open_file(filename, self.open_mode)
711 self.flagIsNewFile = 1
712 self.flagIsNewFile = 1
712
713
713 return 1
714 return 1
714
715
715 @staticmethod
716 @staticmethod
716 def isDateTimeInRange(dt, startDate, endDate, startTime, endTime):
717 def isDateTimeInRange(dt, startDate, endDate, startTime, endTime):
717 """Check if the given datetime is in range"""
718 """Check if the given datetime is in range"""
718
719
719 if startDate <= dt.date() <= endDate:
720 if startDate <= dt.date() <= endDate:
720 if startTime <= dt.time() <= endTime:
721 if startTime <= dt.time() <= endTime:
721 return True
722 return True
722 return False
723 return False
723
724
724 def verifyFile(self, filename):
725 def verifyFile(self, filename):
725 """Check for a valid file
726 """Check for a valid file
726
727
727 Arguments:
728 Arguments:
728 filename -- full path filename
729 filename -- full path filename
729
730
730 Return:
731 Return:
731 boolean
732 boolean
732 """
733 """
733
734
734 return True
735 return True
735
736
736 def checkForRealPath(self, nextFile, nextDay):
737 def checkForRealPath(self, nextFile, nextDay):
737 """Check if the next file to be readed exists"""
738 """Check if the next file to be readed exists"""
738
739
739 raise NotImplementedError
740 raise NotImplementedError
740
741
741 def readFirstHeader(self):
742 def readFirstHeader(self):
742 """Parse the file header"""
743 """Parse the file header"""
743
744
744
745
745 pass
746 pass
746
747
747 def waitDataBlock(self, pointer_location, blocksize=None):
748 def waitDataBlock(self, pointer_location, blocksize=None):
748 """
749 """
749 """
750 """
750
751
751 currentPointer = pointer_location
752 currentPointer = pointer_location
752 if blocksize is None:
753 if blocksize is None:
753 neededSize = self.processingHeaderObj.blockSize # + self.basicHeaderSize
754 neededSize = self.processingHeaderObj.blockSize # + self.basicHeaderSize
754 else:
755 else:
755 neededSize = blocksize
756 neededSize = blocksize
756
757
757 for nTries in range(self.nTries):
758 for nTries in range(self.nTries):
758 self.fp.close()
759 self.fp.close()
759 self.fp = open(self.filename, 'rb')
760 self.fp = open(self.filename, 'rb')
760 self.fp.seek(currentPointer)
761 self.fp.seek(currentPointer)
761
762
762 self.fileSize = os.path.getsize(self.filename)
763 self.fileSize = os.path.getsize(self.filename)
763 currentSize = self.fileSize - currentPointer
764 currentSize = self.fileSize - currentPointer
764
765
765 if (currentSize >= neededSize):
766 if (currentSize >= neededSize):
766 return 1
767 return 1
767
768
768 log.warning(
769 log.warning(
769 "Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1),
770 "Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1),
770 self.name
771 self.name
771 )
772 )
772 time.sleep(self.delay)
773 time.sleep(self.delay)
773
774
774 return 0
775 return 0
775
776
776 class JRODataReader(Reader):
777 class JRODataReader(Reader):
777
778
778 utc = 0
779 utc = 0
779 nReadBlocks = 0
780 nReadBlocks = 0
780 foldercounter = 0
781 foldercounter = 0
781 firstHeaderSize = 0
782 firstHeaderSize = 0
782 basicHeaderSize = 24
783 basicHeaderSize = 24
783 __isFirstTimeOnline = 1
784 __isFirstTimeOnline = 1
785 topic = ''
784 filefmt = "*%Y%j***"
786 filefmt = "*%Y%j***"
785 folderfmt = "*%Y%j"
787 folderfmt = "*%Y%j"
786 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'online', 'delay', 'walk']
788 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'online', 'delay', 'walk']
787
789
788 def getDtypeWidth(self):
790 def getDtypeWidth(self):
789
791
790 dtype_index = get_dtype_index(self.dtype)
792 dtype_index = get_dtype_index(self.dtype)
791 dtype_width = get_dtype_width(dtype_index)
793 dtype_width = get_dtype_width(dtype_index)
792
794
793 return dtype_width
795 return dtype_width
794
796
795 def checkForRealPath(self, nextFile, nextDay):
797 def checkForRealPath(self, nextFile, nextDay):
796 """Check if the next file to be readed exists.
798 """Check if the next file to be readed exists.
797
799
798 Example :
800 Example :
799 nombre correcto del file es .../.../D2009307/P2009307367.ext
801 nombre correcto del file es .../.../D2009307/P2009307367.ext
800
802
801 Entonces la funcion prueba con las siguientes combinaciones
803 Entonces la funcion prueba con las siguientes combinaciones
802 .../.../y2009307367.ext
804 .../.../y2009307367.ext
803 .../.../Y2009307367.ext
805 .../.../Y2009307367.ext
804 .../.../x2009307/y2009307367.ext
806 .../.../x2009307/y2009307367.ext
805 .../.../x2009307/Y2009307367.ext
807 .../.../x2009307/Y2009307367.ext
806 .../.../X2009307/y2009307367.ext
808 .../.../X2009307/y2009307367.ext
807 .../.../X2009307/Y2009307367.ext
809 .../.../X2009307/Y2009307367.ext
808 siendo para este caso, la ultima combinacion de letras, identica al file buscado
810 siendo para este caso, la ultima combinacion de letras, identica al file buscado
809
811
810 Return:
812 Return:
811 str -- fullpath of the file
813 str -- fullpath of the file
812 """
814 """
813
815
814
816
815 if nextFile:
817 if nextFile:
816 self.set += 1
818 self.set += 1
817 if nextDay:
819 if nextDay:
818 self.set = 0
820 self.set = 0
819 self.doy += 1
821 self.doy += 1
820 foldercounter = 0
822 foldercounter = 0
821 prefixDirList = [None, 'd', 'D']
823 prefixDirList = [None, 'd', 'D']
822 if self.ext.lower() == ".r": # voltage
824 if self.ext.lower() == ".r": # voltage
823 prefixFileList = ['d', 'D']
825 prefixFileList = ['d', 'D']
824 elif self.ext.lower() == ".pdata": # spectra
826 elif self.ext.lower() == ".pdata": # spectra
825 prefixFileList = ['p', 'P']
827 prefixFileList = ['p', 'P']
826
828
827 ##############DP##############
829 ##############DP##############
828
830
829 elif self.ext.lower() == ".dat": # dat
831 elif self.ext.lower() == ".dat": # dat
830 prefixFileList = ['z', 'Z']
832 prefixFileList = ['z', 'Z']
831
833
832
834
833
835
834 ##############DP##############
836 ##############DP##############
835 # barrido por las combinaciones posibles
837 # barrido por las combinaciones posibles
836 for prefixDir in prefixDirList:
838 for prefixDir in prefixDirList:
837 thispath = self.path
839 thispath = self.path
838 if prefixDir != None:
840 if prefixDir != None:
839 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
841 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
840 if foldercounter == 0:
842 if foldercounter == 0:
841 thispath = os.path.join(self.path, "%s%04d%03d" %
843 thispath = os.path.join(self.path, "%s%04d%03d" %
842 (prefixDir, self.year, self.doy))
844 (prefixDir, self.year, self.doy))
843 else:
845 else:
844 thispath = os.path.join(self.path, "%s%04d%03d_%02d" % (
846 thispath = os.path.join(self.path, "%s%04d%03d_%02d" % (
845 prefixDir, self.year, self.doy, foldercounter))
847 prefixDir, self.year, self.doy, foldercounter))
846 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
848 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
847 # formo el nombre del file xYYYYDDDSSS.ext
849 # formo el nombre del file xYYYYDDDSSS.ext
848 filename = "%s%04d%03d%03d%s" % (prefixFile, self.year, self.doy, self.set, self.ext)
850 filename = "%s%04d%03d%03d%s" % (prefixFile, self.year, self.doy, self.set, self.ext)
849 fullfilename = os.path.join(
851 fullfilename = os.path.join(
850 thispath, filename)
852 thispath, filename)
851
853
852 if os.path.exists(fullfilename):
854 if os.path.exists(fullfilename):
853 return fullfilename, filename
855 return fullfilename, filename
854
856
855 return None, filename
857 return None, filename
856
858
857 def __waitNewBlock(self):
859 def __waitNewBlock(self):
858 """
860 """
859 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
861 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
860
862
861 Si el modo de lectura es OffLine siempre retorn 0
863 Si el modo de lectura es OffLine siempre retorn 0
862 """
864 """
863 if not self.online:
865 if not self.online:
864 return 0
866 return 0
865
867
866 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
868 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
867 return 0
869 return 0
868
870
869 currentPointer = self.fp.tell()
871 currentPointer = self.fp.tell()
870
872
871 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
873 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
872
874
873 for nTries in range(self.nTries):
875 for nTries in range(self.nTries):
874
876
875 self.fp.close()
877 self.fp.close()
876 self.fp = open(self.filename, 'rb')
878 self.fp = open(self.filename, 'rb')
877 self.fp.seek(currentPointer)
879 self.fp.seek(currentPointer)
878
880
879 self.fileSize = os.path.getsize(self.filename)
881 self.fileSize = os.path.getsize(self.filename)
880 currentSize = self.fileSize - currentPointer
882 currentSize = self.fileSize - currentPointer
881
883
882 if (currentSize >= neededSize):
884 if (currentSize >= neededSize):
883 self.basicHeaderObj.read(self.fp)
885 self.basicHeaderObj.read(self.fp)
884 return 1
886 return 1
885
887
886 if self.fileSize == self.fileSizeByHeader:
888 if self.fileSize == self.fileSizeByHeader:
887 # self.flagEoF = True
889 # self.flagEoF = True
888 return 0
890 return 0
889
891
890 print("[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1))
892 print("[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1))
891 #print(self.filename)
893 #print(self.filename)
892 time.sleep(self.delay)
894 time.sleep(self.delay)
893
895
894 return 0
896 return 0
895
897
896 def __setNewBlock(self):
898 def __setNewBlock(self):
897
899
898 if self.fp == None:
900 if self.fp == None:
899 return 0
901 return 0
900
902
901 if self.flagIsNewFile:
903 if self.flagIsNewFile:
902 self.lastUTTime = self.basicHeaderObj.utc
904 self.lastUTTime = self.basicHeaderObj.utc
903 return 1
905 return 1
904
906
905 if self.realtime:
907 if self.realtime:
906 self.flagDiscontinuousBlock = 1
908 self.flagDiscontinuousBlock = 1
907 if not(self.setNextFile()):
909 if not(self.setNextFile()):
908 return 0
910 return 0
909 else:
911 else:
910 return 1
912 return 1
911
913
912 currentSize = self.fileSize - self.fp.tell()
914 currentSize = self.fileSize - self.fp.tell()
913 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
915 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
914
916
915 if (currentSize >= neededSize):
917 if (currentSize >= neededSize):
916 self.basicHeaderObj.read(self.fp)
918 self.basicHeaderObj.read(self.fp)
917 self.lastUTTime = self.basicHeaderObj.utc
919 self.lastUTTime = self.basicHeaderObj.utc
918 return 1
920 return 1
919
921
920 if self.__waitNewBlock():
922 if self.__waitNewBlock():
921 self.lastUTTime = self.basicHeaderObj.utc
923 self.lastUTTime = self.basicHeaderObj.utc
922 return 1
924 return 1
923
925
924 if not(self.setNextFile()):
926 if not(self.setNextFile()):
925 return 0
927 return 0
926
928
927 deltaTime = self.basicHeaderObj.utc - self.lastUTTime
929 deltaTime = self.basicHeaderObj.utc - self.lastUTTime
928 self.lastUTTime = self.basicHeaderObj.utc
930 self.lastUTTime = self.basicHeaderObj.utc
929
931
930 self.flagDiscontinuousBlock = 0
932 self.flagDiscontinuousBlock = 0
931 if deltaTime > self.maxTimeStep:
933 if deltaTime > self.maxTimeStep:
932 self.flagDiscontinuousBlock = 1
934 self.flagDiscontinuousBlock = 1
933
935
934 return 1
936 return 1
935
937
936 def readNextBlock(self):
938 def readNextBlock(self):
937
939
938 while True:
940 while True:
939 if not(self.__setNewBlock()):
941 if not(self.__setNewBlock()):
940 continue
942 continue
941
943
942 if not(self.readBlock()):
944 if not(self.readBlock()):
943 return 0
945 return 0
944
946
945 self.getBasicHeader()
947 self.getBasicHeader()
946
948
947 if not self.isDateTimeInRange(self.dataOut.datatime, self.startDate, self.endDate, self.startTime, self.endTime):
949 if not self.isDateTimeInRange(self.dataOut.datatime, self.startDate, self.endDate, self.startTime, self.endTime):
948 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.nReadBlocks,
950 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.nReadBlocks,
949 self.processingHeaderObj.dataBlocksPerFile,
951 self.processingHeaderObj.dataBlocksPerFile,
950 self.dataOut.datatime.ctime()))
952 self.dataOut.datatime.ctime()))
951 continue
953 continue
952
954
953 break
955 break
954
956
955 if self.verbose:
957 if self.verbose:
956 print("[Reading] Block No. %d/%d -> %s" % (self.nReadBlocks,
958 print("[Reading] Block No. %d/%d -> %s" % (self.nReadBlocks,
957 self.processingHeaderObj.dataBlocksPerFile,
959 self.processingHeaderObj.dataBlocksPerFile,
958 self.dataOut.datatime.ctime()))
960 self.dataOut.datatime.ctime()))
959 #################DP#################
961 #################DP#################
960 self.dataOut.TimeBlockDate=self.dataOut.datatime.ctime()
962 self.dataOut.TimeBlockDate=self.dataOut.datatime.ctime()
961 self.dataOut.TimeBlockSeconds=time.mktime(time.strptime(self.dataOut.datatime.ctime()))
963 self.dataOut.TimeBlockSeconds=time.mktime(time.strptime(self.dataOut.datatime.ctime()))
962 #################DP#################
964 #################DP#################
963 return 1
965 return 1
964
966
965 def readFirstHeader(self):
967 def readFirstHeader(self):
966
968
967 self.basicHeaderObj.read(self.fp)
969 self.basicHeaderObj.read(self.fp)
968 self.systemHeaderObj.read(self.fp)
970 self.systemHeaderObj.read(self.fp)
969 self.radarControllerHeaderObj.read(self.fp)
971 self.radarControllerHeaderObj.read(self.fp)
970 self.processingHeaderObj.read(self.fp)
972 self.processingHeaderObj.read(self.fp)
971 self.firstHeaderSize = self.basicHeaderObj.size
973 self.firstHeaderSize = self.basicHeaderObj.size
972
974
973 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
975 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
974 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
976 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
975 if datatype == 0:
977 if datatype == 0:
976 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
978 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
977 elif datatype == 1:
979 elif datatype == 1:
978 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
980 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
979 elif datatype == 2:
981 elif datatype == 2:
980 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
982 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
981 elif datatype == 3:
983 elif datatype == 3:
982 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
984 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
983 elif datatype == 4:
985 elif datatype == 4:
984 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
986 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
985 elif datatype == 5:
987 elif datatype == 5:
986 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
988 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
987 else:
989 else:
988 raise ValueError('Data type was not defined')
990 raise ValueError('Data type was not defined')
989
991
990 self.dtype = datatype_str
992 self.dtype = datatype_str
991 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
993 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
992 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
994 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
993 self.firstHeaderSize + self.basicHeaderSize * \
995 self.firstHeaderSize + self.basicHeaderSize * \
994 (self.processingHeaderObj.dataBlocksPerFile - 1)
996 (self.processingHeaderObj.dataBlocksPerFile - 1)
995 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
997 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
996 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
998 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
997 self.getBlockDimension()
999 self.getBlockDimension()
998
1000
999 def verifyFile(self, filename):
1001 def verifyFile(self, filename):
1000
1002
1001 flag = True
1003 flag = True
1002
1004
1003 try:
1005 try:
1004 fp = open(filename, 'rb')
1006 fp = open(filename, 'rb')
1005 except IOError:
1007 except IOError:
1006 log.error("File {} can't be opened".format(filename), self.name)
1008 log.error("File {} can't be opened".format(filename), self.name)
1007 return False
1009 return False
1008
1010
1009 if self.online and self.waitDataBlock(0):
1011 if self.online and self.waitDataBlock(0):
1010 pass
1012 pass
1011
1013
1012 basicHeaderObj = BasicHeader(LOCALTIME)
1014 basicHeaderObj = BasicHeader(LOCALTIME)
1013 systemHeaderObj = SystemHeader()
1015 systemHeaderObj = SystemHeader()
1014 radarControllerHeaderObj = RadarControllerHeader()
1016 radarControllerHeaderObj = RadarControllerHeader()
1015 processingHeaderObj = ProcessingHeader()
1017 processingHeaderObj = ProcessingHeader()
1016
1018
1017 if not(basicHeaderObj.read(fp)):
1019 if not(basicHeaderObj.read(fp)):
1018 flag = False
1020 flag = False
1019 if not(systemHeaderObj.read(fp)):
1021 if not(systemHeaderObj.read(fp)):
1020 flag = False
1022 flag = False
1021 if not(radarControllerHeaderObj.read(fp)):
1023 if not(radarControllerHeaderObj.read(fp)):
1022 flag = False
1024 flag = False
1023 if not(processingHeaderObj.read(fp)):
1025 if not(processingHeaderObj.read(fp)):
1024 flag = False
1026 flag = False
1025 if not self.online:
1027 if not self.online:
1026 dt1 = basicHeaderObj.datatime
1028 dt1 = basicHeaderObj.datatime
1027 pos = self.fileSize-processingHeaderObj.blockSize-24
1029 pos = self.fileSize-processingHeaderObj.blockSize-24
1028 if pos<0:
1030 if pos<0:
1029 flag = False
1031 flag = False
1030 log.error('Invalid size for file: {}'.format(self.filename), self.name)
1032 log.error('Invalid size for file: {}'.format(self.filename), self.name)
1031 else:
1033 else:
1032 fp.seek(pos)
1034 fp.seek(pos)
1033 if not(basicHeaderObj.read(fp)):
1035 if not(basicHeaderObj.read(fp)):
1034 flag = False
1036 flag = False
1035 dt2 = basicHeaderObj.datatime
1037 dt2 = basicHeaderObj.datatime
1036 if not self.isDateTimeInRange(dt1, self.startDate, self.endDate, self.startTime, self.endTime) and not \
1038 if not self.isDateTimeInRange(dt1, self.startDate, self.endDate, self.startTime, self.endTime) and not \
1037 self.isDateTimeInRange(dt2, self.startDate, self.endDate, self.startTime, self.endTime):
1039 self.isDateTimeInRange(dt2, self.startDate, self.endDate, self.startTime, self.endTime):
1038 flag = False
1040 flag = False
1039
1041
1040 fp.close()
1042 fp.close()
1041 return flag
1043 return flag
1042
1044
1043 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1045 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1044
1046
1045 path_empty = True
1047 path_empty = True
1046
1048
1047 dateList = []
1049 dateList = []
1048 pathList = []
1050 pathList = []
1049
1051
1050 multi_path = path.split(',')
1052 multi_path = path.split(',')
1051
1053
1052 if not walk:
1054 if not walk:
1053
1055
1054 for single_path in multi_path:
1056 for single_path in multi_path:
1055
1057
1056 if not os.path.isdir(single_path):
1058 if not os.path.isdir(single_path):
1057 continue
1059 continue
1058
1060
1059 fileList = glob.glob1(single_path, "*" + ext)
1061 fileList = glob.glob1(single_path, "*" + ext)
1060
1062
1061 if not fileList:
1063 if not fileList:
1062 continue
1064 continue
1063
1065
1064 path_empty = False
1066 path_empty = False
1065
1067
1066 fileList.sort()
1068 fileList.sort()
1067
1069
1068 for thisFile in fileList:
1070 for thisFile in fileList:
1069
1071
1070 if not os.path.isfile(os.path.join(single_path, thisFile)):
1072 if not os.path.isfile(os.path.join(single_path, thisFile)):
1071 continue
1073 continue
1072
1074
1073 if not isRadarFile(thisFile):
1075 if not isRadarFile(thisFile):
1074 continue
1076 continue
1075
1077
1076 if not isFileInDateRange(thisFile, startDate, endDate):
1078 if not isFileInDateRange(thisFile, startDate, endDate):
1077 continue
1079 continue
1078
1080
1079 thisDate = getDateFromRadarFile(thisFile)
1081 thisDate = getDateFromRadarFile(thisFile)
1080
1082
1081 if thisDate in dateList or single_path in pathList:
1083 if thisDate in dateList or single_path in pathList:
1082 continue
1084 continue
1083
1085
1084 dateList.append(thisDate)
1086 dateList.append(thisDate)
1085 pathList.append(single_path)
1087 pathList.append(single_path)
1086
1088
1087 else:
1089 else:
1088 for single_path in multi_path:
1090 for single_path in multi_path:
1089
1091
1090 if not os.path.isdir(single_path):
1092 if not os.path.isdir(single_path):
1091 continue
1093 continue
1092
1094
1093 dirList = []
1095 dirList = []
1094
1096
1095 for thisPath in os.listdir(single_path):
1097 for thisPath in os.listdir(single_path):
1096
1098
1097 if not os.path.isdir(os.path.join(single_path, thisPath)):
1099 if not os.path.isdir(os.path.join(single_path, thisPath)):
1098 continue
1100 continue
1099
1101
1100 if not isRadarFolder(thisPath):
1102 if not isRadarFolder(thisPath):
1101 continue
1103 continue
1102
1104
1103 if not isFolderInDateRange(thisPath, startDate, endDate):
1105 if not isFolderInDateRange(thisPath, startDate, endDate):
1104 continue
1106 continue
1105
1107
1106 dirList.append(thisPath)
1108 dirList.append(thisPath)
1107
1109
1108 if not dirList:
1110 if not dirList:
1109 continue
1111 continue
1110
1112
1111 dirList.sort()
1113 dirList.sort()
1112
1114
1113 for thisDir in dirList:
1115 for thisDir in dirList:
1114
1116
1115 datapath = os.path.join(single_path, thisDir, expLabel)
1117 datapath = os.path.join(single_path, thisDir, expLabel)
1116 fileList = glob.glob1(datapath, "*" + ext)
1118 fileList = glob.glob1(datapath, "*" + ext)
1117
1119
1118 if not fileList:
1120 if not fileList:
1119 continue
1121 continue
1120
1122
1121 path_empty = False
1123 path_empty = False
1122
1124
1123 thisDate = getDateFromRadarFolder(thisDir)
1125 thisDate = getDateFromRadarFolder(thisDir)
1124
1126
1125 pathList.append(datapath)
1127 pathList.append(datapath)
1126 dateList.append(thisDate)
1128 dateList.append(thisDate)
1127
1129
1128 dateList.sort()
1130 dateList.sort()
1129
1131
1130 if walk:
1132 if walk:
1131 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1133 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1132 else:
1134 else:
1133 pattern_path = multi_path[0]
1135 pattern_path = multi_path[0]
1134
1136
1135 if path_empty:
1137 if path_empty:
1136 raise schainpy.admin.SchainError("[Reading] No *%s files in %s for %s to %s" % (ext, pattern_path, startDate, endDate))
1138 raise schainpy.admin.SchainError("[Reading] No *%s files in %s for %s to %s" % (ext, pattern_path, startDate, endDate))
1137 else:
1139 else:
1138 if not dateList:
1140 if not dateList:
1139 raise schainpy.admin.SchainError("[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" % (startDate, endDate, ext, path))
1141 raise schainpy.admin.SchainError("[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" % (startDate, endDate, ext, path))
1140
1142
1141 if include_path:
1143 if include_path:
1142 return dateList, pathList
1144 return dateList, pathList
1143
1145
1144 return dateList
1146 return dateList
1145
1147
1146 def setup(self, **kwargs):
1148 def setup(self, **kwargs):
1147
1149
1148 self.set_kwargs(**kwargs)
1150 self.set_kwargs(**kwargs)
1149 if not self.ext.startswith('.'):
1151 if not self.ext.startswith('.'):
1150 self.ext = '.{}'.format(self.ext)
1152 self.ext = '.{}'.format(self.ext)
1151
1153
1152 if self.server is not None:
1154 if self.server is not None:
1153 if 'tcp://' in self.server:
1155 if 'tcp://' in self.server:
1154 address = server
1156 address = self.server
1155 else:
1157 else:
1156 address = 'ipc:///tmp/%s' % self.server
1158 address = 'ipc:///tmp/%s' % self.server
1157 self.server = address
1159 self.server = address
1158 self.context = zmq.Context()
1160 self.context = zmq.Context()
1159 self.receiver = self.context.socket(zmq.PULL)
1161 self.receiver = self.context.socket(zmq.SUB)
1160 self.receiver.connect(self.server)
1162 self.receiver.connect(self.server)
1163 self.receiver.setsockopt(zmq.SUBSCRIBE, str.encode(str(self.topic)))
1161 time.sleep(0.5)
1164 time.sleep(0.5)
1162 print('[Starting] ReceiverData from {}'.format(self.server))
1165 print('[Starting] ReceiverData from {}'.format(self.server))
1163 else:
1166 else:
1164 self.server = None
1167 self.server = None
1165 if self.path == None:
1168 if self.path == None:
1166 raise ValueError("[Reading] The path is not valid")
1169 raise ValueError("[Reading] The path is not valid")
1167
1170
1168 if self.online:
1171 if self.online:
1169 log.log("[Reading] Searching files in online mode...", self.name)
1172 log.log("[Reading] Searching files in online mode...", self.name)
1170
1173
1171 for nTries in range(self.nTries):
1174 for nTries in range(self.nTries):
1172 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1175 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1173 self.endDate, self.expLabel, self.ext, self.walk,
1176 self.endDate, self.expLabel, self.ext, self.walk,
1174 self.filefmt, self.folderfmt)
1177 self.filefmt, self.folderfmt)
1175
1178
1176 try:
1179 try:
1177 fullpath = next(fullpath)
1180 fullpath = next(fullpath)
1178 except:
1181 except:
1179 fullpath = None
1182 fullpath = None
1180
1183
1181 if fullpath:
1184 if fullpath:
1182 break
1185 break
1183
1186
1184 log.warning(
1187 log.warning(
1185 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1188 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1186 self.delay, self.path, nTries + 1),
1189 self.delay, self.path, nTries + 1),
1187 self.name)
1190 self.name)
1188 time.sleep(self.delay)
1191 time.sleep(self.delay)
1189
1192
1190 if not(fullpath):
1193 if not(fullpath):
1191 raise schainpy.admin.SchainError(
1194 raise schainpy.admin.SchainError(
1192 'There isn\'t any valid file in {}'.format(self.path))
1195 'There isn\'t any valid file in {}'.format(self.path))
1193
1196
1194 pathname, filename = os.path.split(fullpath)
1197 pathname, filename = os.path.split(fullpath)
1195 self.year = int(filename[1:5])
1198 self.year = int(filename[1:5])
1196 self.doy = int(filename[5:8])
1199 self.doy = int(filename[5:8])
1197 self.set = int(filename[8:11]) - 1
1200 self.set = int(filename[8:11]) - 1
1198 else:
1201 else:
1199 log.log("Searching files in {}".format(self.path), self.name)
1202 log.log("Searching files in {}".format(self.path), self.name)
1200 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1203 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1201 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1204 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1202
1205
1203 self.setNextFile()
1206 self.setNextFile()
1204
1207
1205 return
1208 return
1206
1209
1207 def getBasicHeader(self):
1210 def getBasicHeader(self):
1208
1211
1209 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond / \
1212 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond / \
1210 1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1213 1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1211
1214
1212 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1215 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1213
1216
1214 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1217 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1215
1218
1216 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1219 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1217
1220
1218 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1221 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1219
1222
1220 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1223 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1221
1224
1222 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
1225 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
1223
1226
1224 def getFirstHeader(self):
1227 def getFirstHeader(self):
1225
1228
1226 raise NotImplementedError
1229 raise NotImplementedError
1227
1230
1228 def getData(self):
1231 def getData(self):
1229
1232
1230 raise NotImplementedError
1233 raise NotImplementedError
1231
1234
1232 def hasNotDataInBuffer(self):
1235 def hasNotDataInBuffer(self):
1233
1236
1234 raise NotImplementedError
1237 raise NotImplementedError
1235
1238
1236 def readBlock(self):
1239 def readBlock(self):
1237
1240
1238 raise NotImplementedError
1241 raise NotImplementedError
1239
1242
1240 def isEndProcess(self):
1243 def isEndProcess(self):
1241
1244
1242 return self.flagNoMoreFiles
1245 return self.flagNoMoreFiles
1243
1246
1244 def printReadBlocks(self):
1247 def printReadBlocks(self):
1245
1248
1246 print("[Reading] Number of read blocks per file %04d" % self.nReadBlocks)
1249 print("[Reading] Number of read blocks per file %04d" % self.nReadBlocks)
1247
1250
1248 def printTotalBlocks(self):
1251 def printTotalBlocks(self):
1249
1252
1250 print("[Reading] Number of read blocks %04d" % self.nTotalBlocks)
1253 print("[Reading] Number of read blocks %04d" % self.nTotalBlocks)
1251
1254
1252 def run(self, **kwargs):
1255 def run(self, **kwargs):
1253 """
1256 """
1254
1257
1255 Arguments:
1258 Arguments:
1256 path :
1259 path :
1257 startDate :
1260 startDate :
1258 endDate :
1261 endDate :
1259 startTime :
1262 startTime :
1260 endTime :
1263 endTime :
1261 set :
1264 set :
1262 expLabel :
1265 expLabel :
1263 ext :
1266 ext :
1264 online :
1267 online :
1265 delay :
1268 delay :
1266 walk :
1269 walk :
1267 getblock :
1270 getblock :
1268 nTxs :
1271 nTxs :
1269 realtime :
1272 realtime :
1270 blocksize :
1273 blocksize :
1271 blocktime :
1274 blocktime :
1272 skip :
1275 skip :
1273 cursor :
1276 cursor :
1274 warnings :
1277 warnings :
1275 server :
1278 server :
1276 verbose :
1279 verbose :
1277 format :
1280 format :
1278 oneDDict :
1281 oneDDict :
1279 twoDDict :
1282 twoDDict :
1280 independentParam :
1283 independentParam :
1281 """
1284 """
1282
1285
1283 if not(self.isConfig):
1286 if not(self.isConfig):
1284 self.setup(**kwargs)
1287 self.setup(**kwargs)
1285 self.isConfig = True
1288 self.isConfig = True
1286 if self.server is None:
1289 if self.server is None:
1287 self.getData()
1290 self.getData()
1288 else:
1291 else:
1289 self.getFromServer()
1292 try:
1293 self.getFromServer()
1294 except Exception as e:
1295 log.warning('Invalid block...')
1296 self.dataOut.flagNoData = True
1290
1297
1291
1298
1292 class JRODataWriter(Reader):
1299 class JRODataWriter(Reader):
1293
1300
1294 """
1301 """
1295 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1302 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1296 de los datos siempre se realiza por bloques.
1303 de los datos siempre se realiza por bloques.
1297 """
1304 """
1298
1305
1299 setFile = None
1306 setFile = None
1300 profilesPerBlock = None
1307 profilesPerBlock = None
1301 blocksPerFile = None
1308 blocksPerFile = None
1302 nWriteBlocks = 0
1309 nWriteBlocks = 0
1303 fileDate = None
1310 fileDate = None
1304
1311
1305 def __init__(self, dataOut=None):
1312 def __init__(self, dataOut=None):
1306 raise NotImplementedError
1313 raise NotImplementedError
1307
1314
1308 def hasAllDataInBuffer(self):
1315 def hasAllDataInBuffer(self):
1309 raise NotImplementedError
1316 raise NotImplementedError
1310
1317
1311 def setBlockDimension(self):
1318 def setBlockDimension(self):
1312 raise NotImplementedError
1319 raise NotImplementedError
1313
1320
1314 def writeBlock(self):
1321 def writeBlock(self):
1315 raise NotImplementedError
1322 raise NotImplementedError
1316
1323
1317 def putData(self):
1324 def putData(self):
1318 raise NotImplementedError
1325 raise NotImplementedError
1319
1326
1320 def getDtypeWidth(self):
1327 def getDtypeWidth(self):
1321
1328
1322 dtype_index = get_dtype_index(self.dtype)
1329 dtype_index = get_dtype_index(self.dtype)
1323 dtype_width = get_dtype_width(dtype_index)
1330 dtype_width = get_dtype_width(dtype_index)
1324
1331
1325 return dtype_width
1332 return dtype_width
1326
1333
1327 def getProcessFlags(self):
1334 def getProcessFlags(self):
1328
1335
1329 processFlags = 0
1336 processFlags = 0
1330
1337
1331 dtype_index = get_dtype_index(self.dtype)
1338 dtype_index = get_dtype_index(self.dtype)
1332 procflag_dtype = get_procflag_dtype(dtype_index)
1339 procflag_dtype = get_procflag_dtype(dtype_index)
1333
1340
1334 processFlags += procflag_dtype
1341 processFlags += procflag_dtype
1335
1342
1336 if self.dataOut.flagDecodeData:
1343 if self.dataOut.flagDecodeData:
1337 processFlags += PROCFLAG.DECODE_DATA
1344 processFlags += PROCFLAG.DECODE_DATA
1338
1345
1339 if self.dataOut.flagDeflipData:
1346 if self.dataOut.flagDeflipData:
1340 processFlags += PROCFLAG.DEFLIP_DATA
1347 processFlags += PROCFLAG.DEFLIP_DATA
1341
1348
1342 if self.dataOut.code is not None:
1349 if self.dataOut.code is not None:
1343 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1350 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1344
1351
1345 if self.dataOut.nCohInt > 1:
1352 if self.dataOut.nCohInt > 1:
1346 processFlags += PROCFLAG.COHERENT_INTEGRATION
1353 processFlags += PROCFLAG.COHERENT_INTEGRATION
1347
1354
1348 if self.dataOut.type == "Spectra":
1355 if self.dataOut.type == "Spectra":
1349 if self.dataOut.nIncohInt > 1:
1356 if self.dataOut.nIncohInt > 1:
1350 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1357 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1351
1358
1352 if self.dataOut.data_dc is not None:
1359 if self.dataOut.data_dc is not None:
1353 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1360 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1354
1361
1355 if self.dataOut.flagShiftFFT:
1362 if self.dataOut.flagShiftFFT:
1356 processFlags += PROCFLAG.SHIFT_FFT_DATA
1363 processFlags += PROCFLAG.SHIFT_FFT_DATA
1357
1364
1358 return processFlags
1365 return processFlags
1359
1366
1360 def setBasicHeader(self):
1367 def setBasicHeader(self):
1361
1368
1362 self.basicHeaderObj.size = self.basicHeaderSize # bytes
1369 self.basicHeaderObj.size = self.basicHeaderSize # bytes
1363 self.basicHeaderObj.version = self.versionFile
1370 self.basicHeaderObj.version = self.versionFile
1364 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1371 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1365 utc = numpy.floor(self.dataOut.utctime)
1372 utc = numpy.floor(self.dataOut.utctime)
1366 milisecond = (self.dataOut.utctime - utc) * 1000.0
1373 milisecond = (self.dataOut.utctime - utc) * 1000.0
1367 self.basicHeaderObj.utc = utc
1374 self.basicHeaderObj.utc = utc
1368 self.basicHeaderObj.miliSecond = milisecond
1375 self.basicHeaderObj.miliSecond = milisecond
1369 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1376 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1370 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1377 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1371 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1378 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1372
1379
1373 def setFirstHeader(self):
1380 def setFirstHeader(self):
1374 """
1381 """
1375 Obtiene una copia del First Header
1382 Obtiene una copia del First Header
1376
1383
1377 Affected:
1384 Affected:
1378
1385
1379 self.basicHeaderObj
1386 self.basicHeaderObj
1380 self.systemHeaderObj
1387 self.systemHeaderObj
1381 self.radarControllerHeaderObj
1388 self.radarControllerHeaderObj
1382 self.processingHeaderObj self.
1389 self.processingHeaderObj self.
1383
1390
1384 Return:
1391 Return:
1385 None
1392 None
1386 """
1393 """
1387
1394
1388 raise NotImplementedError
1395 raise NotImplementedError
1389
1396
1390 def __writeFirstHeader(self):
1397 def __writeFirstHeader(self):
1391 """
1398 """
1392 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1399 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1393
1400
1394 Affected:
1401 Affected:
1395 __dataType
1402 __dataType
1396
1403
1397 Return:
1404 Return:
1398 None
1405 None
1399 """
1406 """
1400
1407
1401 # CALCULAR PARAMETROS
1408 # CALCULAR PARAMETROS
1402
1409
1403 sizeLongHeader = self.systemHeaderObj.size + \
1410 sizeLongHeader = self.systemHeaderObj.size + \
1404 self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1411 self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1405 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1412 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1406
1413
1407 self.basicHeaderObj.write(self.fp)
1414 self.basicHeaderObj.write(self.fp)
1408 self.systemHeaderObj.write(self.fp)
1415 self.systemHeaderObj.write(self.fp)
1409 self.radarControllerHeaderObj.write(self.fp)
1416 self.radarControllerHeaderObj.write(self.fp)
1410 self.processingHeaderObj.write(self.fp)
1417 self.processingHeaderObj.write(self.fp)
1411
1418
1412 def __setNewBlock(self):
1419 def __setNewBlock(self):
1413 """
1420 """
1414 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1421 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1415
1422
1416 Return:
1423 Return:
1417 0 : si no pudo escribir nada
1424 0 : si no pudo escribir nada
1418 1 : Si escribio el Basic el First Header
1425 1 : Si escribio el Basic el First Header
1419 """
1426 """
1420 if self.fp == None:
1427 if self.fp == None:
1421 self.setNextFile()
1428 self.setNextFile()
1422
1429
1423 if self.flagIsNewFile:
1430 if self.flagIsNewFile:
1424 return 1
1431 return 1
1425
1432
1426 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1433 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1427 self.basicHeaderObj.write(self.fp)
1434 self.basicHeaderObj.write(self.fp)
1428 return 1
1435 return 1
1429
1436
1430 if not(self.setNextFile()):
1437 if not(self.setNextFile()):
1431 return 0
1438 return 0
1432
1439
1433 return 1
1440 return 1
1434
1441
1435 def writeNextBlock(self):
1442 def writeNextBlock(self):
1436 """
1443 """
1437 Selecciona el bloque siguiente de datos y los escribe en un file
1444 Selecciona el bloque siguiente de datos y los escribe en un file
1438
1445
1439 Return:
1446 Return:
1440 0 : Si no hizo pudo escribir el bloque de datos
1447 0 : Si no hizo pudo escribir el bloque de datos
1441 1 : Si no pudo escribir el bloque de datos
1448 1 : Si no pudo escribir el bloque de datos
1442 """
1449 """
1443 if not(self.__setNewBlock()):
1450 if not(self.__setNewBlock()):
1444 return 0
1451 return 0
1445
1452
1446 self.writeBlock()
1453 self.writeBlock()
1447
1454
1448 print("[Writing] Block No. %d/%d" % (self.blockIndex,
1455 print("[Writing] Block No. %d/%d" % (self.blockIndex,
1449 self.processingHeaderObj.dataBlocksPerFile))
1456 self.processingHeaderObj.dataBlocksPerFile))
1450
1457
1451 return 1
1458 return 1
1452
1459
1453 def setNextFile(self):
1460 def setNextFile(self):
1454 """Determina el siguiente file que sera escrito
1461 """Determina el siguiente file que sera escrito
1455
1462
1456 Affected:
1463 Affected:
1457 self.filename
1464 self.filename
1458 self.subfolder
1465 self.subfolder
1459 self.fp
1466 self.fp
1460 self.setFile
1467 self.setFile
1461 self.flagIsNewFile
1468 self.flagIsNewFile
1462
1469
1463 Return:
1470 Return:
1464 0 : Si el archivo no puede ser escrito
1471 0 : Si el archivo no puede ser escrito
1465 1 : Si el archivo esta listo para ser escrito
1472 1 : Si el archivo esta listo para ser escrito
1466 """
1473 """
1467 ext = self.ext
1474 ext = self.ext
1468 path = self.path
1475 path = self.path
1469
1476
1470 if self.fp != None:
1477 if self.fp != None:
1471 self.fp.close()
1478 self.fp.close()
1472
1479
1473 if not os.path.exists(path):
1474 os.mkdir(path)
1475
1476 timeTuple = time.localtime(self.dataOut.utctime)
1480 timeTuple = time.localtime(self.dataOut.utctime)
1477 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
1481 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
1478
1482
1479 fullpath = os.path.join(path, subfolder)
1483 fullpath = os.path.join(path, subfolder)
1480 setFile = self.setFile
1484 setFile = self.setFile
1481
1485
1482 if not(os.path.exists(fullpath)):
1486 if not(os.path.exists(fullpath)):
1483 os.mkdir(fullpath)
1487 os.makedirs(fullpath)
1484 setFile = -1 # inicializo mi contador de seteo
1488 setFile = -1 # inicializo mi contador de seteo
1485 else:
1489 else:
1486 filesList = os.listdir(fullpath)
1490 filesList = os.listdir(fullpath)
1487 if len(filesList) > 0:
1491 if len(filesList) > 0:
1488 filesList = sorted(filesList, key=str.lower)
1492 filesList = sorted(filesList, key=str.lower)
1489 filen = filesList[-1]
1493 filen = filesList[-1]
1490 # el filename debera tener el siguiente formato
1494 # el filename debera tener el siguiente formato
1491 # 0 1234 567 89A BCDE (hex)
1495 # 0 1234 567 89A BCDE (hex)
1492 # x YYYY DDD SSS .ext
1496 # x YYYY DDD SSS .ext
1493 if isNumber(filen[8:11]):
1497 if isNumber(filen[8:11]):
1494 # inicializo mi contador de seteo al seteo del ultimo file
1498 # inicializo mi contador de seteo al seteo del ultimo file
1495 setFile = int(filen[8:11])
1499 setFile = int(filen[8:11])
1496 else:
1500 else:
1497 setFile = -1
1501 setFile = -1
1498 else:
1502 else:
1499 setFile = -1 # inicializo mi contador de seteo
1503 setFile = -1 # inicializo mi contador de seteo
1500
1504
1501 setFile += 1
1505 setFile += 1
1502
1506
1503 # If this is a new day it resets some values
1507 # If this is a new day it resets some values
1504 if self.dataOut.datatime.date() > self.fileDate:
1508 if self.dataOut.datatime.date() > self.fileDate:
1505 setFile = 0
1509 setFile = 0
1506 self.nTotalBlocks = 0
1510 self.nTotalBlocks = 0
1507
1511
1508 filen = '{}{:04d}{:03d}{:03d}{}'.format(
1512 filen = '{}{:04d}{:03d}{:03d}{}'.format(
1509 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
1513 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
1510
1514
1511 filename = os.path.join(path, subfolder, filen)
1515 filename = os.path.join(path, subfolder, filen)
1512
1516
1513 fp = open(filename, 'wb')
1517 fp = open(filename, 'wb')
1514
1518
1515 self.blockIndex = 0
1519 self.blockIndex = 0
1516 self.filename = filename
1520 self.filename = filename
1517 self.subfolder = subfolder
1521 self.subfolder = subfolder
1518 self.fp = fp
1522 self.fp = fp
1519 self.setFile = setFile
1523 self.setFile = setFile
1520 self.flagIsNewFile = 1
1524 self.flagIsNewFile = 1
1521 self.fileDate = self.dataOut.datatime.date()
1525 self.fileDate = self.dataOut.datatime.date()
1522 self.setFirstHeader()
1526 self.setFirstHeader()
1523
1527
1524 print('[Writing] Opening file: %s' % self.filename)
1528 print('[Writing] Opening file: %s' % self.filename)
1525
1529
1526 self.__writeFirstHeader()
1530 self.__writeFirstHeader()
1527
1531
1528 return 1
1532 return 1
1529
1533
1530 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1534 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1531 """
1535 """
1532 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1536 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1533
1537
1534 Inputs:
1538 Inputs:
1535 path : directory where data will be saved
1539 path : directory where data will be saved
1536 profilesPerBlock : number of profiles per block
1540 profilesPerBlock : number of profiles per block
1537 set : initial file set
1541 set : initial file set
1538 datatype : An integer number that defines data type:
1542 datatype : An integer number that defines data type:
1539 0 : int8 (1 byte)
1543 0 : int8 (1 byte)
1540 1 : int16 (2 bytes)
1544 1 : int16 (2 bytes)
1541 2 : int32 (4 bytes)
1545 2 : int32 (4 bytes)
1542 3 : int64 (8 bytes)
1546 3 : int64 (8 bytes)
1543 4 : float32 (4 bytes)
1547 4 : float32 (4 bytes)
1544 5 : double64 (8 bytes)
1548 5 : double64 (8 bytes)
1545
1549
1546 Return:
1550 Return:
1547 0 : Si no realizo un buen seteo
1551 0 : Si no realizo un buen seteo
1548 1 : Si realizo un buen seteo
1552 1 : Si realizo un buen seteo
1549 """
1553 """
1550
1554
1551 if ext == None:
1555 if ext == None:
1552 ext = self.ext
1556 ext = self.ext
1553
1557
1554 self.ext = ext.lower()
1558 self.ext = ext.lower()
1555
1559
1556 self.path = path
1560 self.path = path
1557
1561
1558 if set is None:
1562 if set is None:
1559 self.setFile = -1
1563 self.setFile = -1
1560 else:
1564 else:
1561 self.setFile = set - 1
1565 self.setFile = set - 1
1562
1566
1563 self.blocksPerFile = blocksPerFile
1567 self.blocksPerFile = blocksPerFile
1564 self.profilesPerBlock = profilesPerBlock
1568 self.profilesPerBlock = profilesPerBlock
1565 self.dataOut = dataOut
1569 self.dataOut = dataOut
1566 self.fileDate = self.dataOut.datatime.date()
1570 self.fileDate = self.dataOut.datatime.date()
1567 self.dtype = self.dataOut.dtype
1571 self.dtype = self.dataOut.dtype
1568
1572
1569 if datatype is not None:
1573 if datatype is not None:
1570 self.dtype = get_numpy_dtype(datatype)
1574 self.dtype = get_numpy_dtype(datatype)
1571
1575
1572 if not(self.setNextFile()):
1576 if not(self.setNextFile()):
1573 print("[Writing] There isn't a next file")
1577 print("[Writing] There isn't a next file")
1574 return 0
1578 return 0
1575
1579
1576 self.setBlockDimension()
1580 self.setBlockDimension()
1577
1581
1578 return 1
1582 return 1
1579
1583
1580 def run(self, dataOut, path, blocksPerFile=100, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1584 def run(self, dataOut, path, blocksPerFile=100, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1581
1585
1582 if not(self.isConfig):
1586 if not(self.isConfig):
1583
1587
1584 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock,
1588 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock,
1585 set=set, ext=ext, datatype=datatype, **kwargs)
1589 set=set, ext=ext, datatype=datatype, **kwargs)
1586 self.isConfig = True
1590 self.isConfig = True
1587
1591
1588 self.dataOut = dataOut
1592 self.dataOut = dataOut
1589 self.putData()
1593 self.putData()
1590 return self.dataOut
1594 return self.dataOut
1591
1595
1592 @MPDecorator
1596 @MPDecorator
1593 class printInfo(Operation):
1597 class printInfo(Operation):
1594
1598
1595 def __init__(self):
1599 def __init__(self):
1596
1600
1597 Operation.__init__(self)
1601 Operation.__init__(self)
1598 self.__printInfo = True
1602 self.__printInfo = True
1599
1603
1600 def run(self, dataOut, headers = ['systemHeaderObj', 'radarControllerHeaderObj', 'processingHeaderObj']):
1604 def run(self, dataOut, headers = ['systemHeaderObj', 'radarControllerHeaderObj', 'processingHeaderObj']):
1601 if self.__printInfo == False:
1605 if self.__printInfo == False:
1602 return
1606 return
1603
1607
1604 for header in headers:
1608 for header in headers:
1605 if hasattr(dataOut, header):
1609 if hasattr(dataOut, header):
1606 obj = getattr(dataOut, header)
1610 obj = getattr(dataOut, header)
1607 if hasattr(obj, 'printInfo'):
1611 if hasattr(obj, 'printInfo'):
1608 obj.printInfo()
1612 obj.printInfo()
1609 else:
1613 else:
1610 print(obj)
1614 print(obj)
1611 else:
1615 else:
1612 log.warning('Header {} Not found in object'.format(header))
1616 log.warning('Header {} Not found in object'.format(header))
1613
1617
1614 self.__printInfo = False
1618 self.__printInfo = False
@@ -1,649 +1,650
1 '''
1 '''
2 Created on Aug 1, 2017
2 Created on Aug 1, 2017
3
3
4 @author: Juan C. Espinoza
4 @author: Juan C. Espinoza
5 '''
5 '''
6
6
7 import os
7 import os
8 import sys
8 import sys
9 import time
9 import time
10 import json
10 import json
11 import glob
11 import glob
12 import datetime
12 import datetime
13
13
14 import numpy
14 import numpy
15 import h5py
15 import h5py
16
16
17 import schainpy.admin
17 import schainpy.admin
18 from schainpy.model.io.jroIO_base import LOCALTIME, Reader
18 from schainpy.model.io.jroIO_base import LOCALTIME, Reader
19 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
19 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
20 from schainpy.model.data.jrodata import Parameters
20 from schainpy.model.data.jrodata import Parameters
21 from schainpy.utils import log
21 from schainpy.utils import log
22
22
23 try:
23 try:
24 import madrigal.cedar
24 import madrigal.cedar
25 except:
25 except:
26 pass
26 pass
27
27
28 try:
28 try:
29 basestring
29 basestring
30 except:
30 except:
31 basestring = str
31 basestring = str
32
32
33 DEF_CATALOG = {
33 DEF_CATALOG = {
34 'principleInvestigator': 'Marco Milla',
34 'principleInvestigator': 'Marco Milla',
35 'expPurpose': '',
35 'expPurpose': '',
36 'cycleTime': '',
36 'cycleTime': '',
37 'correlativeExp': '',
37 'correlativeExp': '',
38 'sciRemarks': '',
38 'sciRemarks': '',
39 'instRemarks': ''
39 'instRemarks': ''
40 }
40 }
41
41
42 DEF_HEADER = {
42 DEF_HEADER = {
43 'kindatDesc': '',
43 'kindatDesc': '',
44 'analyst': 'Jicamarca User',
44 'analyst': 'Jicamarca User',
45 'comments': '',
45 'comments': '',
46 'history': ''
46 'history': ''
47 }
47 }
48
48
49 MNEMONICS = {
49 MNEMONICS = {
50 10: 'jro',
50 10: 'jro',
51 12: 'jmp',
51 11: 'jbr',
52 11: 'jbr',
52 14: 'jmp', #Added by R. Flores
53 14: 'jmp', #Added by R. Flores
53 840: 'jul',
54 840: 'jul',
54 13: 'jas',
55 13: 'jas',
55 1000: 'pbr',
56 1000: 'pbr',
56 1001: 'hbr',
57 1001: 'hbr',
57 1002: 'obr',
58 1002: 'obr',
58 400: 'clr'
59 400: 'clr'
59
60
60 }
61 }
61
62
62 UT1970 = datetime.datetime(1970, 1, 1) - datetime.timedelta(seconds=time.timezone)
63 UT1970 = datetime.datetime(1970, 1, 1) - datetime.timedelta(seconds=time.timezone)
63
64
64 def load_json(obj):
65 def load_json(obj):
65 '''
66 '''
66 Parse json as string instead of unicode
67 Parse json as string instead of unicode
67 '''
68 '''
68
69
69 if isinstance(obj, str):
70 if isinstance(obj, str):
70 iterable = json.loads(obj)
71 iterable = json.loads(obj)
71 else:
72 else:
72 iterable = obj
73 iterable = obj
73
74
74 if isinstance(iterable, dict):
75 if isinstance(iterable, dict):
75 return {str(k): load_json(v) if isinstance(v, dict) else str(v) if isinstance(v, basestring) else v
76 return {str(k): load_json(v) if isinstance(v, dict) else str(v) if isinstance(v, basestring) else v
76 for k, v in list(iterable.items())}
77 for k, v in list(iterable.items())}
77 elif isinstance(iterable, (list, tuple)):
78 elif isinstance(iterable, (list, tuple)):
78 return [str(v) if isinstance(v, basestring) else v for v in iterable]
79 return [str(v) if isinstance(v, basestring) else v for v in iterable]
79
80
80 return iterable
81 return iterable
81
82
82
83
83 class MADReader(Reader, ProcessingUnit):
84 class MADReader(Reader, ProcessingUnit):
84
85
85 def __init__(self):
86 def __init__(self):
86
87
87 ProcessingUnit.__init__(self)
88 ProcessingUnit.__init__(self)
88
89
89 self.dataOut = Parameters()
90 self.dataOut = Parameters()
90 self.counter_records = 0
91 self.counter_records = 0
91 self.nrecords = None
92 self.nrecords = None
92 self.flagNoMoreFiles = 0
93 self.flagNoMoreFiles = 0
93 self.filename = None
94 self.filename = None
94 self.intervals = set()
95 self.intervals = set()
95 self.datatime = datetime.datetime(1900,1,1)
96 self.datatime = datetime.datetime(1900,1,1)
96 self.format = None
97 self.format = None
97 self.filefmt = "***%Y%m%d*******"
98 self.filefmt = "***%Y%m%d*******"
98
99
99 def setup(self, **kwargs):
100 def setup(self, **kwargs):
100
101
101 self.set_kwargs(**kwargs)
102 self.set_kwargs(**kwargs)
102 self.oneDDict = load_json(self.oneDDict)
103 self.oneDDict = load_json(self.oneDDict)
103 self.twoDDict = load_json(self.twoDDict)
104 self.twoDDict = load_json(self.twoDDict)
104 self.ind2DList = load_json(self.ind2DList)
105 self.ind2DList = load_json(self.ind2DList)
105 self.independentParam = self.ind2DList[0]
106 self.independentParam = self.ind2DList[0]
106
107
107 if self.path is None:
108 if self.path is None:
108 raise ValueError('The path is not valid')
109 raise ValueError('The path is not valid')
109
110
110 self.open_file = open
111 self.open_file = open
111 self.open_mode = 'rb'
112 self.open_mode = 'rb'
112
113
113 if self.format is None:
114 if self.format is None:
114 raise ValueError('The format is not valid choose simple or hdf5')
115 raise ValueError('The format is not valid choose simple or hdf5')
115 elif self.format.lower() in ('simple', 'txt'):
116 elif self.format.lower() in ('simple', 'txt'):
116 self.ext = '.txt'
117 self.ext = '.txt'
117 elif self.format.lower() in ('cedar',):
118 elif self.format.lower() in ('cedar',):
118 self.ext = '.001'
119 self.ext = '.001'
119 else:
120 else:
120 self.ext = '.hdf5'
121 self.ext = '.hdf5'
121 self.open_file = h5py.File
122 self.open_file = h5py.File
122 self.open_mode = 'r'
123 self.open_mode = 'r'
123
124
124 if self.online:
125 if self.online:
125 log.log("Searching files in online mode...", self.name)
126 log.log("Searching files in online mode...", self.name)
126
127
127 for nTries in range(self.nTries):
128 for nTries in range(self.nTries):
128 fullpath = self.searchFilesOnLine(self.path, self.startDate,
129 fullpath = self.searchFilesOnLine(self.path, self.startDate,
129 self.endDate, self.expLabel, self.ext, self.walk,
130 self.endDate, self.expLabel, self.ext, self.walk,
130 self.filefmt, self.folderfmt)
131 self.filefmt, self.folderfmt)
131
132
132 try:
133 try:
133 fullpath = next(fullpath)
134 fullpath = next(fullpath)
134 except:
135 except:
135 fullpath = None
136 fullpath = None
136
137
137 if fullpath:
138 if fullpath:
138 break
139 break
139
140
140 log.warning(
141 log.warning(
141 'Waiting {} sec for a valid file in {}: try {} ...'.format(
142 'Waiting {} sec for a valid file in {}: try {} ...'.format(
142 self.delay, self.path, nTries + 1),
143 self.delay, self.path, nTries + 1),
143 self.name)
144 self.name)
144 time.sleep(self.delay)
145 time.sleep(self.delay)
145
146
146 if not(fullpath):
147 if not(fullpath):
147 raise schainpy.admin.SchainError(
148 raise schainpy.admin.SchainError(
148 'There isn\'t any valid file in {}'.format(self.path))
149 'There isn\'t any valid file in {}'.format(self.path))
149
150
150 else:
151 else:
151 log.log("Searching files in {}".format(self.path), self.name)
152 log.log("Searching files in {}".format(self.path), self.name)
152 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
153 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
153 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
154 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
154
155
155 self.setNextFile()
156 self.setNextFile()
156
157
157 def readFirstHeader(self):
158 def readFirstHeader(self):
158 '''Read header and data'''
159 '''Read header and data'''
159
160
160 self.parseHeader()
161 self.parseHeader()
161 self.parseData()
162 self.parseData()
162 self.blockIndex = 0
163 self.blockIndex = 0
163
164
164 return
165 return
165
166
166 def parseHeader(self):
167 def parseHeader(self):
167 '''
168 '''
168 '''
169 '''
169
170
170 self.output = {}
171 self.output = {}
171 self.version = '2'
172 self.version = '2'
172 s_parameters = None
173 s_parameters = None
173 if self.ext == '.txt':
174 if self.ext == '.txt':
174 self.parameters = [s.strip().lower() for s in self.fp.readline().decode().strip().split(' ') if s]
175 self.parameters = [s.strip().lower() for s in self.fp.readline().decode().strip().split(' ') if s]
175 elif self.ext == '.hdf5':
176 elif self.ext == '.hdf5':
176 self.metadata = self.fp['Metadata']
177 self.metadata = self.fp['Metadata']
177 if '_record_layout' in self.metadata:
178 if '_record_layout' in self.metadata:
178 s_parameters = [s[0].lower().decode() for s in self.metadata['Independent Spatial Parameters']]
179 s_parameters = [s[0].lower().decode() for s in self.metadata['Independent Spatial Parameters']]
179 self.version = '3'
180 self.version = '3'
180 self.parameters = [s[0].lower().decode() for s in self.metadata['Data Parameters']]
181 self.parameters = [s[0].lower().decode() for s in self.metadata['Data Parameters']]
181
182
182 log.success('Parameters found: {}'.format(self.parameters),
183 log.success('Parameters found: {}'.format(self.parameters),
183 'MADReader')
184 'MADReader')
184 if s_parameters:
185 if s_parameters:
185 log.success('Spatial parameters found: {}'.format(s_parameters),
186 log.success('Spatial parameters found: {}'.format(s_parameters),
186 'MADReader')
187 'MADReader')
187
188
188 for param in list(self.oneDDict.keys()):
189 for param in list(self.oneDDict.keys()):
189 if param.lower() not in self.parameters:
190 if param.lower() not in self.parameters:
190 log.warning(
191 log.warning(
191 'Parameter {} not found will be ignored'.format(
192 'Parameter {} not found will be ignored'.format(
192 param),
193 param),
193 'MADReader')
194 'MADReader')
194 self.oneDDict.pop(param, None)
195 self.oneDDict.pop(param, None)
195
196
196 for param, value in list(self.twoDDict.items()):
197 for param, value in list(self.twoDDict.items()):
197 if param.lower() not in self.parameters:
198 if param.lower() not in self.parameters:
198 log.warning(
199 log.warning(
199 'Parameter {} not found, it will be ignored'.format(
200 'Parameter {} not found, it will be ignored'.format(
200 param),
201 param),
201 'MADReader')
202 'MADReader')
202 self.twoDDict.pop(param, None)
203 self.twoDDict.pop(param, None)
203 continue
204 continue
204 if isinstance(value, list):
205 if isinstance(value, list):
205 if value[0] not in self.output:
206 if value[0] not in self.output:
206 self.output[value[0]] = []
207 self.output[value[0]] = []
207 self.output[value[0]].append([])
208 self.output[value[0]].append([])
208
209
209 def parseData(self):
210 def parseData(self):
210 '''
211 '''
211 '''
212 '''
212
213
213 if self.ext == '.txt':
214 if self.ext == '.txt':
214 self.data = numpy.genfromtxt(self.fp, missing_values=('missing'))
215 self.data = numpy.genfromtxt(self.fp, missing_values=('missing'))
215 self.nrecords = self.data.shape[0]
216 self.nrecords = self.data.shape[0]
216 self.ranges = numpy.unique(self.data[:,self.parameters.index(self.independentParam.lower())])
217 self.ranges = numpy.unique(self.data[:,self.parameters.index(self.independentParam.lower())])
217 self.counter_records = 0
218 self.counter_records = 0
218 elif self.ext == '.hdf5':
219 elif self.ext == '.hdf5':
219 self.data = self.fp['Data']
220 self.data = self.fp['Data']
220 self.ranges = numpy.unique(self.data['Table Layout'][self.independentParam.lower()])
221 self.ranges = numpy.unique(self.data['Table Layout'][self.independentParam.lower()])
221 self.times = numpy.unique(self.data['Table Layout']['ut1_unix'])
222 self.times = numpy.unique(self.data['Table Layout']['ut1_unix'])
222 self.counter_records = int(self.data['Table Layout']['recno'][0])
223 self.counter_records = int(self.data['Table Layout']['recno'][0])
223 self.nrecords = int(self.data['Table Layout']['recno'][-1])
224 self.nrecords = int(self.data['Table Layout']['recno'][-1])
224
225
225 def readNextBlock(self):
226 def readNextBlock(self):
226
227
227 while True:
228 while True:
228 self.flagDiscontinuousBlock = 0
229 self.flagDiscontinuousBlock = 0
229 if self.counter_records == self.nrecords:
230 if self.counter_records == self.nrecords:
230 self.setNextFile()
231 self.setNextFile()
231
232
232 self.readBlock()
233 self.readBlock()
233
234
234 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
235 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
235 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
236 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
236 log.warning(
237 log.warning(
237 'Reading Record No. {}/{} -> {} [Skipping]'.format(
238 'Reading Record No. {}/{} -> {} [Skipping]'.format(
238 self.counter_records,
239 self.counter_records,
239 self.nrecords,
240 self.nrecords,
240 self.datatime.ctime()),
241 self.datatime.ctime()),
241 'MADReader')
242 'MADReader')
242 continue
243 continue
243 break
244 break
244
245
245 log.log(
246 log.log(
246 'Reading Record No. {}/{} -> {}'.format(
247 'Reading Record No. {}/{} -> {}'.format(
247 self.counter_records,
248 self.counter_records,
248 self.nrecords,
249 self.nrecords,
249 self.datatime.ctime()),
250 self.datatime.ctime()),
250 'MADReader')
251 'MADReader')
251
252
252 return 1
253 return 1
253
254
254 def readBlock(self):
255 def readBlock(self):
255 '''
256 '''
256 '''
257 '''
257 dum = []
258 dum = []
258 if self.ext == '.txt':
259 if self.ext == '.txt':
259 dt = self.data[self.counter_records][:6].astype(int)
260 dt = self.data[self.counter_records][:6].astype(int)
260 if datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5]).date() > self.datatime.date():
261 if datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5]).date() > self.datatime.date():
261 self.flagDiscontinuousBlock = 1
262 self.flagDiscontinuousBlock = 1
262 self.datatime = datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
263 self.datatime = datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
263 while True:
264 while True:
264 dt = self.data[self.counter_records][:6].astype(int)
265 dt = self.data[self.counter_records][:6].astype(int)
265 datatime = datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
266 datatime = datetime.datetime(dt[0], dt[1], dt[2], dt[3], dt[4], dt[5])
266 if datatime == self.datatime:
267 if datatime == self.datatime:
267 dum.append(self.data[self.counter_records])
268 dum.append(self.data[self.counter_records])
268 self.counter_records += 1
269 self.counter_records += 1
269 if self.counter_records == self.nrecords:
270 if self.counter_records == self.nrecords:
270 break
271 break
271 continue
272 continue
272 self.intervals.add((datatime-self.datatime).seconds)
273 self.intervals.add((datatime-self.datatime).seconds)
273 break
274 break
274 elif self.ext == '.hdf5':
275 elif self.ext == '.hdf5':
275 datatime = datetime.datetime.utcfromtimestamp(
276 datatime = datetime.datetime.utcfromtimestamp(
276 self.times[self.counter_records])
277 self.times[self.counter_records])
277 dum = self.data['Table Layout'][self.data['Table Layout']['recno']==self.counter_records]
278 dum = self.data['Table Layout'][self.data['Table Layout']['recno']==self.counter_records]
278 self.intervals.add((datatime-self.datatime).seconds)
279 self.intervals.add((datatime-self.datatime).seconds)
279 if datatime.date()>self.datatime.date():
280 if datatime.date()>self.datatime.date():
280 self.flagDiscontinuousBlock = 1
281 self.flagDiscontinuousBlock = 1
281 self.datatime = datatime
282 self.datatime = datatime
282 self.counter_records += 1
283 self.counter_records += 1
283
284
284 self.buffer = numpy.array(dum)
285 self.buffer = numpy.array(dum)
285 return
286 return
286
287
287 def set_output(self):
288 def set_output(self):
288 '''
289 '''
289 Storing data from buffer to dataOut object
290 Storing data from buffer to dataOut object
290 '''
291 '''
291
292
292 parameters = [None for __ in self.parameters]
293 parameters = [None for __ in self.parameters]
293
294
294 for param, attr in list(self.oneDDict.items()):
295 for param, attr in list(self.oneDDict.items()):
295 x = self.parameters.index(param.lower())
296 x = self.parameters.index(param.lower())
296 setattr(self.dataOut, attr, self.buffer[0][x])
297 setattr(self.dataOut, attr, self.buffer[0][x])
297
298
298 for param, value in list(self.twoDDict.items()):
299 for param, value in list(self.twoDDict.items()):
299 dummy = numpy.zeros(self.ranges.shape) + numpy.nan
300 dummy = numpy.zeros(self.ranges.shape) + numpy.nan
300 if self.ext == '.txt':
301 if self.ext == '.txt':
301 x = self.parameters.index(param.lower())
302 x = self.parameters.index(param.lower())
302 y = self.parameters.index(self.independentParam.lower())
303 y = self.parameters.index(self.independentParam.lower())
303 ranges = self.buffer[:,y]
304 ranges = self.buffer[:,y]
304 #if self.ranges.size == ranges.size:
305 #if self.ranges.size == ranges.size:
305 # continue
306 # continue
306 index = numpy.where(numpy.in1d(self.ranges, ranges))[0]
307 index = numpy.where(numpy.in1d(self.ranges, ranges))[0]
307 dummy[index] = self.buffer[:,x]
308 dummy[index] = self.buffer[:,x]
308 else:
309 else:
309 ranges = self.buffer[self.independentParam.lower()]
310 ranges = self.buffer[self.independentParam.lower()]
310 index = numpy.where(numpy.in1d(self.ranges, ranges))[0]
311 index = numpy.where(numpy.in1d(self.ranges, ranges))[0]
311 dummy[index] = self.buffer[param.lower()]
312 dummy[index] = self.buffer[param.lower()]
312
313
313 if isinstance(value, str):
314 if isinstance(value, str):
314 if value not in self.independentParam:
315 if value not in self.independentParam:
315 setattr(self.dataOut, value, dummy.reshape(1,-1))
316 setattr(self.dataOut, value, dummy.reshape(1,-1))
316 elif isinstance(value, list):
317 elif isinstance(value, list):
317 self.output[value[0]][value[1]] = dummy
318 self.output[value[0]][value[1]] = dummy
318 parameters[value[1]] = param
319 parameters[value[1]] = param
319 for key, value in list(self.output.items()):
320 for key, value in list(self.output.items()):
320 setattr(self.dataOut, key, numpy.array(value))
321 setattr(self.dataOut, key, numpy.array(value))
321
322
322 self.dataOut.parameters = [s for s in parameters if s]
323 self.dataOut.parameters = [s for s in parameters if s]
323 self.dataOut.heightList = self.ranges
324 self.dataOut.heightList = self.ranges
324 self.dataOut.utctime = (self.datatime - datetime.datetime(1970, 1, 1)).total_seconds()
325 self.dataOut.utctime = (self.datatime - datetime.datetime(1970, 1, 1)).total_seconds()
325 self.dataOut.utctimeInit = self.dataOut.utctime
326 self.dataOut.utctimeInit = self.dataOut.utctime
326 self.dataOut.paramInterval = min(self.intervals)
327 self.dataOut.paramInterval = min(self.intervals)
327 self.dataOut.useLocalTime = False
328 self.dataOut.useLocalTime = False
328 self.dataOut.flagNoData = False
329 self.dataOut.flagNoData = False
329 self.dataOut.nrecords = self.nrecords
330 self.dataOut.nrecords = self.nrecords
330 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
331 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
331
332
332 def getData(self):
333 def getData(self):
333 '''
334 '''
334 Storing data from databuffer to dataOut object
335 Storing data from databuffer to dataOut object
335 '''
336 '''
336
337
337 if not self.readNextBlock():
338 if not self.readNextBlock():
338 self.dataOut.flagNoData = True
339 self.dataOut.flagNoData = True
339 return 0
340 return 0
340
341
341 self.set_output()
342 self.set_output()
342
343
343 return 1
344 return 1
344
345
345 def run(self, **kwargs):
346 def run(self, **kwargs):
346
347
347 if not(self.isConfig):
348 if not(self.isConfig):
348 self.setup(**kwargs)
349 self.setup(**kwargs)
349 self.isConfig = True
350 self.isConfig = True
350
351
351 self.getData()
352 self.getData()
352
353
353 return
354 return
354
355
355 @MPDecorator
356 @MPDecorator
356 class MADWriter(Operation):
357 class MADWriter(Operation):
357 '''Writing module for Madrigal files
358 '''Writing module for Madrigal files
358
359
359 type: external
360 type: external
360
361
361 Inputs:
362 Inputs:
362 path path where files will be created
363 path path where files will be created
363 oneDDict json of one-dimensional parameters in record where keys
364 oneDDict json of one-dimensional parameters in record where keys
364 are Madrigal codes (integers or mnemonics) and values the corresponding
365 are Madrigal codes (integers or mnemonics) and values the corresponding
365 dataOut attribute e.g: {
366 dataOut attribute e.g: {
366 'gdlatr': 'lat',
367 'gdlatr': 'lat',
367 'gdlonr': 'lon',
368 'gdlonr': 'lon',
368 'gdlat2':'lat',
369 'gdlat2':'lat',
369 'glon2':'lon'}
370 'glon2':'lon'}
370 ind2DList list of independent spatial two-dimensional parameters e.g:
371 ind2DList list of independent spatial two-dimensional parameters e.g:
371 ['heigthList']
372 ['heigthList']
372 twoDDict json of two-dimensional parameters in record where keys
373 twoDDict json of two-dimensional parameters in record where keys
373 are Madrigal codes (integers or mnemonics) and values the corresponding
374 are Madrigal codes (integers or mnemonics) and values the corresponding
374 dataOut attribute if multidimensional array specify as tupple
375 dataOut attribute if multidimensional array specify as tupple
375 ('attr', pos) e.g: {
376 ('attr', pos) e.g: {
376 'gdalt': 'heightList',
377 'gdalt': 'heightList',
377 'vn1p2': ('data_output', 0),
378 'vn1p2': ('data_output', 0),
378 'vn2p2': ('data_output', 1),
379 'vn2p2': ('data_output', 1),
379 'vn3': ('data_output', 2),
380 'vn3': ('data_output', 2),
380 'snl': ('data_SNR', 'db')
381 'snl': ('data_SNR', 'db')
381 }
382 }
382 metadata json of madrigal metadata (kinst, kindat, catalog and header)
383 metadata json of madrigal metadata (kinst, kindat, catalog and header)
383 format hdf5, cedar
384 format hdf5, cedar
384 blocks number of blocks per file'''
385 blocks number of blocks per file'''
385
386
386 __attrs__ = ['path', 'oneDDict', 'ind2DList', 'twoDDict','metadata', 'format', 'blocks']
387 __attrs__ = ['path', 'oneDDict', 'ind2DList', 'twoDDict','metadata', 'format', 'blocks']
387 missing = -32767
388 missing = -32767
388 currentDay = None
389 currentDay = None
389
390
390 def __init__(self):
391 def __init__(self):
391
392
392 Operation.__init__(self)
393 Operation.__init__(self)
393 self.dataOut = Parameters()
394 self.dataOut = Parameters()
394 self.counter = 0
395 self.counter = 0
395 self.path = None
396 self.path = None
396 self.fp = None
397 self.fp = None
397
398
398 def run(self, dataOut, path, oneDDict, ind2DList='[]', twoDDict='{}',
399 def run(self, dataOut, path, oneDDict, ind2DList='[]', twoDDict='{}',
399 metadata='{}', format='cedar', **kwargs):
400 metadata='{}', format='cedar', **kwargs):
400
401
401
402
402 #if dataOut.AUX==1: #Modified
403 #if dataOut.AUX==1: #Modified
403
404
404 if not self.isConfig:
405 if not self.isConfig:
405 self.setup(path, oneDDict, ind2DList, twoDDict, metadata, format, **kwargs)
406 self.setup(path, oneDDict, ind2DList, twoDDict, metadata, format, **kwargs)
406 self.isConfig = True
407 self.isConfig = True
407
408
408 self.dataOut = dataOut
409 self.dataOut = dataOut
409 self.putData()
410 self.putData()
410
411
411 return 1
412 return 1
412
413
413 def setup(self, path, oneDDict, ind2DList, twoDDict, metadata, format, **kwargs):
414 def setup(self, path, oneDDict, ind2DList, twoDDict, metadata, format, **kwargs):
414 '''
415 '''
415 Configure Operation
416 Configure Operation
416 '''
417 '''
417
418
418 self.path = path
419 self.path = path
419 self.blocks = kwargs.get('blocks', None)
420 self.blocks = kwargs.get('blocks', None)
420 self.counter = 0
421 self.counter = 0
421 self.oneDDict = load_json(oneDDict)
422 self.oneDDict = load_json(oneDDict)
422 self.twoDDict = load_json(twoDDict)
423 self.twoDDict = load_json(twoDDict)
423 self.ind2DList = load_json(ind2DList)
424 self.ind2DList = load_json(ind2DList)
424 meta = load_json(metadata)
425 meta = load_json(metadata)
425 self.kinst = meta.get('kinst')
426 self.kinst = meta.get('kinst')
426 self.kindat = meta.get('kindat')
427 self.kindat = meta.get('kindat')
427 self.catalog = meta.get('catalog', DEF_CATALOG)
428 self.catalog = meta.get('catalog', DEF_CATALOG)
428 self.header = meta.get('header', DEF_HEADER)
429 self.header = meta.get('header', DEF_HEADER)
429 if format == 'cedar':
430 if format == 'cedar':
430 self.ext = '.dat'
431 self.ext = '.dat'
431 self.extra_args = {}
432 self.extra_args = {}
432 elif format == 'hdf5':
433 elif format == 'hdf5':
433 self.ext = '.hdf5'
434 self.ext = '.hdf5'
434 self.extra_args = {'ind2DList': self.ind2DList}
435 self.extra_args = {'ind2DList': self.ind2DList}
435
436
436 self.keys = [k.lower() for k in self.twoDDict]
437 self.keys = [k.lower() for k in self.twoDDict]
437 if 'range' in self.keys:
438 if 'range' in self.keys:
438 self.keys.remove('range')
439 self.keys.remove('range')
439 if 'gdalt' in self.keys:
440 if 'gdalt' in self.keys:
440 self.keys.remove('gdalt')
441 self.keys.remove('gdalt')
441
442
442 def setFile(self):
443 def setFile(self):
443 '''
444 '''
444 Create new cedar file object
445 Create new cedar file object
445 '''
446 '''
446
447
447 self.mnemonic = MNEMONICS[self.kinst] #TODO get mnemonic from madrigal
448 self.mnemonic = MNEMONICS[self.kinst] #TODO get mnemonic from madrigal
448 date = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
449 date = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
449 #if self.dataOut.input_dat_type:
450 #if self.dataOut.input_dat_type:
450 #date=datetime.datetime.fromtimestamp(self.dataOut.TimeBlockSeconds_for_dp_power)
451 #date=datetime.datetime.fromtimestamp(self.dataOut.TimeBlockSeconds_for_dp_power)
451 #print("date",date)
452 #print("date",date)
452
453
453 filename = '{}{}{}'.format(self.mnemonic,
454 filename = '{}{}{}'.format(self.mnemonic,
454 date.strftime('%Y%m%d_%H%M%S'),
455 date.strftime('%Y%m%d_%H%M%S'),
455 self.ext)
456 self.ext)
456
457
457 self.fullname = os.path.join(self.path, filename)
458 self.fullname = os.path.join(self.path, filename)
458
459
459 if os.path.isfile(self.fullname) :
460 if os.path.isfile(self.fullname) :
460 log.warning(
461 log.warning(
461 'Destination file {} already exists, previous file deleted.'.format(
462 'Destination file {} already exists, previous file deleted.'.format(
462 self.fullname),
463 self.fullname),
463 'MADWriter')
464 'MADWriter')
464 os.remove(self.fullname)
465 os.remove(self.fullname)
465
466
466 try:
467 try:
467 log.success(
468 log.success(
468 'Creating file: {}'.format(self.fullname),
469 'Creating file: {}'.format(self.fullname),
469 'MADWriter')
470 'MADWriter')
470 if not os.path.exists(self.path):
471 if not os.path.exists(self.path):
471 os.makedirs(self.path)
472 os.makedirs(self.path)
472 self.fp = madrigal.cedar.MadrigalCedarFile(self.fullname, True)
473 self.fp = madrigal.cedar.MadrigalCedarFile(self.fullname, True)
473
474
474
475
475 except ValueError as e:
476 except ValueError as e:
476 log.error(
477 log.error(
477 'Impossible to create a cedar object with "madrigal.cedar.MadrigalCedarFile"',
478 'Impossible to create a cedar object with "madrigal.cedar.MadrigalCedarFile"',
478 'MADWriter')
479 'MADWriter')
479 return
480 return
480
481
481 return 1
482 return 1
482
483
483 def writeBlock(self):
484 def writeBlock(self):
484 '''
485 '''
485 Add data records to cedar file taking data from oneDDict and twoDDict
486 Add data records to cedar file taking data from oneDDict and twoDDict
486 attributes.
487 attributes.
487 Allowed parameters in: parcodes.tab
488 Allowed parameters in: parcodes.tab
488 '''
489 '''
489 #self.dataOut.paramInterval=2
490 #self.dataOut.paramInterval=2
490 startTime = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
491 startTime = datetime.datetime.utcfromtimestamp(self.dataOut.utctime)
491
492
492 endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
493 endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
493
494
494 #if self.dataOut.input_dat_type:
495 #if self.dataOut.input_dat_type:
495 #if self.dataOut.experiment=="DP":
496 #if self.dataOut.experiment=="DP":
496 #startTime=datetime.datetime.fromtimestamp(self.dataOut.TimeBlockSeconds_for_dp_power)
497 #startTime=datetime.datetime.fromtimestamp(self.dataOut.TimeBlockSeconds_for_dp_power)
497 #endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
498 #endTime = startTime + datetime.timedelta(seconds=self.dataOut.paramInterval)
498
499
499
500
500 #print("2: ",startTime)
501 #print("2: ",startTime)
501 #print(endTime)
502 #print(endTime)
502 heights = self.dataOut.heightList
503 heights = self.dataOut.heightList
503 #print(heights)
504 #print(heights)
504 #exit(1)
505 #exit(1)
505 #print(self.blocks)
506 #print(self.blocks)
506 #print(startTime)
507 #print(startTime)
507 #print(endTime)
508 #print(endTime)
508 #print(heights)
509 #print(heights)
509 #input()
510 #input()
510 if self.ext == '.dat':
511 if self.ext == '.dat':
511 for key, value in list(self.twoDDict.items()):
512 for key, value in list(self.twoDDict.items()):
512 if isinstance(value, str):
513 if isinstance(value, str):
513 data = getattr(self.dataOut, value)
514 data = getattr(self.dataOut, value)
514 invalid = numpy.isnan(data)
515 invalid = numpy.isnan(data)
515 data[invalid] = self.missing
516 data[invalid] = self.missing
516 elif isinstance(value, (tuple, list)):
517 elif isinstance(value, (tuple, list)):
517 attr, key = value
518 attr, key = value
518 data = getattr(self.dataOut, attr)
519 data = getattr(self.dataOut, attr)
519 invalid = numpy.isnan(data)
520 invalid = numpy.isnan(data)
520 data[invalid] = self.missing
521 data[invalid] = self.missing
521
522
522 out = {}
523 out = {}
523 for key, value in list(self.twoDDict.items()):
524 for key, value in list(self.twoDDict.items()):
524 key = key.lower()
525 key = key.lower()
525 if isinstance(value, str):
526 if isinstance(value, str):
526 if 'db' in value.lower():
527 if 'db' in value.lower():
527 tmp = getattr(self.dataOut, value.replace('_db', ''))
528 tmp = getattr(self.dataOut, value.replace('_db', ''))
528 SNRavg = numpy.average(tmp, axis=0)
529 SNRavg = numpy.average(tmp, axis=0)
529 tmp = 10*numpy.log10(SNRavg)
530 tmp = 10*numpy.log10(SNRavg)
530 else:
531 else:
531 tmp = getattr(self.dataOut, value)
532 tmp = getattr(self.dataOut, value)
532 out[key] = tmp.flatten()[:len(heights)]
533 out[key] = tmp.flatten()[:len(heights)]
533 elif isinstance(value, (tuple, list)):
534 elif isinstance(value, (tuple, list)):
534 attr, x = value
535 attr, x = value
535 data = getattr(self.dataOut, attr)
536 data = getattr(self.dataOut, attr)
536 #print(x)
537 #print(x)
537 #print(len(heights))
538 #print(len(heights))
538 #print(data[int(x)][:len(heights)])
539 #print(data[int(x)][:len(heights)])
539 #print(numpy.shape(out))
540 #print(numpy.shape(out))
540 #print(numpy.shape(data))
541 #print(numpy.shape(data))
541
542
542 out[key] = data[int(x)][:len(heights)]
543 out[key] = data[int(x)][:len(heights)]
543
544
544 a = numpy.array([out[k] for k in self.keys])
545 a = numpy.array([out[k] for k in self.keys])
545 #print(a)
546 #print(a)
546 nrows = numpy.array([numpy.isnan(a[:, x]).all() for x in range(len(heights))])
547 nrows = numpy.array([numpy.isnan(a[:, x]).all() for x in range(len(heights))])
547 index = numpy.where(nrows == False)[0]
548 index = numpy.where(nrows == False)[0]
548
549
549 #print(startTime.minute)
550 #print(startTime.minute)
550 rec = madrigal.cedar.MadrigalDataRecord(
551 rec = madrigal.cedar.MadrigalDataRecord(
551 self.kinst,
552 self.kinst,
552 self.kindat,
553 self.kindat,
553 startTime.year,
554 startTime.year,
554 startTime.month,
555 startTime.month,
555 startTime.day,
556 startTime.day,
556 startTime.hour,
557 startTime.hour,
557 startTime.minute,
558 startTime.minute,
558 startTime.second,
559 startTime.second,
559 startTime.microsecond/10000,
560 startTime.microsecond/10000,
560 endTime.year,
561 endTime.year,
561 endTime.month,
562 endTime.month,
562 endTime.day,
563 endTime.day,
563 endTime.hour,
564 endTime.hour,
564 endTime.minute,
565 endTime.minute,
565 endTime.second,
566 endTime.second,
566 endTime.microsecond/10000,
567 endTime.microsecond/10000,
567 list(self.oneDDict.keys()),
568 list(self.oneDDict.keys()),
568 list(self.twoDDict.keys()),
569 list(self.twoDDict.keys()),
569 len(index),
570 len(index),
570 **self.extra_args
571 **self.extra_args
571 )
572 )
572 #print("rec",rec)
573 #print("rec",rec)
573 # Setting 1d values
574 # Setting 1d values
574 for key in self.oneDDict:
575 for key in self.oneDDict:
575 rec.set1D(key, getattr(self.dataOut, self.oneDDict[key]))
576 rec.set1D(key, getattr(self.dataOut, self.oneDDict[key]))
576
577
577 # Setting 2d values
578 # Setting 2d values
578 nrec = 0
579 nrec = 0
579 for n in index:
580 for n in index:
580 for key in out:
581 for key in out:
581 rec.set2D(key, nrec, out[key][n])
582 rec.set2D(key, nrec, out[key][n])
582 nrec += 1
583 nrec += 1
583
584
584 self.fp.append(rec)
585 self.fp.append(rec)
585 if self.ext == '.hdf5' and self.counter %2 == 0 and self.counter > 0:
586 if self.ext == '.hdf5' and self.counter %2 == 0 and self.counter > 0:
586 #print("here")
587 #print("here")
587 self.fp.dump()
588 self.fp.dump()
588 if self.counter % 20 == 0 and self.counter > 0:
589 if self.counter % 20 == 0 and self.counter > 0:
589 #self.fp.write()
590 #self.fp.write()
590 log.log(
591 log.log(
591 'Writing {} records'.format(
592 'Writing {} records'.format(
592 self.counter),
593 self.counter),
593 'MADWriter')
594 'MADWriter')
594
595
595 def setHeader(self):
596 def setHeader(self):
596 '''
597 '''
597 Create an add catalog and header to cedar file
598 Create an add catalog and header to cedar file
598 '''
599 '''
599
600
600 log.success('Closing file {}'.format(self.fullname), 'MADWriter')
601 log.success('Closing file {}'.format(self.fullname), 'MADWriter')
601
602
602 if self.ext == '.dat':
603 if self.ext == '.dat':
603 self.fp.write()
604 self.fp.write()
604 else:
605 else:
605 self.fp.dump()
606 self.fp.dump()
606 self.fp.close()
607 self.fp.close()
607
608
608 header = madrigal.cedar.CatalogHeaderCreator(self.fullname)
609 header = madrigal.cedar.CatalogHeaderCreator(self.fullname)
609 header.createCatalog(**self.catalog)
610 header.createCatalog(**self.catalog)
610 header.createHeader(**self.header)
611 header.createHeader(**self.header)
611 header.write()
612 header.write()
612
613
613 def timeFlag(self):
614 def timeFlag(self):
614 currentTime = self.dataOut.utctime
615 currentTime = self.dataOut.utctime
615 timeTuple = time.localtime(currentTime)
616 timeTuple = time.localtime(currentTime)
616 dataDay = timeTuple.tm_yday
617 dataDay = timeTuple.tm_yday
617
618
618 if self.currentDay is None:
619 if self.currentDay is None:
619 self.currentDay = dataDay
620 self.currentDay = dataDay
620 return False
621 return False
621
622
622 #Si el dia es diferente
623 #Si el dia es diferente
623 if dataDay != self.currentDay:
624 if dataDay != self.currentDay:
624 self.currentDay = dataDay
625 self.currentDay = dataDay
625 return True
626 return True
626
627
627 else:
628 else:
628 return False
629 return False
629
630
630 def putData(self):
631 def putData(self):
631
632
632 if self.dataOut.flagNoData:
633 if self.dataOut.flagNoData:
633 return 0
634 return 0
634
635
635 if self.dataOut.flagDiscontinuousBlock or self.counter == self.blocks or self.timeFlag():
636 if self.dataOut.flagDiscontinuousBlock or self.counter == self.blocks or self.timeFlag():
636 if self.counter > 0:
637 if self.counter > 0:
637 self.setHeader()
638 self.setHeader()
638 self.counter = 0
639 self.counter = 0
639
640
640 if self.counter == 0:
641 if self.counter == 0:
641 self.setFile()
642 self.setFile()
642
643
643 self.writeBlock()
644 self.writeBlock()
644 self.counter += 1
645 self.counter += 1
645
646
646 def close(self):
647 def close(self):
647
648
648 if self.counter > 0:
649 if self.counter > 0:
649 self.setHeader()
650 self.setHeader()
@@ -1,640 +1,662
1 import os
1 import os
2 import time
2 import time
3 import datetime
3 import datetime
4
4
5 import numpy
5 import numpy
6 import h5py
6 import h5py
7
7
8 import schainpy.admin
8 import schainpy.admin
9 from schainpy.model.data.jrodata import *
9 from schainpy.model.data.jrodata import *
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 from schainpy.model.io.jroIO_base import *
11 from schainpy.model.io.jroIO_base import *
12 from schainpy.utils import log
12 from schainpy.utils import log
13
13
14
14
15 class HDFReader(Reader, ProcessingUnit):
15 class HDFReader(Reader, ProcessingUnit):
16 """Processing unit to read HDF5 format files
16 """Processing unit to read HDF5 format files
17
17
18 This unit reads HDF5 files created with `HDFWriter` operation contains
18 This unit reads HDF5 files created with `HDFWriter` operation contains
19 by default two groups Data and Metadata all variables would be saved as `dataOut`
19 by default two groups Data and Metadata all variables would be saved as `dataOut`
20 attributes.
20 attributes.
21 It is possible to read any HDF5 file by given the structure in the `description`
21 It is possible to read any HDF5 file by given the structure in the `description`
22 parameter, also you can add extra values to metadata with the parameter `extras`.
22 parameter, also you can add extra values to metadata with the parameter `extras`.
23
23
24 Parameters:
24 Parameters:
25 -----------
25 -----------
26 path : str
26 path : str
27 Path where files are located.
27 Path where files are located.
28 startDate : date
28 startDate : date
29 Start date of the files
29 Start date of the files
30 endDate : list
30 endDate : list
31 End date of the files
31 End date of the files
32 startTime : time
32 startTime : time
33 Start time of the files
33 Start time of the files
34 endTime : time
34 endTime : time
35 End time of the files
35 End time of the files
36 description : dict, optional
36 description : dict, optional
37 Dictionary with the description of the HDF5 file
37 Dictionary with the description of the HDF5 file
38 extras : dict, optional
38 extras : dict, optional
39 Dictionary with extra metadata to be be added to `dataOut`
39 Dictionary with extra metadata to be be added to `dataOut`
40
40
41 Examples
41 Examples
42 --------
42 --------
43
43
44 desc = {
44 desc = {
45 'Data': {
45 'Data': {
46 'data_output': ['u', 'v', 'w'],
46 'data_output': ['u', 'v', 'w'],
47 'utctime': 'timestamps',
47 'utctime': 'timestamps',
48 } ,
48 } ,
49 'Metadata': {
49 'Metadata': {
50 'heightList': 'heights'
50 'heightList': 'heights'
51 }
51 }
52 }
52 }
53
53
54 desc = {
54 desc = {
55 'Data': {
55 'Data': {
56 'data_output': 'winds',
56 'data_output': 'winds',
57 'utctime': 'timestamps'
57 'utctime': 'timestamps'
58 },
58 },
59 'Metadata': {
59 'Metadata': {
60 'heightList': 'heights'
60 'heightList': 'heights'
61 }
61 }
62 }
62 }
63
63
64 extras = {
64 extras = {
65 'timeZone': 300
65 'timeZone': 300
66 }
66 }
67
67
68 reader = project.addReadUnit(
68 reader = project.addReadUnit(
69 name='HDFReader',
69 name='HDFReader',
70 path='/path/to/files',
70 path='/path/to/files',
71 startDate='2019/01/01',
71 startDate='2019/01/01',
72 endDate='2019/01/31',
72 endDate='2019/01/31',
73 startTime='00:00:00',
73 startTime='00:00:00',
74 endTime='23:59:59',
74 endTime='23:59:59',
75 # description=json.dumps(desc),
75 # description=json.dumps(desc),
76 # extras=json.dumps(extras),
76 # extras=json.dumps(extras),
77 )
77 )
78
78
79 """
79 """
80
80
81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
82
82
83 def __init__(self):
83 def __init__(self):
84 ProcessingUnit.__init__(self)
84 ProcessingUnit.__init__(self)
85 self.dataOut = Parameters()
85 self.dataOut = Parameters()
86 self.ext = ".hdf5"
86 self.ext = ".hdf5"
87 self.optchar = "D"
87 self.optchar = "D"
88 self.meta = {}
88 self.meta = {}
89 self.data = {}
89 self.data = {}
90 self.open_file = h5py.File
90 self.open_file = h5py.File
91 self.open_mode = 'r'
91 self.open_mode = 'r'
92 self.description = {}
92 self.description = {}
93 self.extras = {}
93 self.extras = {}
94 self.filefmt = "*%Y%j***"
94 self.filefmt = "*%Y%j***"
95 self.folderfmt = "*%Y%j"
95 self.folderfmt = "*%Y%j"
96 self.utcoffset = 0
96 self.utcoffset = 0
97
97
98 def setup(self, **kwargs):
98 def setup(self, **kwargs):
99
99
100 self.set_kwargs(**kwargs)
100 self.set_kwargs(**kwargs)
101 if not self.ext.startswith('.'):
101 if not self.ext.startswith('.'):
102 self.ext = '.{}'.format(self.ext)
102 self.ext = '.{}'.format(self.ext)
103
103
104 if self.online:
104 if self.online:
105 log.log("Searching files in online mode...", self.name)
105 log.log("Searching files in online mode...", self.name)
106
106
107 for nTries in range(self.nTries):
107 for nTries in range(self.nTries):
108 fullpath = self.searchFilesOnLine(self.path, self.startDate,
108 fullpath = self.searchFilesOnLine(self.path, self.startDate,
109 self.endDate, self.expLabel, self.ext, self.walk,
109 self.endDate, self.expLabel, self.ext, self.walk,
110 self.filefmt, self.folderfmt)
110 self.filefmt, self.folderfmt)
111 try:
111 try:
112 fullpath = next(fullpath)
112 fullpath = next(fullpath)
113 except:
113 except:
114 fullpath = None
114 fullpath = None
115
115
116 if fullpath:
116 if fullpath:
117 break
117 break
118
118
119 log.warning(
119 log.warning(
120 'Waiting {} sec for a valid file in {}: try {} ...'.format(
120 'Waiting {} sec for a valid file in {}: try {} ...'.format(
121 self.delay, self.path, nTries + 1),
121 self.delay, self.path, nTries + 1),
122 self.name)
122 self.name)
123 time.sleep(self.delay)
123 time.sleep(self.delay)
124
124
125 if not(fullpath):
125 if not(fullpath):
126 raise schainpy.admin.SchainError(
126 raise schainpy.admin.SchainError(
127 'There isn\'t any valid file in {}'.format(self.path))
127 'There isn\'t any valid file in {}'.format(self.path))
128
128
129 pathname, filename = os.path.split(fullpath)
129 pathname, filename = os.path.split(fullpath)
130 self.year = int(filename[1:5])
130 self.year = int(filename[1:5])
131 self.doy = int(filename[5:8])
131 self.doy = int(filename[5:8])
132 self.set = int(filename[8:11]) - 1
132 self.set = int(filename[8:11]) - 1
133 else:
133 else:
134 log.log("Searching files in {}".format(self.path), self.name)
134 log.log("Searching files in {}".format(self.path), self.name)
135 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
135 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
136 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
136 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
137
137
138 self.setNextFile()
138 self.setNextFile()
139
139
140 return
140 return
141
141
142 def readFirstHeader(self):
142 def readFirstHeader(self):
143 '''Read metadata and data'''
143 '''Read metadata and data'''
144
144
145 self.__readMetadata()
145 self.__readMetadata()
146 self.__readData()
146 self.__readData()
147 self.__setBlockList()
147 self.__setBlockList()
148
148
149 if 'type' in self.meta:
149 if 'type' in self.meta:
150 self.dataOut = eval(self.meta['type'])()
150 self.dataOut = eval(self.meta['type'])()
151
151
152 for attr in self.meta:
152 for attr in self.meta:
153 setattr(self.dataOut, attr, self.meta[attr])
153 setattr(self.dataOut, attr, self.meta[attr])
154
154
155 self.blockIndex = 0
155 self.blockIndex = 0
156
156
157 return
157 return
158
158
159 def __setBlockList(self):
159 def __setBlockList(self):
160 '''
160 '''
161 Selects the data within the times defined
161 Selects the data within the times defined
162
162
163 self.fp
163 self.fp
164 self.startTime
164 self.startTime
165 self.endTime
165 self.endTime
166 self.blockList
166 self.blockList
167 self.blocksPerFile
167 self.blocksPerFile
168
168
169 '''
169 '''
170
170
171 startTime = self.startTime
171 startTime = self.startTime
172 endTime = self.endTime
172 endTime = self.endTime
173 thisUtcTime = self.data['utctime'] + self.utcoffset
173 thisUtcTime = self.data['utctime'] + self.utcoffset
174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
175 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
175 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
176
176
177 thisDate = thisDatetime.date()
177 thisDate = thisDatetime.date()
178 thisTime = thisDatetime.time()
178 thisTime = thisDatetime.time()
179
179
180 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
180 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
181 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
181 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
182
182
183 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
183 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
184
184
185 self.blockList = ind
185 self.blockList = ind
186 self.blocksPerFile = len(ind)
186 self.blocksPerFile = len(ind)
187 # similar to master
188 if len(ind)==0:
189 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.blockIndex,
190 self.blocksPerFile,
191 thisDatetime))
192 self.setNextFile()
193 # similar to master
187 return
194 return
188
195
189 def __readMetadata(self):
196 def __readMetadata(self):
190 '''
197 '''
191 Reads Metadata
198 Reads Metadata
192 '''
199 '''
193
200
194 meta = {}
201 meta = {}
195
202
196 if self.description:
203 if self.description:
197 for key, value in self.description['Metadata'].items():
204 for key, value in self.description['Metadata'].items():
198 meta[key] = self.fp[value][()]
205 meta[key] = self.fp[value][()]
199 else:
206 else:
200 grp = self.fp['Metadata']
207 grp = self.fp['Metadata']
201 for name in grp:
208 for name in grp:
202 meta[name] = grp[name][()]
209 meta[name] = grp[name][()]
203
210
204 if self.extras:
211 if self.extras:
205 for key, value in self.extras.items():
212 for key, value in self.extras.items():
206 meta[key] = value
213 meta[key] = value
207 self.meta = meta
214 self.meta = meta
208
215
209 return
216 return
210
217
211 def __readData(self):
218 def __readData(self):
212
219
213 data = {}
220 data = {}
214
221
215 if self.description:
222 if self.description:
216 for key, value in self.description['Data'].items():
223 for key, value in self.description['Data'].items():
217 if isinstance(value, str):
224 if isinstance(value, str):
218 if isinstance(self.fp[value], h5py.Dataset):
225 if isinstance(self.fp[value], h5py.Dataset):
219 data[key] = self.fp[value][()]
226 data[key] = self.fp[value][()]
220 elif isinstance(self.fp[value], h5py.Group):
227 elif isinstance(self.fp[value], h5py.Group):
221 array = []
228 array = []
222 for ch in self.fp[value]:
229 for ch in self.fp[value]:
223 array.append(self.fp[value][ch][()])
230 array.append(self.fp[value][ch][()])
224 data[key] = numpy.array(array)
231 data[key] = numpy.array(array)
225 elif isinstance(value, list):
232 elif isinstance(value, list):
226 array = []
233 array = []
227 for ch in value:
234 for ch in value:
228 array.append(self.fp[ch][()])
235 array.append(self.fp[ch][()])
229 data[key] = numpy.array(array)
236 data[key] = numpy.array(array)
230 else:
237 else:
231 grp = self.fp['Data']
238 grp = self.fp['Data']
232 for name in grp:
239 for name in grp:
233 if isinstance(grp[name], h5py.Dataset):
240 if isinstance(grp[name], h5py.Dataset):
234 array = grp[name][()]
241 array = grp[name][()]
235 elif isinstance(grp[name], h5py.Group):
242 elif isinstance(grp[name], h5py.Group):
236 array = []
243 array = []
237 for ch in grp[name]:
244 for ch in grp[name]:
238 array.append(grp[name][ch][()])
245 array.append(grp[name][ch][()])
239 array = numpy.array(array)
246 array = numpy.array(array)
240 else:
247 else:
241 log.warning('Unknown type: {}'.format(name))
248 log.warning('Unknown type: {}'.format(name))
242
249
243 if name in self.description:
250 if name in self.description:
244 key = self.description[name]
251 key = self.description[name]
245 else:
252 else:
246 key = name
253 key = name
247 data[key] = array
254 data[key] = array
248
255
249 self.data = data
256 self.data = data
250 return
257 return
251
258
252 def getData(self):
259 def getData(self):
253
260
254 for attr in self.data:
261 for attr in self.data:
255 if self.data[attr].ndim == 1:
262 if self.data[attr].ndim == 1:
256 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
263 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
257 else:
264 else:
258 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
265 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
259
266
260 self.dataOut.flagNoData = False
267 self.dataOut.flagNoData = False
261 self.blockIndex += 1
268 self.blockIndex += 1
262
269
263 log.log("Block No. {}/{} -> {}".format(
270 log.log("Block No. {}/{} -> {}".format(
264 self.blockIndex,
271 self.blockIndex,
265 self.blocksPerFile,
272 self.blocksPerFile,
266 self.dataOut.datatime.ctime()), self.name)
273 self.dataOut.datatime.ctime()), self.name)
267
274
268 return
275 return
269
276
270 def run(self, **kwargs):
277 def run(self, **kwargs):
271
278
272 if not(self.isConfig):
279 if not(self.isConfig):
273 self.setup(**kwargs)
280 self.setup(**kwargs)
274 self.isConfig = True
281 self.isConfig = True
275
282
276 if self.blockIndex == self.blocksPerFile:
283 if self.blockIndex == self.blocksPerFile:
277 self.setNextFile()
284 self.setNextFile()
278
285
279 self.getData()
286 self.getData()
280
287
281 return
288 return
282
289
283 @MPDecorator
290 @MPDecorator
284 class HDFWriter(Operation):
291 class HDFWriter(Operation):
285 """Operation to write HDF5 files.
292 """Operation to write HDF5 files.
286
293
287 The HDF5 file contains by default two groups Data and Metadata where
294 The HDF5 file contains by default two groups Data and Metadata where
288 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
295 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
289 parameters, data attributes are normaly time dependent where the metadata
296 parameters, data attributes are normaly time dependent where the metadata
290 are not.
297 are not.
291 It is possible to customize the structure of the HDF5 file with the
298 It is possible to customize the structure of the HDF5 file with the
292 optional description parameter see the examples.
299 optional description parameter see the examples.
293
300
294 Parameters:
301 Parameters:
295 -----------
302 -----------
296 path : str
303 path : str
297 Path where files will be saved.
304 Path where files will be saved.
298 blocksPerFile : int
305 blocksPerFile : int
299 Number of blocks per file
306 Number of blocks per file
300 metadataList : list
307 metadataList : list
301 List of the dataOut attributes that will be saved as metadata
308 List of the dataOut attributes that will be saved as metadata
302 dataList : int
309 dataList : int
303 List of the dataOut attributes that will be saved as data
310 List of the dataOut attributes that will be saved as data
304 setType : bool
311 setType : bool
305 If True the name of the files corresponds to the timestamp of the data
312 If True the name of the files corresponds to the timestamp of the data
306 description : dict, optional
313 description : dict, optional
307 Dictionary with the desired description of the HDF5 file
314 Dictionary with the desired description of the HDF5 file
308
315
309 Examples
316 Examples
310 --------
317 --------
311
318
312 desc = {
319 desc = {
313 'data_output': {'winds': ['z', 'w', 'v']},
320 'data_output': {'winds': ['z', 'w', 'v']},
314 'utctime': 'timestamps',
321 'utctime': 'timestamps',
315 'heightList': 'heights'
322 'heightList': 'heights'
316 }
323 }
317 desc = {
324 desc = {
318 'data_output': ['z', 'w', 'v'],
325 'data_output': ['z', 'w', 'v'],
319 'utctime': 'timestamps',
326 'utctime': 'timestamps',
320 'heightList': 'heights'
327 'heightList': 'heights'
321 }
328 }
322 desc = {
329 desc = {
323 'Data': {
330 'Data': {
324 'data_output': 'winds',
331 'data_output': 'winds',
325 'utctime': 'timestamps'
332 'utctime': 'timestamps'
326 },
333 },
327 'Metadata': {
334 'Metadata': {
328 'heightList': 'heights'
335 'heightList': 'heights'
329 }
336 }
330 }
337 }
331
338
332 writer = proc_unit.addOperation(name='HDFWriter')
339 writer = proc_unit.addOperation(name='HDFWriter')
333 writer.addParameter(name='path', value='/path/to/file')
340 writer.addParameter(name='path', value='/path/to/file')
334 writer.addParameter(name='blocksPerFile', value='32')
341 writer.addParameter(name='blocksPerFile', value='32')
335 writer.addParameter(name='metadataList', value='heightList,timeZone')
342 writer.addParameter(name='metadataList', value='heightList,timeZone')
336 writer.addParameter(name='dataList',value='data_output,utctime')
343 writer.addParameter(name='dataList',value='data_output,utctime')
337 # writer.addParameter(name='description',value=json.dumps(desc))
344 # writer.addParameter(name='description',value=json.dumps(desc))
338
345
339 """
346 """
340
347
341 ext = ".hdf5"
348 ext = ".hdf5"
342 optchar = "D"
349 optchar = "D"
343 filename = None
350 filename = None
344 path = None
351 path = None
345 setFile = None
352 setFile = None
346 fp = None
353 fp = None
347 firsttime = True
354 firsttime = True
348 #Configurations
355 #Configurations
349 blocksPerFile = None
356 blocksPerFile = None
350 blockIndex = None
357 blockIndex = None
351 dataOut = None
358 dataOut = None
352 #Data Arrays
359 #Data Arrays
353 dataList = None
360 dataList = None
354 metadataList = None
361 metadataList = None
355 currentDay = None
362 currentDay = None
356 lastTime = None
363 lastTime = None
357
364
358 def __init__(self):
365 def __init__(self):
359
366
360 Operation.__init__(self)
367 Operation.__init__(self)
361 return
368 return
362
369
363 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None, uniqueChannel=False):
370 def set_kwargs(self, **kwargs):
371
372 for key, value in kwargs.items():
373 setattr(self, key, value)
374
375 def set_kwargs_obj(self, obj, **kwargs):
376
377 for key, value in kwargs.items():
378 setattr(obj, key, value)
379
380 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None, **kwargs):
364 self.path = path
381 self.path = path
365 self.blocksPerFile = blocksPerFile
382 self.blocksPerFile = blocksPerFile
366 self.metadataList = metadataList
383 self.metadataList = metadataList
367 self.dataList = [s.strip() for s in dataList]
384 self.dataList = [s.strip() for s in dataList]
368 self.setType = setType
385 self.setType = setType
369 self.description = description
386 self.description = description
370 self.uniqueChannel = uniqueChannel
387 self.set_kwargs(**kwargs)
388 #print("self.uniqueChannel: ", self.uniqueChannel)
389 #self.uniqueChannel = uniqueChannel
371
390
372 if self.metadataList is None:
391 if self.metadataList is None:
373 self.metadataList = self.dataOut.metadata_list
392 self.metadataList = self.dataOut.metadata_list
374
393
375 tableList = []
394 tableList = []
376 dsList = []
395 dsList = []
377
396
378 for i in range(len(self.dataList)):
397 for i in range(len(self.dataList)):
379 dsDict = {}
398 dsDict = {}
380 if hasattr(self.dataOut, self.dataList[i]):
399 if hasattr(self.dataOut, self.dataList[i]):
381 dataAux = getattr(self.dataOut, self.dataList[i])
400 dataAux = getattr(self.dataOut, self.dataList[i])
382 dsDict['variable'] = self.dataList[i]
401 dsDict['variable'] = self.dataList[i]
383 else:
402 else:
384 log.warning('Attribute {} not found in dataOut', self.name)
403 log.warning('Attribute {} not found in dataOut', self.name)
385 continue
404 continue
386
405
387 if dataAux is None:
406 if dataAux is None:
388 continue
407 continue
389 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
408 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
390 dsDict['nDim'] = 0
409 dsDict['nDim'] = 0
391 else:
410 else:
392 if uniqueChannel: #Creates extra dimension to avoid the creation of multiple channels
411 if self.uniqueChannel: #Creates extra dimension to avoid the creation of multiple channels
393 dataAux = numpy.expand_dims(dataAux, axis=0)
412 dataAux = numpy.expand_dims(dataAux, axis=0)
394 #setattr(self.dataOut, self.dataList[i], numpy.expand_dims(getattr(self.dataOut, self.dataList[i]), axis=0))
413 #setattr(self.dataOut, self.dataList[i], numpy.expand_dims(getattr(self.dataOut, self.dataList[i]), axis=0))
395 #dataAux = getattr(self.dataOut, self.dataList[i])
414 #dataAux = getattr(self.dataOut, self.dataList[i])
396 #print(getattr(self.dataOut, self.dataList[i]))
415 #print(getattr(self.dataOut, self.dataList[i]))
397 dsDict['nDim'] = len(dataAux.shape)
416 dsDict['nDim'] = len(dataAux.shape)
398 dsDict['shape'] = dataAux.shape
417 dsDict['shape'] = dataAux.shape
399 dsDict['dsNumber'] = dataAux.shape[0]
418 dsDict['dsNumber'] = dataAux.shape[0]
400 dsDict['dtype'] = dataAux.dtype
419 dsDict['dtype'] = dataAux.dtype
401
420
402 dsList.append(dsDict)
421 dsList.append(dsDict)
403
422
404 self.dsList = dsList
423 self.dsList = dsList
405 self.currentDay = self.dataOut.datatime.date()
424 self.currentDay = self.dataOut.datatime.date()
406
425
407 def timeFlag(self):
426 def timeFlag(self):
408 currentTime = self.dataOut.utctime
427 currentTime = self.dataOut.utctime
409 timeTuple = time.localtime(currentTime)
428 timeTuple = time.localtime(currentTime)
410 dataDay = timeTuple.tm_yday
429 dataDay = timeTuple.tm_yday
411
430
412 if self.lastTime is None:
431 if self.lastTime is None:
413 self.lastTime = currentTime
432 self.lastTime = currentTime
414 self.currentDay = dataDay
433 self.currentDay = dataDay
415 return False
434 return False
416
435
417 timeDiff = currentTime - self.lastTime
436 timeDiff = currentTime - self.lastTime
418
437
419 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
438 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
420 if dataDay != self.currentDay:
439 if dataDay != self.currentDay:
421 self.currentDay = dataDay
440 self.currentDay = dataDay
422 return True
441 return True
423 elif timeDiff > 3*60*60:
442 elif timeDiff > 3*60*60:
424 self.lastTime = currentTime
443 self.lastTime = currentTime
425 return True
444 return True
426 else:
445 else:
427 self.lastTime = currentTime
446 self.lastTime = currentTime
428 return False
447 return False
429
448
430 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
449 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
431 dataList=[], setType=None, description={}, uniqueChannel= False):
450 dataList=[], setType=None, description={}, **kwargs):
432
451
433 self.dataOut = dataOut
452 self.dataOut = dataOut
453 self.set_kwargs_obj(self.dataOut, **kwargs)
434 if not(self.isConfig):
454 if not(self.isConfig):
435 self.setup(path=path, blocksPerFile=blocksPerFile,
455 self.setup(path=path, blocksPerFile=blocksPerFile,
436 metadataList=metadataList, dataList=dataList,
456 metadataList=metadataList, dataList=dataList,
437 setType=setType, description=description, uniqueChannel=uniqueChannel)
457 setType=setType, description=description, **kwargs)
438
458
439 self.isConfig = True
459 self.isConfig = True
440 self.setNextFile()
460 self.setNextFile()
441
461
442 self.putData()
462 self.putData()
443
463
444 return
464 return
445
465
446 def setNextFile(self):
466 def setNextFile(self):
447
467
448 ext = self.ext
468 ext = self.ext
449 path = self.path
469 path = self.path
450 setFile = self.setFile
470 setFile = self.setFile
451
471
452 timeTuple = time.localtime(self.dataOut.utctime)
472 timeTuple = time.localtime(self.dataOut.utctime)
453 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
473 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
454 fullpath = os.path.join(path, subfolder)
474 fullpath = os.path.join(path, subfolder)
455
475
456 if os.path.exists(fullpath):
476 if os.path.exists(fullpath):
457 filesList = os.listdir(fullpath)
477 filesList = os.listdir(fullpath)
458 filesList = [k for k in filesList if k.startswith(self.optchar)]
478 filesList = [k for k in filesList if k.startswith(self.optchar)]
459 if len( filesList ) > 0:
479 if len( filesList ) > 0:
460 filesList = sorted(filesList, key=str.lower)
480 filesList = sorted(filesList, key=str.lower)
461 filen = filesList[-1]
481 filen = filesList[-1]
462 # el filename debera tener el siguiente formato
482 # el filename debera tener el siguiente formato
463 # 0 1234 567 89A BCDE (hex)
483 # 0 1234 567 89A BCDE (hex)
464 # x YYYY DDD SSS .ext
484 # x YYYY DDD SSS .ext
465 if isNumber(filen[8:11]):
485 if isNumber(filen[8:11]):
466 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
486 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
467 else:
487 else:
468 setFile = -1
488 setFile = -1
469 else:
489 else:
470 setFile = -1 #inicializo mi contador de seteo
490 setFile = -1 #inicializo mi contador de seteo
471 else:
491 else:
472 os.makedirs(fullpath)
492 os.makedirs(fullpath)
473 setFile = -1 #inicializo mi contador de seteo
493 setFile = -1 #inicializo mi contador de seteo
474
494
475 if self.setType is None:
495 if self.setType is None:
476 setFile += 1
496 setFile += 1
477 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
497 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
478 timeTuple.tm_year,
498 timeTuple.tm_year,
479 timeTuple.tm_yday,
499 timeTuple.tm_yday,
480 setFile,
500 setFile,
481 ext )
501 ext )
482 else:
502 else:
483 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
503 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
484 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
504 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
485 timeTuple.tm_year,
505 timeTuple.tm_year,
486 timeTuple.tm_yday,
506 timeTuple.tm_yday,
487 setFile,
507 setFile,
488 ext )
508 ext )
489
509
490 self.filename = os.path.join( path, subfolder, file )
510 self.filename = os.path.join( path, subfolder, file )
491
511
492 #Setting HDF5 File
512 #Setting HDF5 File
493 self.fp = h5py.File(self.filename, 'w')
513 self.fp = h5py.File(self.filename, 'w')
494 #write metadata
514 #write metadata
495 self.writeMetadata(self.fp)
515 self.writeMetadata(self.fp)
496 #Write data
516 #Write data
497 self.writeData(self.fp)
517 self.writeData(self.fp)
498
518
499 def getLabel(self, name, x=None):
519 def getLabel(self, name, x=None):
500 #print("x: ", x)
520 #print("x: ", x)
501 if x is None:
521 if x is None:
502 if 'Data' in self.description:
522 if 'Data' in self.description:
503 data = self.description['Data']
523 data = self.description['Data']
504 if 'Metadata' in self.description:
524 if 'Metadata' in self.description:
505 data.update(self.description['Metadata'])
525 data.update(self.description['Metadata'])
506 else:
526 else:
507 data = self.description
527 data = self.description
508 if name in data:
528 if name in data:
509 if isinstance(data[name], str):
529 if isinstance(data[name], str):
510 return data[name]
530 return data[name]
511 elif isinstance(data[name], list):
531 elif isinstance(data[name], list):
512 return None
532 return None
513 elif isinstance(data[name], dict):
533 elif isinstance(data[name], dict):
514 for key, value in data[name].items():
534 for key, value in data[name].items():
515 return key
535 return key
516 return name
536 return name
517 else:
537 else:
518 if 'Metadata' in self.description:
538 if 'Data' in self.description:
519 meta = self.description['Metadata']
539 data = self.description['Data']
540 if 'Metadata' in self.description:
541 data.update(self.description['Metadata'])
520 else:
542 else:
521 meta = self.description
543 data = self.description
522 if name in meta:
544 if name in data:
523 if isinstance(meta[name], list):
545 if isinstance(data[name], list):
524 return meta[name][x]
546 return data[name][x]
525 elif isinstance(meta[name], dict):
547 elif isinstance(data[name], dict):
526 for key, value in meta[name].items():
548 for key, value in data[name].items():
527 return value[x]
549 return value[x]
528 if 'cspc' in name:
550 if 'cspc' in name:
529 return 'pair{:02d}'.format(x)
551 return 'pair{:02d}'.format(x)
530 else:
552 else:
531 return 'channel{:02d}'.format(x)
553 return 'channel{:02d}'.format(x)
532
554
533 def writeMetadata(self, fp):
555 def writeMetadata(self, fp):
534
556
535 if self.description:
557 if self.description:
536 if 'Metadata' in self.description:
558 if 'Metadata' in self.description:
537 grp = fp.create_group('Metadata')
559 grp = fp.create_group('Metadata')
538 else:
560 else:
539 grp = fp
561 grp = fp
540 else:
562 else:
541 grp = fp.create_group('Metadata')
563 grp = fp.create_group('Metadata')
542
564
543 for i in range(len(self.metadataList)):
565 for i in range(len(self.metadataList)):
544 if not hasattr(self.dataOut, self.metadataList[i]):
566 if not hasattr(self.dataOut, self.metadataList[i]):
545 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
567 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
546 continue
568 continue
547 value = getattr(self.dataOut, self.metadataList[i])
569 value = getattr(self.dataOut, self.metadataList[i])
548 if isinstance(value, bool):
570 if isinstance(value, bool):
549 if value is True:
571 if value is True:
550 value = 1
572 value = 1
551 else:
573 else:
552 value = 0
574 value = 0
553 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
575 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
554 return
576 return
555
577
556 def writeData(self, fp):
578 def writeData(self, fp):
557
579
558 if self.description:
580 if self.description:
559 if 'Data' in self.description:
581 if 'Data' in self.description:
560 grp = fp.create_group('Data')
582 grp = fp.create_group('Data')
561 else:
583 else:
562 grp = fp
584 grp = fp
563 else:
585 else:
564 grp = fp.create_group('Data')
586 grp = fp.create_group('Data')
565
587
566 dtsets = []
588 dtsets = []
567 data = []
589 data = []
568 #print("self.dsList: ", self.dsList)
590 #print("self.dsList: ", self.dsList)
569 for dsInfo in self.dsList:
591 for dsInfo in self.dsList:
570 if dsInfo['nDim'] == 0:
592 if dsInfo['nDim'] == 0:
571 ds = grp.create_dataset(
593 ds = grp.create_dataset(
572 self.getLabel(dsInfo['variable']),
594 self.getLabel(dsInfo['variable']),
573 (self.blocksPerFile, ),
595 (self.blocksPerFile, ),
574 chunks=True,
596 chunks=True,
575 dtype=numpy.float64)
597 dtype=numpy.float64)
576 dtsets.append(ds)
598 dtsets.append(ds)
577 data.append((dsInfo['variable'], -1))
599 data.append((dsInfo['variable'], -1))
578 else:
600 else:
579 label = self.getLabel(dsInfo['variable'])
601 label = self.getLabel(dsInfo['variable'])
580 if label is not None:
602 if label is not None:
581 sgrp = grp.create_group(label)
603 sgrp = grp.create_group(label)
582 else:
604 else:
583 sgrp = grp
605 sgrp = grp
584 if self.uniqueChannel: #Creates extra dimension to avoid the creation of multiple channels
606 if self.uniqueChannel: #Creates extra dimension to avoid the creation of multiple channels
585 setattr(self.dataOut, dsInfo['variable'], numpy.expand_dims(getattr(self.dataOut, dsInfo['variable']), axis=0))
607 setattr(self.dataOut, dsInfo['variable'], numpy.expand_dims(getattr(self.dataOut, dsInfo['variable']), axis=0))
586 for i in range(dsInfo['dsNumber']):
608 for i in range(dsInfo['dsNumber']):
587 ds = sgrp.create_dataset(
609 ds = sgrp.create_dataset(
588 self.getLabel(dsInfo['variable'], i),
610 self.getLabel(dsInfo['variable'], i),
589 (self.blocksPerFile, ) + dsInfo['shape'][1:],
611 (self.blocksPerFile, ) + dsInfo['shape'][1:],
590 chunks=True,
612 chunks=True,
591 dtype=dsInfo['dtype'])
613 dtype=dsInfo['dtype'])
592 dtsets.append(ds)
614 dtsets.append(ds)
593 data.append((dsInfo['variable'], i))
615 data.append((dsInfo['variable'], i))
594
616
595 fp.flush()
617 fp.flush()
596
618
597 log.log('Creating file: {}'.format(fp.filename), self.name)
619 log.log('Creating file: {}'.format(fp.filename), self.name)
598
620
599 self.ds = dtsets
621 self.ds = dtsets
600 self.data = data
622 self.data = data
601 self.firsttime = True
623 self.firsttime = True
602 self.blockIndex = 0
624 self.blockIndex = 0
603 return
625 return
604
626
605 def putData(self):
627 def putData(self):
606
628
607 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
629 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
608 self.closeFile()
630 self.closeFile()
609 self.setNextFile()
631 self.setNextFile()
610
632
611 for i, ds in enumerate(self.ds):
633 for i, ds in enumerate(self.ds):
612 attr, ch = self.data[i]
634 attr, ch = self.data[i]
613 if ch == -1:
635 if ch == -1:
614 ds[self.blockIndex] = getattr(self.dataOut, attr)
636 ds[self.blockIndex] = getattr(self.dataOut, attr)
615 else:
637 else:
616 if self.uniqueChannel and self.blockIndex != 0: #Creates extra dimension to avoid the creation of multiple channels
638 if self.uniqueChannel and self.blockIndex != 0: #Creates extra dimension to avoid the creation of multiple channels
617 setattr(self.dataOut, attr, numpy.expand_dims(getattr(self.dataOut, attr), axis=0))
639 setattr(self.dataOut, attr, numpy.expand_dims(getattr(self.dataOut, attr), axis=0))
618 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
640 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
619 if self.uniqueChannel: #Deletes extra dimension created to avoid the creation of multiple channels
641 if self.uniqueChannel: #Deletes extra dimension created to avoid the creation of multiple channels
620 setattr(self.dataOut, attr, getattr(self.dataOut, attr)[0])
642 setattr(self.dataOut, attr, getattr(self.dataOut, attr)[0])
621
643
622 self.fp.flush()
644 self.fp.flush()
623 self.blockIndex += 1
645 self.blockIndex += 1
624 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
646 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
625
647
626 return
648 return
627
649
628 def closeFile(self):
650 def closeFile(self):
629
651
630 if self.blockIndex != self.blocksPerFile:
652 if self.blockIndex != self.blocksPerFile:
631 for ds in self.ds:
653 for ds in self.ds:
632 ds.resize(self.blockIndex, axis=0)
654 ds.resize(self.blockIndex, axis=0)
633
655
634 if self.fp:
656 if self.fp:
635 self.fp.flush()
657 self.fp.flush()
636 self.fp.close()
658 self.fp.close()
637
659
638 def close(self):
660 def close(self):
639
661
640 self.closeFile()
662 self.closeFile()
@@ -1,696 +1,700
1 '''
1 '''
2 Created on Jul 2, 2014
2 Created on Jul 2, 2014
3
3
4 @author: roj-idl71
4 @author: roj-idl71
5 '''
5 '''
6
6
7 import numpy
7 import numpy
8
8
9 from .jroIO_base import LOCALTIME, JRODataReader, JRODataWriter
9 from .jroIO_base import LOCALTIME, JRODataReader, JRODataWriter
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
11 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
12 from schainpy.model.data.jrodata import Voltage
12 from schainpy.model.data.jrodata import Voltage
13
13
14
14
15 class VoltageReader(JRODataReader, ProcessingUnit):
15 class VoltageReader(JRODataReader, ProcessingUnit):
16 """
16 """
17 Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura
17 Esta clase permite leer datos de voltage desde archivos en formato rawdata (.r). La lectura
18 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones:
18 de los datos siempre se realiza por bloques. Los datos leidos (array de 3 dimensiones:
19 perfiles*alturas*canales) son almacenados en la variable "buffer".
19 perfiles*alturas*canales) son almacenados en la variable "buffer".
20
20
21 perfiles * alturas * canales
21 perfiles * alturas * canales
22
22
23 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
23 Esta clase contiene instancias (objetos) de las clases BasicHeader, SystemHeader,
24 RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la
24 RadarControllerHeader y Voltage. Los tres primeros se usan para almacenar informacion de la
25 cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de
25 cabecera de datos (metadata), y el cuarto (Voltage) para obtener y almacenar un perfil de
26 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
26 datos desde el "buffer" cada vez que se ejecute el metodo "getData".
27
27
28 Example:
28 Example:
29
29
30 dpath = "/home/myuser/data"
30 dpath = "/home/myuser/data"
31
31
32 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
32 startTime = datetime.datetime(2010,1,20,0,0,0,0,0,0)
33
33
34 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
34 endTime = datetime.datetime(2010,1,21,23,59,59,0,0,0)
35
35
36 readerObj = VoltageReader()
36 readerObj = VoltageReader()
37
37
38 readerObj.setup(dpath, startTime, endTime)
38 readerObj.setup(dpath, startTime, endTime)
39
39
40 while(True):
40 while(True):
41
41
42 #to get one profile
42 #to get one profile
43 profile = readerObj.getData()
43 profile = readerObj.getData()
44
44
45 #print the profile
45 #print the profile
46 print profile
46 print profile
47
47
48 #If you want to see all datablock
48 #If you want to see all datablock
49 print readerObj.datablock
49 print readerObj.datablock
50
50
51 if readerObj.flagNoMoreFiles:
51 if readerObj.flagNoMoreFiles:
52 break
52 break
53
53
54 """
54 """
55
55
56 def __init__(self):
56 def __init__(self):
57 """
57 """
58 Inicializador de la clase VoltageReader para la lectura de datos de voltage.
58 Inicializador de la clase VoltageReader para la lectura de datos de voltage.
59
59
60 Input:
60 Input:
61 dataOut : Objeto de la clase Voltage. Este objeto sera utilizado para
61 dataOut : Objeto de la clase Voltage. Este objeto sera utilizado para
62 almacenar un perfil de datos cada vez que se haga un requerimiento
62 almacenar un perfil de datos cada vez que se haga un requerimiento
63 (getData). El perfil sera obtenido a partir del buffer de datos,
63 (getData). El perfil sera obtenido a partir del buffer de datos,
64 si el buffer esta vacio se hara un nuevo proceso de lectura de un
64 si el buffer esta vacio se hara un nuevo proceso de lectura de un
65 bloque de datos.
65 bloque de datos.
66 Si este parametro no es pasado se creara uno internamente.
66 Si este parametro no es pasado se creara uno internamente.
67
67
68 Variables afectadas:
68 Variables afectadas:
69 self.dataOut
69 self.dataOut
70
70
71 Return:
71 Return:
72 None
72 None
73 """
73 """
74
74
75 ProcessingUnit.__init__(self)
75 ProcessingUnit.__init__(self)
76
76
77 self.ext = ".r"
77 self.ext = ".r"
78 self.optchar = "D"
78 self.optchar = "D"
79 self.basicHeaderObj = BasicHeader(LOCALTIME)
79 self.basicHeaderObj = BasicHeader(LOCALTIME)
80 self.systemHeaderObj = SystemHeader()
80 self.systemHeaderObj = SystemHeader()
81 self.radarControllerHeaderObj = RadarControllerHeader()
81 self.radarControllerHeaderObj = RadarControllerHeader()
82
82
83 self.processingHeaderObj = ProcessingHeader()
83 self.processingHeaderObj = ProcessingHeader()
84 self.lastUTTime = 0
84 self.lastUTTime = 0
85 self.profileIndex = 2**32 - 1
85 self.profileIndex = 2**32 - 1
86 self.dataOut = Voltage()
86 self.dataOut = Voltage()
87 self.selBlocksize = None
87 self.selBlocksize = None
88 self.selBlocktime = None
88 self.selBlocktime = None
89 ##print("1--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
89 ##print("1--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
90 def createObjByDefault(self):
90 def createObjByDefault(self):
91 ##print("2--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
91 ##print("2--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
92 dataObj = Voltage()
92 dataObj = Voltage()
93
93
94 return dataObj
94 return dataObj
95
95
96 def __hasNotDataInBuffer(self):
96 def __hasNotDataInBuffer(self):
97 ##print("3--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
97 ##print("3--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
98 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock * self.nTxs:
98 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock * self.nTxs:
99 return 1
99 return 1
100
100
101 return 0
101 return 0
102
102
103 def getBlockDimension(self):
103 def getBlockDimension(self):
104 """
104 """
105 Obtiene la cantidad de puntos a leer por cada bloque de datos
105 Obtiene la cantidad de puntos a leer por cada bloque de datos
106
106
107 Affected:
107 Affected:
108 self.blocksize
108 self.blocksize
109
109
110 Return:
110 Return:
111 None
111 None
112 """
112 """
113 ##print("4--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
113 ##print("4--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
114 pts2read = self.processingHeaderObj.profilesPerBlock * \
114 pts2read = self.processingHeaderObj.profilesPerBlock * \
115 self.processingHeaderObj.nHeights * self.systemHeaderObj.nChannels
115 self.processingHeaderObj.nHeights * self.systemHeaderObj.nChannels
116 self.blocksize = pts2read
116 self.blocksize = pts2read
117
117
118 def readBlock(self):
118 def readBlock(self):
119
119
120 """
120 """
121 readBlock lee el bloque de datos desde la posicion actual del puntero del archivo
121 readBlock lee el bloque de datos desde la posicion actual del puntero del archivo
122 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
122 (self.fp) y actualiza todos los parametros relacionados al bloque de datos
123 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
123 (metadata + data). La data leida es almacenada en el buffer y el contador del buffer
124 es seteado a 0
124 es seteado a 0
125
125
126 Inputs:
126 Inputs:
127 None
127 None
128
128
129 Return:
129 Return:
130 None
130 None
131
131
132 Affected:
132 Affected:
133 self.profileIndex
133 self.profileIndex
134 self.datablock
134 self.datablock
135 self.flagIsNewFile
135 self.flagIsNewFile
136 self.flagIsNewBlock
136 self.flagIsNewBlock
137 self.nTotalBlocks
137 self.nTotalBlocks
138
138
139 Exceptions:
139 Exceptions:
140 Si un bloque leido no es un bloque valido
140 Si un bloque leido no es un bloque valido
141 """
141 """
142 ##print("5--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
142 ##print("5--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
143 # if self.server is not None:
143 # if self.server is not None:
144 # self.zBlock = self.receiver.recv()
144 # self.zBlock = self.receiver.recv()
145 # self.zHeader = self.zBlock[:24]
145 # self.zHeader = self.zBlock[:24]
146 # self.zDataBlock = self.zBlock[24:]
146 # self.zDataBlock = self.zBlock[24:]
147 # junk = numpy.fromstring(self.zDataBlock, numpy.dtype([('real','<i4'),('imag','<i4')]))
147 # junk = numpy.fromstring(self.zDataBlock, numpy.dtype([('real','<i4'),('imag','<i4')]))
148 # self.processingHeaderObj.profilesPerBlock = 240
148 # self.processingHeaderObj.profilesPerBlock = 240
149 # self.processingHeaderObj.nHeights = 248
149 # self.processingHeaderObj.nHeights = 248
150 # self.systemHeaderObj.nChannels
150 # self.systemHeaderObj.nChannels
151 # else:
151 # else:
152 current_pointer_location = self.fp.tell()
152 current_pointer_location = self.fp.tell()
153 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
153 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
154
154
155 try:
155 try:
156 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
156 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
157 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
157 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
158 except:
158 except:
159 # print "The read block (%3d) has not enough data" %self.nReadBlocks
159 # print "The read block (%3d) has not enough data" %self.nReadBlocks
160
160
161 if self.waitDataBlock(pointer_location=current_pointer_location):
161 if self.waitDataBlock(pointer_location=current_pointer_location):
162 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
162 junk = numpy.fromfile(self.fp, self.dtype, self.blocksize)
163 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
163 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
164 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
164 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
165 # return 0
165 # return 0
166
166
167 # Dimensions : nChannels, nProfiles, nSamples
167 # Dimensions : nChannels, nProfiles, nSamples
168
168
169 junk = numpy.transpose(junk, (2, 0, 1))
169 junk = numpy.transpose(junk, (2, 0, 1))
170 self.datablock = junk['real'] + junk['imag'] * 1j
170 self.datablock = junk['real'] + junk['imag'] * 1j
171
171
172 self.profileIndex = 0
172 self.profileIndex = 0
173
173
174 self.flagIsNewFile = 0
174 self.flagIsNewFile = 0
175 self.flagIsNewBlock = 1
175 self.flagIsNewBlock = 1
176
176
177 self.nTotalBlocks += 1
177 self.nTotalBlocks += 1
178 self.nReadBlocks += 1
178 self.nReadBlocks += 1
179
179
180 return 1
180 return 1
181
181
182 def getFirstHeader(self):
182 def getFirstHeader(self):
183 ##print("6--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
183 ##print("6--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
184
184
185 self.getBasicHeader()
185 self.getBasicHeader()
186
186
187 self.dataOut.processingHeaderObj = self.processingHeaderObj.copy()
187 self.dataOut.processingHeaderObj = self.processingHeaderObj.copy()
188
188
189 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
189 self.dataOut.systemHeaderObj = self.systemHeaderObj.copy()
190
190
191 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
191 self.dataOut.radarControllerHeaderObj = self.radarControllerHeaderObj.copy()
192
192
193 #self.dataOut.ippSeconds_general=self.radarControllerHeaderObj.ippSeconds
193 #self.dataOut.ippSeconds_general=self.radarControllerHeaderObj.ippSeconds
194 #print(self.nTxs)
194 #print(self.nTxs)
195 if self.nTxs > 1:
195 if self.nTxs > 1:
196 #print(self.radarControllerHeaderObj.ippSeconds)
196 #print(self.radarControllerHeaderObj.ippSeconds)
197 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
197 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
198 #print(self.radarControllerHeaderObj.ippSeconds)
198 #print(self.radarControllerHeaderObj.ippSeconds)
199 # Time interval and code are propierties of dataOut. Its value depends of radarControllerHeaderObj.
199 # Time interval and code are propierties of dataOut. Its value depends of radarControllerHeaderObj.
200
200
201 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt
201 # self.dataOut.timeInterval = self.radarControllerHeaderObj.ippSeconds * self.processingHeaderObj.nCohInt
202 #
202 #
203 # if self.radarControllerHeaderObj.code is not None:
203 # if self.radarControllerHeaderObj.code is not None:
204 #
204 #
205 # self.dataOut.nCode = self.radarControllerHeaderObj.nCode
205 # self.dataOut.nCode = self.radarControllerHeaderObj.nCode
206 #
206 #
207 # self.dataOut.nBaud = self.radarControllerHeaderObj.nBaud
207 # self.dataOut.nBaud = self.radarControllerHeaderObj.nBaud
208 #
208 #
209 # self.dataOut.code = self.radarControllerHeaderObj.code
209 # self.dataOut.code = self.radarControllerHeaderObj.code
210
210
211 self.dataOut.dtype = self.dtype
211 self.dataOut.dtype = self.dtype
212
212
213 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
213 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock
214
214
215 self.dataOut.heightList = numpy.arange(
215 self.dataOut.heightList = numpy.arange(
216 self.processingHeaderObj.nHeights) * self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
216 self.processingHeaderObj.nHeights) * self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
217
217
218 self.dataOut.channelList = list(range(self.systemHeaderObj.nChannels))
218 self.dataOut.channelList = list(range(self.systemHeaderObj.nChannels))
219
219
220 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
220 self.dataOut.nCohInt = self.processingHeaderObj.nCohInt
221
221
222 # asumo q la data no esta decodificada
222 # asumo q la data no esta decodificada
223 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode
223 self.dataOut.flagDecodeData = self.processingHeaderObj.flag_decode
224
224
225 # asumo q la data no esta sin flip
225 # asumo q la data no esta sin flip
226 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip
226 self.dataOut.flagDeflipData = self.processingHeaderObj.flag_deflip
227
227
228 self.dataOut.flagShiftFFT = self.processingHeaderObj.shif_fft
228 self.dataOut.flagShiftFFT = self.processingHeaderObj.shif_fft
229
229
230 def reshapeData(self):
230 def reshapeData(self):
231 ##print("7--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
231 ##print("7--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
232 if self.nTxs < 0:
232 if self.nTxs < 0:
233 return
233 return
234
234
235 if self.nTxs == 1:
235 if self.nTxs == 1:
236 return
236 return
237
237
238 if self.nTxs < 1 and self.processingHeaderObj.profilesPerBlock % (1. / self.nTxs) != 0:
238 if self.nTxs < 1 and self.processingHeaderObj.profilesPerBlock % (1. / self.nTxs) != 0:
239 raise ValueError("1./nTxs (=%f), should be a multiple of nProfiles (=%d)" % (
239 raise ValueError("1./nTxs (=%f), should be a multiple of nProfiles (=%d)" % (
240 1. / self.nTxs, self.processingHeaderObj.profilesPerBlock))
240 1. / self.nTxs, self.processingHeaderObj.profilesPerBlock))
241
241
242 if self.nTxs > 1 and self.processingHeaderObj.nHeights % self.nTxs != 0:
242 if self.nTxs > 1 and self.processingHeaderObj.nHeights % self.nTxs != 0:
243 raise ValueError("nTxs (=%d), should be a multiple of nHeights (=%d)" % (
243 raise ValueError("nTxs (=%d), should be a multiple of nHeights (=%d)" % (
244 self.nTxs, self.processingHeaderObj.nHeights))
244 self.nTxs, self.processingHeaderObj.nHeights))
245
245
246 self.datablock = self.datablock.reshape(
246 self.datablock = self.datablock.reshape(
247 (self.systemHeaderObj.nChannels, self.processingHeaderObj.profilesPerBlock * self.nTxs, int(self.processingHeaderObj.nHeights / self.nTxs)))
247 (self.systemHeaderObj.nChannels, self.processingHeaderObj.profilesPerBlock * self.nTxs, int(self.processingHeaderObj.nHeights / self.nTxs)))
248
248
249 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock * self.nTxs
249 self.dataOut.nProfiles = self.processingHeaderObj.profilesPerBlock * self.nTxs
250 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights / self.nTxs) * \
250 self.dataOut.heightList = numpy.arange(self.processingHeaderObj.nHeights / self.nTxs) * \
251 self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
251 self.processingHeaderObj.deltaHeight + self.processingHeaderObj.firstHeight
252 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
252 self.dataOut.radarControllerHeaderObj.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
253
253
254 return
254 return
255
255
256 def readFirstHeaderFromServer(self):
256 def readFirstHeaderFromServer(self):
257
257
258 ##print("8--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
258 ##print("8--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
259 self.getFirstHeader()
259 self.getFirstHeader()
260
260
261 self.firstHeaderSize = self.basicHeaderObj.size
261 self.firstHeaderSize = self.basicHeaderObj.size
262
262
263 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
263 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
264 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
264 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
265 if datatype == 0:
265 if datatype == 0:
266 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
266 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
267 elif datatype == 1:
267 elif datatype == 1:
268 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
268 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
269 elif datatype == 2:
269 elif datatype == 2:
270 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
270 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
271 elif datatype == 3:
271 elif datatype == 3:
272 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
272 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
273 elif datatype == 4:
273 elif datatype == 4:
274 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
274 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
275 elif datatype == 5:
275 elif datatype == 5:
276 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
276 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
277 else:
277 else:
278 raise ValueError('Data type was not defined')
278 raise ValueError('Data type was not defined')
279
279
280 self.dtype = datatype_str
280 self.dtype = datatype_str
281 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
281 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
282 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
282 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
283 self.firstHeaderSize + self.basicHeaderSize * \
283 self.firstHeaderSize + self.basicHeaderSize * \
284 (self.processingHeaderObj.dataBlocksPerFile - 1)
284 (self.processingHeaderObj.dataBlocksPerFile - 1)
285 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
285 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
286 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
286 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
287 self.getBlockDimension()
287 self.getBlockDimension()
288
288
289 def getFromServer(self):
289 def getFromServer(self):
290 ##print("9--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
290 ##print("9--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
291 self.flagDiscontinuousBlock = 0
291 self.flagDiscontinuousBlock = 0
292 self.profileIndex = 0
292 self.profileIndex = 0
293 self.flagIsNewBlock = 1
293 self.flagIsNewBlock = 1
294 self.dataOut.flagNoData = False
294 self.dataOut.flagNoData = False
295 self.nTotalBlocks += 1
295 self.nTotalBlocks += 1
296 self.nReadBlocks += 1
296 self.nReadBlocks += 1
297 self.blockPointer = 0
297 self.blockPointer = 0
298
298
299 block = self.receiver.recv()
299 topic, block = self.receiver.recv_multipart()
300
300
301 self.basicHeaderObj.read(block[self.blockPointer:])
301 self.basicHeaderObj.read(block[self.blockPointer:])
302 self.blockPointer += self.basicHeaderObj.length
302 self.blockPointer += self.basicHeaderObj.length
303 self.systemHeaderObj.read(block[self.blockPointer:])
303 self.systemHeaderObj.read(block[self.blockPointer:])
304 self.blockPointer += self.systemHeaderObj.length
304 self.blockPointer += self.systemHeaderObj.length
305 self.radarControllerHeaderObj.read(block[self.blockPointer:])
305 self.radarControllerHeaderObj.read(block[self.blockPointer:])
306 self.blockPointer += self.radarControllerHeaderObj.length
306 self.blockPointer += self.radarControllerHeaderObj.length
307 self.processingHeaderObj.read(block[self.blockPointer:])
307 self.processingHeaderObj.read(block[self.blockPointer:])
308 self.blockPointer += self.processingHeaderObj.length
308 self.blockPointer += self.processingHeaderObj.length
309 self.readFirstHeaderFromServer()
309 self.readFirstHeaderFromServer()
310
310
311 timestamp = self.basicHeaderObj.get_datatime()
311 timestamp = self.basicHeaderObj.get_datatime()
312 print('[Reading] - Block {} - {}'.format(self.nTotalBlocks, timestamp))
312 print('[Receiving] - Block {} - {} from {}'.format(self.nTotalBlocks, timestamp, topic.decode()))
313 if self.nTotalBlocks == self.processingHeaderObj.dataBlocksPerFile:
314 self.nTotalBlocks = 0
315 self.nReadBlocks = 0
316 print('Receiving the next stream...')
313 current_pointer_location = self.blockPointer
317 current_pointer_location = self.blockPointer
314 junk = numpy.fromstring(
318 junk = numpy.fromstring(
315 block[self.blockPointer:], self.dtype, self.blocksize)
319 block[self.blockPointer:], self.dtype, self.blocksize)
316
320
317 try:
321 try:
318 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
322 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
319 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
323 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
320 except:
324 except:
321 # print "The read block (%3d) has not enough data" %self.nReadBlocks
325 # print "The read block (%3d) has not enough data" %self.nReadBlocks
322 if self.waitDataBlock(pointer_location=current_pointer_location):
326 if self.waitDataBlock(pointer_location=current_pointer_location):
323 junk = numpy.fromstring(
327 junk = numpy.fromstring(
324 block[self.blockPointer:], self.dtype, self.blocksize)
328 block[self.blockPointer:], self.dtype, self.blocksize)
325 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
329 junk = junk.reshape((self.processingHeaderObj.profilesPerBlock,
326 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
330 self.processingHeaderObj.nHeights, self.systemHeaderObj.nChannels))
327 # return 0
331 # return 0
328
332
329 # Dimensions : nChannels, nProfiles, nSamples
333 # Dimensions : nChannels, nProfiles, nSamples
330
334
331 junk = numpy.transpose(junk, (2, 0, 1))
335 junk = numpy.transpose(junk, (2, 0, 1))
332 self.datablock = junk['real'] + junk['imag'] * 1j
336 self.datablock = junk['real'] + junk['imag'] * 1j
333 self.profileIndex = 0
337 self.profileIndex = 0
334 if self.selBlocksize == None:
338 if self.selBlocksize == None:
335 self.selBlocksize = self.dataOut.nProfiles
339 self.selBlocksize = self.dataOut.nProfiles
336 if self.selBlocktime != None:
340 if self.selBlocktime != None:
337 if self.dataOut.nCohInt is not None:
341 if self.dataOut.nCohInt is not None:
338 nCohInt = self.dataOut.nCohInt
342 nCohInt = self.dataOut.nCohInt
339 else:
343 else:
340 nCohInt = 1
344 nCohInt = 1
341 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
345 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
342 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
346 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
343 self.dataOut.data = self.datablock[:,
347 self.dataOut.data = self.datablock[:,
344 self.profileIndex:self.profileIndex + self.selBlocksize, :]
348 self.profileIndex:self.profileIndex + self.selBlocksize, :]
345 datasize = self.dataOut.data.shape[1]
349 datasize = self.dataOut.data.shape[1]
346 if datasize < self.selBlocksize:
350 if datasize < self.selBlocksize:
347 buffer = numpy.zeros(
351 buffer = numpy.zeros(
348 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
352 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
349 buffer[:, :datasize, :] = self.dataOut.data
353 buffer[:, :datasize, :] = self.dataOut.data
350 self.dataOut.data = buffer
354 self.dataOut.data = buffer
351 self.profileIndex = blockIndex
355 self.profileIndex = blockIndex
352
356
353 self.dataOut.flagDataAsBlock = True
357 self.dataOut.flagDataAsBlock = True
354 self.flagIsNewBlock = 1
358 self.flagIsNewBlock = 1
355 self.dataOut.realtime = self.online
359 self.dataOut.realtime = self.online
356
360
357 return self.dataOut.data
361 return self.dataOut.data
358
362
359 def getData(self):
363 def getData(self):
360 """
364 """
361 getData obtiene una unidad de datos del buffer de lectura, un perfil, y la copia al objeto self.dataOut
365 getData obtiene una unidad de datos del buffer de lectura, un perfil, y la copia al objeto self.dataOut
362 del tipo "Voltage" con todos los parametros asociados a este (metadata). cuando no hay datos
366 del tipo "Voltage" con todos los parametros asociados a este (metadata). cuando no hay datos
363 en el buffer de lectura es necesario hacer una nueva lectura de los bloques de datos usando
367 en el buffer de lectura es necesario hacer una nueva lectura de los bloques de datos usando
364 "readNextBlock"
368 "readNextBlock"
365
369
366 Ademas incrementa el contador del buffer "self.profileIndex" en 1.
370 Ademas incrementa el contador del buffer "self.profileIndex" en 1.
367
371
368 Return:
372 Return:
369
373
370 Si el flag self.getByBlock ha sido seteado el bloque completo es copiado a self.dataOut y el self.profileIndex
374 Si el flag self.getByBlock ha sido seteado el bloque completo es copiado a self.dataOut y el self.profileIndex
371 es igual al total de perfiles leidos desde el archivo.
375 es igual al total de perfiles leidos desde el archivo.
372
376
373 Si self.getByBlock == False:
377 Si self.getByBlock == False:
374
378
375 self.dataOut.data = buffer[:, thisProfile, :]
379 self.dataOut.data = buffer[:, thisProfile, :]
376
380
377 shape = [nChannels, nHeis]
381 shape = [nChannels, nHeis]
378
382
379 Si self.getByBlock == True:
383 Si self.getByBlock == True:
380
384
381 self.dataOut.data = buffer[:, :, :]
385 self.dataOut.data = buffer[:, :, :]
382
386
383 shape = [nChannels, nProfiles, nHeis]
387 shape = [nChannels, nProfiles, nHeis]
384
388
385 Variables afectadas:
389 Variables afectadas:
386 self.dataOut
390 self.dataOut
387 self.profileIndex
391 self.profileIndex
388
392
389 Affected:
393 Affected:
390 self.dataOut
394 self.dataOut
391 self.profileIndex
395 self.profileIndex
392 self.flagDiscontinuousBlock
396 self.flagDiscontinuousBlock
393 self.flagIsNewBlock
397 self.flagIsNewBlock
394 """
398 """
395
399
396 ##print("10--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
400 ##print("10--OKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK")
397 if self.flagNoMoreFiles:
401 if self.flagNoMoreFiles:
398 self.dataOut.flagNoData = True
402 self.dataOut.flagNoData = True
399 return 0
403 return 0
400 self.flagDiscontinuousBlock = 0
404 self.flagDiscontinuousBlock = 0
401 self.flagIsNewBlock = 0
405 self.flagIsNewBlock = 0
402 if self.__hasNotDataInBuffer():
406 if self.__hasNotDataInBuffer():
403 if not(self.readNextBlock()):
407 if not(self.readNextBlock()):
404 return 0
408 return 0
405
409
406 self.getFirstHeader()
410 self.getFirstHeader()
407
411
408 self.reshapeData()
412 self.reshapeData()
409 if self.datablock is None:
413 if self.datablock is None:
410 self.dataOut.flagNoData = True
414 self.dataOut.flagNoData = True
411 return 0
415 return 0
412
416
413 if not self.getByBlock:
417 if not self.getByBlock:
414
418
415 """
419 """
416 Return profile by profile
420 Return profile by profile
417
421
418 If nTxs > 1 then one profile is divided by nTxs and number of total
422 If nTxs > 1 then one profile is divided by nTxs and number of total
419 blocks is increased by nTxs (nProfiles *= nTxs)
423 blocks is increased by nTxs (nProfiles *= nTxs)
420 """
424 """
421 self.dataOut.flagDataAsBlock = False
425 self.dataOut.flagDataAsBlock = False
422 self.dataOut.data = self.datablock[:, self.profileIndex, :]
426 self.dataOut.data = self.datablock[:, self.profileIndex, :]
423 self.dataOut.profileIndex = self.profileIndex
427 self.dataOut.profileIndex = self.profileIndex
424
428
425
429
426 self.profileIndex += 1
430 self.profileIndex += 1
427
431
428 else:
432 else:
429 """
433 """
430 Return a block
434 Return a block
431 """
435 """
432 if self.selBlocksize == None:
436 if self.selBlocksize == None:
433 self.selBlocksize = self.dataOut.nProfiles
437 self.selBlocksize = self.dataOut.nProfiles
434 if self.selBlocktime != None:
438 if self.selBlocktime != None:
435 if self.dataOut.nCohInt is not None:
439 if self.dataOut.nCohInt is not None:
436 nCohInt = self.dataOut.nCohInt
440 nCohInt = self.dataOut.nCohInt
437 else:
441 else:
438 nCohInt = 1
442 nCohInt = 1
439 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
443 self.selBlocksize = int(self.dataOut.nProfiles * round(self.selBlocktime / (
440 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
444 nCohInt * self.dataOut.ippSeconds * self.dataOut.nProfiles)))
441
445
442 self.dataOut.data = self.datablock[:,
446 self.dataOut.data = self.datablock[:,
443 self.profileIndex:self.profileIndex + self.selBlocksize, :]
447 self.profileIndex:self.profileIndex + self.selBlocksize, :]
444 self.profileIndex += self.selBlocksize
448 self.profileIndex += self.selBlocksize
445 datasize = self.dataOut.data.shape[1]
449 datasize = self.dataOut.data.shape[1]
446
450
447 if datasize < self.selBlocksize:
451 if datasize < self.selBlocksize:
448 buffer = numpy.zeros(
452 buffer = numpy.zeros(
449 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
453 (self.dataOut.data.shape[0], self.selBlocksize, self.dataOut.data.shape[2]), dtype='complex')
450 buffer[:, :datasize, :] = self.dataOut.data
454 buffer[:, :datasize, :] = self.dataOut.data
451
455
452 while datasize < self.selBlocksize: # Not enough profiles to fill the block
456 while datasize < self.selBlocksize: # Not enough profiles to fill the block
453 if not(self.readNextBlock()):
457 if not(self.readNextBlock()):
454 return 0
458 return 0
455 self.getFirstHeader()
459 self.getFirstHeader()
456 self.reshapeData()
460 self.reshapeData()
457 if self.datablock is None:
461 if self.datablock is None:
458 self.dataOut.flagNoData = True
462 self.dataOut.flagNoData = True
459 return 0
463 return 0
460 # stack data
464 # stack data
461 blockIndex = self.selBlocksize - datasize
465 blockIndex = self.selBlocksize - datasize
462 datablock1 = self.datablock[:, :blockIndex, :]
466 datablock1 = self.datablock[:, :blockIndex, :]
463
467
464 buffer[:, datasize:datasize +
468 buffer[:, datasize:datasize +
465 datablock1.shape[1], :] = datablock1
469 datablock1.shape[1], :] = datablock1
466 datasize += datablock1.shape[1]
470 datasize += datablock1.shape[1]
467
471
468 self.dataOut.data = buffer
472 self.dataOut.data = buffer
469 self.profileIndex = blockIndex
473 self.profileIndex = blockIndex
470
474
471 self.dataOut.flagDataAsBlock = True
475 self.dataOut.flagDataAsBlock = True
472 self.dataOut.nProfiles = self.dataOut.data.shape[1]
476 self.dataOut.nProfiles = self.dataOut.data.shape[1]
473
477
474 #######################DP#######################
478 #######################DP#######################
475 self.dataOut.CurrentBlock=self.nReadBlocks
479 self.dataOut.CurrentBlock=self.nReadBlocks
476 self.dataOut.LastBlock=self.processingHeaderObj.dataBlocksPerFile
480 self.dataOut.LastBlock=self.processingHeaderObj.dataBlocksPerFile
477 #######################DP#######################
481 #######################DP#######################
478 self.dataOut.flagNoData = False
482 self.dataOut.flagNoData = False
479
483
480 #self.getBasicHeader()
484 #self.getBasicHeader()
481
485
482 self.dataOut.realtime = self.online
486 self.dataOut.realtime = self.online
483
487
484 return self.dataOut.data
488 return self.dataOut.data
485
489
486
490
487 @MPDecorator
491 @MPDecorator
488 class VoltageWriter(JRODataWriter, Operation):
492 class VoltageWriter(JRODataWriter, Operation):
489 """
493 """
490 Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura
494 Esta clase permite escribir datos de voltajes a archivos procesados (.r). La escritura
491 de los datos siempre se realiza por bloques.
495 de los datos siempre se realiza por bloques.
492 """
496 """
493
497
494 ext = ".r"
498 ext = ".r"
495
499
496 optchar = "D"
500 optchar = "D"
497
501
498 shapeBuffer = None
502 shapeBuffer = None
499
503
500 def __init__(self):#, **kwargs):
504 def __init__(self):#, **kwargs):
501 """
505 """
502 Inicializador de la clase VoltageWriter para la escritura de datos de espectros.
506 Inicializador de la clase VoltageWriter para la escritura de datos de espectros.
503
507
504 Affected:
508 Affected:
505 self.dataOut
509 self.dataOut
506
510
507 Return: None
511 Return: None
508 """
512 """
509 Operation.__init__(self)#, **kwargs)
513 Operation.__init__(self)#, **kwargs)
510
514
511 self.nTotalBlocks = 0
515 self.nTotalBlocks = 0
512
516
513 self.profileIndex = 0
517 self.profileIndex = 0
514
518
515 self.isConfig = False
519 self.isConfig = False
516
520
517 self.fp = None
521 self.fp = None
518
522
519 self.flagIsNewFile = 1
523 self.flagIsNewFile = 1
520
524
521 self.blockIndex = 0
525 self.blockIndex = 0
522
526
523 self.flagIsNewBlock = 0
527 self.flagIsNewBlock = 0
524
528
525 self.setFile = None
529 self.setFile = None
526
530
527 self.dtype = None
531 self.dtype = None
528
532
529 self.path = None
533 self.path = None
530
534
531 self.filename = None
535 self.filename = None
532
536
533 self.basicHeaderObj = BasicHeader(LOCALTIME)
537 self.basicHeaderObj = BasicHeader(LOCALTIME)
534
538
535 self.systemHeaderObj = SystemHeader()
539 self.systemHeaderObj = SystemHeader()
536
540
537 self.radarControllerHeaderObj = RadarControllerHeader()
541 self.radarControllerHeaderObj = RadarControllerHeader()
538
542
539 self.processingHeaderObj = ProcessingHeader()
543 self.processingHeaderObj = ProcessingHeader()
540
544
541 def hasAllDataInBuffer(self):
545 def hasAllDataInBuffer(self):
542 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock:
546 if self.profileIndex >= self.processingHeaderObj.profilesPerBlock:
543 return 1
547 return 1
544 return 0
548 return 0
545
549
546 def setBlockDimension(self):
550 def setBlockDimension(self):
547 """
551 """
548 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
552 Obtiene las formas dimensionales del los subbloques de datos que componen un bloque
549
553
550 Affected:
554 Affected:
551 self.shape_spc_Buffer
555 self.shape_spc_Buffer
552 self.shape_cspc_Buffer
556 self.shape_cspc_Buffer
553 self.shape_dc_Buffer
557 self.shape_dc_Buffer
554
558
555 Return: None
559 Return: None
556 """
560 """
557 self.shapeBuffer = (self.processingHeaderObj.profilesPerBlock,
561 self.shapeBuffer = (self.processingHeaderObj.profilesPerBlock,
558 self.processingHeaderObj.nHeights,
562 self.processingHeaderObj.nHeights,
559 self.systemHeaderObj.nChannels)
563 self.systemHeaderObj.nChannels)
560
564
561 self.datablock = numpy.zeros((self.systemHeaderObj.nChannels,
565 self.datablock = numpy.zeros((self.systemHeaderObj.nChannels,
562 self.processingHeaderObj.profilesPerBlock,
566 self.processingHeaderObj.profilesPerBlock,
563 self.processingHeaderObj.nHeights),
567 self.processingHeaderObj.nHeights),
564 dtype=numpy.dtype('complex64'))
568 dtype=numpy.dtype('complex64'))
565
569
566 def writeBlock(self):
570 def writeBlock(self):
567 """
571 """
568 Escribe el buffer en el file designado
572 Escribe el buffer en el file designado
569
573
570 Affected:
574 Affected:
571 self.profileIndex
575 self.profileIndex
572 self.flagIsNewFile
576 self.flagIsNewFile
573 self.flagIsNewBlock
577 self.flagIsNewBlock
574 self.nTotalBlocks
578 self.nTotalBlocks
575 self.blockIndex
579 self.blockIndex
576
580
577 Return: None
581 Return: None
578 """
582 """
579 data = numpy.zeros(self.shapeBuffer, self.dtype)
583 data = numpy.zeros(self.shapeBuffer, self.dtype)
580
584
581 junk = numpy.transpose(self.datablock, (1, 2, 0))
585 junk = numpy.transpose(self.datablock, (1, 2, 0))
582
586
583 data['real'] = junk.real
587 data['real'] = junk.real
584 data['imag'] = junk.imag
588 data['imag'] = junk.imag
585
589
586 data = data.reshape((-1))
590 data = data.reshape((-1))
587
591
588 data.tofile(self.fp)
592 data.tofile(self.fp)
589
593
590 self.datablock.fill(0)
594 self.datablock.fill(0)
591
595
592 self.profileIndex = 0
596 self.profileIndex = 0
593 self.flagIsNewFile = 0
597 self.flagIsNewFile = 0
594 self.flagIsNewBlock = 1
598 self.flagIsNewBlock = 1
595
599
596 self.blockIndex += 1
600 self.blockIndex += 1
597 self.nTotalBlocks += 1
601 self.nTotalBlocks += 1
598
602
599 # print "[Writing] Block = %04d" %self.blockIndex
603 # print "[Writing] Block = %04d" %self.blockIndex
600
604
601 def putData(self):
605 def putData(self):
602 """
606 """
603 Setea un bloque de datos y luego los escribe en un file
607 Setea un bloque de datos y luego los escribe en un file
604
608
605 Affected:
609 Affected:
606 self.flagIsNewBlock
610 self.flagIsNewBlock
607 self.profileIndex
611 self.profileIndex
608
612
609 Return:
613 Return:
610 0 : Si no hay data o no hay mas files que puedan escribirse
614 0 : Si no hay data o no hay mas files que puedan escribirse
611 1 : Si se escribio la data de un bloque en un file
615 1 : Si se escribio la data de un bloque en un file
612 """
616 """
613 if self.dataOut.flagNoData:
617 if self.dataOut.flagNoData:
614 return 0
618 return 0
615
619
616 self.flagIsNewBlock = 0
620 self.flagIsNewBlock = 0
617
621
618 if self.dataOut.flagDiscontinuousBlock:
622 if self.dataOut.flagDiscontinuousBlock:
619 self.datablock.fill(0)
623 self.datablock.fill(0)
620 self.profileIndex = 0
624 self.profileIndex = 0
621 self.setNextFile()
625 self.setNextFile()
622
626
623 if self.profileIndex == 0:
627 if self.profileIndex == 0:
624 self.setBasicHeader()
628 self.setBasicHeader()
625
629
626 if not self.dataOut.flagDataAsBlock:
630 if not self.dataOut.flagDataAsBlock:
627 self.datablock[:, self.profileIndex, :] = self.dataOut.data
631 self.datablock[:, self.profileIndex, :] = self.dataOut.data
628
632
629 self.profileIndex += 1
633 self.profileIndex += 1
630 else:
634 else:
631 self.datablock[:,:,:] = self.dataOut.data
635 self.datablock[:,:,:] = self.dataOut.data
632 self.profileIndex = self.processingHeaderObj.profilesPerBlock
636 self.profileIndex = self.processingHeaderObj.profilesPerBlock
633
637
634 if self.hasAllDataInBuffer():
638 if self.hasAllDataInBuffer():
635 # if self.flagIsNewFile:
639 # if self.flagIsNewFile:
636 self.writeNextBlock()
640 self.writeNextBlock()
637 # self.setFirstHeader()
641 # self.setFirstHeader()
638
642
639 return 1
643 return 1
640
644
641 def __getBlockSize(self):
645 def __getBlockSize(self):
642 '''
646 '''
643 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Voltage
647 Este metodos determina el cantidad de bytes para un bloque de datos de tipo Voltage
644 '''
648 '''
645
649
646 dtype_width = self.getDtypeWidth()
650 dtype_width = self.getDtypeWidth()
647
651
648 blocksize = int(self.dataOut.nHeights * self.dataOut.nChannels *
652 blocksize = int(self.dataOut.nHeights * self.dataOut.nChannels *
649 self.profilesPerBlock * dtype_width * 2)
653 self.profilesPerBlock * dtype_width * 2)
650
654
651 return blocksize
655 return blocksize
652
656
653 def setFirstHeader(self):
657 def setFirstHeader(self):
654 """
658 """
655 Obtiene una copia del First Header
659 Obtiene una copia del First Header
656
660
657 Affected:
661 Affected:
658 self.systemHeaderObj
662 self.systemHeaderObj
659 self.radarControllerHeaderObj
663 self.radarControllerHeaderObj
660 self.dtype
664 self.dtype
661
665
662 Return:
666 Return:
663 None
667 None
664 """
668 """
665
669
666 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
670 self.systemHeaderObj = self.dataOut.systemHeaderObj.copy()
667 self.systemHeaderObj.nChannels = self.dataOut.nChannels
671 self.systemHeaderObj.nChannels = self.dataOut.nChannels
668 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
672 self.radarControllerHeaderObj = self.dataOut.radarControllerHeaderObj.copy()
669
673
670 self.processingHeaderObj.dtype = 0 # Voltage
674 self.processingHeaderObj.dtype = 0 # Voltage
671 self.processingHeaderObj.blockSize = self.__getBlockSize()
675 self.processingHeaderObj.blockSize = self.__getBlockSize()
672 self.processingHeaderObj.profilesPerBlock = self.profilesPerBlock
676 self.processingHeaderObj.profilesPerBlock = self.profilesPerBlock
673 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
677 self.processingHeaderObj.dataBlocksPerFile = self.blocksPerFile
674 # podria ser 1 o self.dataOut.processingHeaderObj.nWindows
678 # podria ser 1 o self.dataOut.processingHeaderObj.nWindows
675 self.processingHeaderObj.nWindows = 1
679 self.processingHeaderObj.nWindows = 1
676 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt
680 self.processingHeaderObj.nCohInt = self.dataOut.nCohInt
677 # Cuando la data de origen es de tipo Voltage
681 # Cuando la data de origen es de tipo Voltage
678 self.processingHeaderObj.nIncohInt = 1
682 self.processingHeaderObj.nIncohInt = 1
679 # Cuando la data de origen es de tipo Voltage
683 # Cuando la data de origen es de tipo Voltage
680 self.processingHeaderObj.totalSpectra = 0
684 self.processingHeaderObj.totalSpectra = 0
681
685
682 if self.dataOut.code is not None:
686 if self.dataOut.code is not None:
683 self.processingHeaderObj.code = self.dataOut.code
687 self.processingHeaderObj.code = self.dataOut.code
684 self.processingHeaderObj.nCode = self.dataOut.nCode
688 self.processingHeaderObj.nCode = self.dataOut.nCode
685 self.processingHeaderObj.nBaud = self.dataOut.nBaud
689 self.processingHeaderObj.nBaud = self.dataOut.nBaud
686
690
687 if self.processingHeaderObj.nWindows != 0:
691 if self.processingHeaderObj.nWindows != 0:
688 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
692 self.processingHeaderObj.firstHeight = self.dataOut.heightList[0]
689 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - \
693 self.processingHeaderObj.deltaHeight = self.dataOut.heightList[1] - \
690 self.dataOut.heightList[0]
694 self.dataOut.heightList[0]
691 self.processingHeaderObj.nHeights = self.dataOut.nHeights
695 self.processingHeaderObj.nHeights = self.dataOut.nHeights
692 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
696 self.processingHeaderObj.samplesWin = self.dataOut.nHeights
693
697
694 self.processingHeaderObj.processFlags = self.getProcessFlags()
698 self.processingHeaderObj.processFlags = self.getProcessFlags()
695
699
696 self.setBasicHeader()
700 self.setBasicHeader()
@@ -1,252 +1,252
1 '''
1 '''
2 Base clases to create Processing units and operations, the MPDecorator
2 Base clases to create Processing units and operations, the MPDecorator
3 must be used in plotting and writing operations to allow to run as an
3 must be used in plotting and writing operations to allow to run as an
4 external process.
4 external process.
5 '''
5 '''
6
6
7 import os
7 import os
8 import inspect
8 import inspect
9 import zmq
9 import zmq
10 import time
10 import time
11 import pickle
11 import pickle
12 import traceback
12 import traceback
13 from threading import Thread
13 from threading import Thread
14 from multiprocessing import Process, Queue
14 from multiprocessing import Process, Queue
15 from schainpy.utils import log
15 from schainpy.utils import log
16
16
17 import copy
18
19 QUEUE_SIZE = int(os.environ.get('QUEUE_MAX_SIZE', '10'))
17 QUEUE_SIZE = int(os.environ.get('QUEUE_MAX_SIZE', '10'))
20
18
21 class ProcessingUnit(object):
19 class ProcessingUnit(object):
22 '''
20 '''
23 Base class to create Signal Chain Units
21 Base class to create Signal Chain Units
24 '''
22 '''
25
23
26 proc_type = 'processing'
24 proc_type = 'processing'
25 bypass = False
27
26
28 def __init__(self):
27 def __init__(self):
29
28
30 self.dataIn = None
29 self.dataIn = None
31 self.dataOut = None
30 self.dataOut = None
32 self.isConfig = False
31 self.isConfig = False
33 self.operations = []
32 self.operations = []
34 self.name = 'Test'
33 self.name = 'Test'
35 self.inputs = []
34 self.inputs = []
36
35
37 def setInput(self, unit):
36 def setInput(self, unit):
38
37
39 attr = 'dataIn'
38 attr = 'dataIn'
40 for i, u in enumerate(unit):
39 for i, u in enumerate(unit):
41 if i==0:
40 if i==0:
42 #print(u.dataOut.flagNoData)
41 #print(u.dataOut.flagNoData)
43 #exit(1)
42 #exit(1)
44 self.dataIn = u.dataOut#.copy()
43 self.dataIn = u.dataOut#.copy()
45 self.inputs.append('dataIn')
44 self.inputs.append('dataIn')
46 else:
45 else:
47 setattr(self, 'dataIn{}'.format(i), u.dataOut)#.copy())
46 setattr(self, 'dataIn{}'.format(i), u.dataOut)#.copy())
48 self.inputs.append('dataIn{}'.format(i))
47 self.inputs.append('dataIn{}'.format(i))
49
48
50
49
51 def getAllowedArgs(self):
50 def getAllowedArgs(self):
52 if hasattr(self, '__attrs__'):
51 if hasattr(self, '__attrs__'):
53 return self.__attrs__
52 return self.__attrs__
54 else:
53 else:
55 return inspect.getargspec(self.run).args
54 return inspect.getargspec(self.run).args
56
55
57 def addOperation(self, conf, operation):
56 def addOperation(self, conf, operation):
58 '''
57 '''
59 '''
58 '''
60
59
61 self.operations.append((operation, conf.type, conf.getKwargs()))
60 self.operations.append((operation, conf.type, conf.getKwargs()))
62
61
63 def getOperationObj(self, objId):
62 def getOperationObj(self, objId):
64
63
65 if objId not in list(self.operations.keys()):
64 if objId not in list(self.operations.keys()):
66 return None
65 return None
67
66
68 return self.operations[objId]
67 return self.operations[objId]
69
68
70 def call(self, **kwargs):
69 def call(self, **kwargs):
71 '''
70 '''
72 '''
71 '''
73
72
74 try:
73 try:
75 if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error:
74 if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error:
76 #if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error and not self.dataIn.runNextUnit:
75 #if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error and not self.dataIn.runNextUnit:
77 if self.dataIn.runNextUnit:
76 if self.dataIn.runNextUnit:
78 #print("SUCCESSSSSSS")
77 #print("SUCCESSSSSSS")
79 #exit(1)
78 #exit(1)
80 return not self.dataIn.isReady()
79 return not self.dataIn.isReady()
81 else:
80 else:
82 return self.dataIn.isReady()
81 return self.dataIn.isReady()
83 elif self.dataIn is None or not self.dataIn.error:
82 elif self.dataIn is None or not self.dataIn.error:
84 #print([getattr(self, at) for at in self.inputs])
83 if 'Reader' in self.name and self.bypass:
85 #print("Elif 1")
84 print('Skipping...reader')
85 return self.dataOut.isReady()
86 self.run(**kwargs)
86 self.run(**kwargs)
87 elif self.dataIn.error:
87 elif self.dataIn.error:
88 #print("Elif 2")
88 #print("Elif 2")
89 self.dataOut.error = self.dataIn.error
89 self.dataOut.error = self.dataIn.error
90 self.dataOut.flagNoData = True
90 self.dataOut.flagNoData = True
91 except:
91 except:
92 #print("Except")
92 #print("Except")
93 err = traceback.format_exc()
93 err = traceback.format_exc()
94 if 'SchainWarning' in err:
94 if 'SchainWarning' in err:
95 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), self.name)
95 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), self.name)
96 elif 'SchainError' in err:
96 elif 'SchainError' in err:
97 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), self.name)
97 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), self.name)
98 else:
98 else:
99 log.error(err, self.name)
99 log.error(err, self.name)
100 self.dataOut.error = True
100 self.dataOut.error = True
101 #print("before op")
101 #print("before op")
102 for op, optype, opkwargs in self.operations:
102 for op, optype, opkwargs in self.operations:
103 aux = self.dataOut.copy()
103 aux = self.dataOut.copy()
104 #aux = copy.deepcopy(self.dataOut)
104 #aux = copy.deepcopy(self.dataOut)
105 #print("**********************Before",op)
105 #print("**********************Before",op)
106 if optype == 'other' and not self.dataOut.flagNoData:
106 if optype == 'other' and not self.dataOut.flagNoData:
107 #print("**********************Other",op)
107 #print("**********************Other",op)
108 #print(self.dataOut.flagNoData)
108 #print(self.dataOut.flagNoData)
109 self.dataOut = op.run(self.dataOut, **opkwargs)
109 self.dataOut = op.run(self.dataOut, **opkwargs)
110 elif optype == 'external' and not self.dataOut.flagNoData:
110 elif optype == 'external' and not self.dataOut.flagNoData:
111 op.queue.put(aux)
111 op.queue.put(aux)
112 elif optype == 'external' and self.dataOut.error:
112 elif optype == 'external' and self.dataOut.error:
113 op.queue.put(aux)
113 op.queue.put(aux)
114 #elif optype == 'external' and self.dataOut.isReady():
114 #elif optype == 'external' and self.dataOut.isReady():
115 #op.queue.put(copy.deepcopy(self.dataOut))
115 #op.queue.put(copy.deepcopy(self.dataOut))
116 #print(not self.dataOut.isReady())
116 #print(not self.dataOut.isReady())
117
117
118 try:
118 try:
119 if self.dataOut.runNextUnit:
119 if self.dataOut.runNextUnit:
120 runNextUnit = self.dataOut.runNextUnit
120 runNextUnit = self.dataOut.runNextUnit
121 #print(self.operations)
121 #print(self.operations)
122 #print("Tru")
122 #print("Tru")
123
123
124 else:
124 else:
125 runNextUnit = self.dataOut.isReady()
125 runNextUnit = self.dataOut.isReady()
126 except:
126 except:
127 runNextUnit = self.dataOut.isReady()
127 runNextUnit = self.dataOut.isReady()
128 #exit(1)
128 #exit(1)
129 #if not self.dataOut.isReady():
129 #if not self.dataOut.isReady():
130 #return 'Error' if self.dataOut.error else input()
130 #return 'Error' if self.dataOut.error else input()
131 #print("NexT",runNextUnit)
131 #print("NexT",runNextUnit)
132 #print("error: ",self.dataOut.error)
132 #print("error: ",self.dataOut.error)
133 return 'Error' if self.dataOut.error else runNextUnit# self.dataOut.isReady()
133 return 'Error' if self.dataOut.error else runNextUnit# self.dataOut.isReady()
134
134
135 def setup(self):
135 def setup(self):
136
136
137 raise NotImplementedError
137 raise NotImplementedError
138
138
139 def run(self):
139 def run(self):
140
140
141 raise NotImplementedError
141 raise NotImplementedError
142
142
143 def close(self):
143 def close(self):
144
144
145 return
145 return
146
146
147
147
148 class Operation(object):
148 class Operation(object):
149
149
150 '''
150 '''
151 '''
151 '''
152
152
153 proc_type = 'operation'
153 proc_type = 'operation'
154
154
155 def __init__(self):
155 def __init__(self):
156
156
157 self.id = None
157 self.id = None
158 self.isConfig = False
158 self.isConfig = False
159
159
160 if not hasattr(self, 'name'):
160 if not hasattr(self, 'name'):
161 self.name = self.__class__.__name__
161 self.name = self.__class__.__name__
162
162
163 def getAllowedArgs(self):
163 def getAllowedArgs(self):
164 if hasattr(self, '__attrs__'):
164 if hasattr(self, '__attrs__'):
165 return self.__attrs__
165 return self.__attrs__
166 else:
166 else:
167 return inspect.getargspec(self.run).args
167 return inspect.getargspec(self.run).args
168
168
169 def setup(self):
169 def setup(self):
170
170
171 self.isConfig = True
171 self.isConfig = True
172
172
173 raise NotImplementedError
173 raise NotImplementedError
174
174
175 def run(self, dataIn, **kwargs):
175 def run(self, dataIn, **kwargs):
176 """
176 """
177 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
177 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
178 atributos del objeto dataIn.
178 atributos del objeto dataIn.
179
179
180 Input:
180 Input:
181
181
182 dataIn : objeto del tipo JROData
182 dataIn : objeto del tipo JROData
183
183
184 Return:
184 Return:
185
185
186 None
186 None
187
187
188 Affected:
188 Affected:
189 __buffer : buffer de recepcion de datos.
189 __buffer : buffer de recepcion de datos.
190
190
191 """
191 """
192 if not self.isConfig:
192 if not self.isConfig:
193 self.setup(**kwargs)
193 self.setup(**kwargs)
194
194
195 raise NotImplementedError
195 raise NotImplementedError
196
196
197 def close(self):
197 def close(self):
198
198
199 return
199 return
200
200
201
201
202 def MPDecorator(BaseClass):
202 def MPDecorator(BaseClass):
203 """
203 """
204 Multiprocessing class decorator
204 Multiprocessing class decorator
205
205
206 This function add multiprocessing features to a BaseClass.
206 This function add multiprocessing features to a BaseClass.
207 """
207 """
208
208
209 class MPClass(BaseClass, Process):
209 class MPClass(BaseClass, Process):
210
210
211 def __init__(self, *args, **kwargs):
211 def __init__(self, *args, **kwargs):
212 super(MPClass, self).__init__()
212 super(MPClass, self).__init__()
213 Process.__init__(self)
213 Process.__init__(self)
214
214
215 self.args = args
215 self.args = args
216 self.kwargs = kwargs
216 self.kwargs = kwargs
217 self.t = time.time()
217 self.t = time.time()
218 self.op_type = 'external'
218 self.op_type = 'external'
219 self.name = BaseClass.__name__
219 self.name = BaseClass.__name__
220 self.__doc__ = BaseClass.__doc__
220 self.__doc__ = BaseClass.__doc__
221
221
222 if 'plot' in self.name.lower() and not self.name.endswith('_'):
222 if 'plot' in self.name.lower() and not self.name.endswith('_'):
223 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
223 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
224
224
225 self.start_time = time.time()
225 self.start_time = time.time()
226 self.err_queue = args[3]
226 self.err_queue = args[3]
227 self.queue = Queue(maxsize=QUEUE_SIZE)
227 self.queue = Queue(maxsize=QUEUE_SIZE)
228 self.myrun = BaseClass.run
228 self.myrun = BaseClass.run
229
229
230 def run(self):
230 def run(self):
231
231
232 while True:
232 while True:
233
233
234 dataOut = self.queue.get()
234 dataOut = self.queue.get()
235
235
236 if not dataOut.error:
236 if not dataOut.error:
237 try:
237 try:
238 BaseClass.run(self, dataOut, **self.kwargs)
238 BaseClass.run(self, dataOut, **self.kwargs)
239 except:
239 except:
240 err = traceback.format_exc()
240 err = traceback.format_exc()
241 log.error(err, self.name)
241 log.error(err, self.name)
242 else:
242 else:
243 break
243 break
244
244
245 self.close()
245 self.close()
246
246
247 def close(self):
247 def close(self):
248
248
249 BaseClass.close(self)
249 BaseClass.close(self)
250 log.success('Done...(Time:{:4.2f} secs)'.format(time.time() - self.start_time), self.name)
250 log.success('Done...(Time:{:4.2f} secs)'.format(time.time() - self.start_time), self.name)
251
251
252 return MPClass
252 return MPClass
@@ -1,1049 +1,1062
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Spectra processing Unit and operations
5 """Spectra processing Unit and operations
6
6
7 Here you will find the processing unit `SpectraProc` and several operations
7 Here you will find the processing unit `SpectraProc` and several operations
8 to work with Spectra data type
8 to work with Spectra data type
9 """
9 """
10
10
11 import time
11 import time
12 import itertools
12 import itertools
13
13
14 import numpy
14 import numpy
15
15
16 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator, Operation
16 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator, Operation
17 from schainpy.model.data.jrodata import Spectra
17 from schainpy.model.data.jrodata import Spectra
18 from schainpy.model.data.jrodata import hildebrand_sekhon
18 from schainpy.model.data.jrodata import hildebrand_sekhon
19 from schainpy.utils import log
19 from schainpy.utils import log
20
20
21
21
22 class SpectraProc(ProcessingUnit):
22 class SpectraProc(ProcessingUnit):
23
23
24 def __init__(self):
24 def __init__(self):
25
25
26 ProcessingUnit.__init__(self)
26 ProcessingUnit.__init__(self)
27
27
28 self.buffer = None
28 self.buffer = None
29 self.firstdatatime = None
29 self.firstdatatime = None
30 self.profIndex = 0
30 self.profIndex = 0
31 self.dataOut = Spectra()
31 self.dataOut = Spectra()
32 self.id_min = None
32 self.id_min = None
33 self.id_max = None
33 self.id_max = None
34 self.setupReq = False #Agregar a todas las unidades de proc
34 self.setupReq = False #Agregar a todas las unidades de proc
35
35
36 def __updateSpecFromVoltage(self):
36 def __updateSpecFromVoltage(self):
37
37
38 self.dataOut.timeZone = self.dataIn.timeZone
38 self.dataOut.timeZone = self.dataIn.timeZone
39 self.dataOut.dstFlag = self.dataIn.dstFlag
39 self.dataOut.dstFlag = self.dataIn.dstFlag
40 self.dataOut.errorCount = self.dataIn.errorCount
40 self.dataOut.errorCount = self.dataIn.errorCount
41 self.dataOut.useLocalTime = self.dataIn.useLocalTime
41 self.dataOut.useLocalTime = self.dataIn.useLocalTime
42 try:
42 try:
43 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
43 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
44 except:
44 except:
45 pass
45 pass
46 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
46 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
47 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
47 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
48 self.dataOut.channelList = self.dataIn.channelList
48 self.dataOut.channelList = self.dataIn.channelList
49 self.dataOut.heightList = self.dataIn.heightList
49 self.dataOut.heightList = self.dataIn.heightList
50 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
50 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
51 self.dataOut.nProfiles = self.dataOut.nFFTPoints
51 self.dataOut.nProfiles = self.dataOut.nFFTPoints
52 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
52 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
53 self.dataOut.utctime = self.firstdatatime
53 self.dataOut.utctime = self.firstdatatime
54 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData
54 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData
55 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData
55 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData
56 self.dataOut.flagShiftFFT = False
56 self.dataOut.flagShiftFFT = False
57 self.dataOut.nCohInt = self.dataIn.nCohInt
57 self.dataOut.nCohInt = self.dataIn.nCohInt
58 self.dataOut.nIncohInt = 1
58 self.dataOut.nIncohInt = 1
59 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
59 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
60 self.dataOut.frequency = self.dataIn.frequency
60 self.dataOut.frequency = self.dataIn.frequency
61 self.dataOut.realtime = self.dataIn.realtime
61 self.dataOut.realtime = self.dataIn.realtime
62 self.dataOut.azimuth = self.dataIn.azimuth
62 self.dataOut.azimuth = self.dataIn.azimuth
63 self.dataOut.zenith = self.dataIn.zenith
63 self.dataOut.zenith = self.dataIn.zenith
64 self.dataOut.beam.codeList = self.dataIn.beam.codeList
64 self.dataOut.beam.codeList = self.dataIn.beam.codeList
65 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
65 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
66 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
66 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
67 self.dataOut.runNextUnit = self.dataIn.runNextUnit
67 self.dataOut.runNextUnit = self.dataIn.runNextUnit
68 try:
68 try:
69 self.dataOut.step = self.dataIn.step
69 self.dataOut.step = self.dataIn.step
70 except:
70 except:
71 pass
71 pass
72
72
73 def __getFft(self):
73 def __getFft(self):
74 """
74 """
75 Convierte valores de Voltaje a Spectra
75 Convierte valores de Voltaje a Spectra
76
76
77 Affected:
77 Affected:
78 self.dataOut.data_spc
78 self.dataOut.data_spc
79 self.dataOut.data_cspc
79 self.dataOut.data_cspc
80 self.dataOut.data_dc
80 self.dataOut.data_dc
81 self.dataOut.heightList
81 self.dataOut.heightList
82 self.profIndex
82 self.profIndex
83 self.buffer
83 self.buffer
84 self.dataOut.flagNoData
84 self.dataOut.flagNoData
85 """
85 """
86 fft_volt = numpy.fft.fft(
86 fft_volt = numpy.fft.fft(
87 self.buffer, n=self.dataOut.nFFTPoints, axis=1)
87 self.buffer, n=self.dataOut.nFFTPoints, axis=1)
88 fft_volt = fft_volt.astype(numpy.dtype('complex'))
88 fft_volt = fft_volt.astype(numpy.dtype('complex'))
89 dc = fft_volt[:, 0, :]
89 dc = fft_volt[:, 0, :]
90
90
91 # calculo de self-spectra
91 # calculo de self-spectra
92 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
92 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
93 spc = fft_volt * numpy.conjugate(fft_volt)
93 spc = fft_volt * numpy.conjugate(fft_volt)
94 spc = spc.real
94 spc = spc.real
95
95
96 blocksize = 0
96 blocksize = 0
97 blocksize += dc.size
97 blocksize += dc.size
98 blocksize += spc.size
98 blocksize += spc.size
99
99
100 cspc = None
100 cspc = None
101 pairIndex = 0
101 pairIndex = 0
102 if self.dataOut.pairsList != None:
102 if self.dataOut.pairsList != None:
103 # calculo de cross-spectra
103 # calculo de cross-spectra
104 cspc = numpy.zeros(
104 cspc = numpy.zeros(
105 (self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
105 (self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
106 for pair in self.dataOut.pairsList:
106 for pair in self.dataOut.pairsList:
107 if pair[0] not in self.dataOut.channelList:
107 if pair[0] not in self.dataOut.channelList:
108 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (
108 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (
109 str(pair), str(self.dataOut.channelList)))
109 str(pair), str(self.dataOut.channelList)))
110 if pair[1] not in self.dataOut.channelList:
110 if pair[1] not in self.dataOut.channelList:
111 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (
111 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (
112 str(pair), str(self.dataOut.channelList)))
112 str(pair), str(self.dataOut.channelList)))
113
113
114 cspc[pairIndex, :, :] = fft_volt[pair[0], :, :] * \
114 cspc[pairIndex, :, :] = fft_volt[pair[0], :, :] * \
115 numpy.conjugate(fft_volt[pair[1], :, :])
115 numpy.conjugate(fft_volt[pair[1], :, :])
116 pairIndex += 1
116 pairIndex += 1
117 blocksize += cspc.size
117 blocksize += cspc.size
118
118
119 self.dataOut.data_spc = spc
119 self.dataOut.data_spc = spc
120 self.dataOut.data_cspc = cspc
120 self.dataOut.data_cspc = cspc
121 self.dataOut.data_dc = dc
121 self.dataOut.data_dc = dc
122 self.dataOut.blockSize = blocksize
122 self.dataOut.blockSize = blocksize
123 self.dataOut.flagShiftFFT = False
123 self.dataOut.flagShiftFFT = False
124
124
125 def run(self, nProfiles=None, nFFTPoints=None, pairsList=None, ippFactor=None, shift_fft=False, runNextUnit = 0):
125 def run(self, nProfiles=None, nFFTPoints=None, pairsList=None, ippFactor=None, shift_fft=False, runNextUnit = 0):
126
126
127 self.dataIn.runNextUnit = runNextUnit
127 self.dataIn.runNextUnit = runNextUnit
128 if self.dataIn.type == "Spectra":
128 if self.dataIn.type == "Spectra":
129
129
130 self.dataOut.copy(self.dataIn)
130 self.dataOut.copy(self.dataIn)
131 if shift_fft:
131 if shift_fft:
132 #desplaza a la derecha en el eje 2 determinadas posiciones
132 #desplaza a la derecha en el eje 2 determinadas posiciones
133 shift = int(self.dataOut.nFFTPoints/2)
133 shift = int(self.dataOut.nFFTPoints/2)
134 self.dataOut.data_spc = numpy.roll(self.dataOut.data_spc, shift , axis=1)
134 self.dataOut.data_spc = numpy.roll(self.dataOut.data_spc, shift , axis=1)
135
135
136 if self.dataOut.data_cspc is not None:
136 if self.dataOut.data_cspc is not None:
137 #desplaza a la derecha en el eje 2 determinadas posiciones
137 #desplaza a la derecha en el eje 2 determinadas posiciones
138 self.dataOut.data_cspc = numpy.roll(self.dataOut.data_cspc, shift, axis=1)
138 self.dataOut.data_cspc = numpy.roll(self.dataOut.data_cspc, shift, axis=1)
139 if pairsList:
139 if pairsList:
140 self.__selectPairs(pairsList)
140 self.__selectPairs(pairsList)
141
141
142 elif self.dataIn.type == "Voltage":
142 elif self.dataIn.type == "Voltage":
143
143
144 self.dataOut.flagNoData = True
144 self.dataOut.flagNoData = True
145
145
146 if nFFTPoints == None:
146 if nFFTPoints == None:
147 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
147 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
148
148
149 if nProfiles == None:
149 if nProfiles == None:
150 nProfiles = nFFTPoints
150 nProfiles = nFFTPoints
151 #print(self.dataOut.ipp)
151 #print(self.dataOut.ipp)
152 #exit(1)
152 #exit(1)
153 if ippFactor == None:
153 if ippFactor == None:
154 self.dataOut.ippFactor = 1
154 self.dataOut.ippFactor = 1
155 #if ippFactor is not None:
155 #if ippFactor is not None:
156 #self.dataOut.ippFactor = ippFactor
156 #self.dataOut.ippFactor = ippFactor
157 #print(ippFactor)
157 #print(ippFactor)
158 #print(self.dataOut.ippFactor)
158 #print(self.dataOut.ippFactor)
159 #exit(1)
159 #exit(1)
160
160
161 self.dataOut.nFFTPoints = nFFTPoints
161 self.dataOut.nFFTPoints = nFFTPoints
162
162
163 if self.buffer is None:
163 if self.buffer is None:
164 self.buffer = numpy.zeros((self.dataIn.nChannels,
164 self.buffer = numpy.zeros((self.dataIn.nChannels,
165 nProfiles,
165 nProfiles,
166 self.dataIn.nHeights),
166 self.dataIn.nHeights),
167 dtype='complex')
167 dtype='complex')
168
168
169 if self.dataIn.flagDataAsBlock:
169 if self.dataIn.flagDataAsBlock:
170 nVoltProfiles = self.dataIn.data.shape[1]
170 nVoltProfiles = self.dataIn.data.shape[1]
171
171
172 if nVoltProfiles == nProfiles:
172 if nVoltProfiles == nProfiles:
173 self.buffer = self.dataIn.data.copy()
173 self.buffer = self.dataIn.data.copy()
174 self.profIndex = nVoltProfiles
174 self.profIndex = nVoltProfiles
175
175
176 elif nVoltProfiles < nProfiles:
176 elif nVoltProfiles < nProfiles:
177
177
178 if self.profIndex == 0:
178 if self.profIndex == 0:
179 self.id_min = 0
179 self.id_min = 0
180 self.id_max = nVoltProfiles
180 self.id_max = nVoltProfiles
181 #print(self.id_min)
181 #print(self.id_min)
182 #print(self.id_max)
182 #print(self.id_max)
183 #print(numpy.shape(self.buffer))
183 #print(numpy.shape(self.buffer))
184 self.buffer[:, self.id_min:self.id_max,
184 self.buffer[:, self.id_min:self.id_max,
185 :] = self.dataIn.data
185 :] = self.dataIn.data
186 self.profIndex += nVoltProfiles
186 self.profIndex += nVoltProfiles
187 self.id_min += nVoltProfiles
187 self.id_min += nVoltProfiles
188 self.id_max += nVoltProfiles
188 self.id_max += nVoltProfiles
189 elif nVoltProfiles > nProfiles:
190 self.reader.bypass = True
191 if self.profIndex == 0:
192 self.id_min = 0
193 self.id_max = nProfiles
194
195 self.buffer = self.dataIn.data[:, self.id_min:self.id_max,:]
196 self.profIndex += nProfiles
197 self.id_min += nProfiles
198 self.id_max += nProfiles
199 if self.id_max == nVoltProfiles:
200 self.reader.bypass = False
189 else:
201 else:
190 raise ValueError("The type object %s has %d profiles, it should just has %d profiles" % (
202 raise ValueError("The type object %s has %d profiles, it should just has %d profiles" % (
191 self.dataIn.type, self.dataIn.data.shape[1], nProfiles))
203 self.dataIn.type, self.dataIn.data.shape[1], nProfiles))
192 self.dataOut.flagNoData = True
204 self.dataOut.flagNoData = True
193 else:
205 else:
194 self.buffer[:, self.profIndex, :] = self.dataIn.data.copy()
206 self.buffer[:, self.profIndex, :] = self.dataIn.data.copy()
195 self.profIndex += 1
207 self.profIndex += 1
196
208
197 if self.firstdatatime == None:
209 if self.firstdatatime == None:
198 self.firstdatatime = self.dataIn.utctime
210 self.firstdatatime = self.dataIn.utctime
199
211
200 if self.profIndex == nProfiles:
212 if self.profIndex % nProfiles == 0:
201 self.__updateSpecFromVoltage()
213 self.__updateSpecFromVoltage()
202 if pairsList == None:
214 if pairsList == None:
203 self.dataOut.pairsList = [pair for pair in itertools.combinations(self.dataOut.channelList, 2)]
215 self.dataOut.pairsList = [pair for pair in itertools.combinations(self.dataOut.channelList, 2)]
204 else:
216 else:
205 self.dataOut.pairsList = pairsList
217 self.dataOut.pairsList = pairsList
206 self.__getFft()
218 self.__getFft()
207 self.dataOut.flagNoData = False
219 self.dataOut.flagNoData = False
208 self.firstdatatime = None
220 self.firstdatatime = None
209 self.profIndex = 0
221 if not self.reader.bypass:
222 self.profIndex = 0
210 else:
223 else:
211 raise ValueError("The type of input object '%s' is not valid".format(
224 raise ValueError("The type of input object '%s' is not valid".format(
212 self.dataIn.type))
225 self.dataIn.type))
213
226
214
227
215 def __selectPairs(self, pairsList):
228 def __selectPairs(self, pairsList):
216
229
217 if not pairsList:
230 if not pairsList:
218 return
231 return
219
232
220 pairs = []
233 pairs = []
221 pairsIndex = []
234 pairsIndex = []
222
235
223 for pair in pairsList:
236 for pair in pairsList:
224 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
237 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
225 continue
238 continue
226 pairs.append(pair)
239 pairs.append(pair)
227 pairsIndex.append(pairs.index(pair))
240 pairsIndex.append(pairs.index(pair))
228
241
229 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
242 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
230 self.dataOut.pairsList = pairs
243 self.dataOut.pairsList = pairs
231
244
232 return
245 return
233
246
234 def selectFFTs(self, minFFT, maxFFT ):
247 def selectFFTs(self, minFFT, maxFFT ):
235 """
248 """
236 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
249 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
237 minFFT<= FFT <= maxFFT
250 minFFT<= FFT <= maxFFT
238 """
251 """
239
252
240 if (minFFT > maxFFT):
253 if (minFFT > maxFFT):
241 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
254 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
242
255
243 if (minFFT < self.dataOut.getFreqRange()[0]):
256 if (minFFT < self.dataOut.getFreqRange()[0]):
244 minFFT = self.dataOut.getFreqRange()[0]
257 minFFT = self.dataOut.getFreqRange()[0]
245
258
246 if (maxFFT > self.dataOut.getFreqRange()[-1]):
259 if (maxFFT > self.dataOut.getFreqRange()[-1]):
247 maxFFT = self.dataOut.getFreqRange()[-1]
260 maxFFT = self.dataOut.getFreqRange()[-1]
248
261
249 minIndex = 0
262 minIndex = 0
250 maxIndex = 0
263 maxIndex = 0
251 FFTs = self.dataOut.getFreqRange()
264 FFTs = self.dataOut.getFreqRange()
252
265
253 inda = numpy.where(FFTs >= minFFT)
266 inda = numpy.where(FFTs >= minFFT)
254 indb = numpy.where(FFTs <= maxFFT)
267 indb = numpy.where(FFTs <= maxFFT)
255
268
256 try:
269 try:
257 minIndex = inda[0][0]
270 minIndex = inda[0][0]
258 except:
271 except:
259 minIndex = 0
272 minIndex = 0
260
273
261 try:
274 try:
262 maxIndex = indb[0][-1]
275 maxIndex = indb[0][-1]
263 except:
276 except:
264 maxIndex = len(FFTs)
277 maxIndex = len(FFTs)
265
278
266 self.selectFFTsByIndex(minIndex, maxIndex)
279 self.selectFFTsByIndex(minIndex, maxIndex)
267
280
268 return 1
281 return 1
269
282
270 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
283 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
271 newheis = numpy.where(
284 newheis = numpy.where(
272 self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
285 self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
273
286
274 if hei_ref != None:
287 if hei_ref != None:
275 newheis = numpy.where(self.dataOut.heightList > hei_ref)
288 newheis = numpy.where(self.dataOut.heightList > hei_ref)
276
289
277 minIndex = min(newheis[0])
290 minIndex = min(newheis[0])
278 maxIndex = max(newheis[0])
291 maxIndex = max(newheis[0])
279 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
292 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
280 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
293 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
281
294
282 # determina indices
295 # determina indices
283 nheis = int(self.dataOut.radarControllerHeaderObj.txB /
296 nheis = int(self.dataOut.radarControllerHeaderObj.txB /
284 (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
297 (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
285 avg_dB = 10 * \
298 avg_dB = 10 * \
286 numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
299 numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
287 beacon_dB = numpy.sort(avg_dB)[-nheis:]
300 beacon_dB = numpy.sort(avg_dB)[-nheis:]
288 beacon_heiIndexList = []
301 beacon_heiIndexList = []
289 for val in avg_dB.tolist():
302 for val in avg_dB.tolist():
290 if val >= beacon_dB[0]:
303 if val >= beacon_dB[0]:
291 beacon_heiIndexList.append(avg_dB.tolist().index(val))
304 beacon_heiIndexList.append(avg_dB.tolist().index(val))
292
305
293 #data_spc = data_spc[:,:,beacon_heiIndexList]
306 #data_spc = data_spc[:,:,beacon_heiIndexList]
294 data_cspc = None
307 data_cspc = None
295 if self.dataOut.data_cspc is not None:
308 if self.dataOut.data_cspc is not None:
296 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
309 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
297 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
310 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
298
311
299 data_dc = None
312 data_dc = None
300 if self.dataOut.data_dc is not None:
313 if self.dataOut.data_dc is not None:
301 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
314 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
302 #data_dc = data_dc[:,beacon_heiIndexList]
315 #data_dc = data_dc[:,beacon_heiIndexList]
303
316
304 self.dataOut.data_spc = data_spc
317 self.dataOut.data_spc = data_spc
305 self.dataOut.data_cspc = data_cspc
318 self.dataOut.data_cspc = data_cspc
306 self.dataOut.data_dc = data_dc
319 self.dataOut.data_dc = data_dc
307 self.dataOut.heightList = heightList
320 self.dataOut.heightList = heightList
308 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
321 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
309
322
310 return 1
323 return 1
311
324
312 def selectFFTsByIndex(self, minIndex, maxIndex):
325 def selectFFTsByIndex(self, minIndex, maxIndex):
313 """
326 """
314
327
315 """
328 """
316
329
317 if (minIndex < 0) or (minIndex > maxIndex):
330 if (minIndex < 0) or (minIndex > maxIndex):
318 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
331 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
319
332
320 if (maxIndex >= self.dataOut.nProfiles):
333 if (maxIndex >= self.dataOut.nProfiles):
321 maxIndex = self.dataOut.nProfiles-1
334 maxIndex = self.dataOut.nProfiles-1
322
335
323 #Spectra
336 #Spectra
324 data_spc = self.dataOut.data_spc[:,minIndex:maxIndex+1,:]
337 data_spc = self.dataOut.data_spc[:,minIndex:maxIndex+1,:]
325
338
326 data_cspc = None
339 data_cspc = None
327 if self.dataOut.data_cspc is not None:
340 if self.dataOut.data_cspc is not None:
328 data_cspc = self.dataOut.data_cspc[:,minIndex:maxIndex+1,:]
341 data_cspc = self.dataOut.data_cspc[:,minIndex:maxIndex+1,:]
329
342
330 data_dc = None
343 data_dc = None
331 if self.dataOut.data_dc is not None:
344 if self.dataOut.data_dc is not None:
332 data_dc = self.dataOut.data_dc[minIndex:maxIndex+1,:]
345 data_dc = self.dataOut.data_dc[minIndex:maxIndex+1,:]
333
346
334 self.dataOut.data_spc = data_spc
347 self.dataOut.data_spc = data_spc
335 self.dataOut.data_cspc = data_cspc
348 self.dataOut.data_cspc = data_cspc
336 self.dataOut.data_dc = data_dc
349 self.dataOut.data_dc = data_dc
337
350
338 self.dataOut.ippSeconds = self.dataOut.ippSeconds*(self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
351 self.dataOut.ippSeconds = self.dataOut.ippSeconds*(self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
339 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
352 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
340 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
353 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
341
354
342 return 1
355 return 1
343
356
344 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
357 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
345 # validacion de rango
358 # validacion de rango
346 print("NOISeeee")
359 print("NOISeeee")
347 if minHei == None:
360 if minHei == None:
348 minHei = self.dataOut.heightList[0]
361 minHei = self.dataOut.heightList[0]
349
362
350 if maxHei == None:
363 if maxHei == None:
351 maxHei = self.dataOut.heightList[-1]
364 maxHei = self.dataOut.heightList[-1]
352
365
353 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
366 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
354 print('minHei: %.2f is out of the heights range' % (minHei))
367 print('minHei: %.2f is out of the heights range' % (minHei))
355 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
368 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
356 minHei = self.dataOut.heightList[0]
369 minHei = self.dataOut.heightList[0]
357
370
358 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
371 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
359 print('maxHei: %.2f is out of the heights range' % (maxHei))
372 print('maxHei: %.2f is out of the heights range' % (maxHei))
360 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
373 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
361 maxHei = self.dataOut.heightList[-1]
374 maxHei = self.dataOut.heightList[-1]
362
375
363 # validacion de velocidades
376 # validacion de velocidades
364 velrange = self.dataOut.getVelRange(1)
377 velrange = self.dataOut.getVelRange(1)
365
378
366 if minVel == None:
379 if minVel == None:
367 minVel = velrange[0]
380 minVel = velrange[0]
368
381
369 if maxVel == None:
382 if maxVel == None:
370 maxVel = velrange[-1]
383 maxVel = velrange[-1]
371
384
372 if (minVel < velrange[0]) or (minVel > maxVel):
385 if (minVel < velrange[0]) or (minVel > maxVel):
373 print('minVel: %.2f is out of the velocity range' % (minVel))
386 print('minVel: %.2f is out of the velocity range' % (minVel))
374 print('minVel is setting to %.2f' % (velrange[0]))
387 print('minVel is setting to %.2f' % (velrange[0]))
375 minVel = velrange[0]
388 minVel = velrange[0]
376
389
377 if (maxVel > velrange[-1]) or (maxVel < minVel):
390 if (maxVel > velrange[-1]) or (maxVel < minVel):
378 print('maxVel: %.2f is out of the velocity range' % (maxVel))
391 print('maxVel: %.2f is out of the velocity range' % (maxVel))
379 print('maxVel is setting to %.2f' % (velrange[-1]))
392 print('maxVel is setting to %.2f' % (velrange[-1]))
380 maxVel = velrange[-1]
393 maxVel = velrange[-1]
381
394
382 # seleccion de indices para rango
395 # seleccion de indices para rango
383 minIndex = 0
396 minIndex = 0
384 maxIndex = 0
397 maxIndex = 0
385 heights = self.dataOut.heightList
398 heights = self.dataOut.heightList
386
399
387 inda = numpy.where(heights >= minHei)
400 inda = numpy.where(heights >= minHei)
388 indb = numpy.where(heights <= maxHei)
401 indb = numpy.where(heights <= maxHei)
389
402
390 try:
403 try:
391 minIndex = inda[0][0]
404 minIndex = inda[0][0]
392 except:
405 except:
393 minIndex = 0
406 minIndex = 0
394
407
395 try:
408 try:
396 maxIndex = indb[0][-1]
409 maxIndex = indb[0][-1]
397 except:
410 except:
398 maxIndex = len(heights)
411 maxIndex = len(heights)
399
412
400 if (minIndex < 0) or (minIndex > maxIndex):
413 if (minIndex < 0) or (minIndex > maxIndex):
401 raise ValueError("some value in (%d,%d) is not valid" % (
414 raise ValueError("some value in (%d,%d) is not valid" % (
402 minIndex, maxIndex))
415 minIndex, maxIndex))
403
416
404 if (maxIndex >= self.dataOut.nHeights):
417 if (maxIndex >= self.dataOut.nHeights):
405 maxIndex = self.dataOut.nHeights - 1
418 maxIndex = self.dataOut.nHeights - 1
406
419
407 # seleccion de indices para velocidades
420 # seleccion de indices para velocidades
408 indminvel = numpy.where(velrange >= minVel)
421 indminvel = numpy.where(velrange >= minVel)
409 indmaxvel = numpy.where(velrange <= maxVel)
422 indmaxvel = numpy.where(velrange <= maxVel)
410 try:
423 try:
411 minIndexVel = indminvel[0][0]
424 minIndexVel = indminvel[0][0]
412 except:
425 except:
413 minIndexVel = 0
426 minIndexVel = 0
414
427
415 try:
428 try:
416 maxIndexVel = indmaxvel[0][-1]
429 maxIndexVel = indmaxvel[0][-1]
417 except:
430 except:
418 maxIndexVel = len(velrange)
431 maxIndexVel = len(velrange)
419
432
420 # seleccion del espectro
433 # seleccion del espectro
421 data_spc = self.dataOut.data_spc[:,
434 data_spc = self.dataOut.data_spc[:,
422 minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
435 minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
423 # estimacion de ruido
436 # estimacion de ruido
424 noise = numpy.zeros(self.dataOut.nChannels)
437 noise = numpy.zeros(self.dataOut.nChannels)
425
438
426 for channel in range(self.dataOut.nChannels):
439 for channel in range(self.dataOut.nChannels):
427 daux = data_spc[channel, :, :]
440 daux = data_spc[channel, :, :]
428 sortdata = numpy.sort(daux, axis=None)
441 sortdata = numpy.sort(daux, axis=None)
429 noise[channel] = hildebrand_sekhon(sortdata, self.dataOut.nIncohInt)
442 noise[channel] = hildebrand_sekhon(sortdata, self.dataOut.nIncohInt)
430
443
431 self.dataOut.noise_estimation = noise.copy()
444 self.dataOut.noise_estimation = noise.copy()
432
445
433 return 1
446 return 1
434
447
435 class GetSNR(Operation):
448 class GetSNR(Operation):
436 '''
449 '''
437 Written by R. Flores
450 Written by R. Flores
438 '''
451 '''
439 """Operation to get SNR.
452 """Operation to get SNR.
440
453
441 Parameters:
454 Parameters:
442 -----------
455 -----------
443
456
444 Example
457 Example
445 --------
458 --------
446
459
447 op = proc_unit.addOperation(name='GetSNR', optype='other')
460 op = proc_unit.addOperation(name='GetSNR', optype='other')
448
461
449 """
462 """
450
463
451 def __init__(self, **kwargs):
464 def __init__(self, **kwargs):
452
465
453 Operation.__init__(self, **kwargs)
466 Operation.__init__(self, **kwargs)
454
467
455
468
456 def run(self,dataOut):
469 def run(self,dataOut):
457
470
458 noise = dataOut.getNoise()
471 noise = dataOut.getNoise()
459 #noise = dataOut.getNoise(ymin_index=-10) #Región superior donde solo debería de haber ruido
472 #noise = dataOut.getNoise(ymin_index=-10) #Región superior donde solo debería de haber ruido
460 #print("Noise: ", noise)
473 #print("Noise: ", noise)
461 #print("Noise_dB: ", 10*numpy.log10(noise/dataOut.normFactor))
474 #print("Noise_dB: ", 10*numpy.log10(noise/dataOut.normFactor))
462 #print("Heights: ", dataOut.heightList)
475 #print("Heights: ", dataOut.heightList)
463 #dataOut.data_snr = (dataOut.data_spc.sum(axis=1))/(noise[:,None]*dataOut.normFactor)
476 #dataOut.data_snr = (dataOut.data_spc.sum(axis=1))/(noise[:,None]*dataOut.normFactor)
464 ################dataOut.data_snr = (dataOut.data_spc.sum(axis=1))/(noise[:,None]*dataOut.nFFTPoints) #Before 12Jan2023
477 ################dataOut.data_snr = (dataOut.data_spc.sum(axis=1))/(noise[:,None]*dataOut.nFFTPoints) #Before 12Jan2023
465 #dataOut.data_snr = (dataOut.data_spc.sum(axis=1)-noise[:,None])/(noise[:,None])
478 #dataOut.data_snr = (dataOut.data_spc.sum(axis=1)-noise[:,None])/(noise[:,None])
466 dataOut.data_snr = (dataOut.data_spc.sum(axis=1)-noise[:,None]*dataOut.nFFTPoints)/(noise[:,None]*dataOut.nFFTPoints) #It works apparently
479 dataOut.data_snr = (dataOut.data_spc.sum(axis=1)-noise[:,None]*dataOut.nFFTPoints)/(noise[:,None]*dataOut.nFFTPoints) #It works apparently
467 dataOut.snl = numpy.log10(dataOut.data_snr)
480 dataOut.snl = numpy.log10(dataOut.data_snr)
468 #print("snl: ", dataOut.snl)
481 #print("snl: ", dataOut.snl)
469 #exit(1)
482 #exit(1)
470 #print(dataOut.heightList[-11])
483 #print(dataOut.heightList[-11])
471 #print(numpy.shape(dataOut.heightList))
484 #print(numpy.shape(dataOut.heightList))
472 #print(dataOut.data_snr)
485 #print(dataOut.data_snr)
473 #print(dataOut.data_snr[0,-11])
486 #print(dataOut.data_snr[0,-11])
474 #exit(1)
487 #exit(1)
475 #dataOut.data_snr = numpy.where(10*numpy.log10(dataOut.data_snr)<.5, numpy.nan, dataOut.data_snr)
488 #dataOut.data_snr = numpy.where(10*numpy.log10(dataOut.data_snr)<.5, numpy.nan, dataOut.data_snr)
476 #dataOut.data_snr = numpy.where(10*numpy.log10(dataOut.data_snr)<.1, numpy.nan, dataOut.data_snr)
489 #dataOut.data_snr = numpy.where(10*numpy.log10(dataOut.data_snr)<.1, numpy.nan, dataOut.data_snr)
477 #dataOut.data_snr = numpy.where(10*numpy.log10(dataOut.data_snr)<.0, numpy.nan, dataOut.data_snr)
490 #dataOut.data_snr = numpy.where(10*numpy.log10(dataOut.data_snr)<.0, numpy.nan, dataOut.data_snr)
478 #dataOut.data_snr = numpy.where(dataOut.data_snr<.05, numpy.nan, dataOut.data_snr)
491 #dataOut.data_snr = numpy.where(dataOut.data_snr<.05, numpy.nan, dataOut.data_snr)
479 #dataOut.snl = numpy.where(dataOut.data_snr<.01, numpy.nan, dataOut.snl)
492 #dataOut.snl = numpy.where(dataOut.data_snr<.01, numpy.nan, dataOut.snl)
480 dataOut.snl = numpy.where(dataOut.snl<-1, numpy.nan, dataOut.snl)
493 dataOut.snl = numpy.where(dataOut.snl<-1, numpy.nan, dataOut.snl)
481 '''
494 '''
482 import matplotlib.pyplot as plt
495 import matplotlib.pyplot as plt
483 #plt.plot(10*numpy.log10(dataOut.data_snr[0]),dataOut.heightList)
496 #plt.plot(10*numpy.log10(dataOut.data_snr[0]),dataOut.heightList)
484 plt.plot(dataOut.data_snr[0],dataOut.heightList)#,marker='*')
497 plt.plot(dataOut.data_snr[0],dataOut.heightList)#,marker='*')
485 plt.xlim(-1,10)
498 plt.xlim(-1,10)
486 plt.axvline(1,color='k')
499 plt.axvline(1,color='k')
487 plt.axvline(.1,color='k',linestyle='--')
500 plt.axvline(.1,color='k',linestyle='--')
488 plt.grid()
501 plt.grid()
489 plt.show()
502 plt.show()
490 '''
503 '''
491 #dataOut.data_snr = 10*numpy.log10(dataOut.data_snr)
504 #dataOut.data_snr = 10*numpy.log10(dataOut.data_snr)
492 #dataOut.data_snr = numpy.expand_dims(dataOut.data_snr,axis=0)
505 #dataOut.data_snr = numpy.expand_dims(dataOut.data_snr,axis=0)
493 #print(dataOut.data_snr.shape)
506 #print(dataOut.data_snr.shape)
494 #exit(1)
507 #exit(1)
495 #print("Before: ", dataOut.data_snr[0])
508 #print("Before: ", dataOut.data_snr[0])
496
509
497
510
498 return dataOut
511 return dataOut
499
512
500 class removeDC(Operation):
513 class removeDC(Operation):
501
514
502 def run(self, dataOut, mode=2):
515 def run(self, dataOut, mode=2):
503 self.dataOut = dataOut
516 self.dataOut = dataOut
504 jspectra = self.dataOut.data_spc
517 jspectra = self.dataOut.data_spc
505 jcspectra = self.dataOut.data_cspc
518 jcspectra = self.dataOut.data_cspc
506
519
507 num_chan = jspectra.shape[0]
520 num_chan = jspectra.shape[0]
508 num_hei = jspectra.shape[2]
521 num_hei = jspectra.shape[2]
509
522
510 if jcspectra is not None:
523 if jcspectra is not None:
511 jcspectraExist = True
524 jcspectraExist = True
512 num_pairs = jcspectra.shape[0]
525 num_pairs = jcspectra.shape[0]
513 else:
526 else:
514 jcspectraExist = False
527 jcspectraExist = False
515
528
516 freq_dc = int(jspectra.shape[1] / 2)
529 freq_dc = int(jspectra.shape[1] / 2)
517 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
530 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
518 ind_vel = ind_vel.astype(int)
531 ind_vel = ind_vel.astype(int)
519
532
520 if ind_vel[0] < 0:
533 if ind_vel[0] < 0:
521 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
534 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
522
535
523 if mode == 1:
536 if mode == 1:
524 jspectra[:, freq_dc, :] = (
537 jspectra[:, freq_dc, :] = (
525 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
538 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
526
539
527 if jcspectraExist:
540 if jcspectraExist:
528 jcspectra[:, freq_dc, :] = (
541 jcspectra[:, freq_dc, :] = (
529 jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
542 jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
530
543
531 if mode == 2:
544 if mode == 2:
532
545
533 vel = numpy.array([-2, -1, 1, 2])
546 vel = numpy.array([-2, -1, 1, 2])
534 xx = numpy.zeros([4, 4])
547 xx = numpy.zeros([4, 4])
535
548
536 for fil in range(4):
549 for fil in range(4):
537 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
550 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
538
551
539 xx_inv = numpy.linalg.inv(xx)
552 xx_inv = numpy.linalg.inv(xx)
540 xx_aux = xx_inv[0, :]
553 xx_aux = xx_inv[0, :]
541
554
542 for ich in range(num_chan):
555 for ich in range(num_chan):
543 yy = jspectra[ich, ind_vel, :]
556 yy = jspectra[ich, ind_vel, :]
544 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
557 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
545
558
546 junkid = jspectra[ich, freq_dc, :] <= 0
559 junkid = jspectra[ich, freq_dc, :] <= 0
547 cjunkid = sum(junkid)
560 cjunkid = sum(junkid)
548
561
549 if cjunkid.any():
562 if cjunkid.any():
550 jspectra[ich, freq_dc, junkid.nonzero()] = (
563 jspectra[ich, freq_dc, junkid.nonzero()] = (
551 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
564 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
552
565
553 if jcspectraExist:
566 if jcspectraExist:
554 for ip in range(num_pairs):
567 for ip in range(num_pairs):
555 yy = jcspectra[ip, ind_vel, :]
568 yy = jcspectra[ip, ind_vel, :]
556 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
569 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
557
570
558 self.dataOut.data_spc = jspectra
571 self.dataOut.data_spc = jspectra
559 self.dataOut.data_cspc = jcspectra
572 self.dataOut.data_cspc = jcspectra
560
573
561 return self.dataOut
574 return self.dataOut
562
575
563 class removeInterference(Operation):
576 class removeInterference(Operation):
564
577
565 def removeInterference2(self):
578 def removeInterference2(self):
566
579
567 cspc = self.dataOut.data_cspc
580 cspc = self.dataOut.data_cspc
568 spc = self.dataOut.data_spc
581 spc = self.dataOut.data_spc
569 Heights = numpy.arange(cspc.shape[2])
582 Heights = numpy.arange(cspc.shape[2])
570 realCspc = numpy.abs(cspc)
583 realCspc = numpy.abs(cspc)
571
584
572 for i in range(cspc.shape[0]):
585 for i in range(cspc.shape[0]):
573 LinePower= numpy.sum(realCspc[i], axis=0)
586 LinePower= numpy.sum(realCspc[i], axis=0)
574 Threshold = numpy.amax(LinePower)-numpy.sort(LinePower)[len(Heights)-int(len(Heights)*0.1)]
587 Threshold = numpy.amax(LinePower)-numpy.sort(LinePower)[len(Heights)-int(len(Heights)*0.1)]
575 SelectedHeights = Heights[ numpy.where( LinePower < Threshold ) ]
588 SelectedHeights = Heights[ numpy.where( LinePower < Threshold ) ]
576 InterferenceSum = numpy.sum( realCspc[i,:,SelectedHeights], axis=0 )
589 InterferenceSum = numpy.sum( realCspc[i,:,SelectedHeights], axis=0 )
577 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.98)]
590 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.98)]
578 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.99)]
591 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.99)]
579
592
580
593
581 InterferenceRange = numpy.where( ([InterferenceSum > InterferenceThresholdMin]))# , InterferenceSum < InterferenceThresholdMax]) )
594 InterferenceRange = numpy.where( ([InterferenceSum > InterferenceThresholdMin]))# , InterferenceSum < InterferenceThresholdMax]) )
582 #InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
595 #InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
583 if len(InterferenceRange)<int(cspc.shape[1]*0.3):
596 if len(InterferenceRange)<int(cspc.shape[1]*0.3):
584 cspc[i,InterferenceRange,:] = numpy.NaN
597 cspc[i,InterferenceRange,:] = numpy.NaN
585
598
586 self.dataOut.data_cspc = cspc
599 self.dataOut.data_cspc = cspc
587
600
588 def removeInterference(self, interf = 2, hei_interf = None, nhei_interf = None, offhei_interf = None):
601 def removeInterference(self, interf = 2, hei_interf = None, nhei_interf = None, offhei_interf = None):
589
602
590 jspectra = self.dataOut.data_spc
603 jspectra = self.dataOut.data_spc
591 jcspectra = self.dataOut.data_cspc
604 jcspectra = self.dataOut.data_cspc
592 jnoise = self.dataOut.getNoise()
605 jnoise = self.dataOut.getNoise()
593 num_incoh = self.dataOut.nIncohInt
606 num_incoh = self.dataOut.nIncohInt
594
607
595 num_channel = jspectra.shape[0]
608 num_channel = jspectra.shape[0]
596 num_prof = jspectra.shape[1]
609 num_prof = jspectra.shape[1]
597 num_hei = jspectra.shape[2]
610 num_hei = jspectra.shape[2]
598
611
599 # hei_interf
612 # hei_interf
600 if hei_interf is None:
613 if hei_interf is None:
601 count_hei = int(num_hei / 2)
614 count_hei = int(num_hei / 2)
602 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
615 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
603 hei_interf = numpy.asarray(hei_interf)[0]
616 hei_interf = numpy.asarray(hei_interf)[0]
604 # nhei_interf
617 # nhei_interf
605 if (nhei_interf == None):
618 if (nhei_interf == None):
606 nhei_interf = 5
619 nhei_interf = 5
607 if (nhei_interf < 1):
620 if (nhei_interf < 1):
608 nhei_interf = 1
621 nhei_interf = 1
609 if (nhei_interf > count_hei):
622 if (nhei_interf > count_hei):
610 nhei_interf = count_hei
623 nhei_interf = count_hei
611 if (offhei_interf == None):
624 if (offhei_interf == None):
612 offhei_interf = 0
625 offhei_interf = 0
613
626
614 ind_hei = list(range(num_hei))
627 ind_hei = list(range(num_hei))
615 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
628 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
616 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
629 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
617 mask_prof = numpy.asarray(list(range(num_prof)))
630 mask_prof = numpy.asarray(list(range(num_prof)))
618 num_mask_prof = mask_prof.size
631 num_mask_prof = mask_prof.size
619 comp_mask_prof = [0, num_prof / 2]
632 comp_mask_prof = [0, num_prof / 2]
620
633
621 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
634 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
622 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
635 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
623 jnoise = numpy.nan
636 jnoise = numpy.nan
624 noise_exist = jnoise[0] < numpy.Inf
637 noise_exist = jnoise[0] < numpy.Inf
625
638
626 # Subrutina de Remocion de la Interferencia
639 # Subrutina de Remocion de la Interferencia
627 for ich in range(num_channel):
640 for ich in range(num_channel):
628 # Se ordena los espectros segun su potencia (menor a mayor)
641 # Se ordena los espectros segun su potencia (menor a mayor)
629 power = jspectra[ich, mask_prof, :]
642 power = jspectra[ich, mask_prof, :]
630 power = power[:, hei_interf]
643 power = power[:, hei_interf]
631 power = power.sum(axis=0)
644 power = power.sum(axis=0)
632 psort = power.ravel().argsort()
645 psort = power.ravel().argsort()
633
646
634 # Se estima la interferencia promedio en los Espectros de Potencia empleando
647 # Se estima la interferencia promedio en los Espectros de Potencia empleando
635 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(
648 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(
636 offhei_interf, nhei_interf + offhei_interf))]]]
649 offhei_interf, nhei_interf + offhei_interf))]]]
637
650
638 if noise_exist:
651 if noise_exist:
639 # tmp_noise = jnoise[ich] / num_prof
652 # tmp_noise = jnoise[ich] / num_prof
640 tmp_noise = jnoise[ich]
653 tmp_noise = jnoise[ich]
641 junkspc_interf = junkspc_interf - tmp_noise
654 junkspc_interf = junkspc_interf - tmp_noise
642 #junkspc_interf[:,comp_mask_prof] = 0
655 #junkspc_interf[:,comp_mask_prof] = 0
643
656
644 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
657 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
645 jspc_interf = jspc_interf.transpose()
658 jspc_interf = jspc_interf.transpose()
646 # Calculando el espectro de interferencia promedio
659 # Calculando el espectro de interferencia promedio
647 noiseid = numpy.where(
660 noiseid = numpy.where(
648 jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
661 jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
649 noiseid = noiseid[0]
662 noiseid = noiseid[0]
650 cnoiseid = noiseid.size
663 cnoiseid = noiseid.size
651 interfid = numpy.where(
664 interfid = numpy.where(
652 jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
665 jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
653 interfid = interfid[0]
666 interfid = interfid[0]
654 cinterfid = interfid.size
667 cinterfid = interfid.size
655
668
656 if (cnoiseid > 0):
669 if (cnoiseid > 0):
657 jspc_interf[noiseid] = 0
670 jspc_interf[noiseid] = 0
658
671
659 # Expandiendo los perfiles a limpiar
672 # Expandiendo los perfiles a limpiar
660 if (cinterfid > 0):
673 if (cinterfid > 0):
661 new_interfid = (
674 new_interfid = (
662 numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
675 numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
663 new_interfid = numpy.asarray(new_interfid)
676 new_interfid = numpy.asarray(new_interfid)
664 new_interfid = {x for x in new_interfid}
677 new_interfid = {x for x in new_interfid}
665 new_interfid = numpy.array(list(new_interfid))
678 new_interfid = numpy.array(list(new_interfid))
666 new_cinterfid = new_interfid.size
679 new_cinterfid = new_interfid.size
667 else:
680 else:
668 new_cinterfid = 0
681 new_cinterfid = 0
669
682
670 for ip in range(new_cinterfid):
683 for ip in range(new_cinterfid):
671 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
684 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
672 jspc_interf[new_interfid[ip]
685 jspc_interf[new_interfid[ip]
673 ] = junkspc_interf[ind[nhei_interf // 2], new_interfid[ip]]
686 ] = junkspc_interf[ind[nhei_interf // 2], new_interfid[ip]]
674
687
675 jspectra[ich, :, ind_hei] = jspectra[ich, :,
688 jspectra[ich, :, ind_hei] = jspectra[ich, :,
676 ind_hei] - jspc_interf # Corregir indices
689 ind_hei] - jspc_interf # Corregir indices
677
690
678 # Removiendo la interferencia del punto de mayor interferencia
691 # Removiendo la interferencia del punto de mayor interferencia
679 ListAux = jspc_interf[mask_prof].tolist()
692 ListAux = jspc_interf[mask_prof].tolist()
680 maxid = ListAux.index(max(ListAux))
693 maxid = ListAux.index(max(ListAux))
681
694
682 if cinterfid > 0:
695 if cinterfid > 0:
683 for ip in range(cinterfid * (interf == 2) - 1):
696 for ip in range(cinterfid * (interf == 2) - 1):
684 ind = (jspectra[ich, interfid[ip], :] < tmp_noise *
697 ind = (jspectra[ich, interfid[ip], :] < tmp_noise *
685 (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
698 (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
686 cind = len(ind)
699 cind = len(ind)
687
700
688 if (cind > 0):
701 if (cind > 0):
689 jspectra[ich, interfid[ip], ind] = tmp_noise * \
702 jspectra[ich, interfid[ip], ind] = tmp_noise * \
690 (1 + (numpy.random.uniform(cind) - 0.5) /
703 (1 + (numpy.random.uniform(cind) - 0.5) /
691 numpy.sqrt(num_incoh))
704 numpy.sqrt(num_incoh))
692
705
693 ind = numpy.array([-2, -1, 1, 2])
706 ind = numpy.array([-2, -1, 1, 2])
694 xx = numpy.zeros([4, 4])
707 xx = numpy.zeros([4, 4])
695
708
696 for id1 in range(4):
709 for id1 in range(4):
697 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
710 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
698
711
699 xx_inv = numpy.linalg.inv(xx)
712 xx_inv = numpy.linalg.inv(xx)
700 xx = xx_inv[:, 0]
713 xx = xx_inv[:, 0]
701 ind = (ind + maxid + num_mask_prof) % num_mask_prof
714 ind = (ind + maxid + num_mask_prof) % num_mask_prof
702 yy = jspectra[ich, mask_prof[ind], :]
715 yy = jspectra[ich, mask_prof[ind], :]
703 jspectra[ich, mask_prof[maxid], :] = numpy.dot(
716 jspectra[ich, mask_prof[maxid], :] = numpy.dot(
704 yy.transpose(), xx)
717 yy.transpose(), xx)
705
718
706 indAux = (jspectra[ich, :, :] < tmp_noise *
719 indAux = (jspectra[ich, :, :] < tmp_noise *
707 (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
720 (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
708 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * \
721 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * \
709 (1 - 1 / numpy.sqrt(num_incoh))
722 (1 - 1 / numpy.sqrt(num_incoh))
710
723
711 # Remocion de Interferencia en el Cross Spectra
724 # Remocion de Interferencia en el Cross Spectra
712 if jcspectra is None:
725 if jcspectra is None:
713 return jspectra, jcspectra
726 return jspectra, jcspectra
714 num_pairs = int(jcspectra.size / (num_prof * num_hei))
727 num_pairs = int(jcspectra.size / (num_prof * num_hei))
715 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
728 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
716
729
717 for ip in range(num_pairs):
730 for ip in range(num_pairs):
718
731
719 #-------------------------------------------
732 #-------------------------------------------
720
733
721 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
734 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
722 cspower = cspower[:, hei_interf]
735 cspower = cspower[:, hei_interf]
723 cspower = cspower.sum(axis=0)
736 cspower = cspower.sum(axis=0)
724
737
725 cspsort = cspower.ravel().argsort()
738 cspsort = cspower.ravel().argsort()
726 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(
739 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(
727 offhei_interf, nhei_interf + offhei_interf))]]]
740 offhei_interf, nhei_interf + offhei_interf))]]]
728 junkcspc_interf = junkcspc_interf.transpose()
741 junkcspc_interf = junkcspc_interf.transpose()
729 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
742 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
730
743
731 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
744 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
732
745
733 median_real = int(numpy.median(numpy.real(
746 median_real = int(numpy.median(numpy.real(
734 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
747 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
735 median_imag = int(numpy.median(numpy.imag(
748 median_imag = int(numpy.median(numpy.imag(
736 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
749 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
737 comp_mask_prof = [int(e) for e in comp_mask_prof]
750 comp_mask_prof = [int(e) for e in comp_mask_prof]
738 junkcspc_interf[comp_mask_prof, :] = numpy.complex(
751 junkcspc_interf[comp_mask_prof, :] = numpy.complex(
739 median_real, median_imag)
752 median_real, median_imag)
740
753
741 for iprof in range(num_prof):
754 for iprof in range(num_prof):
742 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
755 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
743 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf // 2]]
756 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf // 2]]
744
757
745 # Removiendo la Interferencia
758 # Removiendo la Interferencia
746 jcspectra[ip, :, ind_hei] = jcspectra[ip,
759 jcspectra[ip, :, ind_hei] = jcspectra[ip,
747 :, ind_hei] - jcspc_interf
760 :, ind_hei] - jcspc_interf
748
761
749 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
762 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
750 maxid = ListAux.index(max(ListAux))
763 maxid = ListAux.index(max(ListAux))
751
764
752 ind = numpy.array([-2, -1, 1, 2])
765 ind = numpy.array([-2, -1, 1, 2])
753 xx = numpy.zeros([4, 4])
766 xx = numpy.zeros([4, 4])
754
767
755 for id1 in range(4):
768 for id1 in range(4):
756 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
769 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
757
770
758 xx_inv = numpy.linalg.inv(xx)
771 xx_inv = numpy.linalg.inv(xx)
759 xx = xx_inv[:, 0]
772 xx = xx_inv[:, 0]
760
773
761 ind = (ind + maxid + num_mask_prof) % num_mask_prof
774 ind = (ind + maxid + num_mask_prof) % num_mask_prof
762 yy = jcspectra[ip, mask_prof[ind], :]
775 yy = jcspectra[ip, mask_prof[ind], :]
763 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
776 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
764
777
765 # Guardar Resultados
778 # Guardar Resultados
766 self.dataOut.data_spc = jspectra
779 self.dataOut.data_spc = jspectra
767 self.dataOut.data_cspc = jcspectra
780 self.dataOut.data_cspc = jcspectra
768
781
769 return 1
782 return 1
770
783
771 def run(self, dataOut, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None, mode=1):
784 def run(self, dataOut, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None, mode=1):
772
785
773 self.dataOut = dataOut
786 self.dataOut = dataOut
774
787
775 if mode == 1:
788 if mode == 1:
776 self.removeInterference(interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None)
789 self.removeInterference(interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None)
777 elif mode == 2:
790 elif mode == 2:
778 self.removeInterference2()
791 self.removeInterference2()
779
792
780 return self.dataOut
793 return self.dataOut
781
794
782 class removeInterferenceAtFreq(Operation):
795 class removeInterferenceAtFreq(Operation):
783 '''
796 '''
784 Written by R. Flores
797 Written by R. Flores
785 '''
798 '''
786 """Operation to remove interfernce at a known frequency(s).
799 """Operation to remove interfernce at a known frequency(s).
787
800
788 Parameters:
801 Parameters:
789 -----------
802 -----------
790 None
803 None
791
804
792 Example
805 Example
793 --------
806 --------
794
807
795 op = proc_unit.addOperation(name='removeInterferenceAtFreq')
808 op = proc_unit.addOperation(name='removeInterferenceAtFreq')
796
809
797 """
810 """
798
811
799 def __init__(self):
812 def __init__(self):
800
813
801 Operation.__init__(self)
814 Operation.__init__(self)
802
815
803 def run(self, dataOut, freq = None, freqList = None):
816 def run(self, dataOut, freq = None, freqList = None):
804
817
805 VelRange = dataOut.getVelRange()
818 VelRange = dataOut.getVelRange()
806 #print("VelRange: ", VelRange)
819 #print("VelRange: ", VelRange)
807
820
808 freq_ids = []
821 freq_ids = []
809
822
810 if freq is not None:
823 if freq is not None:
811 #print("freq")
824 #print("freq")
812 #if freq < 0:
825 #if freq < 0:
813 inda = numpy.where(VelRange >= freq)
826 inda = numpy.where(VelRange >= freq)
814 minIndex = inda[0][0]
827 minIndex = inda[0][0]
815 #print(numpy.shape(dataOut.dataLag_spc))
828 #print(numpy.shape(dataOut.dataLag_spc))
816 dataOut.data_spc[:,minIndex,:] = numpy.nan
829 dataOut.data_spc[:,minIndex,:] = numpy.nan
817
830
818 #inda = numpy.where(VelRange >= ymin_noise)
831 #inda = numpy.where(VelRange >= ymin_noise)
819 #indb = numpy.where(VelRange <= ymax_noise)
832 #indb = numpy.where(VelRange <= ymax_noise)
820
833
821 #minIndex = inda[0][0]
834 #minIndex = inda[0][0]
822 #maxIndex = indb[0][-1]
835 #maxIndex = indb[0][-1]
823
836
824 elif freqList is not None:
837 elif freqList is not None:
825 #print("freqList")
838 #print("freqList")
826 for freq in freqList:
839 for freq in freqList:
827 #if freq < 0:
840 #if freq < 0:
828 inda = numpy.where(VelRange >= freq)
841 inda = numpy.where(VelRange >= freq)
829 minIndex = inda[0][0]
842 minIndex = inda[0][0]
830 #print(numpy.shape(dataOut.dataLag_spc))
843 #print(numpy.shape(dataOut.dataLag_spc))
831 if freq > 0:
844 if freq > 0:
832 #dataOut.data_spc[:,minIndex-1,:] = numpy.nan
845 #dataOut.data_spc[:,minIndex-1,:] = numpy.nan
833 freq_ids.append(minIndex-1)
846 freq_ids.append(minIndex-1)
834 else:
847 else:
835 #dataOut.data_spc[:,minIndex,:] = numpy.nan
848 #dataOut.data_spc[:,minIndex,:] = numpy.nan
836 freq_ids.append(minIndex)
849 freq_ids.append(minIndex)
837 else:
850 else:
838 raise ValueError("freq or freqList should be specified ...")
851 raise ValueError("freq or freqList should be specified ...")
839
852
840 #freq_ids = numpy.array(freq_ids).flatten()
853 #freq_ids = numpy.array(freq_ids).flatten()
841
854
842 avg = numpy.mean(dataOut.data_spc[:,[t for t in range(dataOut.data_spc.shape[0]) if t not in freq_ids],:],axis=1)
855 avg = numpy.mean(dataOut.data_spc[:,[t for t in range(dataOut.data_spc.shape[0]) if t not in freq_ids],:],axis=1)
843
856
844 for p in list(freq_ids):
857 for p in list(freq_ids):
845 dataOut.data_spc[:,p,:] = avg#numpy.nan
858 dataOut.data_spc[:,p,:] = avg#numpy.nan
846
859
847
860
848 return dataOut
861 return dataOut
849
862
850 class IncohInt(Operation):
863 class IncohInt(Operation):
851
864
852 __profIndex = 0
865 __profIndex = 0
853 __withOverapping = False
866 __withOverapping = False
854
867
855 __byTime = False
868 __byTime = False
856 __initime = None
869 __initime = None
857 __lastdatatime = None
870 __lastdatatime = None
858 __integrationtime = None
871 __integrationtime = None
859
872
860 __buffer_spc = None
873 __buffer_spc = None
861 __buffer_cspc = None
874 __buffer_cspc = None
862 __buffer_dc = None
875 __buffer_dc = None
863
876
864 __dataReady = False
877 __dataReady = False
865
878
866 __timeInterval = None
879 __timeInterval = None
867
880
868 n = None
881 n = None
869
882
870 def __init__(self):
883 def __init__(self):
871
884
872 Operation.__init__(self)
885 Operation.__init__(self)
873
886
874 def setup(self, n=None, timeInterval=None, overlapping=False):
887 def setup(self, n=None, timeInterval=None, overlapping=False):
875 """
888 """
876 Set the parameters of the integration class.
889 Set the parameters of the integration class.
877
890
878 Inputs:
891 Inputs:
879
892
880 n : Number of coherent integrations
893 n : Number of coherent integrations
881 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
894 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
882 overlapping :
895 overlapping :
883
896
884 """
897 """
885
898
886 self.__initime = None
899 self.__initime = None
887 self.__lastdatatime = 0
900 self.__lastdatatime = 0
888
901
889 self.__buffer_spc = 0
902 self.__buffer_spc = 0
890 self.__buffer_cspc = 0
903 self.__buffer_cspc = 0
891 self.__buffer_dc = 0
904 self.__buffer_dc = 0
892
905
893 self.__profIndex = 0
906 self.__profIndex = 0
894 self.__dataReady = False
907 self.__dataReady = False
895 self.__byTime = False
908 self.__byTime = False
896
909
897 if n is None and timeInterval is None:
910 if n is None and timeInterval is None:
898 raise ValueError("n or timeInterval should be specified ...")
911 raise ValueError("n or timeInterval should be specified ...")
899
912
900 if n is not None:
913 if n is not None:
901 self.n = int(n)
914 self.n = int(n)
902 else:
915 else:
903
916
904 self.__integrationtime = int(timeInterval)
917 self.__integrationtime = int(timeInterval)
905 self.n = None
918 self.n = None
906 self.__byTime = True
919 self.__byTime = True
907
920
908 def putData(self, data_spc, data_cspc, data_dc):
921 def putData(self, data_spc, data_cspc, data_dc):
909 """
922 """
910 Add a profile to the __buffer_spc and increase in one the __profileIndex
923 Add a profile to the __buffer_spc and increase in one the __profileIndex
911
924
912 """
925 """
913
926
914 self.__buffer_spc += data_spc
927 self.__buffer_spc += data_spc
915
928
916 if data_cspc is None:
929 if data_cspc is None:
917 self.__buffer_cspc = None
930 self.__buffer_cspc = None
918 else:
931 else:
919 self.__buffer_cspc += data_cspc
932 self.__buffer_cspc += data_cspc
920
933
921 if data_dc is None:
934 if data_dc is None:
922 self.__buffer_dc = None
935 self.__buffer_dc = None
923 else:
936 else:
924 self.__buffer_dc += data_dc
937 self.__buffer_dc += data_dc
925
938
926 self.__profIndex += 1
939 self.__profIndex += 1
927
940
928 return
941 return
929
942
930 def pushData(self):
943 def pushData(self):
931 """
944 """
932 Return the sum of the last profiles and the profiles used in the sum.
945 Return the sum of the last profiles and the profiles used in the sum.
933
946
934 Affected:
947 Affected:
935
948
936 self.__profileIndex
949 self.__profileIndex
937
950
938 """
951 """
939
952
940 data_spc = self.__buffer_spc
953 data_spc = self.__buffer_spc
941 data_cspc = self.__buffer_cspc
954 data_cspc = self.__buffer_cspc
942 data_dc = self.__buffer_dc
955 data_dc = self.__buffer_dc
943 n = self.__profIndex
956 n = self.__profIndex
944
957
945 self.__buffer_spc = 0
958 self.__buffer_spc = 0
946 self.__buffer_cspc = 0
959 self.__buffer_cspc = 0
947 self.__buffer_dc = 0
960 self.__buffer_dc = 0
948 self.__profIndex = 0
961 self.__profIndex = 0
949
962
950 return data_spc, data_cspc, data_dc, n
963 return data_spc, data_cspc, data_dc, n
951
964
952 def byProfiles(self, *args):
965 def byProfiles(self, *args):
953
966
954 self.__dataReady = False
967 self.__dataReady = False
955 avgdata_spc = None
968 avgdata_spc = None
956 avgdata_cspc = None
969 avgdata_cspc = None
957 avgdata_dc = None
970 avgdata_dc = None
958
971
959 self.putData(*args)
972 self.putData(*args)
960
973
961 if self.__profIndex == self.n:
974 if self.__profIndex == self.n:
962
975
963 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
976 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
964 self.n = n
977 self.n = n
965 self.__dataReady = True
978 self.__dataReady = True
966
979
967 return avgdata_spc, avgdata_cspc, avgdata_dc
980 return avgdata_spc, avgdata_cspc, avgdata_dc
968
981
969 def byTime(self, datatime, *args):
982 def byTime(self, datatime, *args):
970
983
971 self.__dataReady = False
984 self.__dataReady = False
972 avgdata_spc = None
985 avgdata_spc = None
973 avgdata_cspc = None
986 avgdata_cspc = None
974 avgdata_dc = None
987 avgdata_dc = None
975
988
976 self.putData(*args)
989 self.putData(*args)
977
990
978 if (datatime - self.__initime) >= self.__integrationtime:
991 if (datatime - self.__initime) >= self.__integrationtime:
979 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
992 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
980 self.n = n
993 self.n = n
981 self.__dataReady = True
994 self.__dataReady = True
982
995
983 return avgdata_spc, avgdata_cspc, avgdata_dc
996 return avgdata_spc, avgdata_cspc, avgdata_dc
984
997
985 def integrate(self, datatime, *args):
998 def integrate(self, datatime, *args):
986
999
987 if self.__profIndex == 0:
1000 if self.__profIndex == 0:
988 self.__initime = datatime
1001 self.__initime = datatime
989
1002
990 if self.__byTime:
1003 if self.__byTime:
991 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
1004 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
992 datatime, *args)
1005 datatime, *args)
993 else:
1006 else:
994 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
1007 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
995
1008
996 if not self.__dataReady:
1009 if not self.__dataReady:
997 return None, None, None, None
1010 return None, None, None, None
998
1011
999 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
1012 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
1000
1013
1001 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
1014 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
1002 if n == 1:
1015 if n == 1:
1003 return dataOut
1016 return dataOut
1004 print("JERE")
1017 print("JERE")
1005 dataOut.flagNoData = True
1018 dataOut.flagNoData = True
1006
1019
1007 if not self.isConfig:
1020 if not self.isConfig:
1008 self.setup(n, timeInterval, overlapping)
1021 self.setup(n, timeInterval, overlapping)
1009 self.isConfig = True
1022 self.isConfig = True
1010
1023
1011 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
1024 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
1012 dataOut.data_spc,
1025 dataOut.data_spc,
1013 dataOut.data_cspc,
1026 dataOut.data_cspc,
1014 dataOut.data_dc)
1027 dataOut.data_dc)
1015
1028
1016 if self.__dataReady:
1029 if self.__dataReady:
1017
1030
1018 dataOut.data_spc = avgdata_spc
1031 dataOut.data_spc = avgdata_spc
1019 print(numpy.sum(dataOut.data_spc))
1032 print(numpy.sum(dataOut.data_spc))
1020 exit(1)
1033 exit(1)
1021 dataOut.data_cspc = avgdata_cspc
1034 dataOut.data_cspc = avgdata_cspc
1022 dataOut.data_dc = avgdata_dc
1035 dataOut.data_dc = avgdata_dc
1023 dataOut.nIncohInt *= self.n
1036 dataOut.nIncohInt *= self.n
1024 dataOut.utctime = avgdatatime
1037 dataOut.utctime = avgdatatime
1025 dataOut.flagNoData = False
1038 dataOut.flagNoData = False
1026
1039
1027 return dataOut
1040 return dataOut
1028
1041
1029 class dopplerFlip(Operation):
1042 class dopplerFlip(Operation):
1030
1043
1031 def run(self, dataOut, chann = None):
1044 def run(self, dataOut, chann = None):
1032 # arreglo 1: (num_chan, num_profiles, num_heights)
1045 # arreglo 1: (num_chan, num_profiles, num_heights)
1033 self.dataOut = dataOut
1046 self.dataOut = dataOut
1034 # JULIA-oblicua, indice 2
1047 # JULIA-oblicua, indice 2
1035 # arreglo 2: (num_profiles, num_heights)
1048 # arreglo 2: (num_profiles, num_heights)
1036 jspectra = self.dataOut.data_spc[chann]
1049 jspectra = self.dataOut.data_spc[chann]
1037 jspectra_tmp = numpy.zeros(jspectra.shape)
1050 jspectra_tmp = numpy.zeros(jspectra.shape)
1038 num_profiles = jspectra.shape[0]
1051 num_profiles = jspectra.shape[0]
1039 freq_dc = int(num_profiles / 2)
1052 freq_dc = int(num_profiles / 2)
1040 # Flip con for
1053 # Flip con for
1041 for j in range(num_profiles):
1054 for j in range(num_profiles):
1042 jspectra_tmp[num_profiles-j-1]= jspectra[j]
1055 jspectra_tmp[num_profiles-j-1]= jspectra[j]
1043 # Intercambio perfil de DC con perfil inmediato anterior
1056 # Intercambio perfil de DC con perfil inmediato anterior
1044 jspectra_tmp[freq_dc-1]= jspectra[freq_dc-1]
1057 jspectra_tmp[freq_dc-1]= jspectra[freq_dc-1]
1045 jspectra_tmp[freq_dc]= jspectra[freq_dc]
1058 jspectra_tmp[freq_dc]= jspectra[freq_dc]
1046 # canal modificado es re-escrito en el arreglo de canales
1059 # canal modificado es re-escrito en el arreglo de canales
1047 self.dataOut.data_spc[chann] = jspectra_tmp
1060 self.dataOut.data_spc[chann] = jspectra_tmp
1048
1061
1049 return self.dataOut
1062 return self.dataOut
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now