##// END OF EJS Templates
Eliminación de perfiles, retención de bloques, salida en pequeñps bloques o perfiles, rti de outliers
joabAM -
r1528:9eee9f011a2c
parent child
Show More
@@ -1,126 +1,126
1 1 #include <Python.h>
2 2 #include <numpy/arrayobject.h>
3 3 #include <math.h>
4 4
5 5
6 6 static PyObject *hildebrand_sekhon(PyObject *self, PyObject *args) {
7 7 double navg;
8 8 PyObject *data_obj, *data_array;
9 9
10 10 if (!PyArg_ParseTuple(args, "Od", &data_obj, &navg)) {
11 11 return NULL;
12 12 }
13 13
14 14 data_array = PyArray_FROM_OTF(data_obj, NPY_FLOAT64, NPY_IN_ARRAY);
15 15
16 16 if (data_array == NULL) {
17 17 Py_XDECREF(data_array);
18 18 Py_XDECREF(data_obj);
19 19 return NULL;
20 20 }
21 21 double *sortdata = (double*)PyArray_DATA(data_array);
22 22 int lenOfData = (int)PyArray_SIZE(data_array) ;
23 23 double nums_min = lenOfData*0.2;
24 24 if (nums_min <= 5) nums_min = 5;
25 25 double sump = 0;
26 26 double sumq = 0;
27 27 long j = 0;
28 28 int cont = 1;
29 29 double rtest = 0;
30 30 while ((cont == 1) && (j < lenOfData)) {
31 31 sump = sump + sortdata[j];
32 32 sumq = sumq + pow(sortdata[j], 2);
33 33 if (j > nums_min) {
34 34 rtest = (double)j/(j-1) + 1/navg;
35 35 if ((sumq*j) > (rtest*pow(sump, 2))) {
36 36 j = j - 1;
37 37 sump = sump - sortdata[j];
38 38 sumq = sumq - pow(sortdata[j],2);
39 39 cont = 0;
40 40 }
41 41 }
42 42 j = j + 1;
43 43 }
44 44
45 45 double lnoise = sump / j;
46 46
47 47 Py_DECREF(data_array);
48 48
49 49 // return PyLong_FromLong(lnoise);
50 50 return PyFloat_FromDouble(lnoise);
51 51 }
52 52
53 53 static PyObject *hildebrand_sekhon2(PyObject *self, PyObject *args) {
54 54 double navg;
55 55 PyObject *data_obj, *data_array;
56 56
57 57 if (!PyArg_ParseTuple(args, "Od", &data_obj, &navg)) {
58 58 return NULL;
59 59 }
60 60 data_array = PyArray_FROM_OTF(data_obj, NPY_FLOAT64, NPY_IN_ARRAY);
61 61
62 62 if (data_array == NULL) {
63 63 Py_XDECREF(data_array);
64 64 Py_XDECREF(data_obj);
65 65 return NULL;
66 66 }
67 67 double *sortdata = (double*)PyArray_DATA(data_array);
68 68 int lenOfData = (int)PyArray_SIZE(data_array) ;
69 double nums_min = lenOfData*0.75;
69 double nums_min = lenOfData*0.85;
70 70 if (nums_min <= 5) nums_min = 5;
71 71 double sump = 0;
72 72 double sumq = 0;
73 73 long j = 0;
74 74 int cont = 1;
75 75 double rtest = 0;
76 76 while ((cont == 1) && (j < lenOfData)) {
77 77 sump = sump + sortdata[j];
78 78 sumq = sumq + pow(sortdata[j], 2);
79 79 if (j > nums_min) {
80 80 rtest = (double)j/(j-1) + 1/navg;
81 81 if ((sumq*j) > (rtest*pow(sump, 2))) {
82 82 j = j - 1;
83 83 sump = sump - sortdata[j];
84 84 sumq = sumq - pow(sortdata[j],2);
85 85 cont = 0;
86 86 }
87 87 }
88 88 j = j + 1;
89 89 }
90 90
91 91 Py_DECREF(data_array);
92 92
93 93 return PyLong_FromLong(j);
94 94 }
95 95
96 96
97 97 static PyMethodDef noiseMethods[] = {
98 98 { "hildebrand_sekhon", hildebrand_sekhon, METH_VARARGS, "Get noise with hildebrand_sekhon algorithm" },
99 99 { "hildebrand_sekhon2", hildebrand_sekhon2, METH_VARARGS, "Variation for satellite cleaning" },
100 100 { NULL, NULL, 0, NULL }
101 101 };
102 102
103 103 #if PY_MAJOR_VERSION >= 3
104 104
105 105 static struct PyModuleDef noisemodule = {
106 106 PyModuleDef_HEAD_INIT,
107 107 "_noise",
108 108 "Get noise with hildebrand_sekhon algorithm",
109 109 -1,
110 110 noiseMethods
111 111 };
112 112
113 113 #endif
114 114
115 115 #if PY_MAJOR_VERSION >= 3
116 116 PyMODINIT_FUNC PyInit__noise(void) {
117 117 Py_Initialize();
118 118 import_array();
119 119 return PyModule_Create(&noisemodule);
120 120 }
121 121 #else
122 122 PyMODINIT_FUNC init_noise() {
123 123 Py_InitModule("_noise", noiseMethods);
124 124 import_array();
125 125 }
126 126 #endif
@@ -1,687 +1,685
1 1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """API to create signal chain projects
6 6
7 7 The API is provide through class: Project
8 8 """
9 9
10 10 import re
11 11 import sys
12 12 import ast
13 13 import datetime
14 14 import traceback
15 15 import time
16 16 import multiprocessing
17 17 from multiprocessing import Process, Queue
18 18 from threading import Thread
19 19 from xml.etree.ElementTree import ElementTree, Element, SubElement
20 20
21 21 from schainpy.admin import Alarm, SchainWarning
22 22 from schainpy.model import *
23 23 from schainpy.utils import log
24 24
25 25 if 'darwin' in sys.platform and sys.version_info[0] == 3 and sys.version_info[1] > 7:
26 26 multiprocessing.set_start_method('fork')
27 27
28 28 class ConfBase():
29 29
30 30 def __init__(self):
31 31
32 32 self.id = '0'
33 33 self.name = None
34 34 self.priority = None
35 35 self.parameters = {}
36 36 self.object = None
37 37 self.operations = []
38 38
39 39 def getId(self):
40 40
41 41 return self.id
42 42
43 43 def getNewId(self):
44 44
45 45 return int(self.id) * 10 + len(self.operations) + 1
46 46
47 47 def updateId(self, new_id):
48 48
49 49 self.id = str(new_id)
50 50
51 51 n = 1
52 52 for conf in self.operations:
53 53 conf_id = str(int(new_id) * 10 + n)
54 54 conf.updateId(conf_id)
55 55 n += 1
56 56
57 57 def getKwargs(self):
58 58
59 59 params = {}
60 60
61 61 for key, value in self.parameters.items():
62 62 if value not in (None, '', ' '):
63 63 params[key] = value
64 64
65 65 return params
66 66
67 67 def update(self, **kwargs):
68 68
69 69 for key, value in kwargs.items():
70 70 self.addParameter(name=key, value=value)
71 71
72 72 def addParameter(self, name, value, format=None):
73 73 '''
74 74 '''
75 75
76 76 if isinstance(value, str) and re.search(r'(\d+/\d+/\d+)', value):
77 77 self.parameters[name] = datetime.date(*[int(x) for x in value.split('/')])
78 78 elif isinstance(value, str) and re.search(r'(\d+:\d+:\d+)', value):
79 79 self.parameters[name] = datetime.time(*[int(x) for x in value.split(':')])
80 80 else:
81 81 try:
82 82 self.parameters[name] = ast.literal_eval(value)
83 83 except:
84 84 if isinstance(value, str) and ',' in value:
85 85 self.parameters[name] = value.split(',')
86 86 else:
87 87 self.parameters[name] = value
88 88
89 89 def getParameters(self):
90 90
91 91 params = {}
92 92 for key, value in self.parameters.items():
93 93 s = type(value).__name__
94 94 if s == 'date':
95 95 params[key] = value.strftime('%Y/%m/%d')
96 96 elif s == 'time':
97 97 params[key] = value.strftime('%H:%M:%S')
98 98 else:
99 99 params[key] = str(value)
100 100
101 101 return params
102 102
103 103 def makeXml(self, element):
104 104
105 105 xml = SubElement(element, self.ELEMENTNAME)
106 106 for label in self.xml_labels:
107 107 xml.set(label, str(getattr(self, label)))
108 108
109 109 for key, value in self.getParameters().items():
110 110 xml_param = SubElement(xml, 'Parameter')
111 111 xml_param.set('name', key)
112 112 xml_param.set('value', value)
113 113
114 114 for conf in self.operations:
115 115 conf.makeXml(xml)
116 116
117 117 def __str__(self):
118 118
119 119 if self.ELEMENTNAME == 'Operation':
120 120 s = ' {}[id={}]\n'.format(self.name, self.id)
121 121 else:
122 122 s = '{}[id={}, inputId={}]\n'.format(self.name, self.id, self.inputId)
123 123
124 124 for key, value in self.parameters.items():
125 125 if self.ELEMENTNAME == 'Operation':
126 126 s += ' {}: {}\n'.format(key, value)
127 127 else:
128 128 s += ' {}: {}\n'.format(key, value)
129 129
130 130 for conf in self.operations:
131 131 s += str(conf)
132 132
133 133 return s
134 134
135 135 class OperationConf(ConfBase):
136 136
137 137 ELEMENTNAME = 'Operation'
138 138 xml_labels = ['id', 'name']
139 139
140 140 def setup(self, id, name, priority, project_id, err_queue):
141 141
142 142 self.id = str(id)
143 143 self.project_id = project_id
144 144 self.name = name
145 145 self.type = 'other'
146 146 self.err_queue = err_queue
147 147
148 148 def readXml(self, element, project_id, err_queue):
149 149
150 150 self.id = element.get('id')
151 151 self.name = element.get('name')
152 152 self.type = 'other'
153 153 self.project_id = str(project_id)
154 154 self.err_queue = err_queue
155 155
156 156 for elm in element.iter('Parameter'):
157 157 self.addParameter(elm.get('name'), elm.get('value'))
158 158
159 159 def createObject(self):
160 160
161 161 className = eval(self.name)
162 162
163 163 if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name or 'print' in self.name:
164 164 kwargs = self.getKwargs()
165 165 opObj = className(self.name, self.id, self.project_id, self.err_queue, **kwargs)
166 166 opObj.start()
167 167 self.type = 'external'
168 168 else:
169 169 opObj = className()
170 170
171 171 self.object = opObj
172 172 return opObj
173 173
174 174 class ProcUnitConf(ConfBase):
175 175
176 176 ELEMENTNAME = 'ProcUnit'
177 177 xml_labels = ['id', 'inputId', 'name']
178 178
179 179 def setup(self, project_id, id, name, datatype, inputId, err_queue):
180 180 '''
181 181 '''
182 182
183 183 if datatype == None and name == None:
184 184 raise ValueError('datatype or name should be defined')
185 185
186 186 if name == None:
187 187 if 'Proc' in datatype:
188 188 name = datatype
189 189 else:
190 190 name = '%sProc' % (datatype)
191 191
192 192 if datatype == None:
193 193 datatype = name.replace('Proc', '')
194 194
195 195 self.id = str(id)
196 196 self.project_id = project_id
197 197 self.name = name
198 198 self.datatype = datatype
199 199 self.inputId = inputId
200 200 self.err_queue = err_queue
201 201 self.operations = []
202 202 self.parameters = {}
203 203
204 204 def removeOperation(self, id):
205 205
206 206 i = [1 if x.id==id else 0 for x in self.operations]
207 207 self.operations.pop(i.index(1))
208 208
209 209 def getOperation(self, id):
210 210
211 211 for conf in self.operations:
212 212 if conf.id == id:
213 213 return conf
214 214
215 215 def addOperation(self, name, optype='self'):
216 216 '''
217 217 '''
218 218
219 219 id = self.getNewId()
220 220 conf = OperationConf()
221 221 conf.setup(id, name=name, priority='0', project_id=self.project_id, err_queue=self.err_queue)
222 222 self.operations.append(conf)
223 223
224 224 return conf
225 225
226 226 def readXml(self, element, project_id, err_queue):
227 227
228 228 self.id = element.get('id')
229 229 self.name = element.get('name')
230 230 self.inputId = None if element.get('inputId') == 'None' else element.get('inputId')
231 231 self.datatype = element.get('datatype', self.name.replace(self.ELEMENTNAME.replace('Unit', ''), ''))
232 232 self.project_id = str(project_id)
233 233 self.err_queue = err_queue
234 234 self.operations = []
235 235 self.parameters = {}
236 236
237 237 for elm in element:
238 238 if elm.tag == 'Parameter':
239 239 self.addParameter(elm.get('name'), elm.get('value'))
240 240 elif elm.tag == 'Operation':
241 241 conf = OperationConf()
242 242 conf.readXml(elm, project_id, err_queue)
243 243 self.operations.append(conf)
244 244
245 245 def createObjects(self):
246 246 '''
247 247 Instancia de unidades de procesamiento.
248 248 '''
249 249
250 250 className = eval(self.name)
251 251 kwargs = self.getKwargs()
252 252 procUnitObj = className()
253 253 procUnitObj.name = self.name
254 254 log.success('creating process... id: {}, inputId: {}'.format(self.id,self.inputId), self.name)
255 255
256 256 for conf in self.operations:
257 257
258 258 opObj = conf.createObject()
259 259
260 260 log.success('adding operation: {}, type:{}'.format(conf.name,conf.type), self.name)
261 261
262 262 procUnitObj.addOperation(conf, opObj)
263 263
264 264 self.object = procUnitObj
265 265
266 266 def run(self):
267 267 '''
268 268 '''
269 269 return self.object.call(**self.getKwargs())
270 270
271 271 class ReadUnitConf(ProcUnitConf):
272 272
273 273 ELEMENTNAME = 'ReadUnit'
274 274
275 275 def __init__(self):
276 276
277 277 self.id = None
278 278 self.datatype = None
279 279 self.name = None
280 280 self.inputId = None
281 281 self.operations = []
282 282 self.parameters = {}
283 283
284 284 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
285 285 startTime='', endTime='', server=None, **kwargs):
286 286
287 287 if datatype == None and name == None:
288 288 raise ValueError('datatype or name should be defined')
289 289 if name == None:
290 290 if 'Reader' in datatype:
291 291 name = datatype
292 292 datatype = name.replace('Reader','')
293 293 else:
294 294 name = '{}Reader'.format(datatype)
295 295 if datatype == None:
296 296 if 'Reader' in name:
297 297 datatype = name.replace('Reader','')
298 298 else:
299 299 datatype = name
300 300 name = '{}Reader'.format(name)
301 301
302 302 self.id = id
303 303 self.project_id = project_id
304 304 self.name = name
305 305 self.datatype = datatype
306 306 self.err_queue = err_queue
307 307
308 308 self.addParameter(name='path', value=path)
309 309 self.addParameter(name='startDate', value=startDate)
310 310 self.addParameter(name='endDate', value=endDate)
311 311 self.addParameter(name='startTime', value=startTime)
312 312 self.addParameter(name='endTime', value=endTime)
313 313
314 314 for key, value in kwargs.items():
315 315 self.addParameter(name=key, value=value)
316 316
317 317
318 318 class Project(Process):
319 319 """API to create signal chain projects"""
320 320
321 321 ELEMENTNAME = 'Project'
322 322
323 323 def __init__(self, name=''):
324 324
325 325 Process.__init__(self)
326 326 self.id = '1'
327 327 if name:
328 328 self.name = '{} ({})'.format(Process.__name__, name)
329 329 self.filename = None
330 330 self.description = None
331 331 self.email = None
332 332 self.alarm = []
333 333 self.configurations = {}
334 334 # self.err_queue = Queue()
335 335 self.err_queue = None
336 336 self.started = False
337 337
338 338 def getNewId(self):
339 339
340 340 idList = list(self.configurations.keys())
341 341 id = int(self.id) * 10
342 342
343 343 while True:
344 344 id += 1
345 345
346 346 if str(id) in idList:
347 347 continue
348 348
349 349 break
350 350
351 351 return str(id)
352 352
353 353 def updateId(self, new_id):
354 354
355 355 self.id = str(new_id)
356 356
357 357 keyList = list(self.configurations.keys())
358 358 keyList.sort()
359 359
360 360 n = 1
361 361 new_confs = {}
362 362
363 363 for procKey in keyList:
364 364
365 365 conf = self.configurations[procKey]
366 366 idProcUnit = str(int(self.id) * 10 + n)
367 367 conf.updateId(idProcUnit)
368 368 new_confs[idProcUnit] = conf
369 369 n += 1
370 370
371 371 self.configurations = new_confs
372 372
373 373 def setup(self, id=1, name='', description='', email=None, alarm=[]):
374 374
375 375 self.id = str(id)
376 376 self.description = description
377 377 self.email = email
378 378 self.alarm = alarm
379 379 if name:
380 380 self.name = '{} ({})'.format(Process.__name__, name)
381 381
382 382 def update(self, **kwargs):
383 383
384 384 for key, value in kwargs.items():
385 385 setattr(self, key, value)
386 386
387 387 def clone(self):
388 388
389 389 p = Project()
390 390 p.id = self.id
391 391 p.name = self.name
392 392 p.description = self.description
393 393 p.configurations = self.configurations.copy()
394 394
395 395 return p
396 396
397 397 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
398 398
399 399 '''
400 400 '''
401 401
402 402 if id is None:
403 403 idReadUnit = self.getNewId()
404 404 else:
405 405 idReadUnit = str(id)
406 406
407 407 conf = ReadUnitConf()
408 408 conf.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
409 409 self.configurations[conf.id] = conf
410 410
411 411 return conf
412 412
413 413 def addProcUnit(self, id=None, inputId='0', datatype=None, name=None):
414 414
415 415 '''
416 416 '''
417 417
418 418 if id is None:
419 419 idProcUnit = self.getNewId()
420 420 else:
421 421 idProcUnit = id
422 422
423 423 conf = ProcUnitConf()
424 424 conf.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue)
425 425 self.configurations[conf.id] = conf
426 426
427 427 return conf
428 428
429 429 def removeProcUnit(self, id):
430 430
431 431 if id in self.configurations:
432 432 self.configurations.pop(id)
433 433
434 434 def getReadUnit(self):
435 435
436 436 for obj in list(self.configurations.values()):
437 437 if obj.ELEMENTNAME == 'ReadUnit':
438 438 return obj
439 439
440 440 return None
441 441
442 442 def getProcUnit(self, id):
443 443
444 444 return self.configurations[id]
445 445
446 446 def getUnits(self):
447 447
448 448 keys = list(self.configurations)
449 449 keys.sort()
450 450
451 451 for key in keys:
452 452 yield self.configurations[key]
453 453
454 454 def updateUnit(self, id, **kwargs):
455 455
456 456 conf = self.configurations[id].update(**kwargs)
457 457
458 458 def makeXml(self):
459 459
460 460 xml = Element('Project')
461 461 xml.set('id', str(self.id))
462 462 xml.set('name', self.name)
463 463 xml.set('description', self.description)
464 464
465 465 for conf in self.configurations.values():
466 466 conf.makeXml(xml)
467 467
468 468 self.xml = xml
469 469
470 470 def writeXml(self, filename=None):
471 471
472 472 if filename == None:
473 473 if self.filename:
474 474 filename = self.filename
475 475 else:
476 476 filename = 'schain.xml'
477 477
478 478 if not filename:
479 479 print('filename has not been defined. Use setFilename(filename) for do it.')
480 480 return 0
481 481
482 482 abs_file = os.path.abspath(filename)
483 483
484 484 if not os.access(os.path.dirname(abs_file), os.W_OK):
485 485 print('No write permission on %s' % os.path.dirname(abs_file))
486 486 return 0
487 487
488 488 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
489 489 print('File %s already exists and it could not be overwriten' % abs_file)
490 490 return 0
491 491
492 492 self.makeXml()
493 493
494 494 ElementTree(self.xml).write(abs_file, method='xml')
495 495
496 496 self.filename = abs_file
497 497
498 498 return 1
499 499
500 500 def readXml(self, filename):
501 501
502 502 abs_file = os.path.abspath(filename)
503 503
504 504 self.configurations = {}
505 505
506 506 try:
507 507 self.xml = ElementTree().parse(abs_file)
508 508 except:
509 509 log.error('Error reading %s, verify file format' % filename)
510 510 return 0
511 511
512 512 self.id = self.xml.get('id')
513 513 self.name = self.xml.get('name')
514 514 self.description = self.xml.get('description')
515 515
516 516 for element in self.xml:
517 517 if element.tag == 'ReadUnit':
518 518 conf = ReadUnitConf()
519 519 conf.readXml(element, self.id, self.err_queue)
520 520 self.configurations[conf.id] = conf
521 521 elif element.tag == 'ProcUnit':
522 522 conf = ProcUnitConf()
523 523 input_proc = self.configurations[element.get('inputId')]
524 524 conf.readXml(element, self.id, self.err_queue)
525 525 self.configurations[conf.id] = conf
526 526
527 527 self.filename = abs_file
528 528
529 529 return 1
530 530
531 531 def __str__(self):
532 532
533 533 text = '\nProject[id=%s, name=%s, description=%s]\n\n' % (
534 534 self.id,
535 535 self.name,
536 536 self.description,
537 537 )
538 538
539 539 for conf in self.configurations.values():
540 540 text += '{}'.format(conf)
541 541
542 542 return text
543 543
544 544 def createObjects(self):
545 545
546 546 keys = list(self.configurations.keys())
547 547 keys.sort()
548 548 for key in keys:
549 549 conf = self.configurations[key]
550 550 conf.createObjects()
551 551 if conf.inputId is not None:
552 552 conf.object.setInput(self.configurations[conf.inputId].object)
553 553
554 554 def monitor(self):
555 555
556 556 t = Thread(target=self._monitor, args=(self.err_queue, self.ctx))
557 557 t.start()
558 558
559 559 def _monitor(self, queue, ctx):
560 560
561 561 import socket
562 562
563 563 procs = 0
564 564 err_msg = ''
565 565
566 566 while True:
567 567 msg = queue.get()
568 568 if '#_start_#' in msg:
569 569 procs += 1
570 570 elif '#_end_#' in msg:
571 571 procs -=1
572 572 else:
573 573 err_msg = msg
574 574
575 575 if procs == 0 or 'Traceback' in err_msg:
576 576 break
577 577 time.sleep(0.1)
578 578
579 579 if '|' in err_msg:
580 580 name, err = err_msg.split('|')
581 581 if 'SchainWarning' in err:
582 582 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
583 583 elif 'SchainError' in err:
584 584 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
585 585 else:
586 586 log.error(err, name)
587 587 else:
588 588 name, err = self.name, err_msg
589 589
590 590 time.sleep(1)
591 591
592 592 ctx.term()
593 593
594 594 message = ''.join(err)
595 595
596 596 if err_msg:
597 597 subject = 'SChain v%s: Error running %s\n' % (
598 598 schainpy.__version__, self.name)
599 599
600 600 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
601 601 socket.gethostname())
602 602 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
603 603 subtitle += 'Configuration file: %s\n' % self.filename
604 604 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
605 605
606 606 readUnitConfObj = self.getReadUnit()
607 607 if readUnitConfObj:
608 608 subtitle += '\nInput parameters:\n'
609 609 subtitle += '[Data path = %s]\n' % readUnitConfObj.parameters['path']
610 610 subtitle += '[Start date = %s]\n' % readUnitConfObj.parameters['startDate']
611 611 subtitle += '[End date = %s]\n' % readUnitConfObj.parameters['endDate']
612 612 subtitle += '[Start time = %s]\n' % readUnitConfObj.parameters['startTime']
613 613 subtitle += '[End time = %s]\n' % readUnitConfObj.parameters['endTime']
614 614
615 615 a = Alarm(
616 616 modes=self.alarm,
617 617 email=self.email,
618 618 message=message,
619 619 subject=subject,
620 620 subtitle=subtitle,
621 621 filename=self.filename
622 622 )
623 623
624 624 a.start()
625 625
626 626 def setFilename(self, filename):
627 627
628 628 self.filename = filename
629 629
630 630 def runProcs(self):
631 631
632 632 err = False
633 633 n = len(self.configurations)
634 634 flag_no_read = False
635 635 nProc_noRead = 0
636 636 while not err:
637 637 #print("STAR")
638 638 n_proc = 0
639 639 for conf in self.getUnits():
640 640 #print("CONF: ",conf)
641 641 #print( n_proc, nProc_noRead,flag_no_read)
642 642 if flag_no_read:
643 643 if n_proc >= nProc_noRead:
644 644 ok = conf.run()
645 645 else:
646 646 #print("break")
647 647 #print(ok, n_proc, nProc_noRead, n, flag_no_read)
648 648 n_proc += 1
649 649 continue
650 650 else:
651 651 ok = conf.run()
652 652
653 653 n_proc += 1
654 654 #print(ok, n_proc, nProc_noRead, n, flag_no_read)
655 655
656 656 if ok == 'Error':
657 657 #self.removeProcUnit(conf.id) #remove proc Unit
658 658 n -= 1
659 659 continue
660 660
661 661 elif ok == 'no_Read' and (not flag_no_read):
662 662 nProc_noRead = n_proc - 1
663 663 flag_no_read = True
664 print("No read")
665 664 continue
666 665 elif ok == 'new_Read':
667 666 nProc_noRead = 0
668 667 flag_no_read = False
669 print("read again")
670 668 continue
671 669 elif not ok:
672 670 #print("not ok",ok)
673 671 break
674 672
675 673 if n == 0:
676 674 err = True
677 675
678 676 def run(self):
679 677
680 678 log.success('\nStarting Project {} [id={}]'.format(self.name, self.id), tag='')
681 679 self.started = True
682 680 self.start_time = time.time()
683 681 self.createObjects()
684 682 self.runProcs()
685 683 log.success('{} Done (Time: {:4.2f}s)'.format(
686 684 self.name,
687 685 time.time()-self.start_time), '')
@@ -1,1079 +1,1102
1 1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Definition of diferent Data objects for different types of data
6 6
7 7 Here you will find the diferent data objects for the different types
8 8 of data, this data objects must be used as dataIn or dataOut objects in
9 9 processing units and operations. Currently the supported data objects are:
10 10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
11 11 """
12 12
13 13 import copy
14 14 import numpy
15 15 import datetime
16 16 import json
17 17
18 18 import schainpy.admin
19 19 from schainpy.utils import log
20 20 from .jroheaderIO import SystemHeader, RadarControllerHeader
21 21 from schainpy.model.data import _noise
22 22
23 23
24 24 def getNumpyDtype(dataTypeCode):
25 25
26 26 if dataTypeCode == 0:
27 27 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
28 28 elif dataTypeCode == 1:
29 29 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
30 30 elif dataTypeCode == 2:
31 31 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
32 32 elif dataTypeCode == 3:
33 33 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
34 34 elif dataTypeCode == 4:
35 35 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
36 36 elif dataTypeCode == 5:
37 37 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
38 38 else:
39 39 raise ValueError('dataTypeCode was not defined')
40 40
41 41 return numpyDtype
42 42
43 43
44 44 def getDataTypeCode(numpyDtype):
45 45
46 46 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
47 47 datatype = 0
48 48 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
49 49 datatype = 1
50 50 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
51 51 datatype = 2
52 52 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
53 53 datatype = 3
54 54 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
55 55 datatype = 4
56 56 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
57 57 datatype = 5
58 58 else:
59 59 datatype = None
60 60
61 61 return datatype
62 62
63 63
64 64 def hildebrand_sekhon(data, navg):
65 65 """
66 66 This method is for the objective determination of the noise level in Doppler spectra. This
67 67 implementation technique is based on the fact that the standard deviation of the spectral
68 68 densities is equal to the mean spectral density for white Gaussian noise
69 69
70 70 Inputs:
71 71 Data : heights
72 72 navg : numbers of averages
73 73
74 74 Return:
75 75 mean : noise's level
76 76 """
77 77
78 78 sortdata = numpy.sort(data, axis=None)
79 79 '''
80 80 lenOfData = len(sortdata)
81 nums_min = lenOfData*0.2
81 nums_min = lenOfData*0.5
82 82
83 83 if nums_min <= 5:
84 84
85 85 nums_min = 5
86 86
87 87 sump = 0.
88 88 sumq = 0.
89 89
90 90 j = 0
91 91 cont = 1
92 92
93 93 while((cont == 1)and(j < lenOfData)):
94 94
95 95 sump += sortdata[j]
96 96 sumq += sortdata[j]**2
97 97
98 98 if j > nums_min:
99 99 rtest = float(j)/(j-1) + 1.0/navg
100 100 if ((sumq*j) > (rtest*sump**2)):
101 101 j = j - 1
102 102 sump = sump - sortdata[j]
103 103 sumq = sumq - sortdata[j]**2
104 104 cont = 0
105 105
106 106 j += 1
107 107
108 108 lnoise = sump / j
109 return lnoise
109 110 '''
110 111 return _noise.hildebrand_sekhon(sortdata, navg)
111 112
112 113
113 114 class Beam:
114 115
115 116 def __init__(self):
116 117 self.codeList = []
117 118 self.azimuthList = []
118 119 self.zenithList = []
119 120
120 121
121 122
122 123 class GenericData(object):
123 124
124 125 flagNoData = True
125 126
126 127 def copy(self, inputObj=None):
127 128
128 129 if inputObj == None:
129 130 return copy.deepcopy(self)
130 131
131 132 for key in list(inputObj.__dict__.keys()):
132 133
133 134 attribute = inputObj.__dict__[key]
134 135
135 136 # If this attribute is a tuple or list
136 137 if type(inputObj.__dict__[key]) in (tuple, list):
137 138 self.__dict__[key] = attribute[:]
138 139 continue
139 140
140 141 # If this attribute is another object or instance
141 142 if hasattr(attribute, '__dict__'):
142 143 self.__dict__[key] = attribute.copy()
143 144 continue
144 145
145 146 self.__dict__[key] = inputObj.__dict__[key]
146 147
147 148 def deepcopy(self):
148 149
149 150 return copy.deepcopy(self)
150 151
151 152 def isEmpty(self):
152 153
153 154 return self.flagNoData
154 155
155 156 def isReady(self):
156 157
157 158 return not self.flagNoData
158 159
159 160
160 161 class JROData(GenericData):
161 162
162 163 useInputBuffer = False
163 164 buffer_empty = True
164 165
165 166 systemHeaderObj = SystemHeader()
166 167 radarControllerHeaderObj = RadarControllerHeader()
167 168 type = None
168 169 datatype = None # dtype but in string
169 170 nProfiles = None
170 171 heightList = None
171 172 channelList = None
172 173 flagDiscontinuousBlock = False
173 174 useLocalTime = False
174 175 utctime = None
175 176 timeZone = None
176 177 dstFlag = None
177 178 errorCount = None
178 179 blocksize = None
179 180 flagDecodeData = False # asumo q la data no esta decodificada
180 181 flagDeflipData = False # asumo q la data no esta sin flip
181 182 flagShiftFFT = False
182 183 nCohInt = None
183 184 windowOfFilter = 1
184 185 C = 3e8
185 186 frequency = 49.92e6
186 187 realtime = False
187 188 beacon_heiIndexList = None
188 189 last_block = None
189 190 blocknow = None
190 191 azimuth = None
191 192 zenith = None
192 193 beam = Beam()
193 194 profileIndex = None
194 195 error = None
195 196 data = None
196 197 nmodes = None
197 198 metadata_list = ['heightList', 'timeZone', 'type']
198 199 codeList = []
199 200 azimuthList = []
200 201 elevationList = []
201 202
202 203 def __str__(self):
203 204
204 205 return '{} - {}'.format(self.type, self.datatime())
205 206
206 207 def getNoise(self):
207 208
208 209 raise NotImplementedError
209 210
210 211 @property
211 212 def nChannels(self):
212 213
213 214 return len(self.channelList)
214 215
215 216 @property
216 217 def channelIndexList(self):
217 218
218 219 return list(range(self.nChannels))
219 220
220 221 @property
221 222 def nHeights(self):
222 223
223 224 return len(self.heightList)
224 225
225 226 def getDeltaH(self):
226 227
227 228 return self.heightList[1] - self.heightList[0]
228 229
229 230 @property
230 231 def ltctime(self):
231 232
232 233 if self.useLocalTime:
233 234 return self.utctime - self.timeZone * 60
234 235
235 236 return self.utctime
236 237
237 238 @property
238 239 def datatime(self):
239 240
240 241 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
241 242 return datatimeValue
242 243
243 244 def getTimeRange(self):
244 245
245 246 datatime = []
246 247
247 248 datatime.append(self.ltctime)
248 249 datatime.append(self.ltctime + self.timeInterval + 1)
249 250
250 251 datatime = numpy.array(datatime)
251 252
252 253 return datatime
253 254
254 255 def getFmaxTimeResponse(self):
255 256
256 257 period = (10**-6) * self.getDeltaH() / (0.15)
257 258
258 259 PRF = 1. / (period * self.nCohInt)
259 260
260 261 fmax = PRF
261 262
262 263 return fmax
263 264
264 265 def getFmax(self):
265 266 PRF = 1. / (self.ippSeconds * self.nCohInt)
266 267
267 268 fmax = PRF
268 269 return fmax
269 270
270 271 def getVmax(self):
271 272
272 273 _lambda = self.C / self.frequency
273 274
274 275 vmax = self.getFmax() * _lambda / 2
275 276
276 277 return vmax
277 278
278 279 @property
279 280 def ippSeconds(self):
280 281 '''
281 282 '''
282 283 return self.radarControllerHeaderObj.ippSeconds
283 284
284 285 @ippSeconds.setter
285 286 def ippSeconds(self, ippSeconds):
286 287 '''
287 288 '''
288 289 self.radarControllerHeaderObj.ippSeconds = ippSeconds
289 290
290 291 @property
291 292 def code(self):
292 293 '''
293 294 '''
294 295 return self.radarControllerHeaderObj.code
295 296
296 297 @code.setter
297 298 def code(self, code):
298 299 '''
299 300 '''
300 301 self.radarControllerHeaderObj.code = code
301 302
302 303 @property
303 304 def nCode(self):
304 305 '''
305 306 '''
306 307 return self.radarControllerHeaderObj.nCode
307 308
308 309 @nCode.setter
309 310 def nCode(self, ncode):
310 311 '''
311 312 '''
312 313 self.radarControllerHeaderObj.nCode = ncode
313 314
314 315 @property
315 316 def nBaud(self):
316 317 '''
317 318 '''
318 319 return self.radarControllerHeaderObj.nBaud
319 320
320 321 @nBaud.setter
321 322 def nBaud(self, nbaud):
322 323 '''
323 324 '''
324 325 self.radarControllerHeaderObj.nBaud = nbaud
325 326
326 327 @property
327 328 def ipp(self):
328 329 '''
329 330 '''
330 331 return self.radarControllerHeaderObj.ipp
331 332
332 333 @ipp.setter
333 334 def ipp(self, ipp):
334 335 '''
335 336 '''
336 337 self.radarControllerHeaderObj.ipp = ipp
337 338
338 339 @property
339 340 def metadata(self):
340 341 '''
341 342 '''
342 343
343 344 return {attr: getattr(self, attr) for attr in self.metadata_list}
344 345
345 346
346 347 class Voltage(JROData):
347 348
348 349 dataPP_POW = None
349 350 dataPP_DOP = None
350 351 dataPP_WIDTH = None
351 352 dataPP_SNR = None
352 353
353 354 def __init__(self):
354 355 '''
355 356 Constructor
356 357 '''
357 358
358 359 self.useLocalTime = True
359 360 self.radarControllerHeaderObj = RadarControllerHeader()
360 361 self.systemHeaderObj = SystemHeader()
361 362 self.type = "Voltage"
362 363 self.data = None
363 364 self.nProfiles = None
364 365 self.heightList = None
365 366 self.channelList = None
366 367 self.flagNoData = True
367 368 self.flagDiscontinuousBlock = False
368 369 self.utctime = None
369 370 self.timeZone = 0
370 371 self.dstFlag = None
371 372 self.errorCount = None
372 373 self.nCohInt = None
373 374 self.blocksize = None
374 375 self.flagCohInt = False
375 376 self.flagDecodeData = False # asumo q la data no esta decodificada
376 377 self.flagDeflipData = False # asumo q la data no esta sin flip
377 378 self.flagShiftFFT = False
378 379 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
379 380 self.profileIndex = 0
380 381 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
381 382 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
382 383
383 def getNoisebyHildebrand(self, channel=None):
384 def getNoisebyHildebrand(self, channel=None, ymin_index=None, ymax_index=None):
384 385 """
385 386 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
386 387
387 388 Return:
388 389 noiselevel
389 390 """
390 391
391 392 if channel != None:
392 data = self.data[channel]
393 data = self.data[channel,ymin_index:ymax_index]
393 394 nChannels = 1
394 395 else:
395 data = self.data
396 data = self.data[:,ymin_index:ymax_index]
396 397 nChannels = self.nChannels
397 398
398 399 noise = numpy.zeros(nChannels)
399 400 power = data * numpy.conjugate(data)
400 401
401 402 for thisChannel in range(nChannels):
402 403 if nChannels == 1:
403 404 daux = power[:].real
404 405 else:
405 406 daux = power[thisChannel, :].real
406 407 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
407 408
408 409 return noise
409 410
410 def getNoise(self, type=1, channel=None):
411 def getNoise(self, type=1, channel=None,ymin_index=None, ymax_index=None):
411 412
412 413 if type == 1:
413 noise = self.getNoisebyHildebrand(channel)
414 noise = self.getNoisebyHildebrand(channel,ymin_index, ymax_index)
414 415
415 416 return noise
416 417
417 418 def getPower(self, channel=None):
418 419
419 420 if channel != None:
420 421 data = self.data[channel]
421 422 else:
422 423 data = self.data
423 424
424 425 power = data * numpy.conjugate(data)
425 426 powerdB = 10 * numpy.log10(power.real)
426 427 powerdB = numpy.squeeze(powerdB)
427 428
428 429 return powerdB
429 430
430 431 @property
431 432 def timeInterval(self):
432 433
433 434 return self.ippSeconds * self.nCohInt
434 435
435 436 noise = property(getNoise, "I'm the 'nHeights' property.")
436 437
437 438
438 439 class Spectra(JROData):
439 440
441 data_outlier = 0
442
440 443 def __init__(self):
441 444 '''
442 445 Constructor
443 446 '''
444 447
445 448 self.data_dc = None
446 449 self.data_spc = None
447 450 self.data_cspc = None
448 451 self.useLocalTime = True
449 452 self.radarControllerHeaderObj = RadarControllerHeader()
450 453 self.systemHeaderObj = SystemHeader()
451 454 self.type = "Spectra"
452 455 self.timeZone = 0
453 456 self.nProfiles = None
454 457 self.heightList = None
455 458 self.channelList = None
456 459 self.pairsList = None
457 460 self.flagNoData = True
458 461 self.flagDiscontinuousBlock = False
459 462 self.utctime = None
460 463 self.nCohInt = None
461 464 self.nIncohInt = None
462 465 self.blocksize = None
463 466 self.nFFTPoints = None
464 467 self.wavelength = None
465 468 self.flagDecodeData = False # asumo q la data no esta decodificada
466 469 self.flagDeflipData = False # asumo q la data no esta sin flip
467 470 self.flagShiftFFT = False
468 471 self.ippFactor = 1
469 472 self.beacon_heiIndexList = []
470 473 self.noise_estimation = None
471 474 self.codeList = []
472 475 self.azimuthList = []
473 476 self.elevationList = []
474 477 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
475 478 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp','nIncohInt', 'nFFTPoints', 'nProfiles']
476 479
477 480
481 self.max_nIncohInt = 1
482
483
478 484 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
479 485 """
480 486 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
481 487
482 488 Return:
483 489 noiselevel
484 490 """
485
491 # if hasattr(self.nIncohInt, "__len__"): #nIncohInt is a matrix
492 #
493 # heis = self.data_spc.shape[2]
494 #
495 # noise = numpy.zeros((self.nChannels, heis))
496 # for hei in range(heis):
497 # for channel in range(self.nChannels):
498 # daux = self.data_spc[channel, xmin_index:xmax_index, hei]
499 #
500 # noise[channel,hei] = hildebrand_sekhon(daux, self.nIncohInt[channel,hei])
501 #
502 # else:
503 # noise = numpy.zeros(self.nChannels)
504 # for channel in range(self.nChannels):
505 # daux = self.data_spc[channel,xmin_index:xmax_index, ymin_index:ymax_index]
506 #
507 # noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
486 508 noise = numpy.zeros(self.nChannels)
487 509 for channel in range(self.nChannels):
488 daux = self.data_spc[channel,
489 xmin_index:xmax_index, ymin_index:ymax_index]
490 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
510 daux = self.data_spc[channel,xmin_index:xmax_index, ymin_index:ymax_index]
511
512 noise[channel] = hildebrand_sekhon(daux, self.max_nIncohInt)
491 513
492 514 return noise
493 515
494 516 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
495 517
496 518 if self.noise_estimation is not None:
497 519 # this was estimated by getNoise Operation defined in jroproc_spectra.py
498 520 return self.noise_estimation
499 521 else:
500 522 noise = self.getNoisebyHildebrand(
501 523 xmin_index, xmax_index, ymin_index, ymax_index)
502 524 return noise
503 525
504 526 def getFreqRangeTimeResponse(self, extrapoints=0):
505 527
506 528 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
507 529 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
508 530
509 531 return freqrange
510 532
511 533 def getAcfRange(self, extrapoints=0):
512 534
513 535 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
514 536 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
515 537
516 538 return freqrange
517 539
518 540 def getFreqRange(self, extrapoints=0):
519 541
520 542 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
521 543 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
522 544
523 545 return freqrange
524 546
525 547 def getVelRange(self, extrapoints=0):
526 548
527 549 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
528 550 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
529 551
530 552 if self.nmodes:
531 553 return velrange/self.nmodes
532 554 else:
533 555 return velrange
534 556
535 557 @property
536 558 def nPairs(self):
537 559
538 560 return len(self.pairsList)
539 561
540 562 @property
541 563 def pairsIndexList(self):
542 564
543 565 return list(range(self.nPairs))
544 566
545 567 @property
546 568 def normFactor(self):
547 569
548 570 pwcode = 1
549 571
550 572 if self.flagDecodeData:
551 573 pwcode = numpy.sum(self.code[0]**2)
552 574 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
553 575 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
554 576
577
555 578 return normFactor
556 579
557 580 @property
558 581 def flag_cspc(self):
559 582
560 583 if self.data_cspc is None:
561 584 return True
562 585
563 586 return False
564 587
565 588 @property
566 589 def flag_dc(self):
567 590
568 591 if self.data_dc is None:
569 592 return True
570 593
571 594 return False
572 595
573 596 @property
574 597 def timeInterval(self):
575 598
576 599 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
577 600 if self.nmodes:
578 601 return self.nmodes*timeInterval
579 602 else:
580 603 return timeInterval
581 604
582 605 def getPower(self):
583 606
584 607 factor = self.normFactor
585 z = self.data_spc / factor
608 z = numpy.divide(self.data_spc,factor)
586 609 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
587 610 avg = numpy.average(z, axis=1)
588 611
589 612 return 10 * numpy.log10(avg)
590 613
591 614 def getCoherence(self, pairsList=None, phase=False):
592 615
593 616 z = []
594 617 if pairsList is None:
595 618 pairsIndexList = self.pairsIndexList
596 619 else:
597 620 pairsIndexList = []
598 621 for pair in pairsList:
599 622 if pair not in self.pairsList:
600 623 raise ValueError("Pair %s is not in dataOut.pairsList" % (
601 624 pair))
602 625 pairsIndexList.append(self.pairsList.index(pair))
603 626 for i in range(len(pairsIndexList)):
604 627 pair = self.pairsList[pairsIndexList[i]]
605 628 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
606 629 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
607 630 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
608 631 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
609 632 if phase:
610 633 data = numpy.arctan2(avgcoherenceComplex.imag,
611 634 avgcoherenceComplex.real) * 180 / numpy.pi
612 635 else:
613 636 data = numpy.abs(avgcoherenceComplex)
614 637
615 638 z.append(data)
616 639
617 640 return numpy.array(z)
618 641
619 642 def setValue(self, value):
620 643
621 644 print("This property should not be initialized")
622 645
623 646 return
624 647
625 648 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
626 649
627 650
628 651 class SpectraHeis(Spectra):
629 652
630 653 def __init__(self):
631 654
632 655 self.radarControllerHeaderObj = RadarControllerHeader()
633 656 self.systemHeaderObj = SystemHeader()
634 657 self.type = "SpectraHeis"
635 658 self.nProfiles = None
636 659 self.heightList = None
637 660 self.channelList = None
638 661 self.flagNoData = True
639 662 self.flagDiscontinuousBlock = False
640 663 self.utctime = None
641 664 self.blocksize = None
642 665 self.profileIndex = 0
643 666 self.nCohInt = 1
644 667 self.nIncohInt = 1
645 668
646 669 @property
647 670 def normFactor(self):
648 671 pwcode = 1
649 672 if self.flagDecodeData:
650 673 pwcode = numpy.sum(self.code[0]**2)
651 674
652 675 normFactor = self.nIncohInt * self.nCohInt * pwcode
653 676
654 677 return normFactor
655 678
656 679 @property
657 680 def timeInterval(self):
658 681
659 682 return self.ippSeconds * self.nCohInt * self.nIncohInt
660 683
661 684
662 685 class Fits(JROData):
663 686
664 687 def __init__(self):
665 688
666 689 self.type = "Fits"
667 690 self.nProfiles = None
668 691 self.heightList = None
669 692 self.channelList = None
670 693 self.flagNoData = True
671 694 self.utctime = None
672 695 self.nCohInt = 1
673 696 self.nIncohInt = 1
674 697 self.useLocalTime = True
675 698 self.profileIndex = 0
676 699 self.timeZone = 0
677 700
678 701 def getTimeRange(self):
679 702
680 703 datatime = []
681 704
682 705 datatime.append(self.ltctime)
683 706 datatime.append(self.ltctime + self.timeInterval)
684 707
685 708 datatime = numpy.array(datatime)
686 709
687 710 return datatime
688 711
689 712 def getChannelIndexList(self):
690 713
691 714 return list(range(self.nChannels))
692 715
693 716 def getNoise(self, type=1):
694 717
695 718
696 719 if type == 1:
697 720 noise = self.getNoisebyHildebrand()
698 721
699 722 if type == 2:
700 723 noise = self.getNoisebySort()
701 724
702 725 if type == 3:
703 726 noise = self.getNoisebyWindow()
704 727
705 728 return noise
706 729
707 730 @property
708 731 def timeInterval(self):
709 732
710 733 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
711 734
712 735 return timeInterval
713 736
714 737 @property
715 738 def ippSeconds(self):
716 739 '''
717 740 '''
718 741 return self.ipp_sec
719 742
720 743 noise = property(getNoise, "I'm the 'nHeights' property.")
721 744
722 745
723 746 class Correlation(JROData):
724 747
725 748 def __init__(self):
726 749 '''
727 750 Constructor
728 751 '''
729 752 self.radarControllerHeaderObj = RadarControllerHeader()
730 753 self.systemHeaderObj = SystemHeader()
731 754 self.type = "Correlation"
732 755 self.data = None
733 756 self.dtype = None
734 757 self.nProfiles = None
735 758 self.heightList = None
736 759 self.channelList = None
737 760 self.flagNoData = True
738 761 self.flagDiscontinuousBlock = False
739 762 self.utctime = None
740 763 self.timeZone = 0
741 764 self.dstFlag = None
742 765 self.errorCount = None
743 766 self.blocksize = None
744 767 self.flagDecodeData = False # asumo q la data no esta decodificada
745 768 self.flagDeflipData = False # asumo q la data no esta sin flip
746 769 self.pairsList = None
747 770 self.nPoints = None
748 771
749 772 def getPairsList(self):
750 773
751 774 return self.pairsList
752 775
753 776 def getNoise(self, mode=2):
754 777
755 778 indR = numpy.where(self.lagR == 0)[0][0]
756 779 indT = numpy.where(self.lagT == 0)[0][0]
757 780
758 781 jspectra0 = self.data_corr[:, :, indR, :]
759 782 jspectra = copy.copy(jspectra0)
760 783
761 784 num_chan = jspectra.shape[0]
762 785 num_hei = jspectra.shape[2]
763 786
764 787 freq_dc = jspectra.shape[1] / 2
765 788 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
766 789
767 790 if ind_vel[0] < 0:
768 791 ind_vel[list(range(0, 1))] = ind_vel[list(
769 792 range(0, 1))] + self.num_prof
770 793
771 794 if mode == 1:
772 795 jspectra[:, freq_dc, :] = (
773 796 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
774 797
775 798 if mode == 2:
776 799
777 800 vel = numpy.array([-2, -1, 1, 2])
778 801 xx = numpy.zeros([4, 4])
779 802
780 803 for fil in range(4):
781 804 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
782 805
783 806 xx_inv = numpy.linalg.inv(xx)
784 807 xx_aux = xx_inv[0, :]
785 808
786 809 for ich in range(num_chan):
787 810 yy = jspectra[ich, ind_vel, :]
788 811 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
789 812
790 813 junkid = jspectra[ich, freq_dc, :] <= 0
791 814 cjunkid = sum(junkid)
792 815
793 816 if cjunkid.any():
794 817 jspectra[ich, freq_dc, junkid.nonzero()] = (
795 818 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
796 819
797 820 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
798 821
799 822 return noise
800 823
801 824 @property
802 825 def timeInterval(self):
803 826
804 827 return self.ippSeconds * self.nCohInt * self.nProfiles
805 828
806 829 def splitFunctions(self):
807 830
808 831 pairsList = self.pairsList
809 832 ccf_pairs = []
810 833 acf_pairs = []
811 834 ccf_ind = []
812 835 acf_ind = []
813 836 for l in range(len(pairsList)):
814 837 chan0 = pairsList[l][0]
815 838 chan1 = pairsList[l][1]
816 839
817 840 # Obteniendo pares de Autocorrelacion
818 841 if chan0 == chan1:
819 842 acf_pairs.append(chan0)
820 843 acf_ind.append(l)
821 844 else:
822 845 ccf_pairs.append(pairsList[l])
823 846 ccf_ind.append(l)
824 847
825 848 data_acf = self.data_cf[acf_ind]
826 849 data_ccf = self.data_cf[ccf_ind]
827 850
828 851 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
829 852
830 853 @property
831 854 def normFactor(self):
832 855 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
833 856 acf_pairs = numpy.array(acf_pairs)
834 857 normFactor = numpy.zeros((self.nPairs, self.nHeights))
835 858
836 859 for p in range(self.nPairs):
837 860 pair = self.pairsList[p]
838 861
839 862 ch0 = pair[0]
840 863 ch1 = pair[1]
841 864
842 865 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
843 866 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
844 867 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
845 868
846 869 return normFactor
847 870
848 871
849 872 class Parameters(Spectra):
850 873
851 874 groupList = None # List of Pairs, Groups, etc
852 875 data_param = None # Parameters obtained
853 876 data_pre = None # Data Pre Parametrization
854 877 data_SNR = None # Signal to Noise Ratio
855 878 abscissaList = None # Abscissa, can be velocities, lags or time
856 879 utctimeInit = None # Initial UTC time
857 880 paramInterval = None # Time interval to calculate Parameters in seconds
858 881 useLocalTime = True
859 882 # Fitting
860 883 data_error = None # Error of the estimation
861 884 constants = None
862 885 library = None
863 886 # Output signal
864 887 outputInterval = None # Time interval to calculate output signal in seconds
865 888 data_output = None # Out signal
866 889 nAvg = None
867 890 noise_estimation = None
868 891 GauSPC = None # Fit gaussian SPC
869 892
870 893 def __init__(self):
871 894 '''
872 895 Constructor
873 896 '''
874 897 self.radarControllerHeaderObj = RadarControllerHeader()
875 898 self.systemHeaderObj = SystemHeader()
876 899 self.type = "Parameters"
877 900 self.timeZone = 0
878 901
879 902 def getTimeRange1(self, interval):
880 903
881 904 datatime = []
882 905
883 906 if self.useLocalTime:
884 907 time1 = self.utctimeInit - self.timeZone * 60
885 908 else:
886 909 time1 = self.utctimeInit
887 910
888 911 datatime.append(time1)
889 912 datatime.append(time1 + interval)
890 913 datatime = numpy.array(datatime)
891 914
892 915 return datatime
893 916
894 917 @property
895 918 def timeInterval(self):
896 919
897 920 if hasattr(self, 'timeInterval1'):
898 921 return self.timeInterval1
899 922 else:
900 923 return self.paramInterval
901 924
902 925 def setValue(self, value):
903 926
904 927 print("This property should not be initialized")
905 928
906 929 return
907 930
908 931 def getNoise(self):
909 932
910 933 return self.spc_noise
911 934
912 935 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
913 936
914 937
915 938 class PlotterData(object):
916 939 '''
917 940 Object to hold data to be plotted
918 941 '''
919 942
920 943 MAXNUMX = 200
921 944 MAXNUMY = 200
922 945
923 946 def __init__(self, code, exp_code, localtime=True):
924 947
925 948 self.key = code
926 949 self.exp_code = exp_code
927 950 self.ready = False
928 951 self.flagNoData = False
929 952 self.localtime = localtime
930 953 self.data = {}
931 954 self.meta = {}
932 955 self.__heights = []
933 956
934 957 def __str__(self):
935 958 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
936 959 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
937 960
938 961 def __len__(self):
939 962 return len(self.data)
940 963
941 964 def __getitem__(self, key):
942 965 if isinstance(key, int):
943 966 return self.data[self.times[key]]
944 967 elif isinstance(key, str):
945 968 ret = numpy.array([self.data[x][key] for x in self.times])
946 969 if ret.ndim > 1:
947 970 ret = numpy.swapaxes(ret, 0, 1)
948 971 return ret
949 972
950 973 def __contains__(self, key):
951 974 return key in self.data[self.min_time]
952 975
953 976 def setup(self):
954 977 '''
955 978 Configure object
956 979 '''
957 980 self.type = ''
958 981 self.ready = False
959 982 del self.data
960 983 self.data = {}
961 984 self.__heights = []
962 985 self.__all_heights = set()
963 986
964 987 def shape(self, key):
965 988 '''
966 989 Get the shape of the one-element data for the given key
967 990 '''
968 991
969 992 if len(self.data[self.min_time][key]):
970 993 return self.data[self.min_time][key].shape
971 994 return (0,)
972 995
973 996 def update(self, data, tm, meta={}):
974 997 '''
975 998 Update data object with new dataOut
976 999 '''
977 1000
978 1001 self.data[tm] = data
979 1002
980 1003 for key, value in meta.items():
981 1004 setattr(self, key, value)
982 1005
983 1006 def normalize_heights(self):
984 1007 '''
985 1008 Ensure same-dimension of the data for different heighList
986 1009 '''
987 1010
988 1011 H = numpy.array(list(self.__all_heights))
989 1012 H.sort()
990 1013 for key in self.data:
991 1014 shape = self.shape(key)[:-1] + H.shape
992 1015 for tm, obj in list(self.data[key].items()):
993 1016 h = self.__heights[self.times.tolist().index(tm)]
994 1017 if H.size == h.size:
995 1018 continue
996 1019 index = numpy.where(numpy.in1d(H, h))[0]
997 1020 dummy = numpy.zeros(shape) + numpy.nan
998 1021 if len(shape) == 2:
999 1022 dummy[:, index] = obj
1000 1023 else:
1001 1024 dummy[index] = obj
1002 1025 self.data[key][tm] = dummy
1003 1026
1004 1027 self.__heights = [H for tm in self.times]
1005 1028
1006 1029 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1007 1030 '''
1008 1031 Convert data to json
1009 1032 '''
1010 1033
1011 1034 meta = {}
1012 1035 meta['xrange'] = []
1013 1036 dy = int(len(self.yrange)/self.MAXNUMY) + 1
1014 1037 tmp = self.data[tm][self.key]
1015 1038 shape = tmp.shape
1016 1039 if len(shape) == 2:
1017 1040 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1018 1041 elif len(shape) == 3:
1019 1042 dx = int(self.data[tm][self.key].shape[1]/self.MAXNUMX) + 1
1020 1043 data = self.roundFloats(
1021 1044 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1022 1045 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1023 1046 else:
1024 1047 data = self.roundFloats(self.data[tm][self.key].tolist())
1025 1048
1026 1049 ret = {
1027 1050 'plot': plot_name,
1028 1051 'code': self.exp_code,
1029 1052 'time': float(tm),
1030 1053 'data': data,
1031 1054 }
1032 1055 meta['type'] = plot_type
1033 1056 meta['interval'] = float(self.interval)
1034 1057 meta['localtime'] = self.localtime
1035 1058 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1036 1059 meta.update(self.meta)
1037 1060 ret['metadata'] = meta
1038 1061 return json.dumps(ret)
1039 1062
1040 1063 @property
1041 1064 def times(self):
1042 1065 '''
1043 1066 Return the list of times of the current data
1044 1067 '''
1045 1068
1046 1069 ret = [t for t in self.data]
1047 1070 ret.sort()
1048 1071 return numpy.array(ret)
1049 1072
1050 1073 @property
1051 1074 def min_time(self):
1052 1075 '''
1053 1076 Return the minimun time value
1054 1077 '''
1055 1078
1056 1079 return self.times[0]
1057 1080
1058 1081 @property
1059 1082 def max_time(self):
1060 1083 '''
1061 1084 Return the maximun time value
1062 1085 '''
1063 1086
1064 1087 return self.times[-1]
1065 1088
1066 1089 # @property
1067 1090 # def heights(self):
1068 1091 # '''
1069 1092 # Return the list of heights of the current data
1070 1093 # '''
1071 1094
1072 1095 # return numpy.array(self.__heights[-1])
1073 1096
1074 1097 @staticmethod
1075 1098 def roundFloats(obj):
1076 1099 if isinstance(obj, list):
1077 1100 return list(map(PlotterData.roundFloats, obj))
1078 1101 elif isinstance(obj, float):
1079 1102 return round(obj, 2)
@@ -1,1016 +1,1180
1 1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Classes to plot Spectra data
6 6
7 7 """
8 8
9 9 import os
10 10 import numpy
11 11
12 12 from schainpy.model.graphics.jroplot_base import Plot, plt, log
13 13 from itertools import combinations
14 14 from matplotlib.ticker import LinearLocator
15 15
16 16 class SpectraPlot(Plot):
17 17 '''
18 18 Plot for Spectra data
19 19 '''
20 20
21 21 CODE = 'spc'
22 22 colormap = 'jet'
23 23 plot_type = 'pcolor'
24 24 buffering = False
25 25 channelList = []
26 26 elevationList = []
27 27 azimuthList = []
28 28
29 29 def setup(self):
30 30
31 31 self.nplots = len(self.data.channels)
32 32 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
33 33 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
34 34 self.height = 3.4 * self.nrows
35 35
36 36 self.cb_label = 'dB'
37 37 if self.showprofile:
38 38 self.width = 5.2 * self.ncols
39 39 else:
40 40 self.width = 4.2* self.ncols
41 41 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.12})
42 42 self.ylabel = 'Range [km]'
43 43
44 44
45 45 def update_list(self,dataOut):
46 46 if len(self.channelList) == 0:
47 47 self.channelList = dataOut.channelList
48 48 if len(self.elevationList) == 0:
49 49 self.elevationList = dataOut.elevationList
50 50 if len(self.azimuthList) == 0:
51 51 self.azimuthList = dataOut.azimuthList
52 52
53 53 def update(self, dataOut):
54 54
55 55 self.update_list(dataOut)
56 56 data = {}
57 57 meta = {}
58 58 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
59 59 data['spc'] = spc
60 60 data['rti'] = dataOut.getPower()
61 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
61 #data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
62 62 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
63 63 if self.CODE == 'spc_moments':
64 64 data['moments'] = dataOut.moments
65 65
66 66 return data, meta
67 67
68 68 def plot(self):
69 69 if self.xaxis == "frequency":
70 70 x = self.data.xrange[0]
71 71 self.xlabel = "Frequency (kHz)"
72 72 elif self.xaxis == "time":
73 73 x = self.data.xrange[1]
74 74 self.xlabel = "Time (ms)"
75 75 else:
76 76 x = self.data.xrange[2]
77 77 self.xlabel = "Velocity (m/s)"
78 78
79 79 if self.CODE == 'spc_moments':
80 80 x = self.data.xrange[2]
81 81 self.xlabel = "Velocity (m/s)"
82 82
83 83 self.titles = []
84 84 y = self.data.yrange
85 85 self.y = y
86 86
87 87 data = self.data[-1]
88 88 z = data['spc']
89 print(z.shape, x.shape, y.shape)
89 #print(z.shape, x.shape, y.shape)
90 90 for n, ax in enumerate(self.axes):
91 noise = data['noise'][n]
91 #noise = data['noise'][n]
92 noise=62
92 93 if self.CODE == 'spc_moments':
93 94 mean = data['moments'][n, 1]
94 95 if ax.firsttime:
95 96 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
96 97 self.xmin = self.xmin if self.xmin else -self.xmax
97 98 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
98 99 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
99 100 ax.plt = ax.pcolormesh(x, y, z[n].T,
100 101 vmin=self.zmin,
101 102 vmax=self.zmax,
102 103 cmap=plt.get_cmap(self.colormap)
103 104 )
104 105
105 106 if self.showprofile:
106 107 ax.plt_profile = self.pf_axes[n].plot(
107 108 data['rti'][n], y)[0]
108 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
109 color="k", linestyle="dashed", lw=1)[0]
109 # ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
110 # color="k", linestyle="dashed", lw=1)[0]
110 111 if self.CODE == 'spc_moments':
111 112 ax.plt_mean = ax.plot(mean, y, color='k')[0]
112 113 else:
113 114 ax.plt.set_array(z[n].T.ravel())
114 115 if self.showprofile:
115 116 ax.plt_profile.set_data(data['rti'][n], y)
116 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
117 #ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
117 118 if self.CODE == 'spc_moments':
118 119 ax.plt_mean.set_data(mean, y)
119 120 if len(self.azimuthList) > 0 and len(self.elevationList) > 0:
120 121 self.titles.append('CH {}: {:2.1f}elv {:2.1f}az {:3.2f}dB'.format(self.channelList[n], noise, self.elevationList[n], self.azimuthList[n]))
121 122 else:
122 123 self.titles.append('CH {}: {:3.2f}dB'.format(self.channelList[n], noise))
123 124
124 125
125 126 class CrossSpectraPlot(Plot):
126 127
127 128 CODE = 'cspc'
128 129 colormap = 'jet'
129 130 plot_type = 'pcolor'
130 131 zmin_coh = None
131 132 zmax_coh = None
132 133 zmin_phase = None
133 134 zmax_phase = None
134 135 realChannels = None
135 136 crossPairs = None
136 137
137 138 def setup(self):
138 139
139 140 self.ncols = 4
140 141 self.nplots = len(self.data.pairs) * 2
141 142 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
142 143 self.width = 3.1 * self.ncols
143 144 self.height = 2.6 * self.nrows
144 145 self.ylabel = 'Range [km]'
145 146 self.showprofile = False
146 147 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
147 148
148 149 def update(self, dataOut):
149 150
150 151 data = {}
151 152 meta = {}
152 153
153 154 spc = dataOut.data_spc
154 155 cspc = dataOut.data_cspc
155 156 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
156 157 rawPairs = list(combinations(list(range(dataOut.nChannels)), 2))
157 158 meta['pairs'] = rawPairs
158 159
159 160 if self.crossPairs == None:
160 161 self.crossPairs = dataOut.pairsList
161 162
162 163 tmp = []
163 164
164 165 for n, pair in enumerate(meta['pairs']):
165 166
166 167 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
167 168 coh = numpy.abs(out)
168 169 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
169 170 tmp.append(coh)
170 171 tmp.append(phase)
171 172
172 173 data['cspc'] = numpy.array(tmp)
173 174
174 175 return data, meta
175 176
176 177 def plot(self):
177 178
178 179 if self.xaxis == "frequency":
179 180 x = self.data.xrange[0]
180 181 self.xlabel = "Frequency (kHz)"
181 182 elif self.xaxis == "time":
182 183 x = self.data.xrange[1]
183 184 self.xlabel = "Time (ms)"
184 185 else:
185 186 x = self.data.xrange[2]
186 187 self.xlabel = "Velocity (m/s)"
187 188
188 189 self.titles = []
189 190
190 191 y = self.data.yrange
191 192 self.y = y
192 193
193 194 data = self.data[-1]
194 195 cspc = data['cspc']
195 196
196 197 for n in range(len(self.data.pairs)):
197 198
198 199 pair = self.crossPairs[n]
199 200
200 201 coh = cspc[n*2]
201 202 phase = cspc[n*2+1]
202 203 ax = self.axes[2 * n]
203 204
204 205 if ax.firsttime:
205 206 ax.plt = ax.pcolormesh(x, y, coh.T,
206 207 vmin=self.zmin_coh,
207 208 vmax=self.zmax_coh,
208 209 cmap=plt.get_cmap(self.colormap_coh)
209 210 )
210 211 else:
211 212 ax.plt.set_array(coh.T.ravel())
212 213 self.titles.append(
213 214 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
214 215
215 216 ax = self.axes[2 * n + 1]
216 217 if ax.firsttime:
217 218 ax.plt = ax.pcolormesh(x, y, phase.T,
218 219 vmin=-180,
219 220 vmax=180,
220 221 cmap=plt.get_cmap(self.colormap_phase)
221 222 )
222 223 else:
223 224 ax.plt.set_array(phase.T.ravel())
224 225
225 226 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
226 227
227 228
228 229 class RTIPlot(Plot):
229 230 '''
230 231 Plot for RTI data
231 232 '''
232 233
233 234 CODE = 'rti'
234 235 colormap = 'jet'
235 236 plot_type = 'pcolorbuffer'
236 237 titles = None
237 238 channelList = []
238 239 elevationList = []
239 240 azimuthList = []
240 241
241 242 def setup(self):
242 243 self.xaxis = 'time'
243 244 self.ncols = 1
244 245 #print("dataChannels ",self.data.channels)
245 246 self.nrows = len(self.data.channels)
246 247 self.nplots = len(self.data.channels)
247 248 self.ylabel = 'Range [km]'
248 249 self.xlabel = 'Time'
249 250 self.cb_label = 'dB'
250 251 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
251 252 self.titles = ['{} Channel {}'.format(
252 253 self.CODE.upper(), x) for x in range(self.nplots)]
253 254
254 255 def update_list(self,dataOut):
255 256
256 257 if len(self.channelList) == 0:
257 258 self.channelList = dataOut.channelList
258 259 if len(self.elevationList) == 0:
259 260 self.elevationList = dataOut.elevationList
260 261 if len(self.azimuthList) == 0:
261 262 self.azimuthList = dataOut.azimuthList
262 263
263 264
264 265 def update(self, dataOut):
265 266 if len(self.channelList) == 0:
266 267 self.update_list(dataOut)
267 268 data = {}
268 269 meta = {}
269 270 data['rti'] = dataOut.getPower()
270 271 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
271 272 return data, meta
272 273
273 274 def plot(self):
274 275
275 276 self.x = self.data.times
276 277 self.y = self.data.yrange
277
278 #print(" x, y: ",self.x, self.y)
278 279 self.z = self.data[self.CODE]
279 280 self.z = numpy.array(self.z, dtype=float)
280 281 self.z = numpy.ma.masked_invalid(self.z)
281 282
282 283 try:
283 284 if self.channelList != None:
284 285 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
285 286 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
286 287 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
287 288 else:
288 289 self.titles = ['{} Channel {}'.format(
289 290 self.CODE.upper(), x) for x in self.channelList]
290 291 except:
291 292 if self.channelList.any() != None:
292 293
293 294 self.titles = ['{} Channel {}'.format(
294 295 self.CODE.upper(), x) for x in self.channelList]
295 296
296 297 if self.decimation is None:
297 298 x, y, z = self.fill_gaps(self.x, self.y, self.z)
298 299 else:
299 300 x, y, z = self.fill_gaps(*self.decimate())
300 301
301 302 #dummy_var = self.axes #Extrañamente esto actualiza el valor axes
302 303 for n, ax in enumerate(self.axes):
303 304 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
304 305 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
305 306 data = self.data[-1]
306 307
307 308 if ax.firsttime:
308 309 ax.plt = ax.pcolormesh(x, y, z[n].T,
309 310 vmin=self.zmin,
310 311 vmax=self.zmax,
311 312 cmap=plt.get_cmap(self.colormap)
312 313 )
313 314 if self.showprofile:
314 315 ax.plot_profile = self.pf_axes[n].plot(data[self.CODE][n], self.y)[0]
315 316 if "noise" in self.data:
316 317
317 318 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
318 319 color="k", linestyle="dashed", lw=1)[0]
319 320 else:
320 321 ax.collections.remove(ax.collections[0])
321 322 ax.plt = ax.pcolormesh(x, y, z[n].T,
322 323 vmin=self.zmin,
323 324 vmax=self.zmax,
324 325 cmap=plt.get_cmap(self.colormap)
325 326 )
326 327 if self.showprofile:
327 328 ax.plot_profile.set_data(data[self.CODE][n], self.y)
328 329 if "noise" in self.data:
329 330
330 331 ax.plot_noise.set_data(numpy.repeat(
331 332 data['noise'][n], len(self.y)), self.y)
332 333
333 334
334 335 class CoherencePlot(RTIPlot):
335 336 '''
336 337 Plot for Coherence data
337 338 '''
338 339
339 340 CODE = 'coh'
340 341
341 342 def setup(self):
342 343 self.xaxis = 'time'
343 344 self.ncols = 1
344 345 self.nrows = len(self.data.pairs)
345 346 self.nplots = len(self.data.pairs)
346 347 self.ylabel = 'Range [km]'
347 348 self.xlabel = 'Time'
348 349 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
349 350 if self.CODE == 'coh':
350 351 self.cb_label = ''
351 352 self.titles = [
352 353 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
353 354 else:
354 355 self.cb_label = 'Degrees'
355 356 self.titles = [
356 357 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
357 358
358 359 def update(self, dataOut):
359 360 self.update_list(dataOut)
360 361 data = {}
361 362 meta = {}
362 363 data['coh'] = dataOut.getCoherence()
363 364 meta['pairs'] = dataOut.pairsList
364 365
365 366
366 367 return data, meta
367 368
368 369 class PhasePlot(CoherencePlot):
369 370 '''
370 371 Plot for Phase map data
371 372 '''
372 373
373 374 CODE = 'phase'
374 375 colormap = 'seismic'
375 376
376 377 def update(self, dataOut):
377 378
378 379 data = {}
379 380 meta = {}
380 381 data['phase'] = dataOut.getCoherence(phase=True)
381 382 meta['pairs'] = dataOut.pairsList
382 383
383 384 return data, meta
384 385
385 386 class NoisePlot(Plot):
386 387 '''
387 388 Plot for noise
388 389 '''
389 390
390 391 CODE = 'noise'
391 392 plot_type = 'scatterbuffer'
392 393
393 394 def setup(self):
394 395 self.xaxis = 'time'
395 396 self.ncols = 1
396 397 self.nrows = 1
397 398 self.nplots = 1
398 399 self.ylabel = 'Intensity [dB]'
399 400 self.xlabel = 'Time'
400 401 self.titles = ['Noise']
401 402 self.colorbar = False
402 403 self.plots_adjust.update({'right': 0.85 })
403 404
404 405 def update(self, dataOut):
405 406
406 407 data = {}
407 408 meta = {}
408 409 noise = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
409 410 data['noise'] = noise
410 411 meta['yrange'] = numpy.array([])
411 412
412 413 return data, meta
413 414
414 415 def plot(self):
415 416
416 417 x = self.data.times
417 418 xmin = self.data.min_time
418 419 xmax = xmin + self.xrange * 60 * 60
419 420 Y = self.data['noise']
420 421
421 422 if self.axes[0].firsttime:
422 423 if self.ymin is None: self.ymin = numpy.nanmin(Y) - 5
423 424 if self.ymax is None: self.ymax = numpy.nanmax(Y) + 5
424 425 for ch in self.data.channels:
425 426 y = Y[ch]
426 427 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
427 428 plt.legend(bbox_to_anchor=(1.18, 1.0))
428 429 else:
429 430 for ch in self.data.channels:
430 431 y = Y[ch]
431 432 self.axes[0].lines[ch].set_data(x, y)
432 433
433 434
434 435 class PowerProfilePlot(Plot):
435 436
436 437 CODE = 'pow_profile'
437 438 plot_type = 'scatter'
438 439
439 440 def setup(self):
440 441
441 442 self.ncols = 1
442 443 self.nrows = 1
443 444 self.nplots = 1
444 445 self.height = 4
445 446 self.width = 3
446 447 self.ylabel = 'Range [km]'
447 448 self.xlabel = 'Intensity [dB]'
448 449 self.titles = ['Power Profile']
449 450 self.colorbar = False
450 451
451 452 def update(self, dataOut):
452 453
453 454 data = {}
454 455 meta = {}
455 456 data[self.CODE] = dataOut.getPower()
456 457
457 458 return data, meta
458 459
459 460 def plot(self):
460 461
461 462 y = self.data.yrange
462 463 self.y = y
463 464
464 465 x = self.data[-1][self.CODE]
465 466
466 467 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
467 468 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
468 469
469 470 if self.axes[0].firsttime:
470 471 for ch in self.data.channels:
471 472 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
472 473 plt.legend()
473 474 else:
474 475 for ch in self.data.channels:
475 476 self.axes[0].lines[ch].set_data(x[ch], y)
476 477
477 478
478 479 class SpectraCutPlot(Plot):
479 480
480 481 CODE = 'spc_cut'
481 482 plot_type = 'scatter'
482 483 buffering = False
483 484 heights = []
484 485 channelList = []
485 486 maintitle = "Spectra Cuts"
486 487 flag_setIndex = False
487 488
488 489 def setup(self):
489 490
490 491 self.nplots = len(self.data.channels)
491 492 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
492 493 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
493 494 self.width = 4.2 * self.ncols + 2.5
494 495 self.height = 4.8 * self.nrows
495 496 self.ylabel = 'Power [dB]'
496 497 self.colorbar = False
497 498 self.plots_adjust.update({'left':0.05, 'hspace':0.3, 'right': 0.9, 'bottom':0.08})
498 499
499 500 if len(self.selectedHeightsList) > 0:
500 501 self.maintitle = "Spectra Cut"# for %d km " %(int(self.selectedHeight))
501 502
502 503
503 504
504 505 def update(self, dataOut):
505 506 if len(self.channelList) == 0:
506 507 self.channelList = dataOut.channelList
507 508
508 509 self.heights = dataOut.heightList
509 510 #print("sels: ",self.selectedHeightsList)
510 511 if len(self.selectedHeightsList)>0 and not self.flag_setIndex:
511 512
512 513 for sel_height in self.selectedHeightsList:
513 514 index_list = numpy.where(self.heights >= sel_height)
514 515 index_list = index_list[0]
515 516 self.height_index.append(index_list[0])
516 517 #print("sels i:"", self.height_index)
517 518 self.flag_setIndex = True
518 519 #print(self.height_index)
519 520 data = {}
520 521 meta = {}
521 522 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
522 523
523 524 data['spc'] = spc
524 525 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
525 526
526 527 return data, meta
527 528
528 529 def plot(self):
529 530 if self.xaxis == "frequency":
530 531 x = self.data.xrange[0][1:]
531 532 self.xlabel = "Frequency (kHz)"
532 533 elif self.xaxis == "time":
533 534 x = self.data.xrange[1]
534 535 self.xlabel = "Time (ms)"
535 536 else:
536 537 x = self.data.xrange[2]
537 538 self.xlabel = "Velocity (m/s)"
538 539
539 540 self.titles = []
540 541
541 542 y = self.data.yrange
542 543 z = self.data[-1]['spc']
543 544 #print(z.shape)
544 545 if len(self.height_index) > 0:
545 546 index = self.height_index
546 547 else:
547 548 index = numpy.arange(0, len(y), int((len(y))/9))
548 549 #print("inde x ", index, self.axes)
549 550
550 551 for n, ax in enumerate(self.axes):
551 552
552 553 if ax.firsttime:
553 554
554 555
555 556 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
556 557 self.xmin = self.xmin if self.xmin else -self.xmax
557 558 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
558 559 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
559 560
560 561
561 562 ax.plt = ax.plot(x, z[n, :, index].T)
562 563 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
563 564 self.figures[0].legend(ax.plt, labels, loc='center right', prop={'size': 8})
564 565 ax.minorticks_on()
565 566 ax.grid(which='major', axis='both')
566 567 ax.grid(which='minor', axis='x')
567 568 else:
568 569 for i, line in enumerate(ax.plt):
569 570 line.set_data(x, z[n, :, index[i]])
570 571
571 572
572 573 self.titles.append('CH {}'.format(self.channelList[n]))
573 574 plt.suptitle(self.maintitle, fontsize=10)
574 575
575 576
576 577 class BeaconPhase(Plot):
577 578
578 579 __isConfig = None
579 580 __nsubplots = None
580 581
581 582 PREFIX = 'beacon_phase'
582 583
583 584 def __init__(self):
584 585 Plot.__init__(self)
585 586 self.timerange = 24*60*60
586 587 self.isConfig = False
587 588 self.__nsubplots = 1
588 589 self.counter_imagwr = 0
589 590 self.WIDTH = 800
590 591 self.HEIGHT = 400
591 592 self.WIDTHPROF = 120
592 593 self.HEIGHTPROF = 0
593 594 self.xdata = None
594 595 self.ydata = None
595 596
596 597 self.PLOT_CODE = BEACON_CODE
597 598
598 599 self.FTP_WEI = None
599 600 self.EXP_CODE = None
600 601 self.SUB_EXP_CODE = None
601 602 self.PLOT_POS = None
602 603
603 604 self.filename_phase = None
604 605
605 606 self.figfile = None
606 607
607 608 self.xmin = None
608 609 self.xmax = None
609 610
610 611 def getSubplots(self):
611 612
612 613 ncol = 1
613 614 nrow = 1
614 615
615 616 return nrow, ncol
616 617
617 618 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
618 619
619 620 self.__showprofile = showprofile
620 621 self.nplots = nplots
621 622
622 623 ncolspan = 7
623 624 colspan = 6
624 625 self.__nsubplots = 2
625 626
626 627 self.createFigure(id = id,
627 628 wintitle = wintitle,
628 629 widthplot = self.WIDTH+self.WIDTHPROF,
629 630 heightplot = self.HEIGHT+self.HEIGHTPROF,
630 631 show=show)
631 632
632 633 nrow, ncol = self.getSubplots()
633 634
634 635 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
635 636
636 637 def save_phase(self, filename_phase):
637 638 f = open(filename_phase,'w+')
638 639 f.write('\n\n')
639 640 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
640 641 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
641 642 f.close()
642 643
643 644 def save_data(self, filename_phase, data, data_datetime):
644 645 f=open(filename_phase,'a')
645 646 timetuple_data = data_datetime.timetuple()
646 647 day = str(timetuple_data.tm_mday)
647 648 month = str(timetuple_data.tm_mon)
648 649 year = str(timetuple_data.tm_year)
649 650 hour = str(timetuple_data.tm_hour)
650 651 minute = str(timetuple_data.tm_min)
651 652 second = str(timetuple_data.tm_sec)
652 653 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
653 654 f.close()
654 655
655 656 def plot(self):
656 657 log.warning('TODO: Not yet implemented...')
657 658
658 659 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
659 660 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
660 661 timerange=None,
661 662 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
662 663 server=None, folder=None, username=None, password=None,
663 664 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
664 665
665 666 if dataOut.flagNoData:
666 667 return dataOut
667 668
668 669 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
669 670 return
670 671
671 672 if pairsList == None:
672 673 pairsIndexList = dataOut.pairsIndexList[:10]
673 674 else:
674 675 pairsIndexList = []
675 676 for pair in pairsList:
676 677 if pair not in dataOut.pairsList:
677 678 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
678 679 pairsIndexList.append(dataOut.pairsList.index(pair))
679 680
680 681 if pairsIndexList == []:
681 682 return
682 683
683 684 # if len(pairsIndexList) > 4:
684 685 # pairsIndexList = pairsIndexList[0:4]
685 686
686 687 hmin_index = None
687 688 hmax_index = None
688 689
689 690 if hmin != None and hmax != None:
690 691 indexes = numpy.arange(dataOut.nHeights)
691 692 hmin_list = indexes[dataOut.heightList >= hmin]
692 693 hmax_list = indexes[dataOut.heightList <= hmax]
693 694
694 695 if hmin_list.any():
695 696 hmin_index = hmin_list[0]
696 697
697 698 if hmax_list.any():
698 699 hmax_index = hmax_list[-1]+1
699 700
700 701 x = dataOut.getTimeRange()
701 702
702 703 thisDatetime = dataOut.datatime
703 704
704 705 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
705 706 xlabel = "Local Time"
706 707 ylabel = "Phase (degrees)"
707 708
708 709 update_figfile = False
709 710
710 711 nplots = len(pairsIndexList)
711 712 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
712 713 phase_beacon = numpy.zeros(len(pairsIndexList))
713 714 for i in range(nplots):
714 715 pair = dataOut.pairsList[pairsIndexList[i]]
715 716 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
716 717 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
717 718 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
718 719 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
719 720 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
720 721
721 722 if dataOut.beacon_heiIndexList:
722 723 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
723 724 else:
724 725 phase_beacon[i] = numpy.average(phase)
725 726
726 727 if not self.isConfig:
727 728
728 729 nplots = len(pairsIndexList)
729 730
730 731 self.setup(id=id,
731 732 nplots=nplots,
732 733 wintitle=wintitle,
733 734 showprofile=showprofile,
734 735 show=show)
735 736
736 737 if timerange != None:
737 738 self.timerange = timerange
738 739
739 740 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
740 741
741 742 if ymin == None: ymin = 0
742 743 if ymax == None: ymax = 360
743 744
744 745 self.FTP_WEI = ftp_wei
745 746 self.EXP_CODE = exp_code
746 747 self.SUB_EXP_CODE = sub_exp_code
747 748 self.PLOT_POS = plot_pos
748 749
749 750 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
750 751 self.isConfig = True
751 752 self.figfile = figfile
752 753 self.xdata = numpy.array([])
753 754 self.ydata = numpy.array([])
754 755
755 756 update_figfile = True
756 757
757 758 #open file beacon phase
758 759 path = '%s%03d' %(self.PREFIX, self.id)
759 760 beacon_file = os.path.join(path,'%s.txt'%self.name)
760 761 self.filename_phase = os.path.join(figpath,beacon_file)
761 762 #self.save_phase(self.filename_phase)
762 763
763 764
764 765 #store data beacon phase
765 766 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
766 767
767 768 self.setWinTitle(title)
768 769
769 770
770 771 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
771 772
772 773 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
773 774
774 775 axes = self.axesList[0]
775 776
776 777 self.xdata = numpy.hstack((self.xdata, x[0:1]))
777 778
778 779 if len(self.ydata)==0:
779 780 self.ydata = phase_beacon.reshape(-1,1)
780 781 else:
781 782 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
782 783
783 784
784 785 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
785 786 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
786 787 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
787 788 XAxisAsTime=True, grid='both'
788 789 )
789 790
790 791 self.draw()
791 792
792 793 if dataOut.ltctime >= self.xmax:
793 794 self.counter_imagwr = wr_period
794 795 self.isConfig = False
795 796 update_figfile = True
796 797
797 798 self.save(figpath=figpath,
798 799 figfile=figfile,
799 800 save=save,
800 801 ftp=ftp,
801 802 wr_period=wr_period,
802 803 thisDatetime=thisDatetime,
803 804 update_figfile=update_figfile)
804 805
805 806 return dataOut
806 807
807 808 class NoiselessSpectraPlot(Plot):
808 809 '''
809 810 Plot for Spectra data, subtracting
810 811 the noise in all channels, using for
811 812 amisr-14 data
812 813 '''
813 814
814 815 CODE = 'noiseless_spc'
815 816 colormap = 'nipy_spectral'
816 817 plot_type = 'pcolor'
817 818 buffering = False
818 819 channelList = []
820 last_noise = None
819 821
820 822 def setup(self):
821 823
822 824 self.nplots = len(self.data.channels)
823 825 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
824 826 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
825 827 self.height = 2.6 * self.nrows
826 828
827 829 self.cb_label = 'dB'
828 830 if self.showprofile:
829 831 self.width = 4 * self.ncols
830 832 else:
831 833 self.width = 3.5 * self.ncols
832 834 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
833 835 self.ylabel = 'Range [km]'
834 836
835 837
836 838 def update_list(self,dataOut):
837 839 if len(self.channelList) == 0:
838 840 self.channelList = dataOut.channelList
839 841
840 842 def update(self, dataOut):
841 843
842 844 self.update_list(dataOut)
843 845 data = {}
844 846 meta = {}
845 n0 = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
846 (nch, nff, nh) = dataOut.data_spc.shape
847 n1 = numpy.repeat(n0,nh, axis=0).reshape((nch,nh))
848 noise = numpy.repeat(n1,nff, axis=1).reshape((nch,nff,nh))
849 #print(noise.shape, "noise", noise)
850 847
851 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor) - noise
848 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
849 n0 = 10*numpy.log10(dataOut.getNoise()/float(norm))
852 850
853 data['spc'] = spc
854 data['rti'] = dataOut.getPower() - n1
851 if self.last_noise == None:
852 self.last_noise = n0
853 else:
854 n0 = (n0*0.2 + self.last_noise*0.8)
855 self.last_noise = n0
856
857 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
855 858
856 data['noise'] = n0
859 data['spc'] = spc - n0
860 data['rti'] = dataOut.getPower() - n0
861
862 #data['noise'] = noise
857 863 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
858 864
859 865 return data, meta
860 866
861 867 def plot(self):
862 868 if self.xaxis == "frequency":
863 869 x = self.data.xrange[0]
864 870 self.xlabel = "Frequency (kHz)"
865 871 elif self.xaxis == "time":
866 872 x = self.data.xrange[1]
867 873 self.xlabel = "Time (ms)"
868 874 else:
869 875 x = self.data.xrange[2]
870 876 self.xlabel = "Velocity (m/s)"
871 877
872 878 self.titles = []
873 879 y = self.data.yrange
874 880 self.y = y
875 881
876 882 data = self.data[-1]
877 883 z = data['spc']
878 884
879 885 for n, ax in enumerate(self.axes):
880 noise = data['noise'][n]
886 #noise = data['noise'][n]
881 887
882 888 if ax.firsttime:
883 889 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
884 890 self.xmin = self.xmin if self.xmin else -self.xmax
885 891 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
886 892 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
887 893 ax.plt = ax.pcolormesh(x, y, z[n].T,
888 894 vmin=self.zmin,
889 895 vmax=self.zmax,
890 896 cmap=plt.get_cmap(self.colormap)
891 897 )
892 898
893 899 if self.showprofile:
894 900 ax.plt_profile = self.pf_axes[n].plot(
895 901 data['rti'][n], y)[0]
896 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
897 color="k", linestyle="dashed", lw=1)[0]
902
898 903
899 904 else:
900 905 ax.plt.set_array(z[n].T.ravel())
901 906 if self.showprofile:
902 907 ax.plt_profile.set_data(data['rti'][n], y)
903 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
904 908
905 self.titles.append('CH {}: {:3.2f}dB'.format(self.channelList[n], noise))
909
910 self.titles.append('CH {}'.format(self.channelList[n]))
906 911
907 912
908 913 class NoiselessRTIPlot(Plot):
909 914 '''
910 915 Plot for RTI data
911 916 '''
912 917
913 918 CODE = 'noiseless_rti'
914 919 colormap = 'jet'
915 920 plot_type = 'pcolorbuffer'
916 921 titles = None
917 922 channelList = []
918 923 elevationList = []
919 924 azimuthList = []
925 last_noise = None
920 926
921 927 def setup(self):
922 928 self.xaxis = 'time'
923 929 self.ncols = 1
924 930 #print("dataChannels ",self.data.channels)
925 931 self.nrows = len(self.data.channels)
926 932 self.nplots = len(self.data.channels)
927 933 self.ylabel = 'Range [km]'
928 934 self.xlabel = 'Time'
929 935 self.cb_label = 'dB'
930 936 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
931 937 self.titles = ['{} Channel {}'.format(
932 938 self.CODE.upper(), x) for x in range(self.nplots)]
933 939
934 940 def update_list(self,dataOut):
935 941 if len(self.channelList) == 0:
936 942 self.channelList = dataOut.channelList
937 943 if len(self.elevationList) == 0:
938 944 self.elevationList = dataOut.elevationList
939 945 if len(self.azimuthList) == 0:
940 946 self.azimuthList = dataOut.azimuthList
941 947
942 948 def update(self, dataOut):
943 949 if len(self.channelList) == 0:
944 950 self.update_list(dataOut)
945 951 data = {}
946 952 meta = {}
947 953
948 n0 = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
949 (nch, nff, nh) = dataOut.data_spc.shape
950 #print(nch, nff, nh)
951 if nch != 1:
952 aux = []
953 for c in self.channelList:
954 aux.append(n0[c])
955 n0 = numpy.asarray(aux)
956 noise = numpy.repeat(n0,nh, axis=0).reshape((nch,nh))
957 #print(dataOut.elevationList, dataOut.azimuthList)
958 #print(dataOut.channelList)
959 data['noiseless_rti'] = dataOut.getPower() - noise
960 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
954
955 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
956 n0 = 10*numpy.log10(dataOut.getNoise()/float(norm))
957 #print("noise: ",n0, dataOut.normFactor, norm, dataOut.nIncohInt, dataOut.max_nIncohInt)
958 if self.last_noise == None:
959 self.last_noise = n0
960 else:
961 n0 = (n0*0.2 + self.last_noise*0.8)
962 self.last_noise = n0
963
964
965 data['noiseless_rti'] = dataOut.getPower() - n0
966
967 #data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
968 #print(noise)
961 969 return data, meta
962 970
963 971 def plot(self):
964 972
965 973 self.x = self.data.times
966 974 self.y = self.data.yrange
967 975 self.z = self.data['noiseless_rti']
968 976 self.z = numpy.array(self.z, dtype=float)
969 977 self.z = numpy.ma.masked_invalid(self.z)
970 978
971 979 try:
972 980 if self.channelList != None:
973 981 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
974 982 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
975 983 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
976 984 else:
977 985 self.titles = ['{} Channel {}'.format(
978 986 self.CODE.upper(), x) for x in self.channelList]
979 987 except:
980 988 if self.channelList.any() != None:
981 989
982 990 self.titles = ['{} Channel {}'.format(
983 991 self.CODE.upper(), x) for x in self.channelList]
984 992 if self.decimation is None:
985 993 x, y, z = self.fill_gaps(self.x, self.y, self.z)
986 994 else:
987 995 x, y, z = self.fill_gaps(*self.decimate())
988 996 dummy_var = self.axes #Extrañamente esto actualiza el valor axes
997 #print("plot shapes ", z.shape, x.shape, y.shape)
989 998 for n, ax in enumerate(self.axes):
990 999 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
991 1000 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
992 1001 data = self.data[-1]
993 1002 if ax.firsttime:
994 1003 ax.plt = ax.pcolormesh(x, y, z[n].T,
995 1004 vmin=self.zmin,
996 1005 vmax=self.zmax,
997 1006 cmap=plt.get_cmap(self.colormap)
998 1007 )
999 1008 if self.showprofile:
1000 1009 ax.plot_profile = self.pf_axes[n].plot(data['noiseless_rti'][n], self.y)[0]
1001 1010
1002 if "noise" in self.data:
1003 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
1004 color="k", linestyle="dashed", lw=1)[0]
1005 1011 else:
1006 1012 ax.collections.remove(ax.collections[0])
1007 1013 ax.plt = ax.pcolormesh(x, y, z[n].T,
1008 1014 vmin=self.zmin,
1009 1015 vmax=self.zmax,
1010 1016 cmap=plt.get_cmap(self.colormap)
1011 1017 )
1012 1018 if self.showprofile:
1013 1019 ax.plot_profile.set_data(data['noiseless_rti'][n], self.y)
1014 if "noise" in self.data:
1015 ax.plot_noise.set_data(numpy.repeat(
1016 data['noise'][n], len(self.y)), self.y)
1020 # if "noise" in self.data:
1021 # #ax.plot_noise.set_data(numpy.repeat(data['noise'][n], len(self.y)), self.y)
1022 # ax.plot_noise.set_data(data['noise'][n], self.y)
1023
1024
1025 class OutliersRTIPlot(Plot):
1026 '''
1027 Plot for data_xxxx object
1028 '''
1029
1030 CODE = 'outlier'
1031 colormap = 'cool'
1032 plot_type = 'pcolorbuffer'
1033
1034 def setup(self):
1035 self.xaxis = 'time'
1036 self.ncols = 1
1037 self.nrows = self.data.shape('outlier')[0]
1038 self.nplots = self.nrows
1039 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
1040
1041
1042 if not self.xlabel:
1043 self.xlabel = 'Time'
1044
1045 self.ylabel = 'Height [km]'
1046 if not self.titles:
1047 self.titles = ['Outliers Ch:{}'.format(x) for x in range(self.nrows)]
1048
1049 def update(self, dataOut):
1050
1051 data = {}
1052 data['outlier'] = dataOut.data_outlier
1053
1054 meta = {}
1055
1056 return data, meta
1057
1058 def plot(self):
1059 # self.data.normalize_heights()
1060 self.x = self.data.times
1061 self.y = self.data.yrange
1062 self.z = self.data['outlier']
1063
1064 #self.z = numpy.ma.masked_invalid(self.z)
1065
1066 if self.decimation is None:
1067 x, y, z = self.fill_gaps(self.x, self.y, self.z)
1068 else:
1069 x, y, z = self.fill_gaps(*self.decimate())
1070
1071 for n, ax in enumerate(self.axes):
1072
1073 self.zmax = self.zmax if self.zmax is not None else numpy.max(
1074 self.z[n])
1075 self.zmin = self.zmin if self.zmin is not None else numpy.min(
1076 self.z[n])
1077 data = self.data[-1]
1078 if ax.firsttime:
1079 if self.zlimits is not None:
1080 self.zmin, self.zmax = self.zlimits[n]
1081
1082 ax.plt = ax.pcolormesh(x, y, z[n].T,
1083 vmin=self.zmin,
1084 vmax=self.zmax,
1085 cmap=self.cmaps[n]
1086 )
1087 if self.showprofile:
1088 ax.plot_profile = self.pf_axes[n].plot(data['outlier'][n], self.y)[0]
1089 self.pf_axes[n].set_xlabel('')
1090 else:
1091 if self.zlimits is not None:
1092 self.zmin, self.zmax = self.zlimits[n]
1093 ax.collections.remove(ax.collections[0])
1094 ax.plt = ax.pcolormesh(x, y, z[n].T ,
1095 vmin=self.zmin,
1096 vmax=self.zmax,
1097 cmap=self.cmaps[n]
1098 )
1099 if self.showprofile:
1100 ax.plot_profile.set_data(data['outlier'][n], self.y)
1101 self.pf_axes[n].set_xlabel('')
1102
1103 # class NoiseRTIPlot(Plot):
1104 # '''
1105 # Plot for data_xxxx object
1106 # '''
1107 #
1108 # CODE = 'noise'
1109 # colormap = 'jet'
1110 # plot_type = 'pcolorbuffer'
1111 #
1112 # def setup(self):
1113 # self.xaxis = 'time'
1114 # self.ncols = 1
1115 # self.nrows = self.data.shape('noise')[0]
1116 # self.nplots = self.nrows
1117 # self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
1118 #
1119 #
1120 # if not self.xlabel:
1121 # self.xlabel = 'Time'
1122 #
1123 # self.ylabel = 'Height [km]'
1124 # if not self.titles:
1125 # self.titles = ['noise Ch:{}'.format(x) for x in range(self.nrows)]
1126 #
1127 # def update(self, dataOut):
1128 #
1129 # data = {}
1130 # norm = dataOut.max_nIncohInt*dataOut.nProfiles* dataOut.nCohInt*dataOut.windowOfFilter
1131 # print("max incoh: ",dataOut.max_nIncohInt )
1132 # n0 = 10*numpy.log10(dataOut.getNoise()/norm)
1133 # data['noise'] = n0
1134 #
1135 # meta = {}
1136 #
1137 # return data, meta
1138 #
1139 # def plot(self):
1140 # # self.data.normalize_heights()
1141 # self.x = self.data.times
1142 # self.y = self.data.yrange
1143 # self.z = self.data['noise']
1144 #
1145 # #self.z = numpy.ma.masked_invalid(self.z)
1146 #
1147 # if self.decimation is None:
1148 # x, y, z = self.fill_gaps(self.x, self.y, self.z)
1149 # else:
1150 # x, y, z = self.fill_gaps(*self.decimate())
1151 #
1152 # for n, ax in enumerate(self.axes):
1153 #
1154 # self.zmax = self.zmax if self.zmax is not None else numpy.max(
1155 # self.z[n])
1156 # self.zmin = self.zmin if self.zmin is not None else numpy.min(
1157 # self.z[n])
1158 # data = self.data[-1]
1159 # if ax.firsttime:
1160 # if self.zlimits is not None:
1161 # self.zmin, self.zmax = self.zlimits[n]
1162 #
1163 # ax.plt = ax.pcolormesh(x, y, z[n].T,
1164 # vmin=self.zmin,
1165 # vmax=self.zmax,
1166 # cmap=self.cmaps[n]
1167 # )
1168 # if self.showprofile:
1169 # ax.plot_profile = self.pf_axes[n].plot(data['noise'][n], self.y)[0]
1170 # else:
1171 # if self.zlimits is not None:
1172 # self.zmin, self.zmax = self.zlimits[n]
1173 # ax.collections.remove(ax.collections[0])
1174 # ax.plt = ax.pcolormesh(x, y, z[n].T ,
1175 # vmin=self.zmin,
1176 # vmax=self.zmax,
1177 # cmap=self.cmaps[n]
1178 # )
1179 # if self.showprofile:
1180 # ax.plot_profile.set_data(data['noise'][n], self.y)
@@ -1,665 +1,666
1 1 ''''
2 2 Created on Set 9, 2015
3 3
4 4 @author: roj-idl71 Karim Kuyeng
5 5
6 6 @update: 2021, Joab Apaza
7 7 '''
8 8
9 9 import os
10 10 import sys
11 11 import glob
12 12 import fnmatch
13 13 import datetime
14 14 import time
15 15 import re
16 16 import h5py
17 17 import numpy
18 18
19 19 try:
20 20 from gevent import sleep
21 21 except:
22 22 from time import sleep
23 23
24 24 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
25 25 from schainpy.model.data.jrodata import Voltage
26 26 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
27 27 from numpy import imag
28 28 from schainpy.utils import log
29 29
30 30
31 31 class AMISRReader(ProcessingUnit):
32 32 '''
33 33 classdocs
34 34 '''
35 35
36 36 def __init__(self):
37 37 '''
38 38 Constructor
39 39 '''
40 40
41 41 ProcessingUnit.__init__(self)
42 42
43 43 self.set = None
44 44 self.subset = None
45 45 self.extension_file = '.h5'
46 46 self.dtc_str = 'dtc'
47 47 self.dtc_id = 0
48 48 self.status = True
49 49 self.isConfig = False
50 50 self.dirnameList = []
51 51 self.filenameList = []
52 52 self.fileIndex = None
53 53 self.flagNoMoreFiles = False
54 54 self.flagIsNewFile = 0
55 55 self.filename = ''
56 56 self.amisrFilePointer = None
57 57 self.realBeamCode = []
58 58 self.beamCodeMap = None
59 59 self.azimuthList = []
60 60 self.elevationList = []
61 61 self.dataShape = None
62 62 self.flag_old_beams = False
63 63
64 64
65 65 self.profileIndex = 0
66 66
67 67
68 68 self.beamCodeByFrame = None
69 69 self.radacTimeByFrame = None
70 70
71 71 self.dataset = None
72 72
73 73 self.__firstFile = True
74 74
75 75 self.buffer = None
76 76
77 77 self.timezone = 'ut'
78 78
79 79 self.__waitForNewFile = 20
80 80 self.__filename_online = None
81 81 #Is really necessary create the output object in the initializer
82 82 self.dataOut = Voltage()
83 83 self.dataOut.error=False
84 84 self.margin_days = 1
85 85
86 86 def setup(self,path=None,
87 87 startDate=None,
88 88 endDate=None,
89 89 startTime=None,
90 90 endTime=None,
91 91 walk=True,
92 92 timezone='ut',
93 93 all=0,
94 94 code = None,
95 95 nCode = 0,
96 96 nBaud = 0,
97 97 online=False,
98 98 old_beams=False,
99 99 margin_days=1):
100 100
101 101
102 102
103 103 self.timezone = timezone
104 104 self.all = all
105 105 self.online = online
106 106 self.flag_old_beams = old_beams
107 107 self.code = code
108 108 self.nCode = int(nCode)
109 109 self.nBaud = int(nBaud)
110 110 self.margin_days = margin_days
111 111
112 112
113 113 #self.findFiles()
114 114 if not(online):
115 115 #Busqueda de archivos offline
116 116 self.searchFilesOffLine(path, startDate, endDate, startTime, endTime, walk)
117 117 else:
118 118 self.searchFilesOnLine(path, startDate, endDate, startTime,endTime,walk)
119 119
120 120 if not(self.filenameList):
121 121 raise schainpy.admin.SchainWarning("There is no files into the folder: %s"%(path))
122 122 sys.exit()
123 123
124 124 self.fileIndex = 0
125 125
126 126 self.readNextFile(online)
127 127
128 128 '''
129 129 Add code
130 130 '''
131 131 self.isConfig = True
132 132 # print("Setup Done")
133 133 pass
134 134
135 135
136 136 def readAMISRHeader(self,fp):
137 137
138 138 if self.isConfig and (not self.flagNoMoreFiles):
139 139 newShape = fp.get('Raw11/Data/Samples/Data').shape[1:]
140 140 if self.dataShape != newShape and newShape != None:
141 141 raise schainpy.admin.SchainError("NEW FILE HAS A DIFFERENT SHAPE: ")
142 142 print(self.dataShape,newShape,"\n")
143 143 return 0
144 144 else:
145 145 self.dataShape = fp.get('Raw11/Data/Samples/Data').shape[1:]
146 146
147 147
148 148 header = 'Raw11/Data/RadacHeader'
149 149 self.beamCodeByPulse = fp.get(header+'/BeamCode') # LIST OF BEAMS PER PROFILE, TO BE USED ON REARRANGE
150 150 if (self.startDate> datetime.date(2021, 7, 15)) or self.flag_old_beams: #Se cambió la forma de extracción de Apuntes el 17 o forzar con flag de reorganización
151 151 self.beamcodeFile = fp['Setup/Beamcodefile'][()].decode()
152 152 self.trueBeams = self.beamcodeFile.split("\n")
153 153 self.trueBeams.pop()#remove last
154 154 [self.realBeamCode.append(x) for x in self.trueBeams if x not in self.realBeamCode]
155 155 self.beamCode = [int(x, 16) for x in self.realBeamCode]
156 156 else:
157 157 _beamCode= fp.get('Raw11/Data/Beamcodes') #se usa la manera previa al cambio de apuntes
158 158 self.beamCode = _beamCode[0,:]
159 159
160 160 if self.beamCodeMap == None:
161 161 self.beamCodeMap = fp['Setup/BeamcodeMap']
162 162 for beam in self.beamCode:
163 163 beamAziElev = numpy.where(self.beamCodeMap[:,0]==beam)
164 164 beamAziElev = beamAziElev[0].squeeze()
165 165 self.azimuthList.append(self.beamCodeMap[beamAziElev,1])
166 166 self.elevationList.append(self.beamCodeMap[beamAziElev,2])
167 167 #print("Beamssss: ",self.beamCodeMap[beamAziElev,1],self.beamCodeMap[beamAziElev,2])
168 168 #print(self.beamCode)
169 169 #self.code = fp.get(header+'/Code') # NOT USE FOR THIS
170 170 self.frameCount = fp.get(header+'/FrameCount')# NOT USE FOR THIS
171 171 self.modeGroup = fp.get(header+'/ModeGroup')# NOT USE FOR THIS
172 172 self.nsamplesPulse = fp.get(header+'/NSamplesPulse')# TO GET NSA OR USING DATA FOR THAT
173 173 self.pulseCount = fp.get(header+'/PulseCount')# NOT USE FOR THIS
174 174 self.radacTime = fp.get(header+'/RadacTime')# 1st TIME ON FILE ANDE CALCULATE THE REST WITH IPP*nindexprofile
175 175 self.timeCount = fp.get(header+'/TimeCount')# NOT USE FOR THIS
176 176 self.timeStatus = fp.get(header+'/TimeStatus')# NOT USE FOR THIS
177 177 self.rangeFromFile = fp.get('Raw11/Data/Samples/Range')
178 178 self.frequency = fp.get('Rx/Frequency')
179 179 txAus = fp.get('Raw11/Data/Pulsewidth')
180 180
181 181
182 182 self.nblocks = self.pulseCount.shape[0] #nblocks
183 183
184 184 self.nprofiles = self.pulseCount.shape[1] #nprofile
185 185 self.nsa = self.nsamplesPulse[0,0] #ngates
186 186 self.nchannels = len(self.beamCode)
187 187 self.ippSeconds = (self.radacTime[0][1] -self.radacTime[0][0]) #Ipp in seconds
188 #print("IPPS secs: ",self.ippSeconds)
188 189 #self.__waitForNewFile = self.nblocks # wait depending on the number of blocks since each block is 1 sec
189 190 self.__waitForNewFile = self.nblocks * self.nprofiles * self.ippSeconds # wait until new file is created
190 191
191 192 #filling radar controller header parameters
192 193 self.__ippKm = self.ippSeconds *.15*1e6 # in km
193 194 self.__txA = (txAus[()])*.15 #(ipp[us]*.15km/1us) in km
194 195 self.__txB = 0
195 196 nWindows=1
196 197 self.__nSamples = self.nsa
197 198 self.__firstHeight = self.rangeFromFile[0][0]/1000 #in km
198 199 self.__deltaHeight = (self.rangeFromFile[0][1] - self.rangeFromFile[0][0])/1000
199 200 #print("amisr-ipp:",self.ippSeconds, self.__ippKm)
200 201 #for now until understand why the code saved is different (code included even though code not in tuf file)
201 202 #self.__codeType = 0
202 203 # self.__nCode = None
203 204 # self.__nBaud = None
204 205 self.__code = self.code
205 206 self.__codeType = 0
206 207 if self.code != None:
207 208 self.__codeType = 1
208 209 self.__nCode = self.nCode
209 210 self.__nBaud = self.nBaud
210 211 #self.__code = 0
211 212
212 213 #filling system header parameters
213 214 self.__nSamples = self.nsa
214 215 self.newProfiles = self.nprofiles/self.nchannels
215 216 self.__channelList = list(range(self.nchannels))
216 217
217 218 self.__frequency = self.frequency[0][0]
218 219
219 220
220 221 return 1
221 222
222 223
223 224 def createBuffers(self):
224 225
225 226 pass
226 227
227 228 def __setParameters(self,path='', startDate='',endDate='',startTime='', endTime='', walk=''):
228 229 self.path = path
229 230 self.startDate = startDate
230 231 self.endDate = endDate
231 232 self.startTime = startTime
232 233 self.endTime = endTime
233 234 self.walk = walk
234 235
235 236 def __checkPath(self):
236 237 if os.path.exists(self.path):
237 238 self.status = 1
238 239 else:
239 240 self.status = 0
240 241 print('Path:%s does not exists'%self.path)
241 242
242 243 return
243 244
244 245
245 246 def __selDates(self, amisr_dirname_format):
246 247 try:
247 248 year = int(amisr_dirname_format[0:4])
248 249 month = int(amisr_dirname_format[4:6])
249 250 dom = int(amisr_dirname_format[6:8])
250 251 thisDate = datetime.date(year,month,dom)
251 252 #margen de un día extra, igual luego se filtra for fecha y hora
252 253 if (thisDate>=(self.startDate - datetime.timedelta(days=self.margin_days)) and thisDate <= (self.endDate)+ datetime.timedelta(days=1)):
253 254 return amisr_dirname_format
254 255 except:
255 256 return None
256 257
257 258
258 259 def __findDataForDates(self,online=False):
259 260
260 261 if not(self.status):
261 262 return None
262 263
263 264 pat = '\d+.\d+'
264 265 dirnameList = [re.search(pat,x) for x in os.listdir(self.path)]
265 266 dirnameList = [x for x in dirnameList if x!=None]
266 267 dirnameList = [x.string for x in dirnameList]
267 268 if not(online):
268 269 dirnameList = [self.__selDates(x) for x in dirnameList]
269 270 dirnameList = [x for x in dirnameList if x!=None]
270 271 if len(dirnameList)>0:
271 272 self.status = 1
272 273 self.dirnameList = dirnameList
273 274 self.dirnameList.sort()
274 275 else:
275 276 self.status = 0
276 277 return None
277 278
278 279 def __getTimeFromData(self):
279 280 startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime)
280 281 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
281 282
282 283 print('Filtering Files from %s to %s'%(startDateTime_Reader, endDateTime_Reader))
283 284 print('........................................')
284 285 filter_filenameList = []
285 286 self.filenameList.sort()
286 287 total_files = len(self.filenameList)
287 288 #for i in range(len(self.filenameList)-1):
288 289 for i in range(total_files):
289 290 filename = self.filenameList[i]
290 291 #print("file-> ",filename)
291 292 try:
292 293 fp = h5py.File(filename,'r')
293 294 time_str = fp.get('Time/RadacTimeString')
294 295
295 296 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
296 297 #startDateTimeStr_File = "2019-12-16 09:21:11"
297 298 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
298 299 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
299 300
300 301 #endDateTimeStr_File = "2019-12-16 11:10:11"
301 302 endDateTimeStr_File = time_str[-1][-1].decode('UTF-8').split('.')[0]
302 303 junk = time.strptime(endDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
303 304 endDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
304 305
305 306 fp.close()
306 307
307 308 #print("check time", startDateTime_File)
308 309 if self.timezone == 'lt':
309 310 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
310 311 endDateTime_File = endDateTime_File - datetime.timedelta(minutes = 300)
311 312 if (startDateTime_File >=startDateTime_Reader and endDateTime_File<=endDateTime_Reader):
312 313 filter_filenameList.append(filename)
313 314
314 315 if (startDateTime_File>endDateTime_Reader):
315 316 break
316 317 except Exception as e:
317 318 log.warning("Error opening file {} -> {}".format(os.path.split(filename)[1],e))
318 319
319 320 filter_filenameList.sort()
320 321 self.filenameList = filter_filenameList
321 322
322 323 return 1
323 324
324 325 def __filterByGlob1(self, dirName):
325 326 filter_files = glob.glob1(dirName, '*.*%s'%self.extension_file)
326 327 filter_files.sort()
327 328 filterDict = {}
328 329 filterDict.setdefault(dirName)
329 330 filterDict[dirName] = filter_files
330 331 return filterDict
331 332
332 333 def __getFilenameList(self, fileListInKeys, dirList):
333 334 for value in fileListInKeys:
334 335 dirName = list(value.keys())[0]
335 336 for file in value[dirName]:
336 337 filename = os.path.join(dirName, file)
337 338 self.filenameList.append(filename)
338 339
339 340
340 341 def __selectDataForTimes(self, online=False):
341 342 #aun no esta implementado el filtro for tiempo
342 343 if not(self.status):
343 344 return None
344 345
345 346 dirList = [os.path.join(self.path,x) for x in self.dirnameList]
346 347 fileListInKeys = [self.__filterByGlob1(x) for x in dirList]
347 348 self.__getFilenameList(fileListInKeys, dirList)
348 349 if not(online):
349 350 #filtro por tiempo
350 351 if not(self.all):
351 352 self.__getTimeFromData()
352 353
353 354 if len(self.filenameList)>0:
354 355 self.status = 1
355 356 self.filenameList.sort()
356 357 else:
357 358 self.status = 0
358 359 return None
359 360
360 361 else:
361 362 #get the last file - 1
362 363 self.filenameList = [self.filenameList[-2]]
363 364 new_dirnameList = []
364 365 for dirname in self.dirnameList:
365 366 junk = numpy.array([dirname in x for x in self.filenameList])
366 367 junk_sum = junk.sum()
367 368 if junk_sum > 0:
368 369 new_dirnameList.append(dirname)
369 370 self.dirnameList = new_dirnameList
370 371 return 1
371 372
372 373 def searchFilesOnLine(self, path, startDate, endDate, startTime=datetime.time(0,0,0),
373 374 endTime=datetime.time(23,59,59),walk=True):
374 375
375 376 if endDate ==None:
376 377 startDate = datetime.datetime.utcnow().date()
377 378 endDate = datetime.datetime.utcnow().date()
378 379
379 380 self.__setParameters(path=path, startDate=startDate, endDate=endDate,startTime = startTime,endTime=endTime, walk=walk)
380 381
381 382 self.__checkPath()
382 383
383 384 self.__findDataForDates(online=True)
384 385
385 386 self.dirnameList = [self.dirnameList[-1]]
386 387
387 388 self.__selectDataForTimes(online=True)
388 389
389 390 return
390 391
391 392
392 393 def searchFilesOffLine(self,
393 394 path,
394 395 startDate,
395 396 endDate,
396 397 startTime=datetime.time(0,0,0),
397 398 endTime=datetime.time(23,59,59),
398 399 walk=True):
399 400
400 401 self.__setParameters(path, startDate, endDate, startTime, endTime, walk)
401 402
402 403 self.__checkPath()
403 404
404 405 self.__findDataForDates()
405 406
406 407 self.__selectDataForTimes()
407 408
408 409 for i in range(len(self.filenameList)):
409 410 print("%s" %(self.filenameList[i]))
410 411
411 412 return
412 413
413 414 def __setNextFileOffline(self):
414 415
415 416 try:
416 417 self.filename = self.filenameList[self.fileIndex]
417 418 self.amisrFilePointer = h5py.File(self.filename,'r')
418 419 self.fileIndex += 1
419 420 except:
420 421 self.flagNoMoreFiles = 1
421 422 raise schainpy.admin.SchainError('No more files to read')
422 423 return 0
423 424
424 425 self.flagIsNewFile = 1
425 426 print("Setting the file: %s"%self.filename)
426 427
427 428 return 1
428 429
429 430
430 431 def __setNextFileOnline(self):
431 432 filename = self.filenameList[0]
432 433 if self.__filename_online != None:
433 434 self.__selectDataForTimes(online=True)
434 435 filename = self.filenameList[0]
435 436 wait = 0
436 437 self.__waitForNewFile=300 ## DEBUG:
437 438 while self.__filename_online == filename:
438 439 print('waiting %d seconds to get a new file...'%(self.__waitForNewFile))
439 440 if wait == 5:
440 441 self.flagNoMoreFiles = 1
441 442 return 0
442 443 sleep(self.__waitForNewFile)
443 444 self.__selectDataForTimes(online=True)
444 445 filename = self.filenameList[0]
445 446 wait += 1
446 447
447 448 self.__filename_online = filename
448 449
449 450 self.amisrFilePointer = h5py.File(filename,'r')
450 451 self.flagIsNewFile = 1
451 452 self.filename = filename
452 453 print("Setting the file: %s"%self.filename)
453 454 return 1
454 455
455 456
456 457 def readData(self):
457 458 buffer = self.amisrFilePointer.get('Raw11/Data/Samples/Data')
458 459 re = buffer[:,:,:,0]
459 460 im = buffer[:,:,:,1]
460 461 dataset = re + im*1j
461 462
462 463 self.radacTime = self.amisrFilePointer.get('Raw11/Data/RadacHeader/RadacTime')
463 464 timeset = self.radacTime[:,0]
464 465
465 466 return dataset,timeset
466 467
467 468 def reshapeData(self):
468 469 #self.beamCodeByPulse, self.beamCode, self.nblocks, self.nprofiles, self.nsa,
469 470 channels = self.beamCodeByPulse[0,:]
470 471 nchan = self.nchannels
471 472 #self.newProfiles = self.nprofiles/nchan #must be defined on filljroheader
472 473 nblocks = self.nblocks
473 474 nsamples = self.nsa
474 475
475 476 #Dimensions : nChannels, nProfiles, nSamples
476 477 new_block = numpy.empty((nblocks, nchan, numpy.int_(self.newProfiles), nsamples), dtype="complex64")
477 478 ############################################
478 479
479 480 for thisChannel in range(nchan):
480 481 new_block[:,thisChannel,:,:] = self.dataset[:,numpy.where(channels==self.beamCode[thisChannel])[0],:]
481 482
482 483
483 484 new_block = numpy.transpose(new_block, (1,0,2,3))
484 485 new_block = numpy.reshape(new_block, (nchan,-1, nsamples))
485 486
486 487 return new_block
487 488
488 489 def updateIndexes(self):
489 490
490 491 pass
491 492
492 493 def fillJROHeader(self):
493 494
494 495 #fill radar controller header
495 496 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ipp=self.__ippKm,
496 497 txA=self.__txA,
497 498 txB=0,
498 499 nWindows=1,
499 500 nHeights=self.__nSamples,
500 501 firstHeight=self.__firstHeight,
501 502 deltaHeight=self.__deltaHeight,
502 503 codeType=self.__codeType,
503 504 nCode=self.__nCode, nBaud=self.__nBaud,
504 505 code = self.__code,
505 506 fClock=1)
506 507 #fill system header
507 508 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
508 509 nProfiles=self.newProfiles,
509 510 nChannels=len(self.__channelList),
510 511 adcResolution=14,
511 512 pciDioBusWidth=32)
512 513
513 514 self.dataOut.type = "Voltage"
514 515 self.dataOut.data = None
515 516 self.dataOut.dtype = numpy.dtype([('real','<i8'),('imag','<i8')])
516 517 # self.dataOut.nChannels = 0
517 518
518 519 # self.dataOut.nHeights = 0
519 520
520 521 self.dataOut.nProfiles = self.newProfiles*self.nblocks
521 522 #self.dataOut.heightList = self.__firstHeigth + numpy.arange(self.__nSamples, dtype = numpy.float)*self.__deltaHeigth
522 523 ranges = numpy.reshape(self.rangeFromFile[()],(-1))
523 524 self.dataOut.heightList = ranges/1000.0 #km
524 525 self.dataOut.channelList = self.__channelList
525 526 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights
526 527
527 528 # self.dataOut.channelIndexList = None
528 529
529 530
530 531 self.dataOut.azimuthList = numpy.array(self.azimuthList)
531 532 self.dataOut.elevationList = numpy.array(self.elevationList)
532 533 self.dataOut.codeList = numpy.array(self.beamCode)
533 534 #print(self.dataOut.elevationList)
534 535 self.dataOut.flagNoData = True
535 536
536 537 #Set to TRUE if the data is discontinuous
537 538 self.dataOut.flagDiscontinuousBlock = False
538 539
539 540 self.dataOut.utctime = None
540 541
541 542 #self.dataOut.timeZone = -5 #self.__timezone/60 #timezone like jroheader, difference in minutes between UTC and localtime
542 543 if self.timezone == 'lt':
543 544 self.dataOut.timeZone = time.timezone / 60. #get the timezone in minutes
544 545 else:
545 546 self.dataOut.timeZone = 0 #by default time is UTC
546 547
547 548 self.dataOut.dstFlag = 0
548 549 self.dataOut.errorCount = 0
549 550 self.dataOut.nCohInt = 1
550 551 self.dataOut.flagDecodeData = False #asumo que la data esta decodificada
551 552 self.dataOut.flagDeflipData = False #asumo que la data esta sin flip
552 553 self.dataOut.flagShiftFFT = False
553 554 self.dataOut.ippSeconds = self.ippSeconds
554 555
555 556 #Time interval between profiles
556 557 #self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
557 558
558 559 self.dataOut.frequency = self.__frequency
559 560 self.dataOut.realtime = self.online
560 561 pass
561 562
562 563 def readNextFile(self,online=False):
563 564
564 565 if not(online):
565 566 newFile = self.__setNextFileOffline()
566 567 else:
567 568 newFile = self.__setNextFileOnline()
568 569
569 570 if not(newFile):
570 571 self.dataOut.error = True
571 572 return 0
572 573
573 574 if not self.readAMISRHeader(self.amisrFilePointer):
574 575 self.dataOut.error = True
575 576 return 0
576 577
577 578 self.createBuffers()
578 579 self.fillJROHeader()
579 580
580 581 #self.__firstFile = False
581 582
582 583
583 584
584 585 self.dataset,self.timeset = self.readData()
585 586
586 587 if self.endDate!=None:
587 588 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
588 589 time_str = self.amisrFilePointer.get('Time/RadacTimeString')
589 590 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
590 591 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
591 592 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
592 593 if self.timezone == 'lt':
593 594 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
594 595 if (startDateTime_File>endDateTime_Reader):
595 596 return 0
596 597
597 598 self.jrodataset = self.reshapeData()
598 599 #----self.updateIndexes()
599 600 self.profileIndex = 0
600 601
601 602 return 1
602 603
603 604
604 605 def __hasNotDataInBuffer(self):
605 606 if self.profileIndex >= (self.newProfiles*self.nblocks):
606 607 return 1
607 608 return 0
608 609
609 610
610 611 def getData(self):
611 612
612 613 if self.flagNoMoreFiles:
613 614 self.dataOut.flagNoData = True
614 615 return 0
615 616
616 617 if self.__hasNotDataInBuffer():
617 618 if not (self.readNextFile(self.online)):
618 619 return 0
619 620
620 621
621 622 if self.dataset is None: # setear esta condicion cuando no hayan datos por leer
622 623 self.dataOut.flagNoData = True
623 624 return 0
624 625
625 626 #self.dataOut.data = numpy.reshape(self.jrodataset[self.profileIndex,:],(1,-1))
626 627
627 628 self.dataOut.data = self.jrodataset[:,self.profileIndex,:]
628 629
629 630 #print("R_t",self.timeset)
630 631
631 632 #self.dataOut.utctime = self.jrotimeset[self.profileIndex]
632 633 #verificar basic header de jro data y ver si es compatible con este valor
633 634 #self.dataOut.utctime = self.timeset + (self.profileIndex * self.ippSeconds * self.nchannels)
634 635 indexprof = numpy.mod(self.profileIndex, self.newProfiles)
635 636 indexblock = self.profileIndex/self.newProfiles
636 637 #print (indexblock, indexprof)
637 638 diffUTC = 0
638 639 t_comp = (indexprof * self.ippSeconds * self.nchannels) + diffUTC #
639 640
640 641 #print("utc :",indexblock," __ ",t_comp)
641 642 #print(numpy.shape(self.timeset))
642 643 self.dataOut.utctime = self.timeset[numpy.int_(indexblock)] + t_comp
643 644 #self.dataOut.utctime = self.timeset[self.profileIndex] + t_comp
644 645
645 646 self.dataOut.profileIndex = self.profileIndex
646 647 #print("N profile:",self.profileIndex,self.newProfiles,self.nblocks,self.dataOut.utctime)
647 648 self.dataOut.flagNoData = False
648 649 # if indexprof == 0:
649 650 # print("kamisr: ",self.dataOut.utctime)
650 651
651 652 self.profileIndex += 1
652 653
653 654 return self.dataOut.data #retorno necesario??
654 655
655 656
656 657 def run(self, **kwargs):
657 658 '''
658 659 This method will be called many times so here you should put all your code
659 660 '''
660 661 #print("running kamisr")
661 662 if not self.isConfig:
662 663 self.setup(**kwargs)
663 664 self.isConfig = True
664 665
665 666 self.getData()
@@ -1,1890 +1,1948
1 1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 2 # All rights reserved.
3 3 #
4 4 # Distributed under the terms of the BSD 3-clause license.
5 5 """Spectra processing Unit and operations
6 6
7 7 Here you will find the processing unit `SpectraProc` and several operations
8 8 to work with Spectra data type
9 9 """
10 10
11 11 import time
12 12 import itertools
13 13
14 14 import numpy
15 15 import math
16 16
17 17 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator, Operation
18 18 from schainpy.model.data.jrodata import Spectra
19 19 from schainpy.model.data.jrodata import hildebrand_sekhon
20 20 from schainpy.model.data import _noise
21 21
22 22 from schainpy.utils import log
23
23 import matplotlib.pyplot as plt
24 24 from scipy.optimize import curve_fit
25 25
26 26 class SpectraProc(ProcessingUnit):
27 27
28 28 def __init__(self):
29 29
30 30 ProcessingUnit.__init__(self)
31 31
32 32 self.buffer = None
33 33 self.firstdatatime = None
34 34 self.profIndex = 0
35 35 self.dataOut = Spectra()
36 36 self.id_min = None
37 37 self.id_max = None
38 38 self.setupReq = False #Agregar a todas las unidades de proc
39 39
40 40 def __updateSpecFromVoltage(self):
41 41
42 42
43 43
44 44 self.dataOut.timeZone = self.dataIn.timeZone
45 45 self.dataOut.dstFlag = self.dataIn.dstFlag
46 46 self.dataOut.errorCount = self.dataIn.errorCount
47 47 self.dataOut.useLocalTime = self.dataIn.useLocalTime
48 48 try:
49 49 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
50 50 except:
51 51 pass
52 52 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
53 53 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
54 54 self.dataOut.channelList = self.dataIn.channelList
55 55 self.dataOut.heightList = self.dataIn.heightList
56 56 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
57 57 self.dataOut.nProfiles = self.dataOut.nFFTPoints
58 58 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
59 59 self.dataOut.utctime = self.firstdatatime
60 60 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData
61 61 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData
62 62 self.dataOut.flagShiftFFT = False
63 63 self.dataOut.nCohInt = self.dataIn.nCohInt
64 64 self.dataOut.nIncohInt = 1
65 65 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
66 66 self.dataOut.frequency = self.dataIn.frequency
67 67 self.dataOut.realtime = self.dataIn.realtime
68 68 self.dataOut.azimuth = self.dataIn.azimuth
69 69 self.dataOut.zenith = self.dataIn.zenith
70 70 self.dataOut.codeList = self.dataIn.codeList
71 71 self.dataOut.azimuthList = self.dataIn.azimuthList
72 72 self.dataOut.elevationList = self.dataIn.elevationList
73 73
74 74
75 75 def __getFft(self):
76 76 """
77 77 Convierte valores de Voltaje a Spectra
78 78
79 79 Affected:
80 80 self.dataOut.data_spc
81 81 self.dataOut.data_cspc
82 82 self.dataOut.data_dc
83 83 self.dataOut.heightList
84 84 self.profIndex
85 85 self.buffer
86 86 self.dataOut.flagNoData
87 87 """
88 88 fft_volt = numpy.fft.fft(
89 89 self.buffer, n=self.dataOut.nFFTPoints, axis=1)
90 90 fft_volt = fft_volt.astype(numpy.dtype('complex'))
91 91 dc = fft_volt[:, 0, :]
92 92
93 93 # calculo de self-spectra
94 94 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
95 95 spc = fft_volt * numpy.conjugate(fft_volt)
96 96 spc = spc.real
97 97
98 98 blocksize = 0
99 99 blocksize += dc.size
100 100 blocksize += spc.size
101 101
102 102 cspc = None
103 103 pairIndex = 0
104 104 if self.dataOut.pairsList != None:
105 105 # calculo de cross-spectra
106 106 cspc = numpy.zeros(
107 107 (self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
108 108 for pair in self.dataOut.pairsList:
109 109 if pair[0] not in self.dataOut.channelList:
110 110 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (
111 111 str(pair), str(self.dataOut.channelList)))
112 112 if pair[1] not in self.dataOut.channelList:
113 113 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (
114 114 str(pair), str(self.dataOut.channelList)))
115 115
116 116 cspc[pairIndex, :, :] = fft_volt[pair[0], :, :] * \
117 117 numpy.conjugate(fft_volt[pair[1], :, :])
118 118 pairIndex += 1
119 119 blocksize += cspc.size
120 120
121 121 self.dataOut.data_spc = spc
122 122 self.dataOut.data_cspc = cspc
123 123 self.dataOut.data_dc = dc
124 124 self.dataOut.blockSize = blocksize
125 125 self.dataOut.flagShiftFFT = False
126 126
127 127 def run(self, nProfiles=None, nFFTPoints=None, pairsList=None, ippFactor=None, shift_fft=False):
128
128 #print("run spc proc")
129 129 if self.dataIn.type == "Spectra":
130 130
131 131 try:
132 132 self.dataOut.copy(self.dataIn)
133 133
134 134 except Exception as e:
135 135 print("Error dataIn ",e)
136 136
137 137 if shift_fft:
138 138 #desplaza a la derecha en el eje 2 determinadas posiciones
139 139 shift = int(self.dataOut.nFFTPoints/2)
140 140 self.dataOut.data_spc = numpy.roll(self.dataOut.data_spc, shift , axis=1)
141 141
142 142 if self.dataOut.data_cspc is not None:
143 143 #desplaza a la derecha en el eje 2 determinadas posiciones
144 144 self.dataOut.data_cspc = numpy.roll(self.dataOut.data_cspc, shift, axis=1)
145 145 if pairsList:
146 146 self.__selectPairs(pairsList)
147 147
148 148
149 149 elif self.dataIn.type == "Voltage":
150 150
151 151 self.dataOut.flagNoData = True
152 152
153 153 if nFFTPoints == None:
154 154 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
155 155
156 156 if nProfiles == None:
157 157 nProfiles = nFFTPoints
158 158
159 159 if ippFactor == None:
160 160 self.dataOut.ippFactor = 1
161 161
162 162 self.dataOut.nFFTPoints = nFFTPoints
163 163 #print(" volts ch,prof, h: ", self.dataIn.data.shape)
164 164 if self.buffer is None:
165 165 self.buffer = numpy.zeros((self.dataIn.nChannels,
166 166 nProfiles,
167 167 self.dataIn.nHeights),
168 168 dtype='complex')
169 169
170 170 if self.dataIn.flagDataAsBlock:
171 171 nVoltProfiles = self.dataIn.data.shape[1]
172 172
173 173 if nVoltProfiles == nProfiles:
174 174 self.buffer = self.dataIn.data.copy()
175 175 self.profIndex = nVoltProfiles
176 176
177 177 elif nVoltProfiles < nProfiles:
178 178
179 179 if self.profIndex == 0:
180 180 self.id_min = 0
181 181 self.id_max = nVoltProfiles
182 182
183 183 self.buffer[:, self.id_min:self.id_max,
184 184 :] = self.dataIn.data
185 185 self.profIndex += nVoltProfiles
186 186 self.id_min += nVoltProfiles
187 187 self.id_max += nVoltProfiles
188 188 else:
189 189 raise ValueError("The type object %s has %d profiles, it should just has %d profiles" % (
190 190 self.dataIn.type, self.dataIn.data.shape[1], nProfiles))
191 191 self.dataOut.flagNoData = True
192 192 else:
193 193 self.buffer[:, self.profIndex, :] = self.dataIn.data.copy()
194 194 self.profIndex += 1
195 195
196 196 if self.firstdatatime == None:
197 197 self.firstdatatime = self.dataIn.utctime
198 198
199 199 if self.profIndex == nProfiles:
200 200
201 201 self.__updateSpecFromVoltage()
202
202 203 if pairsList == None:
203 204 self.dataOut.pairsList = [pair for pair in itertools.combinations(self.dataOut.channelList, 2)]
204 205 else:
205 206 self.dataOut.pairsList = pairsList
206 207 self.__getFft()
207 208 self.dataOut.flagNoData = False
208 209 self.firstdatatime = None
209 210 self.profIndex = 0
210 211
212
211 213 else:
212 214 raise ValueError("The type of input object '%s' is not valid".format(
213 215 self.dataIn.type))
214 216
215 217
216 218 def __selectPairs(self, pairsList):
217 219
218 220 if not pairsList:
219 221 return
220 222
221 223 pairs = []
222 224 pairsIndex = []
223 225
224 226 for pair in pairsList:
225 227 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
226 228 continue
227 229 pairs.append(pair)
228 230 pairsIndex.append(pairs.index(pair))
229 231
230 232 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
231 233 self.dataOut.pairsList = pairs
232 234
233 235 return
234 236
235 237 def selectFFTs(self, minFFT, maxFFT ):
236 238 """
237 239 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
238 240 minFFT<= FFT <= maxFFT
239 241 """
240 242
241 243 if (minFFT > maxFFT):
242 244 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
243 245
244 246 if (minFFT < self.dataOut.getFreqRange()[0]):
245 247 minFFT = self.dataOut.getFreqRange()[0]
246 248
247 249 if (maxFFT > self.dataOut.getFreqRange()[-1]):
248 250 maxFFT = self.dataOut.getFreqRange()[-1]
249 251
250 252 minIndex = 0
251 253 maxIndex = 0
252 254 FFTs = self.dataOut.getFreqRange()
253 255
254 256 inda = numpy.where(FFTs >= minFFT)
255 257 indb = numpy.where(FFTs <= maxFFT)
256 258
257 259 try:
258 260 minIndex = inda[0][0]
259 261 except:
260 262 minIndex = 0
261 263
262 264 try:
263 265 maxIndex = indb[0][-1]
264 266 except:
265 267 maxIndex = len(FFTs)
266 268
267 269 self.selectFFTsByIndex(minIndex, maxIndex)
268 270
269 271 return 1
270 272
271 273 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
272 274 newheis = numpy.where(
273 275 self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
274 276
275 277 if hei_ref != None:
276 278 newheis = numpy.where(self.dataOut.heightList > hei_ref)
277 279
278 280 minIndex = min(newheis[0])
279 281 maxIndex = max(newheis[0])
280 282 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
281 283 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
282 284
283 285 # determina indices
284 286 nheis = int(self.dataOut.radarControllerHeaderObj.txB /
285 287 (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
286 288 avg_dB = 10 * \
287 289 numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
288 290 beacon_dB = numpy.sort(avg_dB)[-nheis:]
289 291 beacon_heiIndexList = []
290 292 for val in avg_dB.tolist():
291 293 if val >= beacon_dB[0]:
292 294 beacon_heiIndexList.append(avg_dB.tolist().index(val))
293 295
294 296 #data_spc = data_spc[:,:,beacon_heiIndexList]
295 297 data_cspc = None
296 298 if self.dataOut.data_cspc is not None:
297 299 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
298 300 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
299 301
300 302 data_dc = None
301 303 if self.dataOut.data_dc is not None:
302 304 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
303 305 #data_dc = data_dc[:,beacon_heiIndexList]
304 306
305 307 self.dataOut.data_spc = data_spc
306 308 self.dataOut.data_cspc = data_cspc
307 309 self.dataOut.data_dc = data_dc
308 310 self.dataOut.heightList = heightList
309 311 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
310 312
311 313 return 1
312 314
313 315 def selectFFTsByIndex(self, minIndex, maxIndex):
314 316 """
315 317
316 318 """
317 319
318 320 if (minIndex < 0) or (minIndex > maxIndex):
319 321 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
320 322
321 323 if (maxIndex >= self.dataOut.nProfiles):
322 324 maxIndex = self.dataOut.nProfiles-1
323 325
324 326 #Spectra
325 327 data_spc = self.dataOut.data_spc[:,minIndex:maxIndex+1,:]
326 328
327 329 data_cspc = None
328 330 if self.dataOut.data_cspc is not None:
329 331 data_cspc = self.dataOut.data_cspc[:,minIndex:maxIndex+1,:]
330 332
331 333 data_dc = None
332 334 if self.dataOut.data_dc is not None:
333 335 data_dc = self.dataOut.data_dc[minIndex:maxIndex+1,:]
334 336
335 337 self.dataOut.data_spc = data_spc
336 338 self.dataOut.data_cspc = data_cspc
337 339 self.dataOut.data_dc = data_dc
338 340
339 341 self.dataOut.ippSeconds = self.dataOut.ippSeconds*(self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
340 342 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
341 343 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
342 344
343 345 return 1
344 346
345 347 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
346 348 # validacion de rango
347 349 if minHei == None:
348 350 minHei = self.dataOut.heightList[0]
349 351
350 352 if maxHei == None:
351 353 maxHei = self.dataOut.heightList[-1]
352 354
353 355 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
354 356 print('minHei: %.2f is out of the heights range' % (minHei))
355 357 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
356 358 minHei = self.dataOut.heightList[0]
357 359
358 360 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
359 361 print('maxHei: %.2f is out of the heights range' % (maxHei))
360 362 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
361 363 maxHei = self.dataOut.heightList[-1]
362 364
363 365 # validacion de velocidades
364 366 velrange = self.dataOut.getVelRange(1)
365 367
366 368 if minVel == None:
367 369 minVel = velrange[0]
368 370
369 371 if maxVel == None:
370 372 maxVel = velrange[-1]
371 373
372 374 if (minVel < velrange[0]) or (minVel > maxVel):
373 375 print('minVel: %.2f is out of the velocity range' % (minVel))
374 376 print('minVel is setting to %.2f' % (velrange[0]))
375 377 minVel = velrange[0]
376 378
377 379 if (maxVel > velrange[-1]) or (maxVel < minVel):
378 380 print('maxVel: %.2f is out of the velocity range' % (maxVel))
379 381 print('maxVel is setting to %.2f' % (velrange[-1]))
380 382 maxVel = velrange[-1]
381 383
382 384 # seleccion de indices para rango
383 385 minIndex = 0
384 386 maxIndex = 0
385 387 heights = self.dataOut.heightList
386 388
387 389 inda = numpy.where(heights >= minHei)
388 390 indb = numpy.where(heights <= maxHei)
389 391
390 392 try:
391 393 minIndex = inda[0][0]
392 394 except:
393 395 minIndex = 0
394 396
395 397 try:
396 398 maxIndex = indb[0][-1]
397 399 except:
398 400 maxIndex = len(heights)
399 401
400 402 if (minIndex < 0) or (minIndex > maxIndex):
401 403 raise ValueError("some value in (%d,%d) is not valid" % (
402 404 minIndex, maxIndex))
403 405
404 406 if (maxIndex >= self.dataOut.nHeights):
405 407 maxIndex = self.dataOut.nHeights - 1
406 408
407 409 # seleccion de indices para velocidades
408 410 indminvel = numpy.where(velrange >= minVel)
409 411 indmaxvel = numpy.where(velrange <= maxVel)
410 412 try:
411 413 minIndexVel = indminvel[0][0]
412 414 except:
413 415 minIndexVel = 0
414 416
415 417 try:
416 418 maxIndexVel = indmaxvel[0][-1]
417 419 except:
418 420 maxIndexVel = len(velrange)
419 421
420 422 # seleccion del espectro
421 423 data_spc = self.dataOut.data_spc[:,
422 424 minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
423 425 # estimacion de ruido
424 426 noise = numpy.zeros(self.dataOut.nChannels)
425 427
426 428 for channel in range(self.dataOut.nChannels):
427 429 daux = data_spc[channel, :, :]
428 430 sortdata = numpy.sort(daux, axis=None)
429 431 noise[channel] = hildebrand_sekhon(sortdata, self.dataOut.nIncohInt)
430 432
431 433 self.dataOut.noise_estimation = noise.copy()
432 434
433 435 return 1
434 436
435 437 class removeDC(Operation):
436 438
437 439 def run(self, dataOut, mode=2):
438 440 self.dataOut = dataOut
439 441 jspectra = self.dataOut.data_spc
440 442 jcspectra = self.dataOut.data_cspc
441 443
442 444 num_chan = jspectra.shape[0]
443 445 num_hei = jspectra.shape[2]
444 446
445 447 if jcspectra is not None:
446 448 jcspectraExist = True
447 449 num_pairs = jcspectra.shape[0]
448 450 else:
449 451 jcspectraExist = False
450 452
451 453 freq_dc = int(jspectra.shape[1] / 2)
452 454 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
453 455 ind_vel = ind_vel.astype(int)
454 456
455 457 if ind_vel[0] < 0:
456 458 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
457 459
458 460 if mode == 1:
459 461 jspectra[:, freq_dc, :] = (
460 462 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
461 463
462 464 if jcspectraExist:
463 465 jcspectra[:, freq_dc, :] = (
464 466 jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
465 467
466 468 if mode == 2:
467 469
468 470 vel = numpy.array([-2, -1, 1, 2])
469 471 xx = numpy.zeros([4, 4])
470 472
471 473 for fil in range(4):
472 474 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
473 475
474 476 xx_inv = numpy.linalg.inv(xx)
475 477 xx_aux = xx_inv[0, :]
476 478
477 479 for ich in range(num_chan):
478 480 yy = jspectra[ich, ind_vel, :]
479 481 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
480 482
481 483 junkid = jspectra[ich, freq_dc, :] <= 0
482 484 cjunkid = sum(junkid)
483 485
484 486 if cjunkid.any():
485 487 jspectra[ich, freq_dc, junkid.nonzero()] = (
486 488 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
487 489
488 490 if jcspectraExist:
489 491 for ip in range(num_pairs):
490 492 yy = jcspectra[ip, ind_vel, :]
491 493 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
492 494
493 495 self.dataOut.data_spc = jspectra
494 496 self.dataOut.data_cspc = jcspectra
495 497
496 498 return self.dataOut
497 499
498 500 class getNoise(Operation):
499 501 warnings = False
500 502 def __init__(self):
501 503
502 504 Operation.__init__(self)
503 505
504 506 def run(self, dataOut, minHei=None, maxHei=None,minVel=None, maxVel=None, minFreq= None, maxFreq=None, warnings=False):
505 507 self.dataOut = dataOut
506 508 self.warnings = warnings
507 509 if minHei == None:
508 510 minHei = self.dataOut.heightList[0]
509 511
510 512 if maxHei == None:
511 513 maxHei = self.dataOut.heightList[-1]
512 514
513 515 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
514 516 if self.warnings:
515 517 print('minHei: %.2f is out of the heights range' % (minHei))
516 518 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
517 519 minHei = self.dataOut.heightList[0]
518 520
519 521 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
520 522 if self.warnings:
521 523 print('maxHei: %.2f is out of the heights range' % (maxHei))
522 524 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
523 525 maxHei = self.dataOut.heightList[-1]
524 526
525 527
526 528 #indices relativos a los puntos de fft, puede ser de acuerdo a velocidad o frecuencia
527 529 minIndexFFT = 0
528 530 maxIndexFFT = 0
529 531 # validacion de velocidades
530 532 indminPoint = None
531 533 indmaxPoint = None
534 if self.dataOut.type == 'Spectra':
535 if minVel == None and maxVel == None :
532 536
533 if minVel == None and maxVel == None:
537 freqrange = self.dataOut.getFreqRange(1)
534 538
535 freqrange = self.dataOut.getFreqRange(1)
539 if minFreq == None:
540 minFreq = freqrange[0]
536 541
537 if minFreq == None:
538 minFreq = freqrange[0]
542 if maxFreq == None:
543 maxFreq = freqrange[-1]
539 544
540 if maxFreq == None:
541 maxFreq = freqrange[-1]
545 if (minFreq < freqrange[0]) or (minFreq > maxFreq):
546 if self.warnings:
547 print('minFreq: %.2f is out of the frequency range' % (minFreq))
548 print('minFreq is setting to %.2f' % (freqrange[0]))
549 minFreq = freqrange[0]
542 550
543 if (minFreq < freqrange[0]) or (minFreq > maxFreq):
544 if self.warnings:
545 print('minFreq: %.2f is out of the frequency range' % (minFreq))
546 print('minFreq is setting to %.2f' % (freqrange[0]))
547 minFreq = freqrange[0]
551 if (maxFreq > freqrange[-1]) or (maxFreq < minFreq):
552 if self.warnings:
553 print('maxFreq: %.2f is out of the frequency range' % (maxFreq))
554 print('maxFreq is setting to %.2f' % (freqrange[-1]))
555 maxFreq = freqrange[-1]
548 556
549 if (maxFreq > freqrange[-1]) or (maxFreq < minFreq):
550 if self.warnings:
551 print('maxFreq: %.2f is out of the frequency range' % (maxFreq))
552 print('maxFreq is setting to %.2f' % (freqrange[-1]))
553 maxFreq = freqrange[-1]
557 indminPoint = numpy.where(freqrange >= minFreq)
558 indmaxPoint = numpy.where(freqrange <= maxFreq)
554 559
555 indminPoint = numpy.where(freqrange >= minFreq)
556 indmaxPoint = numpy.where(freqrange <= maxFreq)
560 else:
557 561
558 else:
559 velrange = self.dataOut.getVelRange(1)
562 velrange = self.dataOut.getVelRange(1)
560 563
561 if minVel == None:
562 minVel = velrange[0]
564 if minVel == None:
565 minVel = velrange[0]
563 566
564 if maxVel == None:
565 maxVel = velrange[-1]
567 if maxVel == None:
568 maxVel = velrange[-1]
566 569
567 if (minVel < velrange[0]) or (minVel > maxVel):
568 if self.warnings:
569 print('minVel: %.2f is out of the velocity range' % (minVel))
570 print('minVel is setting to %.2f' % (velrange[0]))
571 minVel = velrange[0]
570 if (minVel < velrange[0]) or (minVel > maxVel):
571 if self.warnings:
572 print('minVel: %.2f is out of the velocity range' % (minVel))
573 print('minVel is setting to %.2f' % (velrange[0]))
574 minVel = velrange[0]
572 575
573 if (maxVel > velrange[-1]) or (maxVel < minVel):
574 if self.warnings:
575 print('maxVel: %.2f is out of the velocity range' % (maxVel))
576 print('maxVel is setting to %.2f' % (velrange[-1]))
577 maxVel = velrange[-1]
576 if (maxVel > velrange[-1]) or (maxVel < minVel):
577 if self.warnings:
578 print('maxVel: %.2f is out of the velocity range' % (maxVel))
579 print('maxVel is setting to %.2f' % (velrange[-1]))
580 maxVel = velrange[-1]
578 581
579 indminPoint = numpy.where(velrange >= minVel)
580 indmaxPoint = numpy.where(velrange <= maxVel)
582 indminPoint = numpy.where(velrange >= minVel)
583 indmaxPoint = numpy.where(velrange <= maxVel)
581 584
582 585
583 586 # seleccion de indices para rango
584 587 minIndex = 0
585 588 maxIndex = 0
586 589 heights = self.dataOut.heightList
587 590
588 591 inda = numpy.where(heights >= minHei)
589 592 indb = numpy.where(heights <= maxHei)
590 593
591 594 try:
592 595 minIndex = inda[0][0]
593 596 except:
594 597 minIndex = 0
595 598
596 599 try:
597 600 maxIndex = indb[0][-1]
598 601 except:
599 602 maxIndex = len(heights)
600 603
601 604 if (minIndex < 0) or (minIndex > maxIndex):
602 605 raise ValueError("some value in (%d,%d) is not valid" % (
603 606 minIndex, maxIndex))
604 607
605 608 if (maxIndex >= self.dataOut.nHeights):
606 609 maxIndex = self.dataOut.nHeights - 1
607 610 #############################################################3
608 611 # seleccion de indices para velocidades
612 if self.dataOut.type == 'Spectra':
613 try:
614 minIndexFFT = indminPoint[0][0]
615 except:
616 minIndexFFT = 0
609 617
610 try:
611 minIndexFFT = indminPoint[0][0]
612 except:
613 minIndexFFT = 0
618 try:
619 maxIndexFFT = indmaxPoint[0][-1]
620 except:
621 maxIndexFFT = len( self.dataOut.getFreqRange(1))
614 622
615 try:
616 maxIndexFFT = indmaxPoint[0][-1]
617 except:
618 maxIndexFFT = len( self.dataOut.getFreqRange(1))
619 623
620 #print(minIndex, maxIndex,minIndexVel, maxIndexVel)
621 624 self.dataOut.noise_estimation = None
622 noise = self.dataOut.getNoise(xmin_index=minIndexFFT, xmax_index=maxIndexFFT, ymin_index=minIndex, ymax_index=maxIndex)
623
625 noise = None
626 if self.dataOut.type == 'Voltage':
627 noise = self.dataOut.getNoise(ymin_index=minIndex, ymax_index=maxIndex)
628 #print(minIndex, maxIndex,minIndexVel, maxIndexVel)
629 elif self.dataOut.type == 'Spectra':
630 noise = self.dataOut.getNoise(xmin_index=minIndexFFT, xmax_index=maxIndexFFT, ymin_index=minIndex, ymax_index=maxIndex)
631 else:
632 noise = self.dataOut.getNoise(xmin_index=minIndexFFT, xmax_index=maxIndexFFT, ymin_index=minIndex, ymax_index=maxIndex)
624 633 self.dataOut.noise_estimation = noise.copy() # dataOut.noise
625 634 #print("2: ",10*numpy.log10(self.dataOut.noise_estimation/64))
635
626 636 return self.dataOut
627 637
628 638
629 639
630 640 # import matplotlib.pyplot as plt
631 641
632 642 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
633 643 z = (x - a1) / a2
634 644 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
635 645 return y
636 646
637 647
638 648 class CleanRayleigh(Operation):
639 649
640 650 def __init__(self):
641 651
642 652 Operation.__init__(self)
643 653 self.i=0
644 654 self.isConfig = False
645 655 self.__dataReady = False
646 656 self.__profIndex = 0
647 657 self.byTime = False
648 658 self.byProfiles = False
649 659
650 660 self.bloques = None
651 661 self.bloque0 = None
652 662
653 663 self.index = 0
654 664
655 665 self.buffer = 0
656 666 self.buffer2 = 0
657 667 self.buffer3 = 0
658 668
659 669
660 670 def setup(self,dataOut,min_hei,max_hei,n, timeInterval,factor_stdv):
661 671
662 672 self.nChannels = dataOut.nChannels
663 673 self.nProf = dataOut.nProfiles
664 674 self.nPairs = dataOut.data_cspc.shape[0]
665 675 self.pairsArray = numpy.array(dataOut.pairsList)
666 676 self.spectra = dataOut.data_spc
667 677 self.cspectra = dataOut.data_cspc
668 678 self.heights = dataOut.heightList #alturas totales
669 679 self.nHeights = len(self.heights)
670 680 self.min_hei = min_hei
671 681 self.max_hei = max_hei
672 682 if (self.min_hei == None):
673 683 self.min_hei = 0
674 684 if (self.max_hei == None):
675 685 self.max_hei = dataOut.heightList[-1]
676 686 self.hval = ((self.max_hei>=self.heights) & (self.heights >= self.min_hei)).nonzero()
677 687 self.heightsClean = self.heights[self.hval] #alturas filtradas
678 688 self.hval = self.hval[0] # forma (N,), an solo N elementos -> Indices de alturas
679 689 self.nHeightsClean = len(self.heightsClean)
680 690 self.channels = dataOut.channelList
681 691 self.nChan = len(self.channels)
682 692 self.nIncohInt = dataOut.nIncohInt
683 693 self.__initime = dataOut.utctime
684 694 self.maxAltInd = self.hval[-1]+1
685 695 self.minAltInd = self.hval[0]
686 696
687 697 self.crosspairs = dataOut.pairsList
688 698 self.nPairs = len(self.crosspairs)
689 699 self.normFactor = dataOut.normFactor
690 700 self.nFFTPoints = dataOut.nFFTPoints
691 701 self.ippSeconds = dataOut.ippSeconds
692 702 self.currentTime = self.__initime
693 703 self.pairsArray = numpy.array(dataOut.pairsList)
694 704 self.factor_stdv = factor_stdv
695 705
696 706 if n != None :
697 707 self.byProfiles = True
698 708 self.nIntProfiles = n
699 709 else:
700 710 self.__integrationtime = timeInterval
701 711
702 712 self.__dataReady = False
703 713 self.isConfig = True
704 714
705 715
706 716
707 717 def run(self, dataOut,min_hei=None,max_hei=None, n=None, timeInterval=10,factor_stdv=2.5):
708
718 #print("runing cleanRayleigh")
709 719 if not self.isConfig :
710 720
711 721 self.setup(dataOut, min_hei,max_hei,n,timeInterval,factor_stdv)
712 722
713 723 tini=dataOut.utctime
714 724
715 725 if self.byProfiles:
716 726 if self.__profIndex == self.nIntProfiles:
717 727 self.__dataReady = True
718 728 else:
719 729 if (tini - self.__initime) >= self.__integrationtime:
720 730
721 731 self.__dataReady = True
722 732 self.__initime = tini
723 733
724 734 #if (tini.tm_min % 2) == 0 and (tini.tm_sec < 5 and self.fint==0):
725 735
726 736 if self.__dataReady:
727 737
728 738 self.__profIndex = 0
729 739 jspc = self.buffer
730 740 jcspc = self.buffer2
731 741 #jnoise = self.buffer3
732 742 self.buffer = dataOut.data_spc
733 743 self.buffer2 = dataOut.data_cspc
734 744 #self.buffer3 = dataOut.noise
735 745 self.currentTime = dataOut.utctime
736 746 if numpy.any(jspc) :
737 747 #print( jspc.shape, jcspc.shape)
738 748 jspc = numpy.reshape(jspc,(int(len(jspc)/self.nChannels),self.nChannels,self.nFFTPoints,self.nHeights))
739 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/self.nPairs),self.nPairs,self.nFFTPoints,self.nHeights))
749 try:
750 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/self.nPairs),self.nPairs,self.nFFTPoints,self.nHeights))
751 except:
752 print("no cspc")
740 753 self.__dataReady = False
741 754 #print( jspc.shape, jcspc.shape)
742 755 dataOut.flagNoData = False
743 756 else:
744 757 dataOut.flagNoData = True
745 758 self.__dataReady = False
746 759 return dataOut
747 760 else:
748 761 #print( len(self.buffer))
749 762 if numpy.any(self.buffer):
750 763 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
751 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
752 self.buffer3 += dataOut.data_dc
764 try:
765 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
766 self.buffer3 += dataOut.data_dc
767 except:
768 pass
753 769 else:
754 770 self.buffer = dataOut.data_spc
755 771 self.buffer2 = dataOut.data_cspc
756 772 self.buffer3 = dataOut.data_dc
757 773 #print self.index, self.fint
758 774 #print self.buffer2.shape
759 775 dataOut.flagNoData = True ## NOTE: ?? revisar LUEGO
760 776 self.__profIndex += 1
761 777 return dataOut ## NOTE: REV
762 778
763 779
764 780 #index = tini.tm_hour*12+tini.tm_min/5
765 '''REVISAR'''
781 '''
782 REVISAR
783 '''
766 784 # jspc = jspc/self.nFFTPoints/self.normFactor
767 785 # jcspc = jcspc/self.nFFTPoints/self.normFactor
768 786
769 787
770 788
771 789 tmp_spectra,tmp_cspectra = self.cleanRayleigh(dataOut,jspc,jcspc,self.factor_stdv)
772 790 dataOut.data_spc = tmp_spectra
773 791 dataOut.data_cspc = tmp_cspectra
774 792
775 793 #dataOut.data_spc,dataOut.data_cspc = self.cleanRayleigh(dataOut,jspc,jcspc,self.factor_stdv)
776 794
777 795 dataOut.data_dc = self.buffer3
778 796 dataOut.nIncohInt *= self.nIntProfiles
797 dataOut.max_nIncohInt = self.nIntProfiles
779 798 dataOut.utctime = self.currentTime #tiempo promediado
780 799 #print("Time: ",time.localtime(dataOut.utctime))
781 800 # dataOut.data_spc = sat_spectra
782 801 # dataOut.data_cspc = sat_cspectra
783 802 self.buffer = 0
784 803 self.buffer2 = 0
785 804 self.buffer3 = 0
786 805
787 806 return dataOut
788 807
789 808 def cleanRayleigh(self,dataOut,spectra,cspectra,factor_stdv):
790 #print("OP cleanRayleigh")
809 print("OP cleanRayleigh")
791 810 #import matplotlib.pyplot as plt
792 811 #for k in range(149):
793 812 #channelsProcssd = []
794 813 #channelA_ok = False
795 814 #rfunc = cspectra.copy() #self.bloques
796 815 rfunc = spectra.copy()
797 816 #rfunc = cspectra
798 817 #val_spc = spectra*0.0 #self.bloque0*0.0
799 818 #val_cspc = cspectra*0.0 #self.bloques*0.0
800 819 #in_sat_spectra = spectra.copy() #self.bloque0
801 820 #in_sat_cspectra = cspectra.copy() #self.bloques
802 821
803 822
804 823 ###ONLY FOR TEST:
805 824 raxs = math.ceil(math.sqrt(self.nPairs))
825 if raxs == 0:
826 raxs = 1
806 827 caxs = math.ceil(self.nPairs/raxs)
807 828 if self.nPairs <4:
808 829 raxs = 2
809 830 caxs = 2
810 831 #print(raxs, caxs)
811 832 fft_rev = 14 #nFFT to plot
812 833 hei_rev = ((self.heights >= 550) & (self.heights <= 551)).nonzero() #hei to plot
813 834 hei_rev = hei_rev[0]
814 835 #print(hei_rev)
815 836
816 837 #print numpy.absolute(rfunc[:,0,0,14])
817 838
818 839 gauss_fit, covariance = None, None
819 840 for ih in range(self.minAltInd,self.maxAltInd):
820 841 for ifreq in range(self.nFFTPoints):
821 842 '''
822 843 ###ONLY FOR TEST:
823 844 if ifreq ==fft_rev and ih==hei_rev: #TO VIEW A SIGNLE FREQUENCY
824 845 fig, axs = plt.subplots(raxs, caxs)
825 846 fig2, axs2 = plt.subplots(raxs, caxs)
826 847 col_ax = 0
827 848 row_ax = 0
828 849 '''
829 850 #print(self.nPairs)
830 851 for ii in range(self.nChan): #PARES DE CANALES SELF y CROSS
831 852 # if self.crosspairs[ii][1]-self.crosspairs[ii][0] > 1: # APLICAR SOLO EN PARES CONTIGUOS
832 853 # continue
833 854 # if not self.crosspairs[ii][0] in channelsProcssd:
834 855 # channelA_ok = True
835 856 #print("pair: ",self.crosspairs[ii])
836 857 '''
837 858 ###ONLY FOR TEST:
838 859 if (col_ax%caxs==0 and col_ax!=0 and self.nPairs !=1):
839 860 col_ax = 0
840 861 row_ax += 1
841 862 '''
842 863 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih])) #Potencia?
843 864 #print(func2clean.shape)
844 865 val = (numpy.isfinite(func2clean)==True).nonzero()
845 866
846 867 if len(val)>0: #limitador
847 868 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
848 869 if min_val <= -40 :
849 870 min_val = -40
850 871 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
851 872 if max_val >= 200 :
852 873 max_val = 200
853 874 #print min_val, max_val
854 875 step = 1
855 876 #print("Getting bins and the histogram")
856 877 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
857 878 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
858 879 #print(len(y_dist),len(binstep[:-1]))
859 880 #print(row_ax,col_ax, " ..")
860 881 #print(self.pairsArray[ii][0],self.pairsArray[ii][1])
861 882 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
862 883 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
863 884 parg = [numpy.amax(y_dist),mean,sigma]
864 885
865 886 newY = None
866 887
867 888 try :
868 889 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
869 890 mode = gauss_fit[1]
870 891 stdv = gauss_fit[2]
871 892 #print(" FIT OK",gauss_fit)
872 893 '''
873 894 ###ONLY FOR TEST:
874 895 if ifreq ==fft_rev and ih==hei_rev: #TO VIEW A SIGNLE FREQUENCY
875 896 newY = fit_func(x_dist,gauss_fit[0],gauss_fit[1],gauss_fit[2])
876 897 axs[row_ax,col_ax].plot(binstep[:-1],y_dist,color='green')
877 898 axs[row_ax,col_ax].plot(binstep[:-1],newY,color='red')
878 899 axs[row_ax,col_ax].set_title("CH "+str(self.channels[ii]))
879 900 '''
880 901 except:
881 902 mode = mean
882 903 stdv = sigma
883 904 #print("FIT FAIL")
884 905 #continue
885 906
886 907
887 908 #print(mode,stdv)
888 909 #Removing echoes greater than mode + std_factor*stdv
889 910 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
890 911 #noval tiene los indices que se van a remover
891 912 #print("Chan ",ii," novals: ",len(noval[0]))
892 913 if len(noval[0]) > 0: #forma de array (N,) es igual a longitud (N)
893 914 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
894 915 #print(novall)
895 916 #print(" ",self.pairsArray[ii])
896 917 #cross_pairs = self.pairsArray[ii]
897 918 #Getting coherent echoes which are removed.
898 919 # if len(novall[0]) > 0:
899 920 #
900 921 # val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
901 922 # val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
902 923 # val_cspc[novall[0],ii,ifreq,ih] = 1
903 924 #print("OUT NOVALL 1")
904 925 try:
905 926 pair = (self.channels[ii],self.channels[ii + 1])
906 927 except:
907 928 pair = (99,99)
908 929 #print("par ", pair)
909 930 if ( pair in self.crosspairs):
910 931 q = self.crosspairs.index(pair)
911 932 #print("está aqui: ", q, (ii,ii + 1))
912 933 new_a = numpy.delete(cspectra[:,q,ifreq,ih], noval[0])
913 934 cspectra[noval,q,ifreq,ih] = numpy.mean(new_a) #mean CrossSpectra
914 935
915 936 #if channelA_ok:
916 937 #chA = self.channels.index(cross_pairs[0])
917 938 new_b = numpy.delete(spectra[:,ii,ifreq,ih], noval[0])
918 939 spectra[noval,ii,ifreq,ih] = numpy.mean(new_b) #mean Spectra Pair A
919 940 #channelA_ok = False
920 941
921 942 # chB = self.channels.index(cross_pairs[1])
922 943 # new_c = numpy.delete(spectra[:,chB,ifreq,ih], noval[0])
923 944 # spectra[noval,chB,ifreq,ih] = numpy.mean(new_c) #mean Spectra Pair B
924 945 #
925 946 # channelsProcssd.append(self.crosspairs[ii][0]) # save channel A
926 947 # channelsProcssd.append(self.crosspairs[ii][1]) # save channel B
927 948 '''
928 949 ###ONLY FOR TEST:
929 950 if ifreq ==fft_rev and ih==hei_rev: #TO VIEW A SIGNLE FREQUENCY
930 951 func2clean = 10*numpy.log10(numpy.absolute(spectra[:,ii,ifreq,ih]))
931 952 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
932 953 axs2[row_ax,col_ax].plot(binstep[:-1],newY,color='red')
933 954 axs2[row_ax,col_ax].plot(binstep[:-1],y_dist,color='green')
934 955 axs2[row_ax,col_ax].set_title("CH "+str(self.channels[ii]))
935 956 '''
936 957 '''
937 958 ###ONLY FOR TEST:
938 959 col_ax += 1 #contador de ploteo columnas
939 960 ##print(col_ax)
940 961 ###ONLY FOR TEST:
941 962 if ifreq ==fft_rev and ih==hei_rev: #TO VIEW A SIGNLE FREQUENCY
942 963 title = str(dataOut.datatime)+" nFFT: "+str(ifreq)+" Alt: "+str(self.heights[ih])+ " km"
943 964 title2 = str(dataOut.datatime)+" nFFT: "+str(ifreq)+" Alt: "+str(self.heights[ih])+ " km CLEANED"
944 965 fig.suptitle(title)
945 966 fig2.suptitle(title2)
946 967 plt.show()
947 968 '''
948 969 ##################################################################################################
949 970
950 971 #print("Getting average of the spectra and cross-spectra from incoherent echoes.")
951 972 out_spectra = numpy.zeros([self.nChan,self.nFFTPoints,self.nHeights], dtype=float) #+numpy.nan
952 973 out_cspectra = numpy.zeros([self.nPairs,self.nFFTPoints,self.nHeights], dtype=complex) #+numpy.nan
953 974 for ih in range(self.nHeights):
954 975 for ifreq in range(self.nFFTPoints):
955 976 for ich in range(self.nChan):
956 977 tmp = spectra[:,ich,ifreq,ih]
957 978 valid = (numpy.isfinite(tmp[:])==True).nonzero()
958 979
959 980 if len(valid[0]) >0 :
960 981 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)#/len(valid[0])
961 982
962 983 for icr in range(self.nPairs):
963 984 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
964 985 valid = (numpy.isfinite(tmp)==True).nonzero()
965 986 if len(valid[0]) > 0:
966 987 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)#/len(valid[0])
967 988
968 989 return out_spectra, out_cspectra
969 990
970 991 def REM_ISOLATED_POINTS(self,array,rth):
971 992 # import matplotlib.pyplot as plt
972 993 if rth == None :
973 994 rth = 4
974 995 #print("REM ISO")
975 996 num_prof = len(array[0,:,0])
976 997 num_hei = len(array[0,0,:])
977 998 n2d = len(array[:,0,0])
978 999
979 1000 for ii in range(n2d) :
980 1001 #print ii,n2d
981 1002 tmp = array[ii,:,:]
982 1003 #print tmp.shape, array[ii,101,:],array[ii,102,:]
983 1004
984 1005 # fig = plt.figure(figsize=(6,5))
985 1006 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
986 1007 # ax = fig.add_axes([left, bottom, width, height])
987 1008 # x = range(num_prof)
988 1009 # y = range(num_hei)
989 1010 # cp = ax.contour(y,x,tmp)
990 1011 # ax.clabel(cp, inline=True,fontsize=10)
991 1012 # plt.show()
992 1013
993 1014 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
994 1015 tmp = numpy.reshape(tmp,num_prof*num_hei)
995 1016 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
996 1017 indxs2 = (tmp > 0).nonzero()
997 1018
998 1019 indxs1 = (indxs1[0])
999 1020 indxs2 = indxs2[0]
1000 1021 #indxs1 = numpy.array(indxs1[0])
1001 1022 #indxs2 = numpy.array(indxs2[0])
1002 1023 indxs = None
1003 1024 #print indxs1 , indxs2
1004 1025 for iv in range(len(indxs2)):
1005 1026 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
1006 1027 #print len(indxs2), indv
1007 1028 if len(indv[0]) > 0 :
1008 1029 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
1009 1030 # print indxs
1010 1031 indxs = indxs[1:]
1011 1032 #print(indxs, len(indxs))
1012 1033 if len(indxs) < 4 :
1013 1034 array[ii,:,:] = 0.
1014 1035 return
1015 1036
1016 1037 xpos = numpy.mod(indxs ,num_hei)
1017 1038 ypos = (indxs / num_hei)
1018 1039 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
1019 1040 #print sx
1020 1041 xpos = xpos[sx]
1021 1042 ypos = ypos[sx]
1022 1043
1023 1044 # *********************************** Cleaning isolated points **********************************
1024 1045 ic = 0
1025 1046 while True :
1026 1047 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
1027 1048 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
1028 1049 #plt.plot(r)
1029 1050 #plt.show()
1030 1051 no_coh1 = (numpy.isfinite(r)==True).nonzero()
1031 1052 no_coh2 = (r <= rth).nonzero()
1032 1053 #print r, no_coh1, no_coh2
1033 1054 no_coh1 = numpy.array(no_coh1[0])
1034 1055 no_coh2 = numpy.array(no_coh2[0])
1035 1056 no_coh = None
1036 1057 #print valid1 , valid2
1037 1058 for iv in range(len(no_coh2)):
1038 1059 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
1039 1060 if len(indv[0]) > 0 :
1040 1061 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
1041 1062 no_coh = no_coh[1:]
1042 1063 #print len(no_coh), no_coh
1043 1064 if len(no_coh) < 4 :
1044 1065 #print xpos[ic], ypos[ic], ic
1045 1066 # plt.plot(r)
1046 1067 # plt.show()
1047 1068 xpos[ic] = numpy.nan
1048 1069 ypos[ic] = numpy.nan
1049 1070
1050 1071 ic = ic + 1
1051 1072 if (ic == len(indxs)) :
1052 1073 break
1053 1074 #print( xpos, ypos)
1054 1075
1055 1076 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
1056 1077 #print indxs[0]
1057 1078 if len(indxs[0]) < 4 :
1058 1079 array[ii,:,:] = 0.
1059 1080 return
1060 1081
1061 1082 xpos = xpos[indxs[0]]
1062 1083 ypos = ypos[indxs[0]]
1063 1084 for i in range(0,len(ypos)):
1064 1085 ypos[i]=int(ypos[i])
1065 1086 junk = tmp
1066 1087 tmp = junk*0.0
1067 1088
1068 1089 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
1069 1090 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
1070 1091
1071 1092 #print array.shape
1072 1093 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
1073 1094 #print tmp.shape
1074 1095
1075 1096 # fig = plt.figure(figsize=(6,5))
1076 1097 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
1077 1098 # ax = fig.add_axes([left, bottom, width, height])
1078 1099 # x = range(num_prof)
1079 1100 # y = range(num_hei)
1080 1101 # cp = ax.contour(y,x,array[ii,:,:])
1081 1102 # ax.clabel(cp, inline=True,fontsize=10)
1082 1103 # plt.show()
1083 1104 return array
1084 1105
1085 1106
1086 1107 class IntegrationFaradaySpectra(Operation):
1087 1108
1088 1109 __profIndex = 0
1089 1110 __withOverapping = False
1090 1111
1091 1112 __byTime = False
1092 1113 __initime = None
1093 1114 __lastdatatime = None
1094 1115 __integrationtime = None
1095 1116
1096 1117 __buffer_spc = None
1097 1118 __buffer_cspc = None
1098 1119 __buffer_dc = None
1099 1120
1100 1121 __dataReady = False
1101 1122
1102 1123 __timeInterval = None
1103
1124 n_ints = None #matriz de numero de integracions (CH,HEI)
1104 1125 n = None
1105 1126 minHei_ind = None
1106 1127 maxHei_ind = None
1107 1128 navg = 1.0
1108 1129 factor = 0.0
1130 dataoutliers = None # (CHANNELS, HEIGHTS)
1109 1131
1110 1132 def __init__(self):
1111 1133
1112 1134 Operation.__init__(self)
1113 1135
1114 1136 def setup(self, dataOut,n=None, timeInterval=None, overlapping=False, DPL=None, minHei=None, maxHei=None, avg=1,factor=0.75):
1115 1137 """
1116 1138 Set the parameters of the integration class.
1117 1139
1118 1140 Inputs:
1119 1141
1120 1142 n : Number of coherent integrations
1121 1143 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
1122 1144 overlapping :
1123 1145
1124 1146 """
1125 1147
1126 1148 self.__initime = None
1127 1149 self.__lastdatatime = 0
1128 1150
1129 1151 self.__buffer_spc = []
1130 1152 self.__buffer_cspc = []
1131 1153 self.__buffer_dc = 0
1132 1154
1133 1155 self.__profIndex = 0
1134 1156 self.__dataReady = False
1135 1157 self.__byTime = False
1136 1158
1137 1159 self.factor = factor
1138 1160 self.navg = avg
1139 1161 #self.ByLags = dataOut.ByLags ###REDEFINIR
1140 1162 self.ByLags = False
1163 self.maxProfilesInt = 1
1141 1164
1142 1165 if DPL != None:
1143 1166 self.DPL=DPL
1144 1167 else:
1145 1168 #self.DPL=dataOut.DPL ###REDEFINIR
1146 1169 self.DPL=0
1147 1170
1148 1171 if n is None and timeInterval is None:
1149 1172 raise ValueError("n or timeInterval should be specified ...")
1150 1173
1151 1174 if n is not None:
1152 1175 self.n = int(n)
1153 1176 else:
1154 1177 self.__integrationtime = int(timeInterval)
1155 1178 self.n = None
1156 1179 self.__byTime = True
1157 1180
1158 1181 if minHei == None:
1159 1182 minHei = self.dataOut.heightList[0]
1160 1183
1161 1184 if maxHei == None:
1162 1185 maxHei = self.dataOut.heightList[-1]
1163 1186
1164 1187 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
1165 1188 print('minHei: %.2f is out of the heights range' % (minHei))
1166 1189 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
1167 1190 minHei = self.dataOut.heightList[0]
1168 1191
1169 1192 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
1170 1193 print('maxHei: %.2f is out of the heights range' % (maxHei))
1171 1194 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
1172 1195 maxHei = self.dataOut.heightList[-1]
1173 1196
1174 1197 ind_list1 = numpy.where(self.dataOut.heightList >= minHei)
1175 1198 ind_list2 = numpy.where(self.dataOut.heightList <= maxHei)
1176 1199 self.minHei_ind = ind_list1[0][0]
1177 1200 self.maxHei_ind = ind_list2[0][-1]
1178 1201
1179 1202 def putData(self, data_spc, data_cspc, data_dc):
1180 1203 """
1181 1204 Add a profile to the __buffer_spc and increase in one the __profileIndex
1182 1205
1183 1206 """
1184 1207
1185 1208 self.__buffer_spc.append(data_spc)
1186 1209
1187 1210 if data_cspc is None:
1188 1211 self.__buffer_cspc = None
1189 1212 else:
1190 1213 self.__buffer_cspc.append(data_cspc)
1191 1214
1192 1215 if data_dc is None:
1193 1216 self.__buffer_dc = None
1194 1217 else:
1195 1218 self.__buffer_dc += data_dc
1196 1219
1197 1220 self.__profIndex += 1
1198 1221
1199 1222 return
1200 1223
1201 1224 def hildebrand_sekhon_Integration(self,sortdata,navg, factor):
1202 1225 #data debe estar ordenado
1203 1226 #sortdata = numpy.sort(data, axis=None)
1204 1227 #sortID=data.argsort()
1205 1228 lenOfData = len(sortdata)
1206 1229 nums_min = lenOfData*factor
1207 1230 if nums_min <= 5:
1208 1231 nums_min = 5
1209 1232 sump = 0.
1210 1233 sumq = 0.
1211 1234 j = 0
1212 1235 cont = 1
1213 1236 while((cont == 1)and(j < lenOfData)):
1214 1237 sump += sortdata[j]
1215 1238 sumq += sortdata[j]**2
1216 1239 if j > nums_min:
1217 1240 rtest = float(j)/(j-1) + 1.0/navg
1218 1241 if ((sumq*j) > (rtest*sump**2)):
1219 1242 j = j - 1
1220 1243 sump = sump - sortdata[j]
1221 1244 sumq = sumq - sortdata[j]**2
1222 1245 cont = 0
1223 1246 j += 1
1224 1247 #lnoise = sump / j
1225 1248 #print("H S done")
1226 1249 #return j,sortID
1227 1250 return j
1228 1251
1229 1252
1230 1253 def pushData(self):
1231 1254 """
1232 1255 Return the sum of the last profiles and the profiles used in the sum.
1233 1256
1234 1257 Affected:
1235 1258
1236 1259 self.__profileIndex
1237 1260
1238 1261 """
1239 1262 bufferH=None
1240 1263 buffer=None
1241 1264 buffer1=None
1242 1265 buffer_cspc=None
1243 1266 self.__buffer_spc=numpy.array(self.__buffer_spc)
1244 1267 try:
1245 1268 self.__buffer_cspc=numpy.array(self.__buffer_cspc)
1246 1269 except :
1247 1270 #print("No cpsc",e)
1248 1271 pass
1249 1272 #print("FREQ_DC",self.__buffer_spc.shape,self.__buffer_cspc.shape)
1250 1273
1251 1274 freq_dc = int(self.__buffer_spc.shape[2] / 2)
1252 1275 #print("FREQ_DC",freq_dc,self.__buffer_spc.shape,self.nHeights)
1253 1276
1277 self.dataOutliers = numpy.zeros((self.nChannels,self.nHeights)) # --> almacen de outliers
1278
1254 1279 for k in range(self.minHei_ind,self.maxHei_ind):
1255 1280 try:
1256 1281 buffer_cspc=numpy.copy(self.__buffer_cspc[:,:,:,k])
1257 1282 except:
1258 1283 #print("No cpsc",e)
1259 1284 pass
1260 1285 outliers_IDs_cspc=[]
1261 1286 cspc_outliers_exist=False
1262 1287 for i in range(self.nChannels):#dataOut.nChannels):
1263 1288
1264 1289 buffer1=numpy.copy(self.__buffer_spc[:,i,:,k])
1265 1290 indexes=[]
1266 1291 #sortIDs=[]
1267 1292 outliers_IDs=[]
1268 1293
1269 for j in range(self.nProfiles):
1294 for j in range(self.nProfiles): #frecuencias en el tiempo
1270 1295 # if i==0 and j==freq_dc: #NOT CONSIDERING DC PROFILE AT CHANNEL 0
1271 1296 # continue
1272 1297 # if i==1 and j==0: #NOT CONSIDERING DC PROFILE AT CHANNEL 1
1273 1298 # continue
1274 1299 buffer=buffer1[:,j]
1275 1300 sortdata = numpy.sort(buffer, axis=None)
1301
1276 1302 sortID=buffer.argsort()
1277 1303 index = _noise.hildebrand_sekhon2(sortdata,self.navg)
1278 1304
1279 1305 #index,sortID=self.hildebrand_sekhon_Integration(buffer,1,self.factor)
1280 1306
1307 # fig,ax = plt.subplots()
1308 # ax.set_title(str(k)+" "+str(j))
1309 # x=range(len(sortdata))
1310 # ax.scatter(x,sortdata)
1311 # ax.axvline(index)
1312 # plt.show()
1313
1281 1314 indexes.append(index)
1282 1315 #sortIDs.append(sortID)
1283 1316 outliers_IDs=numpy.append(outliers_IDs,sortID[index:])
1284 1317
1318 #print("Outliers: ",outliers_IDs)
1285 1319 outliers_IDs=numpy.array(outliers_IDs)
1286 1320 outliers_IDs=outliers_IDs.ravel()
1287 1321 outliers_IDs=numpy.unique(outliers_IDs)
1288 1322 outliers_IDs=outliers_IDs.astype(numpy.dtype('int64'))
1289 1323 indexes=numpy.array(indexes)
1290 1324 indexmin=numpy.min(indexes)
1291 1325
1326
1327 #print(indexmin,buffer1.shape[0], k)
1328
1329 # fig,ax = plt.subplots()
1330 # ax.plot(sortdata)
1331 # ax2 = ax.twinx()
1332 # x=range(len(indexes))
1333 # #plt.scatter(x,indexes)
1334 # ax2.scatter(x,indexes)
1335 # plt.show()
1336
1292 1337 if indexmin != buffer1.shape[0]:
1293 1338 if self.nChannels > 1:
1294 1339 cspc_outliers_exist= True
1295 1340
1296 1341 lt=outliers_IDs
1297 avg=numpy.mean(buffer1[[t for t in range(buffer1.shape[0]) if t not in lt],:],axis=0)
1342 #avg=numpy.mean(buffer1[[t for t in range(buffer1.shape[0]) if t not in lt],:],axis=0)
1298 1343
1299 1344 for p in list(outliers_IDs):
1300 buffer1[p,:]=avg
1345 #buffer1[p,:]=avg
1346 buffer1[p,:] = numpy.NaN
1347
1348 self.dataOutliers[i,k] = len(outliers_IDs)
1301 1349
1302 1350 self.__buffer_spc[:,i,:,k]=numpy.copy(buffer1)
1303 ###cspc IDs
1304 #indexmin_cspc+=indexmin_cspc
1351
1305 1352 outliers_IDs_cspc=numpy.append(outliers_IDs_cspc,outliers_IDs)
1306 1353
1307 #if not breakFlag:
1354
1355
1308 1356 outliers_IDs_cspc=outliers_IDs_cspc.astype(numpy.dtype('int64'))
1309 1357 if cspc_outliers_exist :
1310 #sortdata=numpy.sort(buffer_cspc,axis=0)
1311 #avg=numpy.mean(sortdata[:indexmin_cpsc,:],axis=0)
1358
1312 1359 lt=outliers_IDs_cspc
1313 1360
1314 avg=numpy.mean(buffer_cspc[[t for t in range(buffer_cspc.shape[0]) if t not in lt],:],axis=0)
1361 #avg=numpy.mean(buffer_cspc[[t for t in range(buffer_cspc.shape[0]) if t not in lt],:],axis=0)
1315 1362 for p in list(outliers_IDs_cspc):
1316 buffer_cspc[p,:]=avg
1363 #buffer_cspc[p,:]=avg
1364 buffer_cspc[p,:] = numpy.NaN
1317 1365
1318 1366 try:
1319 1367 self.__buffer_cspc[:,:,:,k]=numpy.copy(buffer_cspc)
1320 1368 except:
1321 1369 #print("No cpsc",e)
1322 1370 pass
1323 1371 #else:
1324 1372 #break
1325 1373
1326 1374
1327 1375
1328
1376 nOutliers = len(outliers_IDs)
1377 #print("Outliers n: ",self.dataOutliers,nOutliers)
1329 1378 buffer=None
1330 1379 bufferH=None
1331 1380 buffer1=None
1332 1381 buffer_cspc=None
1333 1382
1334 #print("cpsc",self.__buffer_cspc[:,0,0,0,0])
1335 #exit()
1336 1383
1337 1384 buffer=None
1338 #print(self.__buffer_spc[:,1,3,20,0])
1339 #print(self.__buffer_spc[:,1,5,37,0])
1340 data_spc = numpy.sum(self.__buffer_spc,axis=0)
1385
1386 #data_spc = numpy.sum(self.__buffer_spc,axis=0)
1387 data_spc = numpy.nansum(self.__buffer_spc,axis=0)
1341 1388 try:
1342 data_cspc = numpy.sum(self.__buffer_cspc,axis=0)
1389 #data_cspc = numpy.sum(self.__buffer_cspc,axis=0)
1390 data_cspc = numpy.nansum(self.__buffer_cspc,axis=0)
1343 1391 except:
1344 1392 #print("No cpsc",e)
1345 1393 pass
1346 1394
1347 1395
1348 #print(numpy.shape(data_spc))
1349 #data_spc[1,4,20,0]=numpy.nan
1350
1351 #data_cspc = self.__buffer_cspc
1352 #print("pushData pre Done")
1353 1396 data_dc = self.__buffer_dc
1354 n = self.__profIndex
1397 #(CH, HEIGH)
1398 self.maxProfilesInt = self.__profIndex
1399 n = self.__profIndex - self.dataOutliers
1355 1400
1356 1401 self.__buffer_spc = []
1357 1402 self.__buffer_cspc = []
1358 1403 self.__buffer_dc = 0
1359 1404 self.__profIndex = 0
1360 #print("pushData Done")
1405
1361 1406 return data_spc, data_cspc, data_dc, n
1362 1407
1363 1408 def byProfiles(self, *args):
1364 1409
1365 1410 self.__dataReady = False
1366 1411 avgdata_spc = None
1367 1412 avgdata_cspc = None
1368 1413 avgdata_dc = None
1369 1414
1370 1415 self.putData(*args)
1371 1416
1372 1417 if self.__profIndex == self.n:
1373 1418
1374 1419 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1375 self.n = n
1420 self.n_ints = n
1376 1421 self.__dataReady = True
1377 1422
1378 1423 return avgdata_spc, avgdata_cspc, avgdata_dc
1379 1424
1380 1425 def byTime(self, datatime, *args):
1381 1426
1382 1427 self.__dataReady = False
1383 1428 avgdata_spc = None
1384 1429 avgdata_cspc = None
1385 1430 avgdata_dc = None
1386 1431
1387 1432 self.putData(*args)
1388 1433
1389 1434 if (datatime - self.__initime) >= self.__integrationtime:
1390 1435 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1391 self.n = n
1436 self.n_ints = n
1392 1437 self.__dataReady = True
1393 1438
1394 1439 return avgdata_spc, avgdata_cspc, avgdata_dc
1395 1440
1396 1441 def integrate(self, datatime, *args):
1397 1442
1398 1443 if self.__profIndex == 0:
1399 1444 self.__initime = datatime
1400 1445
1401 1446 if self.__byTime:
1402 1447 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
1403 1448 datatime, *args)
1404 1449 else:
1405 1450 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
1406 1451
1407 1452 if not self.__dataReady:
1408 1453 return None, None, None, None
1409 1454
1410 1455 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
1411 1456
1412 1457 def run(self, dataOut, n=None, DPL = None,timeInterval=None, overlapping=False, minHei=None, maxHei=None, avg=1, factor=0.75):
1413 1458 self.dataOut = dataOut.copy()
1414 1459 if n == 1:
1415 1460 return self.dataOut
1416 1461
1417 1462 self.dataOut.flagNoData = True
1418 1463 if self.dataOut.nChannels == 1:
1419 1464 self.dataOut.data_cspc = None #si es un solo canal no vale la pena acumular DATOS
1420 1465 #print(self.dataOut.data_spc.shape, self.dataOut.data_cspc)
1421 1466 if not self.isConfig:
1422 1467 self.setup(self.dataOut, n, timeInterval, overlapping,DPL ,minHei, maxHei, avg, factor)
1423 1468 self.isConfig = True
1424 1469
1425 1470 if not self.ByLags:
1426 1471 self.nProfiles=self.dataOut.nProfiles
1427 1472 self.nChannels=self.dataOut.nChannels
1428 1473 self.nHeights=self.dataOut.nHeights
1429 1474 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(self.dataOut.utctime,
1430 1475 self.dataOut.data_spc,
1431 1476 self.dataOut.data_cspc,
1432 1477 self.dataOut.data_dc)
1433 1478 else:
1434 1479 self.nProfiles=self.dataOut.nProfiles
1435 1480 self.nChannels=self.dataOut.nChannels
1436 1481 self.nHeights=self.dataOut.nHeights
1437 1482 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(self.dataOut.utctime,
1438 1483 self.dataOut.dataLag_spc,
1439 1484 self.dataOut.dataLag_cspc,
1440 1485 self.dataOut.dataLag_dc)
1441 1486
1442 1487 if self.__dataReady:
1443 1488
1444 1489 if not self.ByLags:
1445 1490 if self.nChannels == 1:
1446 1491 #print("f int", avgdata_spc.shape)
1447 1492 self.dataOut.data_spc = avgdata_spc
1448 1493 self.dataOut.data_cspc = avgdata_spc
1449 1494 else:
1450 1495 self.dataOut.data_spc = numpy.squeeze(avgdata_spc)
1451 1496 self.dataOut.data_cspc = numpy.squeeze(avgdata_cspc)
1452 1497 self.dataOut.data_dc = avgdata_dc
1453
1498 self.dataOut.data_outlier = self.dataOutliers
1454 1499
1455 1500 else:
1456 1501 self.dataOut.dataLag_spc = avgdata_spc
1457 1502 self.dataOut.dataLag_cspc = avgdata_cspc
1458 1503 self.dataOut.dataLag_dc = avgdata_dc
1459 1504
1460 1505 self.dataOut.data_spc=self.dataOut.dataLag_spc[:,:,:,self.dataOut.LagPlot]
1461 1506 self.dataOut.data_cspc=self.dataOut.dataLag_cspc[:,:,:,self.dataOut.LagPlot]
1462 1507 self.dataOut.data_dc=self.dataOut.dataLag_dc[:,:,self.dataOut.LagPlot]
1463 1508
1464 1509
1465 self.dataOut.nIncohInt *= self.n
1510 self.dataOut.nIncohInt *= self.n_ints
1511 self.dataOut.max_nIncohInt = self.maxProfilesInt
1512 #print(self.dataOut.max_nIncohInt)
1466 1513 self.dataOut.utctime = avgdatatime
1467 1514 self.dataOut.flagNoData = False
1468
1515 #print("Faraday Integration DONE...")
1469 1516 return self.dataOut
1470 1517
1471 1518 class removeInterference(Operation):
1472 1519
1473 1520 def removeInterference2(self):
1474 1521
1475 1522 cspc = self.dataOut.data_cspc
1476 1523 spc = self.dataOut.data_spc
1477 1524 Heights = numpy.arange(cspc.shape[2])
1478 1525 realCspc = numpy.abs(cspc)
1479 1526
1480 1527 for i in range(cspc.shape[0]):
1481 1528 LinePower= numpy.sum(realCspc[i], axis=0)
1482 1529 Threshold = numpy.amax(LinePower)-numpy.sort(LinePower)[len(Heights)-int(len(Heights)*0.1)]
1483 1530 SelectedHeights = Heights[ numpy.where( LinePower < Threshold ) ]
1484 1531 InterferenceSum = numpy.sum( realCspc[i,:,SelectedHeights], axis=0 )
1485 1532 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.98)]
1486 1533 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.99)]
1487 1534
1488 1535
1489 1536 InterferenceRange = numpy.where( ([InterferenceSum > InterferenceThresholdMin]))# , InterferenceSum < InterferenceThresholdMax]) )
1490 1537 #InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
1491 1538 if len(InterferenceRange)<int(cspc.shape[1]*0.3):
1492 1539 cspc[i,InterferenceRange,:] = numpy.NaN
1493 1540
1494 1541 self.dataOut.data_cspc = cspc
1495 1542
1496 1543 def removeInterference(self, interf = 2, hei_interf = None, nhei_interf = None, offhei_interf = None):
1497 1544
1498 1545 jspectra = self.dataOut.data_spc
1499 1546 jcspectra = self.dataOut.data_cspc
1500 1547 jnoise = self.dataOut.getNoise()
1501 1548 num_incoh = self.dataOut.nIncohInt
1502 1549
1503 1550 num_channel = jspectra.shape[0]
1504 1551 num_prof = jspectra.shape[1]
1505 1552 num_hei = jspectra.shape[2]
1506 1553
1507 1554 # hei_interf
1508 1555 if hei_interf is None:
1509 1556 count_hei = int(num_hei / 2)
1510 1557 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
1511 1558 hei_interf = numpy.asarray(hei_interf)[0]
1512 1559 # nhei_interf
1513 1560 if (nhei_interf == None):
1514 1561 nhei_interf = 5
1515 1562 if (nhei_interf < 1):
1516 1563 nhei_interf = 1
1517 1564 if (nhei_interf > count_hei):
1518 1565 nhei_interf = count_hei
1519 1566 if (offhei_interf == None):
1520 1567 offhei_interf = 0
1521 1568
1522 1569 ind_hei = list(range(num_hei))
1523 1570 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
1524 1571 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
1525 1572 mask_prof = numpy.asarray(list(range(num_prof)))
1526 1573 num_mask_prof = mask_prof.size
1527 1574 comp_mask_prof = [0, num_prof / 2]
1528 1575
1529 1576 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
1530 1577 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
1531 1578 jnoise = numpy.nan
1532 1579 noise_exist = jnoise[0] < numpy.Inf
1533 1580
1534 1581 # Subrutina de Remocion de la Interferencia
1535 1582 for ich in range(num_channel):
1536 1583 # Se ordena los espectros segun su potencia (menor a mayor)
1537 1584 power = jspectra[ich, mask_prof, :]
1538 1585 power = power[:, hei_interf]
1539 1586 power = power.sum(axis=0)
1540 1587 psort = power.ravel().argsort()
1541 1588
1542 1589 # Se estima la interferencia promedio en los Espectros de Potencia empleando
1543 1590 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(
1544 1591 offhei_interf, nhei_interf + offhei_interf))]]]
1545 1592
1546 1593 if noise_exist:
1547 1594 # tmp_noise = jnoise[ich] / num_prof
1548 1595 tmp_noise = jnoise[ich]
1549 1596 junkspc_interf = junkspc_interf - tmp_noise
1550 1597 #junkspc_interf[:,comp_mask_prof] = 0
1551 1598
1552 1599 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
1553 1600 jspc_interf = jspc_interf.transpose()
1554 1601 # Calculando el espectro de interferencia promedio
1555 1602 noiseid = numpy.where(
1556 1603 jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
1557 1604 noiseid = noiseid[0]
1558 1605 cnoiseid = noiseid.size
1559 1606 interfid = numpy.where(
1560 1607 jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
1561 1608 interfid = interfid[0]
1562 1609 cinterfid = interfid.size
1563 1610
1564 1611 if (cnoiseid > 0):
1565 1612 jspc_interf[noiseid] = 0
1566 1613
1567 1614 # Expandiendo los perfiles a limpiar
1568 1615 if (cinterfid > 0):
1569 1616 new_interfid = (
1570 1617 numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
1571 1618 new_interfid = numpy.asarray(new_interfid)
1572 1619 new_interfid = {x for x in new_interfid}
1573 1620 new_interfid = numpy.array(list(new_interfid))
1574 1621 new_cinterfid = new_interfid.size
1575 1622 else:
1576 1623 new_cinterfid = 0
1577 1624
1578 1625 for ip in range(new_cinterfid):
1579 1626 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
1580 1627 jspc_interf[new_interfid[ip]
1581 1628 ] = junkspc_interf[ind[nhei_interf // 2], new_interfid[ip]]
1582 1629
1583 1630 jspectra[ich, :, ind_hei] = jspectra[ich, :,
1584 1631 ind_hei] - jspc_interf # Corregir indices
1585 1632
1586 1633 # Removiendo la interferencia del punto de mayor interferencia
1587 1634 ListAux = jspc_interf[mask_prof].tolist()
1588 1635 maxid = ListAux.index(max(ListAux))
1589 1636
1590 1637 if cinterfid > 0:
1591 1638 for ip in range(cinterfid * (interf == 2) - 1):
1592 1639 ind = (jspectra[ich, interfid[ip], :] < tmp_noise *
1593 1640 (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
1594 1641 cind = len(ind)
1595 1642
1596 1643 if (cind > 0):
1597 1644 jspectra[ich, interfid[ip], ind] = tmp_noise * \
1598 1645 (1 + (numpy.random.uniform(cind) - 0.5) /
1599 1646 numpy.sqrt(num_incoh))
1600 1647
1601 1648 ind = numpy.array([-2, -1, 1, 2])
1602 1649 xx = numpy.zeros([4, 4])
1603 1650
1604 1651 for id1 in range(4):
1605 1652 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
1606 1653
1607 1654 xx_inv = numpy.linalg.inv(xx)
1608 1655 xx = xx_inv[:, 0]
1609 1656 ind = (ind + maxid + num_mask_prof) % num_mask_prof
1610 1657 yy = jspectra[ich, mask_prof[ind], :]
1611 1658 jspectra[ich, mask_prof[maxid], :] = numpy.dot(
1612 1659 yy.transpose(), xx)
1613 1660
1614 1661 indAux = (jspectra[ich, :, :] < tmp_noise *
1615 1662 (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
1616 1663 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * \
1617 1664 (1 - 1 / numpy.sqrt(num_incoh))
1618 1665
1619 1666 # Remocion de Interferencia en el Cross Spectra
1620 1667 if jcspectra is None:
1621 1668 return jspectra, jcspectra
1622 1669 num_pairs = int(jcspectra.size / (num_prof * num_hei))
1623 1670 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
1624 1671
1625 1672 for ip in range(num_pairs):
1626 1673
1627 1674 #-------------------------------------------
1628 1675
1629 1676 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
1630 1677 cspower = cspower[:, hei_interf]
1631 1678 cspower = cspower.sum(axis=0)
1632 1679
1633 1680 cspsort = cspower.ravel().argsort()
1634 1681 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(
1635 1682 offhei_interf, nhei_interf + offhei_interf))]]]
1636 1683 junkcspc_interf = junkcspc_interf.transpose()
1637 1684 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
1638 1685
1639 1686 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
1640 1687
1641 1688 median_real = int(numpy.median(numpy.real(
1642 1689 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
1643 1690 median_imag = int(numpy.median(numpy.imag(
1644 1691 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
1645 1692 comp_mask_prof = [int(e) for e in comp_mask_prof]
1646 1693 junkcspc_interf[comp_mask_prof, :] = numpy.complex(
1647 1694 median_real, median_imag)
1648 1695
1649 1696 for iprof in range(num_prof):
1650 1697 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
1651 1698 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf // 2]]
1652 1699
1653 1700 # Removiendo la Interferencia
1654 1701 jcspectra[ip, :, ind_hei] = jcspectra[ip,
1655 1702 :, ind_hei] - jcspc_interf
1656 1703
1657 1704 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
1658 1705 maxid = ListAux.index(max(ListAux))
1659 1706
1660 1707 ind = numpy.array([-2, -1, 1, 2])
1661 1708 xx = numpy.zeros([4, 4])
1662 1709
1663 1710 for id1 in range(4):
1664 1711 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
1665 1712
1666 1713 xx_inv = numpy.linalg.inv(xx)
1667 1714 xx = xx_inv[:, 0]
1668 1715
1669 1716 ind = (ind + maxid + num_mask_prof) % num_mask_prof
1670 1717 yy = jcspectra[ip, mask_prof[ind], :]
1671 1718 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
1672 1719
1673 1720 # Guardar Resultados
1674 1721 self.dataOut.data_spc = jspectra
1675 1722 self.dataOut.data_cspc = jcspectra
1676 1723
1677 1724 return 1
1678 1725
1679 1726 def run(self, dataOut, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None, mode=1):
1680 1727
1681 1728 self.dataOut = dataOut
1682 1729
1683 1730 if mode == 1:
1684 1731 self.removeInterference(interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None)
1685 1732 elif mode == 2:
1686 1733 self.removeInterference2()
1687 1734
1688 1735 return self.dataOut
1689 1736
1690 1737
1691 1738 class IncohInt(Operation):
1692 1739
1693 1740 __profIndex = 0
1694 1741 __withOverapping = False
1695 1742
1696 1743 __byTime = False
1697 1744 __initime = None
1698 1745 __lastdatatime = None
1699 1746 __integrationtime = None
1700 1747
1701 1748 __buffer_spc = None
1702 1749 __buffer_cspc = None
1703 1750 __buffer_dc = None
1704 1751
1705 1752 __dataReady = False
1706 1753
1707 1754 __timeInterval = None
1708
1755 incohInt = 0
1756 nOutliers = 0
1709 1757 n = None
1710 1758
1711 1759 def __init__(self):
1712 1760
1713 1761 Operation.__init__(self)
1714 1762
1715 1763 def setup(self, n=None, timeInterval=None, overlapping=False):
1716 1764 """
1717 1765 Set the parameters of the integration class.
1718 1766
1719 1767 Inputs:
1720 1768
1721 1769 n : Number of coherent integrations
1722 1770 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
1723 1771 overlapping :
1724 1772
1725 1773 """
1726 1774
1727 1775 self.__initime = None
1728 1776 self.__lastdatatime = 0
1729 1777
1730 1778 self.__buffer_spc = 0
1731 1779 self.__buffer_cspc = 0
1732 1780 self.__buffer_dc = 0
1733 1781
1734 1782 self.__profIndex = 0
1735 1783 self.__dataReady = False
1736 1784 self.__byTime = False
1737
1785 self.incohInt = 0
1786 self.nOutliers = 0
1738 1787 if n is None and timeInterval is None:
1739 1788 raise ValueError("n or timeInterval should be specified ...")
1740 1789
1741 1790 if n is not None:
1742 1791 self.n = int(n)
1743 1792 else:
1744 1793
1745 1794 self.__integrationtime = int(timeInterval)
1746 1795 self.n = None
1747 1796 self.__byTime = True
1748 1797
1749 1798 def putData(self, data_spc, data_cspc, data_dc):
1750 1799 """
1751 1800 Add a profile to the __buffer_spc and increase in one the __profileIndex
1752 1801
1753 1802 """
1754 1803 if data_spc.all() == numpy.nan :
1755 1804 print("nan ")
1756 1805 return
1757 1806 self.__buffer_spc += data_spc
1758 1807
1759 1808 if data_cspc is None:
1760 1809 self.__buffer_cspc = None
1761 1810 else:
1762 1811 self.__buffer_cspc += data_cspc
1763 1812
1764 1813 if data_dc is None:
1765 1814 self.__buffer_dc = None
1766 1815 else:
1767 1816 self.__buffer_dc += data_dc
1768 1817
1769 1818 self.__profIndex += 1
1770 1819
1771 1820 return
1772 1821
1773 1822 def pushData(self):
1774 1823 """
1775 1824 Return the sum of the last profiles and the profiles used in the sum.
1776 1825
1777 1826 Affected:
1778 1827
1779 1828 self.__profileIndex
1780 1829
1781 1830 """
1782 1831
1783 1832 data_spc = self.__buffer_spc
1784 1833 data_cspc = self.__buffer_cspc
1785 1834 data_dc = self.__buffer_dc
1786 1835 n = self.__profIndex
1787 1836
1788 1837 self.__buffer_spc = 0
1789 1838 self.__buffer_cspc = 0
1790 1839 self.__buffer_dc = 0
1791 self.__profIndex = 0
1840
1792 1841
1793 1842 return data_spc, data_cspc, data_dc, n
1794 1843
1795 1844 def byProfiles(self, *args):
1796 1845
1797 1846 self.__dataReady = False
1798 1847 avgdata_spc = None
1799 1848 avgdata_cspc = None
1800 1849 avgdata_dc = None
1801 1850
1802 1851 self.putData(*args)
1803 1852
1804 1853 if self.__profIndex == self.n:
1805 1854
1806 1855 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1807 1856 self.n = n
1808 1857 self.__dataReady = True
1809 1858
1810 1859 return avgdata_spc, avgdata_cspc, avgdata_dc
1811 1860
1812 1861 def byTime(self, datatime, *args):
1813 1862
1814 1863 self.__dataReady = False
1815 1864 avgdata_spc = None
1816 1865 avgdata_cspc = None
1817 1866 avgdata_dc = None
1818 1867
1819 1868 self.putData(*args)
1820 1869
1821 1870 if (datatime - self.__initime) >= self.__integrationtime:
1822 1871 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1823 1872 self.n = n
1824 1873 self.__dataReady = True
1825 1874
1826 1875 return avgdata_spc, avgdata_cspc, avgdata_dc
1827 1876
1828 1877 def integrate(self, datatime, *args):
1829 1878
1830 1879 if self.__profIndex == 0:
1831 1880 self.__initime = datatime
1832 1881
1833 1882 if self.__byTime:
1834 1883 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
1835 1884 datatime, *args)
1836 1885 else:
1837 1886 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
1838 1887
1839 1888 if not self.__dataReady:
1840 1889 return None, None, None, None
1841 1890
1842 1891 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
1843 1892
1844 1893 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
1845 1894 if n == 1:
1846 1895 return dataOut
1847 1896
1897 if dataOut.flagNoData == True:
1898 return dataOut
1899
1848 1900 dataOut.flagNoData = True
1849 1901
1850 1902 if not self.isConfig:
1851 1903 self.setup(n, timeInterval, overlapping)
1852 1904 self.isConfig = True
1853 1905
1854 1906 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
1855 1907 dataOut.data_spc,
1856 1908 dataOut.data_cspc,
1857 1909 dataOut.data_dc)
1858
1910 self.incohInt += dataOut.nIncohInt
1911 self.nOutliers += dataOut.data_outlier
1859 1912 if self.__dataReady:
1860 1913
1861 1914 dataOut.data_spc = avgdata_spc
1862 1915 dataOut.data_cspc = avgdata_cspc
1863 1916 dataOut.data_dc = avgdata_dc
1864 dataOut.nIncohInt *= self.n
1917 dataOut.nIncohInt = self.incohInt
1918 dataOut.data_outlier = self.nOutliers
1865 1919 dataOut.utctime = avgdatatime
1866 1920 dataOut.flagNoData = False
1921 dataOut.max_nIncohInt = self.__profIndex
1922 self.incohInt = 0
1923 self.nOutliers = 0
1924 self.__profIndex = 0
1867 1925
1868 1926 return dataOut
1869 1927
1870 1928 class dopplerFlip(Operation):
1871 1929
1872 1930 def run(self, dataOut):
1873 1931 # arreglo 1: (num_chan, num_profiles, num_heights)
1874 1932 self.dataOut = dataOut
1875 1933 # JULIA-oblicua, indice 2
1876 1934 # arreglo 2: (num_profiles, num_heights)
1877 1935 jspectra = self.dataOut.data_spc[2]
1878 1936 jspectra_tmp = numpy.zeros(jspectra.shape)
1879 1937 num_profiles = jspectra.shape[0]
1880 1938 freq_dc = int(num_profiles / 2)
1881 1939 # Flip con for
1882 1940 for j in range(num_profiles):
1883 1941 jspectra_tmp[num_profiles-j-1]= jspectra[j]
1884 1942 # Intercambio perfil de DC con perfil inmediato anterior
1885 1943 jspectra_tmp[freq_dc-1]= jspectra[freq_dc-1]
1886 1944 jspectra_tmp[freq_dc]= jspectra[freq_dc]
1887 1945 # canal modificado es re-escrito en el arreglo de canales
1888 1946 self.dataOut.data_spc[2] = jspectra_tmp
1889 1947
1890 1948 return self.dataOut
@@ -1,2234 +1,2361
1 1 import sys
2 2 import numpy,math
3 3 from scipy import interpolate
4 4 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
5 5 from schainpy.model.data.jrodata import Voltage,hildebrand_sekhon
6 6 from schainpy.utils import log
7 7 from schainpy.model.io.utils import getHei_index
8 8 from time import time
9 9 import datetime
10 10 import numpy
11 import copy
11 #import copy
12 from schainpy.model.data import _noise
12 13
13 14 class VoltageProc(ProcessingUnit):
14 15
15 16 def __init__(self):
16 17
17 18 ProcessingUnit.__init__(self)
18 19
19 20 self.dataOut = Voltage()
20 21 self.flip = 1
21 22 self.setupReq = False
22 23
23 24 def run(self):
24 25 #print("running volt proc")
25 26 if self.dataIn.type == 'AMISR':
26 27 self.__updateObjFromAmisrInput()
27 28
28 29 if self.dataOut.buffer_empty:
29 30 if self.dataIn.type == 'Voltage':
30 31 self.dataOut.copy(self.dataIn)
31 32 #print("new volts reading")
32 33
33 34
34 35 def __updateObjFromAmisrInput(self):
35 36
36 37 self.dataOut.timeZone = self.dataIn.timeZone
37 38 self.dataOut.dstFlag = self.dataIn.dstFlag
38 39 self.dataOut.errorCount = self.dataIn.errorCount
39 40 self.dataOut.useLocalTime = self.dataIn.useLocalTime
40 41
41 42 self.dataOut.flagNoData = self.dataIn.flagNoData
42 43 self.dataOut.data = self.dataIn.data
43 44 self.dataOut.utctime = self.dataIn.utctime
44 45 self.dataOut.channelList = self.dataIn.channelList
45 46 #self.dataOut.timeInterval = self.dataIn.timeInterval
46 47 self.dataOut.heightList = self.dataIn.heightList
47 48 self.dataOut.nProfiles = self.dataIn.nProfiles
48 49
49 50 self.dataOut.nCohInt = self.dataIn.nCohInt
50 51 self.dataOut.ippSeconds = self.dataIn.ippSeconds
51 52 self.dataOut.frequency = self.dataIn.frequency
52 53
53 54 self.dataOut.azimuth = self.dataIn.azimuth
54 55 self.dataOut.zenith = self.dataIn.zenith
55 56
56 57 self.dataOut.beam.codeList = self.dataIn.beam.codeList
57 58 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
58 59 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
59 60
60 61
61 62 class selectChannels(Operation):
62 63
63 64 def run(self, dataOut, channelList=None):
64 65 self.channelList = channelList
65 66 if self.channelList == None:
66 67 print("Missing channelList")
67 68 return dataOut
68 69 channelIndexList = []
69 70
70 71 if type(dataOut.channelList) is not list: #leer array desde HDF5
71 72 try:
72 73 dataOut.channelList = dataOut.channelList.tolist()
73 74 except Exception as e:
74 75 print("Select Channels: ",e)
75 76 for channel in self.channelList:
76 77 if channel not in dataOut.channelList:
77 78 raise ValueError("Channel %d is not in %s" %(channel, str(dataOut.channelList)))
78 79
79 80 index = dataOut.channelList.index(channel)
80 81 channelIndexList.append(index)
81 82 dataOut = self.selectChannelsByIndex(dataOut,channelIndexList)
82 83 return dataOut
83 84
84 85 def selectChannelsByIndex(self, dataOut, channelIndexList):
85 86 """
86 87 Selecciona un bloque de datos en base a canales segun el channelIndexList
87 88
88 89 Input:
89 90 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
90 91
91 92 Affected:
92 93 dataOut.data
93 94 dataOut.channelIndexList
94 95 dataOut.nChannels
95 96 dataOut.m_ProcessingHeader.totalSpectra
96 97 dataOut.systemHeaderObj.numChannels
97 98 dataOut.m_ProcessingHeader.blockSize
98 99
99 100 Return:
100 101 None
101 102 """
102 103 #print("selectChannelsByIndex")
103 104 # for channelIndex in channelIndexList:
104 105 # if channelIndex not in dataOut.channelIndexList:
105 106 # raise ValueError("The value %d in channelIndexList is not valid" %channelIndex)
106 107
107 108 if dataOut.type == 'Voltage':
108 109 if dataOut.flagDataAsBlock:
109 110 """
110 111 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
111 112 """
112 113 data = dataOut.data[channelIndexList,:,:]
113 114 else:
114 115 data = dataOut.data[channelIndexList,:]
115 116
116 117 dataOut.data = data
117 118 # dataOut.channelList = [dataOut.channelList[i] for i in channelIndexList]
118 119 dataOut.channelList = range(len(channelIndexList))
119 120
120 121 elif dataOut.type == 'Spectra':
121 122 if hasattr(dataOut, 'data_spc'):
122 123 if dataOut.data_spc is None:
123 124 raise ValueError("data_spc is None")
124 125 return dataOut
125 126 else:
126 127 data_spc = dataOut.data_spc[channelIndexList, :]
127 128 dataOut.data_spc = data_spc
128 129
129 130 # if hasattr(dataOut, 'data_dc') :# and
130 131 # if dataOut.data_dc is None:
131 132 # raise ValueError("data_dc is None")
132 133 # return dataOut
133 134 # else:
134 135 # data_dc = dataOut.data_dc[channelIndexList, :]
135 136 # dataOut.data_dc = data_dc
136 137 # dataOut.channelList = [dataOut.channelList[i] for i in channelIndexList]
137 138 dataOut.channelList = channelIndexList
138 139 dataOut = self.__selectPairsByChannel(dataOut,channelIndexList)
139 140
140 141 return dataOut
141 142
142 143 def __selectPairsByChannel(self, dataOut, channelList=None):
143 144 #print("__selectPairsByChannel")
144 145 if channelList == None:
145 146 return
146 147
147 148 pairsIndexListSelected = []
148 149 for pairIndex in dataOut.pairsIndexList:
149 150 # First pair
150 151 if dataOut.pairsList[pairIndex][0] not in channelList:
151 152 continue
152 153 # Second pair
153 154 if dataOut.pairsList[pairIndex][1] not in channelList:
154 155 continue
155 156
156 157 pairsIndexListSelected.append(pairIndex)
157 158 if not pairsIndexListSelected:
158 159 dataOut.data_cspc = None
159 160 dataOut.pairsList = []
160 161 return
161 162
162 163 dataOut.data_cspc = dataOut.data_cspc[pairsIndexListSelected]
163 164 dataOut.pairsList = [dataOut.pairsList[i]
164 165 for i in pairsIndexListSelected]
165 166
166 167 return dataOut
167 168
168 169 class selectHeights(Operation):
169 170
170 171 def run(self, dataOut, minHei=None, maxHei=None, minIndex=None, maxIndex=None):
171 172 """
172 173 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
173 174 minHei <= height <= maxHei
174 175
175 176 Input:
176 177 minHei : valor minimo de altura a considerar
177 178 maxHei : valor maximo de altura a considerar
178 179
179 180 Affected:
180 181 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
181 182
182 183 Return:
183 184 1 si el metodo se ejecuto con exito caso contrario devuelve 0
184 185 """
185 186
186 187 self.dataOut = dataOut
187 188
188 189 if minHei and maxHei:
189 190
190 191 if (minHei < dataOut.heightList[0]):
191 192 minHei = dataOut.heightList[0]
192 193
193 194 if (maxHei > dataOut.heightList[-1]):
194 195 maxHei = dataOut.heightList[-1]
195 196
196 197 minIndex = 0
197 198 maxIndex = 0
198 199 heights = dataOut.heightList
199 200
200 201 inda = numpy.where(heights >= minHei)
201 202 indb = numpy.where(heights <= maxHei)
202 203
203 204 try:
204 205 minIndex = inda[0][0]
205 206 except:
206 207 minIndex = 0
207 208
208 209 try:
209 210 maxIndex = indb[0][-1]
210 211 except:
211 212 maxIndex = len(heights)
212 213
213 214 self.selectHeightsByIndex(minIndex, maxIndex)
214 215
215 216 return dataOut
216 217
217 218 def selectHeightsByIndex(self, minIndex, maxIndex):
218 219 """
219 220 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
220 221 minIndex <= index <= maxIndex
221 222
222 223 Input:
223 224 minIndex : valor de indice minimo de altura a considerar
224 225 maxIndex : valor de indice maximo de altura a considerar
225 226
226 227 Affected:
227 228 self.dataOut.data
228 229 self.dataOut.heightList
229 230
230 231 Return:
231 232 1 si el metodo se ejecuto con exito caso contrario devuelve 0
232 233 """
233 234
234 235 if self.dataOut.type == 'Voltage':
235 236 if (minIndex < 0) or (minIndex > maxIndex):
236 237 raise ValueError("Height index range (%d,%d) is not valid" % (minIndex, maxIndex))
237 238
238 239 if (maxIndex >= self.dataOut.nHeights):
239 240 maxIndex = self.dataOut.nHeights
240 241
241 242 #voltage
242 243 if self.dataOut.flagDataAsBlock:
243 244 """
244 245 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
245 246 """
246 247 data = self.dataOut.data[:,:, minIndex:maxIndex]
247 248 else:
248 249 data = self.dataOut.data[:, minIndex:maxIndex]
249 250
250 251 # firstHeight = self.dataOut.heightList[minIndex]
251 252
252 253 self.dataOut.data = data
253 254 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
254 255
255 256 if self.dataOut.nHeights <= 1:
256 257 raise ValueError("selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights))
257 258 elif self.dataOut.type == 'Spectra':
258 259 if (minIndex < 0) or (minIndex > maxIndex):
259 260 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (
260 261 minIndex, maxIndex))
261 262
262 263 if (maxIndex >= self.dataOut.nHeights):
263 264 maxIndex = self.dataOut.nHeights - 1
264 265
265 266 # Spectra
266 267 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
267 268
268 269 data_cspc = None
269 270 if self.dataOut.data_cspc is not None:
270 271 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
271 272
272 273 data_dc = None
273 274 if self.dataOut.data_dc is not None:
274 275 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
275 276
276 277 self.dataOut.data_spc = data_spc
277 278 self.dataOut.data_cspc = data_cspc
278 279 self.dataOut.data_dc = data_dc
279 280
280 281 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
281 282
282 283 return 1
283 284
284 285
285 286 class filterByHeights(Operation):
286 287
287 288 def run(self, dataOut, window):
288 289
289 290 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
290 291
291 292 if window == None:
292 293 window = (dataOut.radarControllerHeaderObj.txA/dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
293 294
294 295 newdelta = deltaHeight * window
295 296 r = dataOut.nHeights % window
296 297 newheights = (dataOut.nHeights-r)/window
297 298
298 299 if newheights <= 1:
299 300 raise ValueError("filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(dataOut.nHeights, window))
300 301
301 302 if dataOut.flagDataAsBlock:
302 303 """
303 304 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
304 305 """
305 306 buffer = dataOut.data[:, :, 0:int(dataOut.nHeights-r)]
306 307 buffer = buffer.reshape(dataOut.nChannels, dataOut.nProfiles, int(dataOut.nHeights/window), window)
307 308 buffer = numpy.sum(buffer,3)
308 309
309 310 else:
310 311 buffer = dataOut.data[:,0:int(dataOut.nHeights-r)]
311 312 buffer = buffer.reshape(dataOut.nChannels,int(dataOut.nHeights/window),int(window))
312 313 buffer = numpy.sum(buffer,2)
313 314
314 315 dataOut.data = buffer
315 316 dataOut.heightList = dataOut.heightList[0] + numpy.arange( newheights )*newdelta
316 317 dataOut.windowOfFilter = window
317 318
318 319 return dataOut
319 320
320 321
321 322 class setH0(Operation):
322 323
323 324 def run(self, dataOut, h0, deltaHeight = None):
324 325
325 326 if not deltaHeight:
326 327 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
327 328
328 329 nHeights = dataOut.nHeights
329 330
330 331 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
331 332
332 333 dataOut.heightList = newHeiRange
333 334
334 335 return dataOut
335 336
336 337
337 338 class deFlip(Operation):
338 339
339 340 def run(self, dataOut, channelList = []):
340 341
341 342 data = dataOut.data.copy()
342 343
343 344 if dataOut.flagDataAsBlock:
344 345 flip = self.flip
345 346 profileList = list(range(dataOut.nProfiles))
346 347
347 348 if not channelList:
348 349 for thisProfile in profileList:
349 350 data[:,thisProfile,:] = data[:,thisProfile,:]*flip
350 351 flip *= -1.0
351 352 else:
352 353 for thisChannel in channelList:
353 354 if thisChannel not in dataOut.channelList:
354 355 continue
355 356
356 357 for thisProfile in profileList:
357 358 data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip
358 359 flip *= -1.0
359 360
360 361 self.flip = flip
361 362
362 363 else:
363 364 if not channelList:
364 365 data[:,:] = data[:,:]*self.flip
365 366 else:
366 367 for thisChannel in channelList:
367 368 if thisChannel not in dataOut.channelList:
368 369 continue
369 370
370 371 data[thisChannel,:] = data[thisChannel,:]*self.flip
371 372
372 373 self.flip *= -1.
373 374
374 375 dataOut.data = data
375 376
376 377 return dataOut
377 378
378 379
379 380 class setAttribute(Operation):
380 381 '''
381 382 Set an arbitrary attribute(s) to dataOut
382 383 '''
383 384
384 385 def __init__(self):
385 386
386 387 Operation.__init__(self)
387 388 self._ready = False
388 389
389 390 def run(self, dataOut, **kwargs):
390 391
391 392 for key, value in kwargs.items():
392 393 setattr(dataOut, key, value)
393 394
394 395 return dataOut
395 396
396 397
397 398 @MPDecorator
398 399 class printAttribute(Operation):
399 400 '''
400 401 Print an arbitrary attribute of dataOut
401 402 '''
402 403
403 404 def __init__(self):
404 405
405 406 Operation.__init__(self)
406 407
407 408 def run(self, dataOut, attributes):
408 409
409 410 if isinstance(attributes, str):
410 411 attributes = [attributes]
411 412 for attr in attributes:
412 413 if hasattr(dataOut, attr):
413 414 log.log(getattr(dataOut, attr), attr)
414 415
415 416
416 417 class interpolateHeights(Operation):
417 418
418 419 def run(self, dataOut, topLim, botLim):
419 420 #69 al 72 para julia
420 421 #82-84 para meteoros
421 422 if len(numpy.shape(dataOut.data))==2:
422 423 sampInterp = (dataOut.data[:,botLim-1] + dataOut.data[:,topLim+1])/2
423 424 sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1)))
424 425 #dataOut.data[:,botLim:limSup+1] = sampInterp
425 426 dataOut.data[:,botLim:topLim+1] = sampInterp
426 427 else:
427 428 nHeights = dataOut.data.shape[2]
428 429 x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights)))
429 430 y = dataOut.data[:,:,list(range(botLim))+list(range(topLim+1,nHeights))]
430 431 f = interpolate.interp1d(x, y, axis = 2)
431 432 xnew = numpy.arange(botLim,topLim+1)
432 433 ynew = f(xnew)
433 434 dataOut.data[:,:,botLim:topLim+1] = ynew
434 435
435 436 return dataOut
436 437
437 438
438 439 class CohInt(Operation):
439 440
440 441 isConfig = False
441 442 __profIndex = 0
442 443 __byTime = False
443 444 __initime = None
444 445 __lastdatatime = None
445 446 __integrationtime = None
446 447 __buffer = None
447 448 __bufferStride = []
448 449 __dataReady = False
449 450 __profIndexStride = 0
450 451 __dataToPutStride = False
451 452 n = None
452 453
453 454 def __init__(self, **kwargs):
454 455
455 456 Operation.__init__(self, **kwargs)
456 457
457 458 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
458 459 """
459 460 Set the parameters of the integration class.
460 461
461 462 Inputs:
462 463
463 464 n : Number of coherent integrations
464 465 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
465 466 overlapping :
466 467 """
467 468
468 469 self.__initime = None
469 470 self.__lastdatatime = 0
470 471 self.__buffer = None
471 472 self.__dataReady = False
472 473 self.byblock = byblock
473 474 self.stride = stride
474 475
475 476 if n == None and timeInterval == None:
476 477 raise ValueError("n or timeInterval should be specified ...")
477 478
478 479 if n != None:
479 480 self.n = n
480 481 self.__byTime = False
481 482 else:
482 483 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
483 484 self.n = 9999
484 485 self.__byTime = True
485 486
486 487 if overlapping:
487 488 self.__withOverlapping = True
488 489 self.__buffer = None
489 490 else:
490 491 self.__withOverlapping = False
491 492 self.__buffer = 0
492 493
493 494 self.__profIndex = 0
494 495
495 496 def putData(self, data):
496 497
497 498 """
498 499 Add a profile to the __buffer and increase in one the __profileIndex
499 500
500 501 """
501 502
502 503 if not self.__withOverlapping:
503 504 self.__buffer += data.copy()
504 505 self.__profIndex += 1
505 506 return
506 507
507 508 #Overlapping data
508 509 nChannels, nHeis = data.shape
509 510 data = numpy.reshape(data, (1, nChannels, nHeis))
510 511
511 512 #If the buffer is empty then it takes the data value
512 513 if self.__buffer is None:
513 514 self.__buffer = data
514 515 self.__profIndex += 1
515 516 return
516 517
517 518 #If the buffer length is lower than n then stakcing the data value
518 519 if self.__profIndex < self.n:
519 520 self.__buffer = numpy.vstack((self.__buffer, data))
520 521 self.__profIndex += 1
521 522 return
522 523
523 524 #If the buffer length is equal to n then replacing the last buffer value with the data value
524 525 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
525 526 self.__buffer[self.n-1] = data
526 527 self.__profIndex = self.n
527 528 return
528 529
529 530
530 531 def pushData(self):
531 532 """
532 533 Return the sum of the last profiles and the profiles used in the sum.
533 534
534 535 Affected:
535 536
536 537 self.__profileIndex
537 538
538 539 """
539 540
540 541 if not self.__withOverlapping:
541 542 data = self.__buffer
542 543 n = self.__profIndex
543 544
544 545 self.__buffer = 0
545 546 self.__profIndex = 0
546 547
547 548 return data, n
548 549
549 550 #Integration with Overlapping
550 551 data = numpy.sum(self.__buffer, axis=0)
551 552 # print data
552 553 # raise
553 554 n = self.__profIndex
554 555
555 556 return data, n
556 557
557 558 def byProfiles(self, data):
558 559
559 560 self.__dataReady = False
560 561 avgdata = None
561 562 # n = None
562 563 # print data
563 564 # raise
564 565 self.putData(data)
565 566
566 567 if self.__profIndex == self.n:
567 568 avgdata, n = self.pushData()
568 569 self.__dataReady = True
569 570
570 571 return avgdata
571 572
572 573 def byTime(self, data, datatime):
573 574
574 575 self.__dataReady = False
575 576 avgdata = None
576 577 n = None
577 578
578 579 self.putData(data)
579 580
580 581 if (datatime - self.__initime) >= self.__integrationtime:
581 582 avgdata, n = self.pushData()
582 583 self.n = n
583 584 self.__dataReady = True
584 585
585 586 return avgdata
586 587
587 588 def integrateByStride(self, data, datatime):
588 589 # print data
589 590 if self.__profIndex == 0:
590 591 self.__buffer = [[data.copy(), datatime]]
591 592 else:
592 593 self.__buffer.append([data.copy(),datatime])
593 594 self.__profIndex += 1
594 595 self.__dataReady = False
595 596
596 597 if self.__profIndex == self.n * self.stride :
597 598 self.__dataToPutStride = True
598 599 self.__profIndexStride = 0
599 600 self.__profIndex = 0
600 601 self.__bufferStride = []
601 602 for i in range(self.stride):
602 603 current = self.__buffer[i::self.stride]
603 604 data = numpy.sum([t[0] for t in current], axis=0)
604 605 avgdatatime = numpy.average([t[1] for t in current])
605 606 # print data
606 607 self.__bufferStride.append((data, avgdatatime))
607 608
608 609 if self.__dataToPutStride:
609 610 self.__dataReady = True
610 611 self.__profIndexStride += 1
611 612 if self.__profIndexStride == self.stride:
612 613 self.__dataToPutStride = False
613 614 # print self.__bufferStride[self.__profIndexStride - 1]
614 615 # raise
615 616 return self.__bufferStride[self.__profIndexStride - 1]
616 617
617 618
618 619 return None, None
619 620
620 621 def integrate(self, data, datatime=None):
621 622
622 623 if self.__initime == None:
623 624 self.__initime = datatime
624 625
625 626 if self.__byTime:
626 627 avgdata = self.byTime(data, datatime)
627 628 else:
628 629 avgdata = self.byProfiles(data)
629 630
630 631
631 632 self.__lastdatatime = datatime
632 633
633 634 if avgdata is None:
634 635 return None, None
635 636
636 637 avgdatatime = self.__initime
637 638
638 639 deltatime = datatime - self.__lastdatatime
639 640
640 641 if not self.__withOverlapping:
641 642 self.__initime = datatime
642 643 else:
643 644 self.__initime += deltatime
644 645
645 646 return avgdata, avgdatatime
646 647
647 648 def integrateByBlock(self, dataOut):
648 649
649 650 times = int(dataOut.data.shape[1]/self.n)
650 651 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
651 652
652 653 id_min = 0
653 654 id_max = self.n
654 655
655 656 for i in range(times):
656 657 junk = dataOut.data[:,id_min:id_max,:]
657 658 avgdata[:,i,:] = junk.sum(axis=1)
658 659 id_min += self.n
659 660 id_max += self.n
660 661
661 662 timeInterval = dataOut.ippSeconds*self.n
662 663 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
663 664 self.__dataReady = True
664 665 return avgdata, avgdatatime
665 666
666 667 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
667 668
668 669 if not self.isConfig:
669 670 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
670 671 self.isConfig = True
671 672
672 673 if dataOut.flagDataAsBlock:
673 674 """
674 675 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
675 676 """
676 677 avgdata, avgdatatime = self.integrateByBlock(dataOut)
677 678 dataOut.nProfiles /= self.n
678 679 else:
679 680 if stride is None:
680 681 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
681 682 else:
682 683 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
683 684
684 685
685 686 # dataOut.timeInterval *= n
686 687 dataOut.flagNoData = True
687 688
688 689 if self.__dataReady:
689 690 dataOut.data = avgdata
690 691 if not dataOut.flagCohInt:
691 692 dataOut.nCohInt *= self.n
692 693 dataOut.flagCohInt = True
693 694 dataOut.utctime = avgdatatime
694 695 # print avgdata, avgdatatime
695 696 # raise
696 697 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
697 698 dataOut.flagNoData = False
698 699 return dataOut
699 700
700 701 class Decoder(Operation):
701 702
702 703 isConfig = False
703 704 __profIndex = 0
704 705
705 706 code = None
706 707
707 708 nCode = None
708 709 nBaud = None
709 710
710 711 def __init__(self, **kwargs):
711 712
712 713 Operation.__init__(self, **kwargs)
713 714
714 715 self.times = None
715 716 self.osamp = None
716 717 # self.__setValues = False
717 718 self.isConfig = False
718 719 self.setupReq = False
719 720 def setup(self, code, osamp, dataOut):
720 721
721 722 self.__profIndex = 0
722 723
723 724 self.code = code
724 725
725 726 self.nCode = len(code)
726 727 self.nBaud = len(code[0])
727 728 if (osamp != None) and (osamp >1):
728 729 self.osamp = osamp
729 730 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
730 731 self.nBaud = self.nBaud*self.osamp
731 732
732 733 self.__nChannels = dataOut.nChannels
733 734 self.__nProfiles = dataOut.nProfiles
734 735 self.__nHeis = dataOut.nHeights
735 736
736 737 if self.__nHeis < self.nBaud:
737 738 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
738 739
739 740 #Frequency
740 741 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
741 742
742 743 __codeBuffer[:,0:self.nBaud] = self.code
743 744
744 745 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
745 746
746 747 if dataOut.flagDataAsBlock:
747 748
748 749 self.ndatadec = self.__nHeis #- self.nBaud + 1
749 750
750 751 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
751 752
752 753 else:
753 754
754 755 #Time
755 756 self.ndatadec = self.__nHeis #- self.nBaud + 1
756 757
757 758 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
758 759
759 760 def __convolutionInFreq(self, data):
760 761
761 762 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
762 763
763 764 fft_data = numpy.fft.fft(data, axis=1)
764 765
765 766 conv = fft_data*fft_code
766 767
767 768 data = numpy.fft.ifft(conv,axis=1)
768 769
769 770 return data
770 771
771 772 def __convolutionInFreqOpt(self, data):
772 773
773 774 raise NotImplementedError
774 775
775 776 def __convolutionInTime(self, data):
776 777
777 778 code = self.code[self.__profIndex]
778 779 for i in range(self.__nChannels):
779 780 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
780 781
781 782 return self.datadecTime
782 783
783 784 def __convolutionByBlockInTime(self, data):
784 785
785 786 repetitions = int(self.__nProfiles / self.nCode)
786 787 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
787 788 junk = junk.flatten()
788 789 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
789 790 profilesList = range(self.__nProfiles)
790 791
791 792 for i in range(self.__nChannels):
792 793 for j in profilesList:
793 794 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
794 795 return self.datadecTime
795 796
796 797 def __convolutionByBlockInFreq(self, data):
797 798
798 799 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
799 800
800 801
801 802 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
802 803
803 804 fft_data = numpy.fft.fft(data, axis=2)
804 805
805 806 conv = fft_data*fft_code
806 807
807 808 data = numpy.fft.ifft(conv,axis=2)
808 809
809 810 return data
810 811
811 812
812 813 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
813 814
814 815 if dataOut.flagDecodeData:
815 816 print("This data is already decoded, recoding again ...")
816 817
817 818 if not self.isConfig:
818 819
819 820 if code is None:
820 821 if dataOut.code is None:
821 822 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
822 823
823 824 code = dataOut.code
824 825 else:
825 826 code = numpy.array(code).reshape(nCode,nBaud)
826 827 self.setup(code, osamp, dataOut)
827 828
828 829 self.isConfig = True
829 830
830 831 if mode == 3:
831 832 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
832 833
833 834 if times != None:
834 835 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
835 836
836 837 if self.code is None:
837 838 print("Fail decoding: Code is not defined.")
838 839 return
839 840
840 841 self.__nProfiles = dataOut.nProfiles
841 842 datadec = None
842 843
843 844 if mode == 3:
844 845 mode = 0
845 846
846 847 if dataOut.flagDataAsBlock:
847 848 """
848 849 Decoding when data have been read as block,
849 850 """
850 851
851 852 if mode == 0:
852 853 datadec = self.__convolutionByBlockInTime(dataOut.data)
853 854 if mode == 1:
854 855 datadec = self.__convolutionByBlockInFreq(dataOut.data)
855 856 else:
856 857 """
857 858 Decoding when data have been read profile by profile
858 859 """
859 860 if mode == 0:
860 861 datadec = self.__convolutionInTime(dataOut.data)
861 862
862 863 if mode == 1:
863 864 datadec = self.__convolutionInFreq(dataOut.data)
864 865
865 866 if mode == 2:
866 867 datadec = self.__convolutionInFreqOpt(dataOut.data)
867 868
868 869 if datadec is None:
869 870 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
870 871
871 872 dataOut.code = self.code
872 873 dataOut.nCode = self.nCode
873 874 dataOut.nBaud = self.nBaud
874 875
875 876 dataOut.data = datadec
876 877
877 878 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
878 879
879 880 dataOut.flagDecodeData = True #asumo q la data esta decodificada
880 881
881 882 if self.__profIndex == self.nCode-1:
882 883 self.__profIndex = 0
883 884 return dataOut
884 885
885 886 self.__profIndex += 1
886 887
887 888 return dataOut
888 889 # dataOut.flagDeflipData = True #asumo q la data no esta sin flip
889 890
890 891
891 892 class ProfileConcat(Operation):
892 893
893 894 isConfig = False
894 895 buffer = None
895 896
896 897 def __init__(self, **kwargs):
897 898
898 899 Operation.__init__(self, **kwargs)
899 900 self.profileIndex = 0
900 901
901 902 def reset(self):
902 903 self.buffer = numpy.zeros_like(self.buffer)
903 904 self.start_index = 0
904 905 self.times = 1
905 906
906 907 def setup(self, data, m, n=1):
907 908 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
908 909 self.nHeights = data.shape[1]#.nHeights
909 910 self.start_index = 0
910 911 self.times = 1
911 912
912 913 def concat(self, data):
913 914
914 915 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
915 916 self.start_index = self.start_index + self.nHeights
916 917
917 918 def run(self, dataOut, m):
918 919 dataOut.flagNoData = True
919 920
920 921 if not self.isConfig:
921 922 self.setup(dataOut.data, m, 1)
922 923 self.isConfig = True
923 924
924 925 if dataOut.flagDataAsBlock:
925 926 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
926 927
927 928 else:
928 929 self.concat(dataOut.data)
929 930 self.times += 1
930 931 if self.times > m:
931 932 dataOut.data = self.buffer
932 933 self.reset()
933 934 dataOut.flagNoData = False
934 935 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
935 936 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
936 937 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
937 938 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
938 939 dataOut.ippSeconds *= m
939 940 return dataOut
940 941
941 942 class ProfileSelector(Operation):
942 943
943 944 profileIndex = None
944 945 # Tamanho total de los perfiles
945 946 nProfiles = None
946 947
947 948 def __init__(self, **kwargs):
948 949
949 950 Operation.__init__(self, **kwargs)
950 951 self.profileIndex = 0
951 952
952 953 def incProfileIndex(self):
953 954
954 955 self.profileIndex += 1
955 956
956 957 if self.profileIndex >= self.nProfiles:
957 958 self.profileIndex = 0
958 959
959 960 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
960 961
961 962 if profileIndex < minIndex:
962 963 return False
963 964
964 965 if profileIndex > maxIndex:
965 966 return False
966 967
967 968 return True
968 969
969 970 def isThisProfileInList(self, profileIndex, profileList):
970 971
971 972 if profileIndex not in profileList:
972 973 return False
973 974
974 975 return True
975 976
976 977 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
977 978
978 979 """
979 980 ProfileSelector:
980 981
981 982 Inputs:
982 983 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
983 984
984 985 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
985 986
986 987 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
987 988
988 989 """
989 990
990 991 if rangeList is not None:
991 992 if type(rangeList[0]) not in (tuple, list):
992 993 rangeList = [rangeList]
993 994
994 995 dataOut.flagNoData = True
995 996
996 997 if dataOut.flagDataAsBlock:
997 998 """
998 999 data dimension = [nChannels, nProfiles, nHeis]
999 1000 """
1000 1001 if profileList != None:
1001 1002 dataOut.data = dataOut.data[:,profileList,:]
1002 1003
1003 1004 if profileRangeList != None:
1004 1005 minIndex = profileRangeList[0]
1005 1006 maxIndex = profileRangeList[1]
1006 1007 profileList = list(range(minIndex, maxIndex+1))
1007 1008
1008 1009 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
1009 1010
1010 1011 if rangeList != None:
1011 1012
1012 1013 profileList = []
1013 1014
1014 1015 for thisRange in rangeList:
1015 1016 minIndex = thisRange[0]
1016 1017 maxIndex = thisRange[1]
1017 1018
1018 1019 profileList.extend(list(range(minIndex, maxIndex+1)))
1019 1020
1020 1021 dataOut.data = dataOut.data[:,profileList,:]
1021 1022
1022 1023 dataOut.nProfiles = len(profileList)
1023 1024 dataOut.profileIndex = dataOut.nProfiles - 1
1024 1025 dataOut.flagNoData = False
1025 1026
1026 1027 return dataOut
1027 1028
1028 1029 """
1029 1030 data dimension = [nChannels, nHeis]
1030 1031 """
1031 1032
1032 1033 if profileList != None:
1033 1034
1034 1035 if self.isThisProfileInList(dataOut.profileIndex, profileList):
1035 1036
1036 1037 self.nProfiles = len(profileList)
1037 1038 dataOut.nProfiles = self.nProfiles
1038 1039 dataOut.profileIndex = self.profileIndex
1039 1040 dataOut.flagNoData = False
1040 1041
1041 1042 self.incProfileIndex()
1042 1043 return dataOut
1043 1044
1044 1045 if profileRangeList != None:
1045 1046
1046 1047 minIndex = profileRangeList[0]
1047 1048 maxIndex = profileRangeList[1]
1048 1049
1049 1050 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1050 1051
1051 1052 self.nProfiles = maxIndex - minIndex + 1
1052 1053 dataOut.nProfiles = self.nProfiles
1053 1054 dataOut.profileIndex = self.profileIndex
1054 1055 dataOut.flagNoData = False
1055 1056
1056 1057 self.incProfileIndex()
1057 1058 return dataOut
1058 1059
1059 1060 if rangeList != None:
1060 1061
1061 1062 nProfiles = 0
1062 1063
1063 1064 for thisRange in rangeList:
1064 1065 minIndex = thisRange[0]
1065 1066 maxIndex = thisRange[1]
1066 1067
1067 1068 nProfiles += maxIndex - minIndex + 1
1068 1069
1069 1070 for thisRange in rangeList:
1070 1071
1071 1072 minIndex = thisRange[0]
1072 1073 maxIndex = thisRange[1]
1073 1074
1074 1075 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1075 1076
1076 1077 self.nProfiles = nProfiles
1077 1078 dataOut.nProfiles = self.nProfiles
1078 1079 dataOut.profileIndex = self.profileIndex
1079 1080 dataOut.flagNoData = False
1080 1081
1081 1082 self.incProfileIndex()
1082 1083
1083 1084 break
1084 1085
1085 1086 return dataOut
1086 1087
1087 1088
1088 1089 if beam != None: #beam is only for AMISR data
1089 1090 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
1090 1091 dataOut.flagNoData = False
1091 1092 dataOut.profileIndex = self.profileIndex
1092 1093
1093 1094 self.incProfileIndex()
1094 1095
1095 1096 return dataOut
1096 1097
1097 1098 raise ValueError("ProfileSelector needs profileList, profileRangeList or rangeList parameter")
1098 1099
1099 1100
1100 1101 class Reshaper(Operation):
1101 1102
1102 1103 def __init__(self, **kwargs):
1103 1104
1104 1105 Operation.__init__(self, **kwargs)
1105 1106
1106 1107 self.__buffer = None
1107 1108 self.__nitems = 0
1108 1109
1109 1110 def __appendProfile(self, dataOut, nTxs):
1110 1111
1111 1112 if self.__buffer is None:
1112 1113 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
1113 1114 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
1114 1115
1115 1116 ini = dataOut.nHeights * self.__nitems
1116 1117 end = ini + dataOut.nHeights
1117 1118
1118 1119 self.__buffer[:, ini:end] = dataOut.data
1119 1120
1120 1121 self.__nitems += 1
1121 1122
1122 1123 return int(self.__nitems*nTxs)
1123 1124
1124 1125 def __getBuffer(self):
1125 1126
1126 1127 if self.__nitems == int(1./self.__nTxs):
1127 1128
1128 1129 self.__nitems = 0
1129 1130
1130 1131 return self.__buffer.copy()
1131 1132
1132 1133 return None
1133 1134
1134 1135 def __checkInputs(self, dataOut, shape, nTxs):
1135 1136
1136 1137 if shape is None and nTxs is None:
1137 1138 raise ValueError("Reshaper: shape of factor should be defined")
1138 1139
1139 1140 if nTxs:
1140 1141 if nTxs < 0:
1141 1142 raise ValueError("nTxs should be greater than 0")
1142 1143
1143 1144 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
1144 1145 raise ValueError("nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)))
1145 1146
1146 1147 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
1147 1148
1148 1149 return shape, nTxs
1149 1150
1150 1151 if len(shape) != 2 and len(shape) != 3:
1151 1152 raise ValueError("shape dimension should be equal to 2 or 3. shape = (nProfiles, nHeis) or (nChannels, nProfiles, nHeis). Actually shape = (%d, %d, %d)" %(dataOut.nChannels, dataOut.nProfiles, dataOut.nHeights))
1152 1153
1153 1154 if len(shape) == 2:
1154 1155 shape_tuple = [dataOut.nChannels]
1155 1156 shape_tuple.extend(shape)
1156 1157 else:
1157 1158 shape_tuple = list(shape)
1158 1159
1159 1160 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
1160 1161
1161 1162 return shape_tuple, nTxs
1162 1163
1163 1164 def run(self, dataOut, shape=None, nTxs=None):
1164 1165
1165 1166 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
1166 1167
1167 1168 dataOut.flagNoData = True
1168 1169 profileIndex = None
1169 1170
1170 1171 if dataOut.flagDataAsBlock:
1171 1172
1172 1173 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
1173 1174 dataOut.flagNoData = False
1174 1175
1175 1176 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
1176 1177
1177 1178 else:
1178 1179
1179 1180 if self.__nTxs < 1:
1180 1181
1181 1182 self.__appendProfile(dataOut, self.__nTxs)
1182 1183 new_data = self.__getBuffer()
1183 1184
1184 1185 if new_data is not None:
1185 1186 dataOut.data = new_data
1186 1187 dataOut.flagNoData = False
1187 1188
1188 1189 profileIndex = dataOut.profileIndex*nTxs
1189 1190
1190 1191 else:
1191 1192 raise ValueError("nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)")
1192 1193
1193 1194 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1194 1195
1195 1196 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
1196 1197
1197 1198 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
1198 1199
1199 1200 dataOut.profileIndex = profileIndex
1200 1201
1201 1202 dataOut.ippSeconds /= self.__nTxs
1202 1203
1203 1204 return dataOut
1204 1205
1205 1206 class SplitProfiles(Operation):
1206 1207
1207 1208 def __init__(self, **kwargs):
1208 1209
1209 1210 Operation.__init__(self, **kwargs)
1210 1211
1211 1212 def run(self, dataOut, n):
1212 1213
1213 1214 dataOut.flagNoData = True
1214 1215 profileIndex = None
1215 1216
1216 1217 if dataOut.flagDataAsBlock:
1217 1218
1218 1219 #nchannels, nprofiles, nsamples
1219 1220 shape = dataOut.data.shape
1220 1221
1221 1222 if shape[2] % n != 0:
1222 1223 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
1223 1224
1224 1225 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
1225 1226
1226 1227 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1227 1228 dataOut.flagNoData = False
1228 1229
1229 1230 profileIndex = int(dataOut.nProfiles/n) - 1
1230 1231
1231 1232 else:
1232 1233
1233 1234 raise ValueError("Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)")
1234 1235
1235 1236 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1236 1237
1237 1238 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
1238 1239
1239 1240 dataOut.nProfiles = int(dataOut.nProfiles*n)
1240 1241
1241 1242 dataOut.profileIndex = profileIndex
1242 1243
1243 1244 dataOut.ippSeconds /= n
1244 1245
1245 1246 return dataOut
1246 1247
1247 1248 class CombineProfiles(Operation):
1248 1249 def __init__(self, **kwargs):
1249 1250
1250 1251 Operation.__init__(self, **kwargs)
1251 1252
1252 1253 self.__remData = None
1253 1254 self.__profileIndex = 0
1254 1255
1255 1256 def run(self, dataOut, n):
1256 1257
1257 1258 dataOut.flagNoData = True
1258 1259 profileIndex = None
1259 1260
1260 1261 if dataOut.flagDataAsBlock:
1261 1262
1262 1263 #nchannels, nprofiles, nsamples
1263 1264 shape = dataOut.data.shape
1264 1265 new_shape = shape[0], shape[1]/n, shape[2]*n
1265 1266
1266 1267 if shape[1] % n != 0:
1267 1268 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]))
1268 1269
1269 1270 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1270 1271 dataOut.flagNoData = False
1271 1272
1272 1273 profileIndex = int(dataOut.nProfiles*n) - 1
1273 1274
1274 1275 else:
1275 1276
1276 1277 #nchannels, nsamples
1277 1278 if self.__remData is None:
1278 1279 newData = dataOut.data
1279 1280 else:
1280 1281 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
1281 1282
1282 1283 self.__profileIndex += 1
1283 1284
1284 1285 if self.__profileIndex < n:
1285 1286 self.__remData = newData
1286 1287 #continue
1287 1288 return
1288 1289
1289 1290 self.__profileIndex = 0
1290 1291 self.__remData = None
1291 1292
1292 1293 dataOut.data = newData
1293 1294 dataOut.flagNoData = False
1294 1295
1295 1296 profileIndex = dataOut.profileIndex/n
1296 1297
1297 1298
1298 1299 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1299 1300
1300 1301 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
1301 1302
1302 1303 dataOut.nProfiles = int(dataOut.nProfiles/n)
1303 1304
1304 1305 dataOut.profileIndex = profileIndex
1305 1306
1306 1307 dataOut.ippSeconds *= n
1307 1308
1308 1309 return dataOut
1309 1310
1310 1311 class PulsePairVoltage(Operation):
1311 1312 '''
1312 1313 Function PulsePair(Signal Power, Velocity)
1313 1314 The real component of Lag[0] provides Intensity Information
1314 1315 The imag component of Lag[1] Phase provides Velocity Information
1315 1316
1316 1317 Configuration Parameters:
1317 1318 nPRF = Number of Several PRF
1318 1319 theta = Degree Azimuth angel Boundaries
1319 1320
1320 1321 Input:
1321 1322 self.dataOut
1322 1323 lag[N]
1323 1324 Affected:
1324 1325 self.dataOut.spc
1325 1326 '''
1326 1327 isConfig = False
1327 1328 __profIndex = 0
1328 1329 __initime = None
1329 1330 __lastdatatime = None
1330 1331 __buffer = None
1331 1332 noise = None
1332 1333 __dataReady = False
1333 1334 n = None
1334 1335 __nch = 0
1335 1336 __nHeis = 0
1336 1337 removeDC = False
1337 1338 ipp = None
1338 1339 lambda_ = 0
1339 1340
1340 1341 def __init__(self,**kwargs):
1341 1342 Operation.__init__(self,**kwargs)
1342 1343
1343 1344 def setup(self, dataOut, n = None, removeDC=False):
1344 1345 '''
1345 1346 n= Numero de PRF's de entrada
1346 1347 '''
1347 1348 self.__initime = None
1348 1349 self.__lastdatatime = 0
1349 1350 self.__dataReady = False
1350 1351 self.__buffer = 0
1351 1352 self.__profIndex = 0
1352 1353 self.noise = None
1353 1354 self.__nch = dataOut.nChannels
1354 1355 self.__nHeis = dataOut.nHeights
1355 1356 self.removeDC = removeDC
1356 1357 self.lambda_ = 3.0e8/(9345.0e6)
1357 1358 self.ippSec = dataOut.ippSeconds
1358 1359 self.nCohInt = dataOut.nCohInt
1359 1360
1360 1361 if n == None:
1361 1362 raise ValueError("n should be specified.")
1362 1363
1363 1364 if n != None:
1364 1365 if n<2:
1365 1366 raise ValueError("n should be greater than 2")
1366 1367
1367 1368 self.n = n
1368 1369 self.__nProf = n
1369 1370
1370 1371 self.__buffer = numpy.zeros((dataOut.nChannels,
1371 1372 n,
1372 1373 dataOut.nHeights),
1373 1374 dtype='complex')
1374 1375
1375 1376 def putData(self,data):
1376 1377 '''
1377 1378 Add a profile to he __buffer and increase in one the __profiel Index
1378 1379 '''
1379 1380 self.__buffer[:,self.__profIndex,:]= data
1380 1381 self.__profIndex += 1
1381 1382 return
1382 1383
1383 1384 def pushData(self,dataOut):
1384 1385 '''
1385 1386 Return the PULSEPAIR and the profiles used in the operation
1386 1387 Affected : self.__profileIndex
1387 1388 '''
1388 1389 #----------------- Remove DC-----------------------------------
1389 1390 if self.removeDC==True:
1390 1391 mean = numpy.mean(self.__buffer,1)
1391 1392 tmp = mean.reshape(self.__nch,1,self.__nHeis)
1392 1393 dc= numpy.tile(tmp,[1,self.__nProf,1])
1393 1394 self.__buffer = self.__buffer - dc
1394 1395 #------------------Calculo de Potencia ------------------------
1395 1396 pair0 = self.__buffer*numpy.conj(self.__buffer)
1396 1397 pair0 = pair0.real
1397 1398 lag_0 = numpy.sum(pair0,1)
1398 1399 #------------------Calculo de Ruido x canal--------------------
1399 1400 self.noise = numpy.zeros(self.__nch)
1400 1401 for i in range(self.__nch):
1401 1402 daux = numpy.sort(pair0[i,:,:],axis= None)
1402 1403 self.noise[i]=hildebrand_sekhon( daux ,self.nCohInt)
1403 1404
1404 1405 self.noise = self.noise.reshape(self.__nch,1)
1405 1406 self.noise = numpy.tile(self.noise,[1,self.__nHeis])
1406 1407 noise_buffer = self.noise.reshape(self.__nch,1,self.__nHeis)
1407 1408 noise_buffer = numpy.tile(noise_buffer,[1,self.__nProf,1])
1408 1409 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
1409 1410 #------------------ P= S+N ,P=lag_0/N ---------------------------------
1410 1411 #-------------------- Power --------------------------------------------------
1411 1412 data_power = lag_0/(self.n*self.nCohInt)
1412 1413 #------------------ Senal ---------------------------------------------------
1413 1414 data_intensity = pair0 - noise_buffer
1414 1415 data_intensity = numpy.sum(data_intensity,axis=1)*(self.n*self.nCohInt)#*self.nCohInt)
1415 1416 #data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
1416 1417 for i in range(self.__nch):
1417 1418 for j in range(self.__nHeis):
1418 1419 if data_intensity[i][j] < 0:
1419 1420 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
1420 1421
1421 1422 #----------------- Calculo de Frecuencia y Velocidad doppler--------
1422 1423 pair1 = self.__buffer[:,:-1,:]*numpy.conjugate(self.__buffer[:,1:,:])
1423 1424 lag_1 = numpy.sum(pair1,1)
1424 1425 data_freq = (-1/(2.0*math.pi*self.ippSec*self.nCohInt))*numpy.angle(lag_1)
1425 1426 data_velocity = (self.lambda_/2.0)*data_freq
1426 1427
1427 1428 #---------------- Potencia promedio estimada de la Senal-----------
1428 1429 lag_0 = lag_0/self.n
1429 1430 S = lag_0-self.noise
1430 1431
1431 1432 #---------------- Frecuencia Doppler promedio ---------------------
1432 1433 lag_1 = lag_1/(self.n-1)
1433 1434 R1 = numpy.abs(lag_1)
1434 1435
1435 1436 #---------------- Calculo del SNR----------------------------------
1436 1437 data_snrPP = S/self.noise
1437 1438 for i in range(self.__nch):
1438 1439 for j in range(self.__nHeis):
1439 1440 if data_snrPP[i][j] < 1.e-20:
1440 1441 data_snrPP[i][j] = 1.e-20
1441 1442
1442 1443 #----------------- Calculo del ancho espectral ----------------------
1443 1444 L = S/R1
1444 1445 L = numpy.where(L<0,1,L)
1445 1446 L = numpy.log(L)
1446 1447 tmp = numpy.sqrt(numpy.absolute(L))
1447 1448 data_specwidth = (self.lambda_/(2*math.sqrt(2)*math.pi*self.ippSec*self.nCohInt))*tmp*numpy.sign(L)
1448 1449 n = self.__profIndex
1449 1450
1450 1451 self.__buffer = numpy.zeros((self.__nch, self.__nProf,self.__nHeis), dtype='complex')
1451 1452 self.__profIndex = 0
1452 1453 return data_power,data_intensity,data_velocity,data_snrPP,data_specwidth,n
1453 1454
1454 1455
1455 1456 def pulsePairbyProfiles(self,dataOut):
1456 1457
1457 1458 self.__dataReady = False
1458 1459 data_power = None
1459 1460 data_intensity = None
1460 1461 data_velocity = None
1461 1462 data_specwidth = None
1462 1463 data_snrPP = None
1463 1464 self.putData(data=dataOut.data)
1464 1465 if self.__profIndex == self.n:
1465 1466 data_power,data_intensity, data_velocity,data_snrPP,data_specwidth, n = self.pushData(dataOut=dataOut)
1466 1467 self.__dataReady = True
1467 1468
1468 1469 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth
1469 1470
1470 1471
1471 1472 def pulsePairOp(self, dataOut, datatime= None):
1472 1473
1473 1474 if self.__initime == None:
1474 1475 self.__initime = datatime
1475 1476 data_power, data_intensity, data_velocity, data_snrPP, data_specwidth = self.pulsePairbyProfiles(dataOut)
1476 1477 self.__lastdatatime = datatime
1477 1478
1478 1479 if data_power is None:
1479 1480 return None, None, None,None,None,None
1480 1481
1481 1482 avgdatatime = self.__initime
1482 1483 deltatime = datatime - self.__lastdatatime
1483 1484 self.__initime = datatime
1484 1485
1485 1486 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth, avgdatatime
1486 1487
1487 1488 def run(self, dataOut,n = None,removeDC= False, overlapping= False,**kwargs):
1488 1489
1489 1490 if not self.isConfig:
1490 1491 self.setup(dataOut = dataOut, n = n , removeDC=removeDC , **kwargs)
1491 1492 self.isConfig = True
1492 1493 data_power, data_intensity, data_velocity,data_snrPP,data_specwidth, avgdatatime = self.pulsePairOp(dataOut, dataOut.utctime)
1493 1494 dataOut.flagNoData = True
1494 1495
1495 1496 if self.__dataReady:
1496 1497 dataOut.nCohInt *= self.n
1497 1498 dataOut.dataPP_POW = data_intensity # S
1498 1499 dataOut.dataPP_POWER = data_power # P
1499 1500 dataOut.dataPP_DOP = data_velocity
1500 1501 dataOut.dataPP_SNR = data_snrPP
1501 1502 dataOut.dataPP_WIDTH = data_specwidth
1502 1503 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1503 1504 dataOut.utctime = avgdatatime
1504 1505 dataOut.flagNoData = False
1505 1506 return dataOut
1506 1507
1507 1508
1508 1509
1509 1510 # import collections
1510 1511 # from scipy.stats import mode
1511 1512 #
1512 1513 # class Synchronize(Operation):
1513 1514 #
1514 1515 # isConfig = False
1515 1516 # __profIndex = 0
1516 1517 #
1517 1518 # def __init__(self, **kwargs):
1518 1519 #
1519 1520 # Operation.__init__(self, **kwargs)
1520 1521 # # self.isConfig = False
1521 1522 # self.__powBuffer = None
1522 1523 # self.__startIndex = 0
1523 1524 # self.__pulseFound = False
1524 1525 #
1525 1526 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1526 1527 #
1527 1528 # #Read data
1528 1529 #
1529 1530 # powerdB = dataOut.getPower(channel = channel)
1530 1531 # noisedB = dataOut.getNoise(channel = channel)[0]
1531 1532 #
1532 1533 # self.__powBuffer.extend(powerdB.flatten())
1533 1534 #
1534 1535 # dataArray = numpy.array(self.__powBuffer)
1535 1536 #
1536 1537 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1537 1538 #
1538 1539 # maxValue = numpy.nanmax(filteredPower)
1539 1540 #
1540 1541 # if maxValue < noisedB + 10:
1541 1542 # #No se encuentra ningun pulso de transmision
1542 1543 # return None
1543 1544 #
1544 1545 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1545 1546 #
1546 1547 # if len(maxValuesIndex) < 2:
1547 1548 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1548 1549 # return None
1549 1550 #
1550 1551 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1551 1552 #
1552 1553 # #Seleccionar solo valores con un espaciamiento de nSamples
1553 1554 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1554 1555 #
1555 1556 # if len(pulseIndex) < 2:
1556 1557 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1557 1558 # return None
1558 1559 #
1559 1560 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1560 1561 #
1561 1562 # #remover senales que se distancien menos de 10 unidades o muestras
1562 1563 # #(No deberian existir IPP menor a 10 unidades)
1563 1564 #
1564 1565 # realIndex = numpy.where(spacing > 10 )[0]
1565 1566 #
1566 1567 # if len(realIndex) < 2:
1567 1568 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1568 1569 # return None
1569 1570 #
1570 1571 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1571 1572 # realPulseIndex = pulseIndex[realIndex]
1572 1573 #
1573 1574 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1574 1575 #
1575 1576 # print "IPP = %d samples" %period
1576 1577 #
1577 1578 # self.__newNSamples = dataOut.nHeights #int(period)
1578 1579 # self.__startIndex = int(realPulseIndex[0])
1579 1580 #
1580 1581 # return 1
1581 1582 #
1582 1583 #
1583 1584 # def setup(self, nSamples, nChannels, buffer_size = 4):
1584 1585 #
1585 1586 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1586 1587 # maxlen = buffer_size*nSamples)
1587 1588 #
1588 1589 # bufferList = []
1589 1590 #
1590 1591 # for i in range(nChannels):
1591 1592 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1592 1593 # maxlen = buffer_size*nSamples)
1593 1594 #
1594 1595 # bufferList.append(bufferByChannel)
1595 1596 #
1596 1597 # self.__nSamples = nSamples
1597 1598 # self.__nChannels = nChannels
1598 1599 # self.__bufferList = bufferList
1599 1600 #
1600 1601 # def run(self, dataOut, channel = 0):
1601 1602 #
1602 1603 # if not self.isConfig:
1603 1604 # nSamples = dataOut.nHeights
1604 1605 # nChannels = dataOut.nChannels
1605 1606 # self.setup(nSamples, nChannels)
1606 1607 # self.isConfig = True
1607 1608 #
1608 1609 # #Append new data to internal buffer
1609 1610 # for thisChannel in range(self.__nChannels):
1610 1611 # bufferByChannel = self.__bufferList[thisChannel]
1611 1612 # bufferByChannel.extend(dataOut.data[thisChannel])
1612 1613 #
1613 1614 # if self.__pulseFound:
1614 1615 # self.__startIndex -= self.__nSamples
1615 1616 #
1616 1617 # #Finding Tx Pulse
1617 1618 # if not self.__pulseFound:
1618 1619 # indexFound = self.__findTxPulse(dataOut, channel)
1619 1620 #
1620 1621 # if indexFound == None:
1621 1622 # dataOut.flagNoData = True
1622 1623 # return
1623 1624 #
1624 1625 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1625 1626 # self.__pulseFound = True
1626 1627 # self.__startIndex = indexFound
1627 1628 #
1628 1629 # #If pulse was found ...
1629 1630 # for thisChannel in range(self.__nChannels):
1630 1631 # bufferByChannel = self.__bufferList[thisChannel]
1631 1632 # #print self.__startIndex
1632 1633 # x = numpy.array(bufferByChannel)
1633 1634 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1634 1635 #
1635 1636 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1636 1637 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1637 1638 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1638 1639 #
1639 1640 # dataOut.data = self.__arrayBuffer
1640 1641 #
1641 1642 # self.__startIndex += self.__newNSamples
1642 1643 #
1643 1644 # return
1644 1645 class SSheightProfiles(Operation):
1645 1646
1646 1647 step = None
1647 1648 nsamples = None
1648 1649 bufferShape = None
1649 1650 profileShape = None
1650 1651 sshProfiles = None
1651 1652 profileIndex = None
1652 1653
1653 1654 def __init__(self, **kwargs):
1654 1655
1655 1656 Operation.__init__(self, **kwargs)
1656 1657 self.isConfig = False
1657 1658
1658 1659 def setup(self,dataOut ,step = None , nsamples = None):
1659 1660
1660 1661 if step == None and nsamples == None:
1661 1662 raise ValueError("step or nheights should be specified ...")
1662 1663
1663 1664 self.step = step
1664 1665 self.nsamples = nsamples
1665 1666 self.__nChannels = dataOut.nChannels
1666 1667 self.__nProfiles = dataOut.nProfiles
1667 1668 self.__nHeis = dataOut.nHeights
1668 1669 shape = dataOut.data.shape #nchannels, nprofiles, nsamples
1669 1670
1670 1671 residue = (shape[1] - self.nsamples) % self.step
1671 1672 if residue != 0:
1672 1673 print("The residue is %d, step=%d should be multiple of %d to avoid loss of %d samples"%(residue,step,shape[1] - self.nsamples,residue))
1673 1674
1674 1675 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1675 1676 numberProfile = self.nsamples
1676 1677 numberSamples = (shape[1] - self.nsamples)/self.step
1677 1678
1678 1679 self.bufferShape = int(shape[0]), int(numberSamples), int(numberProfile) # nchannels, nsamples , nprofiles
1679 1680 self.profileShape = int(shape[0]), int(numberProfile), int(numberSamples) # nchannels, nprofiles, nsamples
1680 1681
1681 1682 self.buffer = numpy.zeros(self.bufferShape , dtype=numpy.complex)
1682 1683 self.sshProfiles = numpy.zeros(self.profileShape, dtype=numpy.complex)
1683 1684
1684 1685 def run(self, dataOut, step, nsamples, code = None, repeat = None):
1685 1686 dataOut.flagNoData = True
1686 1687
1687 1688 profileIndex = None
1688 1689 #print("nProfiles, nHeights ",dataOut.nProfiles, dataOut.nHeights)
1689 1690 #print(dataOut.getFreqRange(1)/1000.)
1690 1691 #exit(1)
1691 1692 if dataOut.flagDataAsBlock:
1692 1693 dataOut.data = numpy.average(dataOut.data,axis=1)
1693 1694 #print("jee")
1694 1695 dataOut.flagDataAsBlock = False
1695 1696 if not self.isConfig:
1696 1697 self.setup(dataOut, step=step , nsamples=nsamples)
1697 1698 #print("Setup done")
1698 1699 self.isConfig = True
1699 1700
1700 1701
1701 1702 if code is not None:
1702 1703 code = numpy.array(code)
1703 1704 code_block = code
1704 1705
1705 1706 if repeat is not None:
1706 1707 code_block = numpy.repeat(code_block, repeats=repeat, axis=1)
1707 1708 #print(code_block.shape)
1708 1709 for i in range(self.buffer.shape[1]):
1709 1710
1710 1711 if code is not None:
1711 1712 self.buffer[:,i] = dataOut.data[:,i*self.step:i*self.step + self.nsamples]*code_block
1712 1713
1713 1714 else:
1714 1715
1715 1716 self.buffer[:,i] = dataOut.data[:,i*self.step:i*self.step + self.nsamples]#*code[dataOut.profileIndex,:]
1716 1717
1717 1718 #self.buffer[:,j,self.__nHeis-j*self.step - self.nheights:self.__nHeis-j*self.step] = numpy.flip(dataOut.data[:,j*self.step:j*self.step + self.nheights])
1718 1719
1719 1720 for j in range(self.buffer.shape[0]):
1720 1721 self.sshProfiles[j] = numpy.transpose(self.buffer[j])
1721 1722
1722 1723 profileIndex = self.nsamples
1723 1724 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1724 1725 ippSeconds = (deltaHeight*1.0e-6)/(0.15)
1725 1726 #print("ippSeconds, dH: ",ippSeconds,deltaHeight)
1726 1727 try:
1727 1728 if dataOut.concat_m is not None:
1728 1729 ippSeconds= ippSeconds/float(dataOut.concat_m)
1729 1730 #print "Profile concat %d"%dataOut.concat_m
1730 1731 except:
1731 1732 pass
1732 1733
1733 1734 dataOut.data = self.sshProfiles
1734 1735 dataOut.flagNoData = False
1735 1736 dataOut.heightList = numpy.arange(self.buffer.shape[1]) *self.step*deltaHeight + dataOut.heightList[0]
1736 1737 dataOut.nProfiles = int(dataOut.nProfiles*self.nsamples)
1737 1738
1738 1739 dataOut.profileIndex = profileIndex
1739 1740 dataOut.flagDataAsBlock = True
1740 1741 dataOut.ippSeconds = ippSeconds
1741 1742 dataOut.step = self.step
1742 1743 #print(numpy.shape(dataOut.data))
1743 1744 #exit(1)
1744 1745
1745 1746 return dataOut
1746 1747 ################################################################################3############################3
1747 1748 ################################################################################3############################3
1748 1749 ################################################################################3############################3
1749 1750 ################################################################################3############################3
1750 1751
1751 1752 class SSheightProfiles2(Operation):
1752 1753 '''
1753 1754 Procesa por perfiles y por bloques
1754 1755 '''
1755 1756
1756 1757 step = None
1757 1758 nsamples = None
1758 1759 bufferShape = None
1759 1760 profileShape = None
1760 1761 sshProfiles = None
1761 1762 profileIndex = None
1763 deltaHeight = None
1764 init_range = None
1762 1765
1763 1766 def __init__(self, **kwargs):
1764 1767
1765 1768 Operation.__init__(self, **kwargs)
1766 1769 self.isConfig = False
1767 1770
1768 1771 def setup(self,dataOut ,step = None , nsamples = None):
1769 1772
1770 1773 if step == None and nsamples == None:
1771 1774 raise ValueError("step or nheights should be specified ...")
1772 1775
1773 1776 self.step = step
1774 1777 self.nsamples = nsamples
1775 1778 self.__nChannels = int(dataOut.nChannels)
1776 1779 self.__nProfiles = int(dataOut.nProfiles)
1777 1780 self.__nHeis = int(dataOut.nHeights)
1778 1781
1779 1782 residue = (self.__nHeis - self.nsamples) % self.step
1780 1783 if residue != 0:
1781 1784 print("The residue is %d, step=%d should be multiple of %d to avoid loss of %d samples"%(residue,step,shape[1] - self.nsamples,residue))
1782 1785
1783 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1786 self.deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1787 self.init_range = dataOut.heightList[0]
1784 1788 #numberProfile = self.nsamples
1785 1789 self.numberSamples = (self.__nHeis - self.nsamples)/self.step
1786 1790
1787 1791 self.new_nHeights = self.numberSamples
1788 1792
1789 1793 self.bufferShape = int(self.__nChannels), int(self.numberSamples), int(self.nsamples) # nchannels, nsamples , nprofiles
1790 1794 self.profileShape = int(self.__nChannels), int(self.nsamples), int(self.numberSamples) # nchannels, nprofiles, nsamples
1791 1795
1792 1796 self.buffer = numpy.zeros(self.bufferShape , dtype=numpy.complex)
1793 1797 self.sshProfiles = numpy.zeros(self.profileShape, dtype=numpy.complex)
1794 1798
1795 1799 def getNewProfiles(self, data, code=None, repeat=None):
1796 1800
1797 1801 if code is not None:
1798 1802 code = numpy.array(code)
1799 1803 code_block = code
1800 1804
1801 1805 if repeat is not None:
1802 1806 code_block = numpy.repeat(code_block, repeats=repeat, axis=1)
1803 #print("buff, data, :",self.buffer.shape, data.shape)
1807 if data.ndim == 2:
1808 data = data.reshape(1,1,self.__nHeis )
1809 #print("buff, data, :",self.buffer.shape, data.shape,self.sshProfiles.shape)
1804 1810 for i in range(int(self.new_nHeights)): #nuevas alturas
1805 1811 if code is not None:
1806 self.buffer[:,i] = data[:,i*self.step:i*self.step + self.nsamples]*code_block
1812 self.buffer[:,i,:] = data[:,:,i*self.step:i*self.step + self.nsamples]*code_block
1807 1813 else:
1808 self.buffer[:,i] = data[:,i*self.step:i*self.step + self.nsamples]#*code[dataOut.profileIndex,:]
1814 self.buffer[:,i,:] = data[:,:,i*self.step:i*self.step + self.nsamples]#*code[dataOut.profileIndex,:]
1809 1815
1810 1816 for j in range(self.__nChannels): #en los cananles
1811 self.sshProfiles[j] = numpy.transpose(self.buffer[j])
1812
1817 self.sshProfiles[j,:,:] = numpy.transpose(self.buffer[j,:,:])
1818 #print("new profs Done")
1813 1819
1814 1820
1815 1821
1816 1822 def run(self, dataOut, step, nsamples, code = None, repeat = None):
1817 1823
1824 if dataOut.flagNoData == True:
1825 return dataOut
1818 1826 dataOut.flagNoData = True
1819 1827 #print("init data shape:", dataOut.data.shape)
1820 1828 #print("ch: {} prof: {} hs: {}".format(int(dataOut.nChannels),
1821 1829 # int(dataOut.nProfiles),int(dataOut.nHeights)))
1822 1830
1823 1831 profileIndex = None
1824 1832 # if not dataOut.flagDataAsBlock:
1825 1833 # dataOut.nProfiles = 1
1826 1834
1827 1835 if not self.isConfig:
1828 1836 self.setup(dataOut, step=step , nsamples=nsamples)
1829 1837 #print("Setup done")
1830 1838 self.isConfig = True
1831 1839
1832 1840 dataBlock = None
1833 1841
1834 1842 nprof = 1
1835 1843 if dataOut.flagDataAsBlock:
1836 1844 nprof = int(dataOut.nProfiles)
1837 1845
1838 1846 #print("dataOut nProfiles:", dataOut.nProfiles)
1839 1847 for profile in range(nprof):
1840 1848 if dataOut.flagDataAsBlock:
1849 #print("read blocks")
1841 1850 self.getNewProfiles(dataOut.data[:,profile,:], code=code, repeat=repeat)
1842 1851 else:
1843 self.getNewProfiles(dataOut.data, code=code, repeat=repeat)
1852 #print("read profiles")
1853 self.getNewProfiles(dataOut.data, code=code, repeat=repeat) #only one channe
1844 1854 if profile == 0:
1845 1855 dataBlock = self.sshProfiles.copy()
1846 1856 else: #by blocks
1847 1857 dataBlock = numpy.concatenate((dataBlock,self.sshProfiles), axis=1) #profile axis
1848 print("by blocks: ",dataBlock.shape, self.sshProfiles.shape)
1858 #print("by blocks: ",dataBlock.shape, self.sshProfiles.shape)
1849 1859
1850 1860 profileIndex = self.nsamples
1851 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1852 ippSeconds = (deltaHeight*1.0e-6)/(0.15)
1861 #deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1862 ippSeconds = (self.deltaHeight*1.0e-6)/(0.15)
1853 1863
1854 1864
1855 1865 dataOut.data = dataBlock
1856 dataOut.heightList = numpy.arange(self.new_nHeights) *self.step*deltaHeight + dataOut.heightList[0]
1857 #print("show me: ",dataOut.nHeights, self.new_nHeights)
1858 #dataOut.nHeights = int(self.new_nHeights)
1866 #print("show me: ",self.step,self.deltaHeight, dataOut.heightList, self.new_nHeights)
1867 dataOut.heightList = numpy.arange(int(self.new_nHeights)) *self.step*self.deltaHeight + self.init_range
1868
1859 1869 dataOut.ippSeconds = ippSeconds
1860 1870 dataOut.step = self.step
1861 1871 dataOut.flagNoData = False
1862 1872 if dataOut.flagDataAsBlock:
1863 1873 dataOut.nProfiles = int(dataOut.nProfiles*self.nsamples)
1864 1874
1865 1875 else:
1866 1876 dataOut.nProfiles = int(self.nsamples)
1867 1877 dataOut.profileIndex = dataOut.nProfiles
1868 1878 dataOut.flagDataAsBlock = True
1869 1879
1870 1880 dataBlock = None
1871 1881 #print("new data shape:", dataOut.data.shape)
1872 1882
1873 1883 return dataOut
1874 1884
1875 1885
1876 1886
1877 1887
1878 1888 #import skimage.color
1879 1889 #import skimage.io
1880 import matplotlib.pyplot as plt
1890 #import matplotlib.pyplot as plt
1881 1891
1882 class clean2DArray(Operation):
1892 class removeProfileByFaradayHS(Operation):
1883 1893 '''
1884 1894
1885 1895 '''
1886 1896 isConfig = False
1887 1897 n = None
1888 __timeInterval = None
1898
1889 1899 __profIndex = 0
1890 __byTime = False
1900
1891 1901 __dataReady = False
1892 1902 __buffer_data = []
1893 1903 __buffer_times = []
1894 1904 __initime = None
1895 1905 __count_exec = 0
1896 1906 __profIndex = 0
1897 1907 buffer = None
1898 1908 lenProfileOut = 1
1899 1909
1900 1910 init_prof = 0
1901 1911 end_prof = 0
1902 1912 n_profiles = 0
1903 1913 first_utcBlock = None
1914 outliers_IDs_list = []
1904 1915 __dh = 0
1905 1916
1906 1917 def __init__(self, **kwargs):
1907 1918
1908 1919 Operation.__init__(self, **kwargs)
1909 1920 self.isConfig = False
1910 1921
1911 def setup(self,dataOut, n=None , timeInterval=None):
1922 def setup(self,dataOut, n=None , navg=0.8, profileMargin=50,thHistOutlier=3, minHei=None, maxHei=None):
1912 1923
1913 1924 if n == None and timeInterval == None:
1914 1925 raise ValueError("nprofiles or timeInterval should be specified ...")
1915 1926
1916 1927 if n != None:
1917 1928 self.n = n
1918 self.__byTime = False
1919 else:
1920 self.__timeInterval = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
1921 self.n = 9999
1922 self.__byTime = True
1923 1929
1930 self.navg = navg
1931 self.profileMargin = profileMargin
1932 self.thHistOutlier = thHistOutlier
1924 1933 self.__profIndex = 0
1925 1934 self.buffer = None
1926 1935 self.lenProfileOut = 1
1927
1936 self.n_prof_released = 0
1937 self.heightList = dataOut.heightList
1928 1938 self.init_prof = 0
1929 1939 self.end_prof = 0
1930 1940 self.n_profiles = 0
1931 1941 self.first_utcBlock = None
1932 1942 self.__dh = dataOut.heightList[1] - dataOut.heightList[0]
1943 minHei = minHei
1944 maxHei = maxHei
1945 if minHei==None :
1946 minHei = dataOut.heightList[0]
1947 if maxHei==None :
1948 maxHei = dataOut.heightList[-1]
1949 self.minHei_idx,self.maxHei_idx = getHei_index(minHei, maxHei, dataOut.heightList)
1950
1951
1952 def filterSatsProfiles(self):
1953 data = self.__buffer_data
1954 #print(data.shape)
1955 nChannels, profiles, heights = data.shape
1956 indexes=[]
1957 outliers_IDs=[]
1958 for c in range(nChannels):
1959 for h in range(self.minHei_idx, self.maxHei_idx):
1960 power = data[c,:,h] * numpy.conjugate(data[c,:,h])
1961 power = power.real
1962 #power = (numpy.abs(data[c,:,h].real))
1963 sortdata = numpy.sort(power, axis=None)
1964 sortID=power.argsort()
1965 index = _noise.hildebrand_sekhon2(sortdata,self.navg) #0.75-> buen valor
1966
1967 indexes.append(index)
1968 outliers_IDs=numpy.append(outliers_IDs,sortID[index:])
1969 # print(outliers_IDs)
1970 # fig,ax = plt.subplots()
1971 # #ax.set_title(str(k)+" "+str(j))
1972 # x=range(len(sortdata))
1973 # ax.scatter(x,sortdata)
1974 # ax.axvline(index)
1975 # plt.grid()
1976 # plt.show()
1977
1978 outliers_IDs = outliers_IDs.astype(numpy.dtype('int64'))
1979 outliers_IDs = numpy.unique(outliers_IDs)
1980 outs_lines = numpy.sort(outliers_IDs)
1981 # #print("outliers Ids: ", outs_lines, outs_lines.shape)
1982 #hist, bin_edges = numpy.histogram(outs_lines, bins=10, density=True)
1983
1984
1985 #Agrupando el histograma de outliers,
1986 my_bins = numpy.linspace(0,9600, 96, endpoint=False)
1987
1988
1989 hist, bins = numpy.histogram(outs_lines,bins=my_bins)
1990 hist_outliers_indexes = numpy.where(hist > self.thHistOutlier) #es outlier
1991 #print(hist_outliers_indexes[0])
1992 bins_outliers_indexes = [int(i) for i in bins[hist_outliers_indexes]] #
1993 #print(bins_outliers_indexes)
1994 outlier_loc_index = []
1995
1996 #outlier_loc_index = [k for k in range(bins_outliers_indexes[n]-50,bins_outliers_indexes[n+1]+50) for n in range(len(bins_outliers_indexes)-1) ]
1997 for n in range(len(bins_outliers_indexes)-1):
1998 #outlier_loc_index = [k for k in range(bins_outliers_indexes[n]-50,bins_outliers_indexes[n+1]+50)]
1999 for k in range(bins_outliers_indexes[n]-self.profileMargin,bins_outliers_indexes[n+1]+self.profileMargin):
2000 outlier_loc_index.append(k)
2001
2002 outlier_loc_index = numpy.asarray(outlier_loc_index)
2003 #print(numpy.unique(outlier_loc_index))
2004
2005
2006
2007 # x, y = numpy.meshgrid(numpy.arange(profiles), self.heightList)
2008 # fig, ax = plt.subplots(1,2,figsize=(8, 6))
2009 #
2010 # dat = data[0,:,:].real
2011 # m = numpy.nanmean(dat)
2012 # o = numpy.nanstd(dat)
2013 # #print(m, o, x.shape, y.shape)
2014 # c = ax[0].pcolormesh(x, y, dat.T, cmap ='YlGnBu', vmin = (m-2*o), vmax = (m+2*o))
2015 # ax[0].vlines(outs_lines,200,600, linestyles='dashed', label = 'outs', color='w')
2016 # fig.colorbar(c)
2017 # ax[0].vlines(outlier_loc_index,650,750, linestyles='dashed', label = 'outs', color='r')
2018 # ax[1].hist(outs_lines,bins=my_bins)
2019 # plt.show()
2020
2021
2022 self.outliers_IDs_list = numpy.unique(outlier_loc_index)
2023 return data
1933 2024
1934 2025 def cleanOutliersByBlock(self):
1935 2026 #print(self.__buffer_data[0].shape)
1936 2027 data = self.__buffer_data#.copy()
1937 2028 #print("cleaning shape inpt: ",data.shape)
1938
2029 '''
1939 2030 self.__buffer_data = []
1940 2031
1941 2032 spectrum = numpy.fft.fft2(data, axes=(0,2))
1942 2033 #print("spc : ",spectrum.shape)
1943 2034 (nch,nsamples, nh) = spectrum.shape
1944
1945 #nch =
1946
2035 data2 = None
2036 #print(data.shape)
2037 spectrum2 = spectrum.copy()
1947 2038 for ch in range(nch):
1948 2039 dh = self.__dh
1949 2040 dt1 = (dh*1.0e-6)/(0.15)
1950 2041 dt2 = self.__buffer_times[1]-self.__buffer_times[0]
1951 2042 freqv = numpy.fft.fftfreq(nh, d=dt1)
1952 2043 freqh = numpy.fft.fftfreq(self.n, d=dt2)
1953 2044 #print("spc loop: ")
1954 x, y = numpy.meshgrid(numpy.sort(freqh),numpy.sort(freqv))
1955 z = numpy.abs(spectrum[ch,:,:])
1956
1957
1958 dat = numpy.log10(z.T)
1959 m = numpy.mean(dat)
1960 o = numpy.std(dat)
1961 fig, ax = plt.subplots(figsize=(8, 6))
1962 2045
1963 c = ax.pcolormesh(x, y, dat, cmap ='YlGnBu', vmin = (m-2*o), vmax = (m+2*o))
1964 #c = ax.pcolor( z.T , cmap ='gray', vmin = (m-2*o), vmax = (m+2*o))
1965 date_time = datetime.datetime.fromtimestamp(self.__buffer_times[0]).strftime('%Y-%m-%d %H:%M:%S.%f')
1966 #strftime('%Y-%m-%d %H:%M:%S')
1967 ax.set_title('Spectrum magnitude '+date_time)
1968 fig.canvas.set_window_title('Spectrum magnitude {} '.format(self.n)+date_time)
1969 fig.colorbar(c)
1970 2046
1971 plt.show()
1972 2047
2048 x, y = numpy.meshgrid(numpy.sort(freqh),numpy.sort(freqv))
2049 z = numpy.abs(spectrum[ch,:,:])
2050 # Find all peaks higher than the 98th percentile
2051 peaks = z < numpy.percentile(z, 98)
2052 #print(peaks)
2053 # Set those peak coefficients to zero
2054 spectrum2 = spectrum2 * peaks.astype(int)
2055 data2 = numpy.fft.ifft2(spectrum2)
1973 2056
2057 dat = numpy.log10(z.T)
2058 dat2 = numpy.log10(spectrum2.T)
2059
2060 # m = numpy.mean(dat)
2061 # o = numpy.std(dat)
2062 # fig, ax = plt.subplots(2,1,figsize=(8, 6))
2063 #
2064 # c = ax[0].pcolormesh(x, y, dat, cmap ='YlGnBu', vmin = (m-2*o), vmax = (m+2*o))
2065 # #c = ax.pcolor( z.T , cmap ='gray', vmin = (m-2*o), vmax = (m+2*o))
2066 # date_time = datetime.datetime.fromtimestamp(self.__buffer_times[0]).strftime('%Y-%m-%d %H:%M:%S.%f')
2067 # #strftime('%Y-%m-%d %H:%M:%S')
2068 # ax[0].set_title('Spectrum magnitude '+date_time)
2069 # fig.canvas.set_window_title('Spectrum magnitude {} '.format(self.n)+date_time)
2070 #
2071 #
2072 # c = ax[1].pcolormesh(x, y, dat, cmap ='YlGnBu', vmin = (m-2*o), vmax = (m+2*o))
2073 # fig.colorbar(c)
2074 # plt.show()
2075
2076 #print(data2.shape)
2077
2078 data = data2
1974 2079
1975 2080 #cleanBlock = numpy.fft.ifft2(spectrum, axes=(0,2)).reshape()
2081 '''
2082 #print("cleanOutliersByBlock Done")
1976 2083
1977 print("cleanOutliersByBlock Done")
1978 return data
1979
1980 def byTime(self, data, datatime):
1981
1982 self.__dataReady = False
1983
1984 self.fillBuffer(data, datatime)
1985 dataBlock = None
1986
1987 if (datatime - self.__initime) >= self.__timeInterval:
1988 dataBlock = self.cleanOutliersByBlock()
1989 self.__dataReady = True
1990 self.n = self.__profIndex
1991 return dataBlock
1992
1993 def byProfiles(self, data, datatime):
1994 self.__dataReady = False
1995
1996 self.fillBuffer(data, datatime)
1997 dataBlock = None
2084 return self.filterSatsProfiles()
1998 2085
1999 if self.__profIndex == self.n:
2000 #print("apnd : ",data)
2001 dataBlock = self.cleanOutliersByBlock()
2002 self.__dataReady = True
2003 2086
2004 return dataBlock
2005 2087
2006 2088 def fillBuffer(self, data, datatime):
2007 2089
2008 2090 if self.__profIndex == 0:
2009 2091 self.__buffer_data = data.copy()
2010 2092
2011 2093 else:
2012 2094 self.__buffer_data = numpy.concatenate((self.__buffer_data,data), axis=1)#en perfiles
2013 2095 self.__profIndex += 1
2014 self.__buffer_times.append(datatime)
2096 #self.__buffer_times.append(datatime)
2015 2097
2016 2098 def getData(self, data, datatime=None):
2017 2099
2018 2100 if self.__profIndex == 0:
2019 2101 self.__initime = datatime
2020 2102
2021 if self.__byTime:
2022 dataBlock = self.byTime(data, datatime)
2023 else:
2024 dataBlock = self.byProfiles(data, datatime)
2025 2103
2104 self.__dataReady = False
2026 2105
2106 self.fillBuffer(data, datatime)
2107 dataBlock = None
2108
2109 if self.__profIndex == self.n:
2110 #print("apnd : ",data)
2111 #dataBlock = self.cleanOutliersByBlock()
2112 dataBlock = self.filterSatsProfiles()
2113 self.__dataReady = True
2114
2115 return dataBlock
2027 2116
2028 2117 if dataBlock is None:
2029 return None
2118 return None, None
2030 2119
2031 2120
2032 2121
2033 2122 return dataBlock
2034 2123
2035 def releaseBlock(self, dataOut):
2124 def releaseBlock(self):
2036 2125
2037 2126 if self.n % self.lenProfileOut != 0:
2038 2127 raise ValueError("lenProfileOut %d must be submultiple of nProfiles %d" %(self.lenProfileOut, self.n_profiles))
2039 2128 return None
2040 2129
2041 dataOut.data = self.buffer[:,self.init_prof:self.end_prof:,:] #ch, prof, alt
2042 dataOut.profileIndex = self.lenProfileOut
2043 dataOut.utctime = self.first_utcBlock + self.init_prof*dataOut.ippSeconds
2130 data = self.buffer[:,self.init_prof:self.end_prof:,:] #ch, prof, alt
2131
2044 2132 self.init_prof = self.end_prof
2045 2133 self.end_prof += self.lenProfileOut
2046 print("data release shape: ",dataOut.data.shape, self.end_prof)
2134 #print("data release shape: ",dataOut.data.shape, self.end_prof)
2135 self.n_prof_released += 1
2047 2136
2048 if self.end_prof >= (self.n +self.lenProfileOut):
2049 self.init_prof = 0
2050 self.__profIndex = 0
2051 self.buffer = None
2052 dataOut.buffer_empty = True
2053 return dataOut
2054 2137
2055 def run(self, dataOut, n=None, timeInterval=None, nProfilesOut=1):
2138 #print("f_no_data ", dataOut.flagNoData)
2139 return data
2140
2141 def run(self, dataOut, n=None, navg=0.8, nProfilesOut=1, profile_margin=50,th_hist_outlier=3,minHei=None, maxHei=None):
2056 2142 #print("run op buffer 2D")
2057 2143 self.nChannels = dataOut.nChannels
2058 2144 self.nHeights = dataOut.nHeights
2059 2145
2060 2146 if not self.isConfig:
2061 self.setup(dataOut,n=n, timeInterval=timeInterval)
2147 #print("init p idx: ", dataOut.profileIndex )
2148 self.setup(dataOut,n=n, navg=navg,profileMargin=profile_margin,
2149 thHistOutlier=th_hist_outlier,minHei=minHei, maxHei=maxHei)
2062 2150 self.isConfig = True
2063 2151
2064 2152 dataBlock = None
2065 2153
2066 2154 if not dataOut.buffer_empty: #hay datos acumulados
2067 2155
2068 2156 if self.init_prof == 0:
2157 self.n_prof_released = 0
2069 2158 self.lenProfileOut = nProfilesOut
2070 2159 dataOut.flagNoData = False
2071 2160 #print("tp 2 ",dataOut.data.shape)
2072 2161 #(ch, self.n_profiles, nh) = self.buffer.shape
2073 2162 #print("tp 3 ",self.dataOut.data.shape)
2074 2163 #print("rel: ",self.buffer[:,-1,:])
2075 2164 self.init_prof = 0
2076 2165 self.end_prof = self.lenProfileOut
2077 self.first_utcBlock = dataOut.utctime
2166
2078 2167 dataOut.nProfiles = self.lenProfileOut
2079 dataOut.error = False
2168 if nProfilesOut == 1:
2169 dataOut.flagDataAsBlock = False
2170 else:
2080 2171 dataOut.flagDataAsBlock = True
2081 2172 #print("prof: ",self.init_prof)
2082 2173 dataOut.flagNoData = False
2083 return self.releaseBlock(dataOut)
2174 if numpy.isin(self.n_prof_released, self.outliers_IDs_list):
2175 #print("omitting: ", self.n_prof_released)
2176 dataOut.flagNoData = True
2177
2178 dataOut.utctime = self.first_utcBlock + self.init_prof*dataOut.ippSeconds
2179 #dataOut.data = self.releaseBlock()
2180 #########################################################3
2181 if self.n % self.lenProfileOut != 0:
2182 raise ValueError("lenProfileOut %d must be submultiple of nProfiles %d" %(self.lenProfileOut, self.n_profiles))
2183 return None
2184
2185 dataOut.data = self.buffer[:,self.init_prof:self.end_prof:,:] #ch, prof, alt
2186
2187 self.init_prof = self.end_prof
2188 self.end_prof += self.lenProfileOut
2189 #print("data release shape: ",dataOut.data.shape, self.end_prof)
2190 self.n_prof_released += 1
2191
2192 if self.end_prof >= (self.n +self.lenProfileOut):
2193
2194 self.init_prof = 0
2195 self.__profIndex = 0
2196 self.buffer = None
2197 dataOut.buffer_empty = True
2198 self.outliers_IDs_list = []
2199 self.n_prof_released = 0
2200 dataOut.flagNoData = False #enviar ultimo aunque sea outlier :(
2201 #print("cleaning...", dataOut.buffer_empty)
2202 dataOut.profileIndex = 0 #self.lenProfileOut
2203 ####################################################################
2204 return dataOut
2084 2205
2085 2206
2086 2207 #print("tp 223 ",dataOut.data.shape)
2087 2208 dataOut.flagNoData = True
2088 2209
2089 2210
2090 2211
2091 2212 try:
2092 2213 #dataBlock = self.getData(dataOut.data.reshape(self.nChannels,1,self.nHeights), dataOut.utctime)
2093 2214 dataBlock = self.getData(numpy.reshape(dataOut.data,(self.nChannels,1,self.nHeights)), dataOut.utctime)
2094 2215 self.__count_exec +=1
2095 2216 except Exception as e:
2096 2217 print("Error getting profiles data",self.__count_exec )
2097 2218 print(e)
2098 2219 sys.exit()
2099 2220
2100 2221 if self.__dataReady:
2222 #print("omitting: ", len(self.outliers_IDs_list))
2101 2223 self.__count_exec = 0
2102 2224 #dataOut.data =
2103 self.buffer = numpy.flip(dataBlock, axis=1)
2104
2225 #self.buffer = numpy.flip(dataBlock, axis=1)
2226 self.buffer = dataBlock
2227 self.first_utcBlock = self.__initime
2105 2228 dataOut.utctime = self.__initime
2106 2229 dataOut.nProfiles = self.__profIndex
2107 2230 #dataOut.flagNoData = False
2231 self.init_prof = 0
2108 2232 self.__profIndex = 0
2109 2233 self.__initime = None
2110 2234 dataBlock = None
2111 2235 self.__buffer_times = []
2112 2236 dataOut.error = False
2113 2237 dataOut.useInputBuffer = True
2114 2238 dataOut.buffer_empty = False
2115 print("1 ch: {} prof: {} hs: {}".format(int(dataOut.nChannels),
2116 int(dataOut.nProfiles),int(dataOut.nHeights)))
2117 #return None
2239 #print("1 ch: {} prof: {} hs: {}".format(int(dataOut.nChannels),int(dataOut.nProfiles),int(dataOut.nHeights)))
2240
2118 2241
2119 2242
2120 2243 #print(self.__count_exec)
2121 2244
2122 2245 return dataOut
2123 2246
2124 class CleanProfileSats(Operation):
2247 class RemoveProfileSats(Operation):
2125 2248 '''
2126 2249 Omite los perfiles contaminados con señal de satelites,
2127 2250 In: minHei = min_sat_range
2128 2251 max_sat_range
2129 2252 min_hei_ref
2130 2253 max_hei_ref
2131 2254 th = diference between profiles mean, ref and sats
2132 2255 Out:
2133 2256 profile clean
2134 2257 '''
2135 2258
2136 2259 isConfig = False
2137 2260 min_sats = 0
2138 2261 max_sats = 999999999
2139 2262 min_ref= 0
2140 2263 max_ref= 9999999999
2141 2264 needReshape = False
2142 2265 count = 0
2143 2266 thdB = 0
2144 2267 byRanges = False
2145 2268 min_sats = None
2146 2269 max_sats = None
2270 noise = 0
2147 2271
2148 2272 def __init__(self, **kwargs):
2149 2273
2150 2274 Operation.__init__(self, **kwargs)
2151 2275 self.isConfig = False
2152 2276
2153 2277
2154 2278 def setup(self, dataOut, minHei, maxHei, minRef, maxRef, th, thdB, rangeHeiList):
2155 2279
2156 2280 if rangeHeiList!=None:
2157 2281 self.byRanges = True
2158 2282 else:
2159 2283 if minHei==None or maxHei==None :
2160 2284 raise ValueError("Parameters heights are required")
2161 2285 if minRef==None or maxRef==None:
2162 2286 raise ValueError("Parameters heights are required")
2163 2287
2164 2288 if self.byRanges:
2165 2289 self.min_sats = []
2166 2290 self.max_sats = []
2167 2291 for min,max in rangeHeiList:
2168 2292 a,b = getHei_index(min, max, dataOut.heightList)
2169 2293 self.min_sats.append(a)
2170 2294 self.max_sats.append(b)
2171 2295 else:
2172 2296 self.min_sats, self.max_sats = getHei_index(minHei, maxHei, dataOut.heightList)
2173 2297 self.min_ref, self.max_ref = getHei_index(minRef, maxRef, dataOut.heightList)
2174 2298 self.th = th
2175 2299 self.thdB = thdB
2176 2300 self.isConfig = True
2177 2301
2178 2302
2179 2303 def compareRanges(self,data, minHei,maxHei):
2180 ref = data[0,self.min_ref:self.max_ref] * numpy.conjugate(data[0,self.min_ref:self.max_ref])
2181 p_ref = 10*numpy.log10(ref.real)
2182 m_ref = numpy.mean(p_ref)
2304
2305 # ref = data[0,self.min_ref:self.max_ref] * numpy.conjugate(data[0,self.min_ref:self.max_ref])
2306 # p_ref = 10*numpy.log10(ref.real)
2307 # m_ref = numpy.mean(p_ref)
2308
2309 m_ref = self.noise
2183 2310
2184 2311 sats = data[0,minHei:maxHei] * numpy.conjugate(data[0,minHei:maxHei])
2185 2312 p_sats = 10*numpy.log10(sats.real)
2186 2313 m_sats = numpy.mean(p_sats)
2187 2314
2188 if m_sats > (m_ref + self.th) and (m_sats > self.thdB):
2189 #print("msats: ",m_sats," mRef: ", m_ref, (m_sats - m_ref))
2315 if m_sats > (m_ref + self.th): #and (m_sats > self.thdB):
2316 #print("msats: ",m_sats," \tmRef: ", m_ref, "\t",(m_sats - m_ref))
2190 2317 #print("Removing profiles...")
2191 2318 return False
2192 2319
2193 2320 return True
2194 2321
2195 2322 def isProfileClean(self, data):
2196 2323 '''
2197 2324 Analiza solo 1 canal, y descarta todos...
2198 2325 '''
2199 2326
2200 2327 clean = True
2201 2328
2202 2329 if self.byRanges:
2203 2330
2204 2331 for n in range(len(self.min_sats)):
2205 2332 c = self.compareRanges(data,self.min_sats[n],self.max_sats[n])
2206 2333 clean = clean and c
2207 2334 else:
2208 2335
2209 2336 clean = (self.compareRanges(data, self.min_sats,self.max_sats))
2210 2337
2211 2338 return clean
2212 2339
2213 2340
2214 2341
2215 2342 def run(self, dataOut, minHei=None, maxHei=None, minRef=None, maxRef=None, th=5, thdB=65, rangeHeiList=None):
2216 2343 dataOut.flagNoData = True
2217 2344
2218 2345 if not self.isConfig:
2219 2346 self.setup(dataOut, minHei, maxHei, minRef, maxRef, th, thdB, rangeHeiList)
2220 2347 self.isConfig = True
2221
2348 #print(self.min_sats,self.max_sats)
2222 2349 if dataOut.flagDataAsBlock:
2223 2350 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
2224 2351
2225 2352 else:
2226
2353 self.noise =10*numpy.log10(dataOut.getNoisebyHildebrand(ymin_index=self.min_ref, ymax_index=self.max_ref))
2227 2354 if not self.isProfileClean(dataOut.data):
2228 2355 return dataOut
2229 2356 #dataOut.data = numpy.full((dataOut.nChannels,dataOut.nHeights),numpy.NAN)
2230 2357 #self.count += 1
2231 2358
2232 2359 dataOut.flagNoData = False
2233 2360
2234 2361 return dataOut
General Comments 0
You need to be logged in to leave comments. Login now