##// END OF EJS Templates
Modificación a kmamisr para ejecutarse en la versión 3, creación de scripts con terminación v3 para difereciarlos, se comentó la linea #720 de JroIO_param.py debido a que reiniciaba la lista de archivos, ocasionando la reescritura del archivo hdf5. Alguna otra modificación aparente es producto de algunas variaciones en espacios al usar la función print()
joabAM -
r1279:c53fe2a4a291
parent child
Show More
@@ -1,1290 +1,1295
1 '''
1 '''
2 Updated on January , 2018, for multiprocessing purposes
2 Updated on January , 2018, for multiprocessing purposes
3 Author: Sergio Cortez
3 Author: Sergio Cortez
4 Created on September , 2012
4 Created on September , 2012
5 '''
5 '''
6 from platform import python_version
6 from platform import python_version
7 import sys
7 import sys
8 import ast
8 import ast
9 import datetime
9 import datetime
10 import traceback
10 import traceback
11 import math
11 import math
12 import time
12 import time
13 import zmq
13 import zmq
14 from multiprocessing import Process, Queue, Event, Value, cpu_count
14 from multiprocessing import Process, Queue, Event, Value, cpu_count
15 from threading import Thread
15 from threading import Thread
16 from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
16 from xml.etree.ElementTree import ElementTree, Element, SubElement, tostring
17 from xml.dom import minidom
17 from xml.dom import minidom
18
18
19
19
20 from schainpy.admin import Alarm, SchainWarning
20 from schainpy.admin import Alarm, SchainWarning
21 from schainpy.model import *
21 from schainpy.model import *
22 from schainpy.utils import log
22 from schainpy.utils import log
23
23
24
24
25 DTYPES = {
25 DTYPES = {
26 'Voltage': '.r',
26 'Voltage': '.r',
27 'Spectra': '.pdata'
27 'Spectra': '.pdata'
28 }
28 }
29
29
30
30
31 def MPProject(project, n=cpu_count()):
31 def MPProject(project, n=cpu_count()):
32 '''
32 '''
33 Project wrapper to run schain in n processes
33 Project wrapper to run schain in n processes
34 '''
34 '''
35
35
36 rconf = project.getReadUnitObj()
36 rconf = project.getReadUnitObj()
37 op = rconf.getOperationObj('run')
37 op = rconf.getOperationObj('run')
38 dt1 = op.getParameterValue('startDate')
38 dt1 = op.getParameterValue('startDate')
39 dt2 = op.getParameterValue('endDate')
39 dt2 = op.getParameterValue('endDate')
40 tm1 = op.getParameterValue('startTime')
40 tm1 = op.getParameterValue('startTime')
41 tm2 = op.getParameterValue('endTime')
41 tm2 = op.getParameterValue('endTime')
42 days = (dt2 - dt1).days
42 days = (dt2 - dt1).days
43
43
44 for day in range(days + 1):
44 for day in range(days + 1):
45 skip = 0
45 skip = 0
46 cursor = 0
46 cursor = 0
47 processes = []
47 processes = []
48 dt = dt1 + datetime.timedelta(day)
48 dt = dt1 + datetime.timedelta(day)
49 dt_str = dt.strftime('%Y/%m/%d')
49 dt_str = dt.strftime('%Y/%m/%d')
50 reader = JRODataReader()
50 reader = JRODataReader()
51 paths, files = reader.searchFilesOffLine(path=rconf.path,
51 paths, files = reader.searchFilesOffLine(path=rconf.path,
52 startDate=dt,
52 startDate=dt,
53 endDate=dt,
53 endDate=dt,
54 startTime=tm1,
54 startTime=tm1,
55 endTime=tm2,
55 endTime=tm2,
56 ext=DTYPES[rconf.datatype])
56 ext=DTYPES[rconf.datatype])
57 nFiles = len(files)
57 nFiles = len(files)
58 if nFiles == 0:
58 if nFiles == 0:
59 continue
59 continue
60 skip = int(math.ceil(nFiles / n))
60 skip = int(math.ceil(nFiles / n))
61 while nFiles > cursor * skip:
61 while nFiles > cursor * skip:
62 rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor,
62 rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor,
63 skip=skip)
63 skip=skip)
64 p = project.clone()
64 p = project.clone()
65 p.start()
65 p.start()
66 processes.append(p)
66 processes.append(p)
67 cursor += 1
67 cursor += 1
68
68
69 def beforeExit(exctype, value, trace):
69 def beforeExit(exctype, value, trace):
70 for process in processes:
70 for process in processes:
71 process.terminate()
71 process.terminate()
72 process.join()
72 process.join()
73 print(traceback.print_tb(trace))
73 print(traceback.print_tb(trace))
74
74
75 sys.excepthook = beforeExit
75 sys.excepthook = beforeExit
76
76
77 for process in processes:
77 for process in processes:
78 process.join()
78 process.join()
79 process.terminate()
79 process.terminate()
80
80
81 time.sleep(3)
81 time.sleep(3)
82
82
83 def wait(context):
83 def wait(context):
84
84
85 time.sleep(1)
85 time.sleep(1)
86 c = zmq.Context()
86 c = zmq.Context()
87 receiver = c.socket(zmq.SUB)
87 receiver = c.socket(zmq.SUB)
88 receiver.connect('ipc:///tmp/schain_{}_pub'.format(self.id))
88 receiver.connect('ipc:///tmp/schain_{}_pub'.format(self.id))
89 receiver.setsockopt(zmq.SUBSCRIBE, self.id.encode())
89 receiver.setsockopt(zmq.SUBSCRIBE, self.id.encode())
90 msg = receiver.recv_multipart()[1]
90 msg = receiver.recv_multipart()[1]
91 context.terminate()
91 context.terminate()
92
92
93 class ParameterConf():
93 class ParameterConf():
94
94
95 id = None
95 id = None
96 name = None
96 name = None
97 value = None
97 value = None
98 format = None
98 format = None
99
99
100 __formated_value = None
100 __formated_value = None
101
101
102 ELEMENTNAME = 'Parameter'
102 ELEMENTNAME = 'Parameter'
103
103
104 def __init__(self):
104 def __init__(self):
105
105
106 self.format = 'str'
106 self.format = 'str'
107
107
108 def getElementName(self):
108 def getElementName(self):
109
109
110 return self.ELEMENTNAME
110 return self.ELEMENTNAME
111
111
112 def getValue(self):
112 def getValue(self):
113
113
114 value = self.value
114 value = self.value
115 format = self.format
115 format = self.format
116
116
117 if self.__formated_value != None:
117 if self.__formated_value != None:
118
118
119 return self.__formated_value
119 return self.__formated_value
120
120
121 if format == 'obj':
121 if format == 'obj':
122 return value
122 return value
123
123
124 if format == 'str':
124 if format == 'str':
125 self.__formated_value = str(value)
125 self.__formated_value = str(value)
126 return self.__formated_value
126 return self.__formated_value
127
127
128 if value == '':
128 if value == '':
129 raise ValueError('%s: This parameter value is empty' % self.name)
129 raise ValueError('%s: This parameter value is empty' % self.name)
130
130
131 if format == 'list':
131 if format == 'list':
132 strList = [s.strip() for s in value.split(',')]
132 strList = [s.strip() for s in value.split(',')]
133 self.__formated_value = strList
133 self.__formated_value = strList
134
134
135 return self.__formated_value
135 return self.__formated_value
136
136
137 if format == 'intlist':
137 if format == 'intlist':
138 '''
138 '''
139 Example:
139 Example:
140 value = (0,1,2)
140 value = (0,1,2)
141 '''
141 '''
142
142
143 new_value = ast.literal_eval(value)
143 new_value = ast.literal_eval(value)
144
144
145 if type(new_value) not in (tuple, list):
145 if type(new_value) not in (tuple, list):
146 new_value = [int(new_value)]
146 new_value = [int(new_value)]
147
147
148 self.__formated_value = new_value
148 self.__formated_value = new_value
149
149
150 return self.__formated_value
150 return self.__formated_value
151
151
152 if format == 'floatlist':
152 if format == 'floatlist':
153 '''
153 '''
154 Example:
154 Example:
155 value = (0.5, 1.4, 2.7)
155 value = (0.5, 1.4, 2.7)
156 '''
156 '''
157
157
158 new_value = ast.literal_eval(value)
158 new_value = ast.literal_eval(value)
159
159
160 if type(new_value) not in (tuple, list):
160 if type(new_value) not in (tuple, list):
161 new_value = [float(new_value)]
161 new_value = [float(new_value)]
162
162
163 self.__formated_value = new_value
163 self.__formated_value = new_value
164
164
165 return self.__formated_value
165 return self.__formated_value
166
166
167 if format == 'date':
167 if format == 'date':
168 strList = value.split('/')
168 strList = value.split('/')
169 intList = [int(x) for x in strList]
169 intList = [int(x) for x in strList]
170 date = datetime.date(intList[0], intList[1], intList[2])
170 date = datetime.date(intList[0], intList[1], intList[2])
171
171
172 self.__formated_value = date
172 self.__formated_value = date
173
173
174 return self.__formated_value
174 return self.__formated_value
175
175
176 if format == 'time':
176 if format == 'time':
177 strList = value.split(':')
177 strList = value.split(':')
178 intList = [int(x) for x in strList]
178 intList = [int(x) for x in strList]
179 time = datetime.time(intList[0], intList[1], intList[2])
179 time = datetime.time(intList[0], intList[1], intList[2])
180
180
181 self.__formated_value = time
181 self.__formated_value = time
182
182
183 return self.__formated_value
183 return self.__formated_value
184
184
185 if format == 'pairslist':
185 if format == 'pairslist':
186 '''
186 '''
187 Example:
187 Example:
188 value = (0,1),(1,2)
188 value = (0,1),(1,2)
189 '''
189 '''
190
190
191 new_value = ast.literal_eval(value)
191 new_value = ast.literal_eval(value)
192
192
193 if type(new_value) not in (tuple, list):
193 if type(new_value) not in (tuple, list):
194 raise ValueError('%s has to be a tuple or list of pairs' % value)
194 raise ValueError('%s has to be a tuple or list of pairs' % value)
195
195
196 if type(new_value[0]) not in (tuple, list):
196 if type(new_value[0]) not in (tuple, list):
197 if len(new_value) != 2:
197 if len(new_value) != 2:
198 raise ValueError('%s has to be a tuple or list of pairs' % value)
198 raise ValueError('%s has to be a tuple or list of pairs' % value)
199 new_value = [new_value]
199 new_value = [new_value]
200
200
201 for thisPair in new_value:
201 for thisPair in new_value:
202 if len(thisPair) != 2:
202 if len(thisPair) != 2:
203 raise ValueError('%s has to be a tuple or list of pairs' % value)
203 raise ValueError('%s has to be a tuple or list of pairs' % value)
204
204
205 self.__formated_value = new_value
205 self.__formated_value = new_value
206
206
207 return self.__formated_value
207 return self.__formated_value
208
208
209 if format == 'multilist':
209 if format == 'multilist':
210 '''
210 '''
211 Example:
211 Example:
212 value = (0,1,2),(3,4,5)
212 value = (0,1,2),(3,4,5)
213 '''
213 '''
214 multiList = ast.literal_eval(value)
214 multiList = ast.literal_eval(value)
215
215
216 if type(multiList[0]) == int:
216 if type(multiList[0]) == int:
217 multiList = ast.literal_eval('(' + value + ')')
217 multiList = ast.literal_eval('(' + value + ')')
218
218
219 self.__formated_value = multiList
219 self.__formated_value = multiList
220
220
221 return self.__formated_value
221 return self.__formated_value
222
222
223 if format == 'bool':
223 if format == 'bool':
224 value = int(value)
224 value = int(value)
225
225
226 if format == 'int':
226 if format == 'int':
227 value = float(value)
227 value = float(value)
228
228
229 format_func = eval(format)
229 format_func = eval(format)
230
230
231 self.__formated_value = format_func(value)
231 self.__formated_value = format_func(value)
232
232
233 return self.__formated_value
233 return self.__formated_value
234
234
235 def updateId(self, new_id):
235 def updateId(self, new_id):
236
236
237 self.id = str(new_id)
237 self.id = str(new_id)
238
238
239 def setup(self, id, name, value, format='str'):
239 def setup(self, id, name, value, format='str'):
240 self.id = str(id)
240 self.id = str(id)
241 self.name = name
241 self.name = name
242 if format == 'obj':
242 if format == 'obj':
243 self.value = value
243 self.value = value
244 else:
244 else:
245 self.value = str(value)
245 self.value = str(value)
246 self.format = str.lower(format)
246 self.format = str.lower(format)
247
247
248 self.getValue()
248 self.getValue()
249
249
250 return 1
250 return 1
251
251
252 def update(self, name, value, format='str'):
252 def update(self, name, value, format='str'):
253
253
254 self.name = name
254 self.name = name
255 self.value = str(value)
255 self.value = str(value)
256 self.format = format
256 self.format = format
257
257
258 def makeXml(self, opElement):
258 def makeXml(self, opElement):
259 if self.name not in ('queue',):
259 if self.name not in ('queue',):
260 parmElement = SubElement(opElement, self.ELEMENTNAME)
260 parmElement = SubElement(opElement, self.ELEMENTNAME)
261 parmElement.set('id', str(self.id))
261 parmElement.set('id', str(self.id))
262 parmElement.set('name', self.name)
262 parmElement.set('name', self.name)
263 parmElement.set('value', self.value)
263 parmElement.set('value', self.value)
264 parmElement.set('format', self.format)
264 parmElement.set('format', self.format)
265
265
266 def readXml(self, parmElement):
266 def readXml(self, parmElement):
267
267
268 self.id = parmElement.get('id')
268 self.id = parmElement.get('id')
269 self.name = parmElement.get('name')
269 self.name = parmElement.get('name')
270 self.value = parmElement.get('value')
270 self.value = parmElement.get('value')
271 self.format = str.lower(parmElement.get('format'))
271 self.format = str.lower(parmElement.get('format'))
272
272
273 # Compatible with old signal chain version
273 # Compatible with old signal chain version
274 if self.format == 'int' and self.name == 'idfigure':
274 if self.format == 'int' and self.name == 'idfigure':
275 self.name = 'id'
275 self.name = 'id'
276
276
277 def printattr(self):
277 def printattr(self):
278
278
279 print('Parameter[%s]: name = %s, value = %s, format = %s, project_id = %s' % (self.id, self.name, self.value, self.format, self.project_id))
279 print('Parameter[%s]: name = %s, value = %s, format = %s, project_id = %s' % (self.id, self.name, self.value, self.format, self.project_id))
280
280
281 class OperationConf():
281 class OperationConf():
282
282
283 ELEMENTNAME = 'Operation'
283 ELEMENTNAME = 'Operation'
284
284
285 def __init__(self):
285 def __init__(self):
286
286
287 self.id = '0'
287 self.id = '0'
288 self.name = None
288 self.name = None
289 self.priority = None
289 self.priority = None
290 self.topic = None
290 self.topic = None
291
291
292 def __getNewId(self):
292 def __getNewId(self):
293
293
294 return int(self.id) * 10 + len(self.parmConfObjList) + 1
294 return int(self.id) * 10 + len(self.parmConfObjList) + 1
295
295
296 def getId(self):
296 def getId(self):
297 return self.id
297 return self.id
298
298
299 def updateId(self, new_id):
299 def updateId(self, new_id):
300
300
301 self.id = str(new_id)
301 self.id = str(new_id)
302
302
303 n = 1
303 n = 1
304 for parmObj in self.parmConfObjList:
304 for parmObj in self.parmConfObjList:
305
305
306 idParm = str(int(new_id) * 10 + n)
306 idParm = str(int(new_id) * 10 + n)
307 parmObj.updateId(idParm)
307 parmObj.updateId(idParm)
308
308
309 n += 1
309 n += 1
310
310
311 def getElementName(self):
311 def getElementName(self):
312
312
313 return self.ELEMENTNAME
313 return self.ELEMENTNAME
314
314
315 def getParameterObjList(self):
315 def getParameterObjList(self):
316
316
317 return self.parmConfObjList
317 return self.parmConfObjList
318
318
319 def getParameterObj(self, parameterName):
319 def getParameterObj(self, parameterName):
320
320
321 for parmConfObj in self.parmConfObjList:
321 for parmConfObj in self.parmConfObjList:
322
322
323 if parmConfObj.name != parameterName:
323 if parmConfObj.name != parameterName:
324 continue
324 continue
325
325
326 return parmConfObj
326 return parmConfObj
327
327
328 return None
328 return None
329
329
330 def getParameterObjfromValue(self, parameterValue):
330 def getParameterObjfromValue(self, parameterValue):
331
331
332 for parmConfObj in self.parmConfObjList:
332 for parmConfObj in self.parmConfObjList:
333
333
334 if parmConfObj.getValue() != parameterValue:
334 if parmConfObj.getValue() != parameterValue:
335 continue
335 continue
336
336
337 return parmConfObj.getValue()
337 return parmConfObj.getValue()
338
338
339 return None
339 return None
340
340
341 def getParameterValue(self, parameterName):
341 def getParameterValue(self, parameterName):
342
342
343 parameterObj = self.getParameterObj(parameterName)
343 parameterObj = self.getParameterObj(parameterName)
344
344
345 # if not parameterObj:
345 # if not parameterObj:
346 # return None
346 # return None
347
347
348 value = parameterObj.getValue()
348 value = parameterObj.getValue()
349
349
350 return value
350 return value
351
351
352 def getKwargs(self):
352 def getKwargs(self):
353
353
354 kwargs = {}
354 kwargs = {}
355
355
356 for parmConfObj in self.parmConfObjList:
356 for parmConfObj in self.parmConfObjList:
357 if self.name == 'run' and parmConfObj.name == 'datatype':
357 if self.name == 'run' and parmConfObj.name == 'datatype':
358 continue
358 continue
359
359
360 kwargs[parmConfObj.name] = parmConfObj.getValue()
360 kwargs[parmConfObj.name] = parmConfObj.getValue()
361
361
362 return kwargs
362 return kwargs
363
363
364 def setup(self, id, name, priority, type, project_id, err_queue, lock):
364 def setup(self, id, name, priority, type, project_id, err_queue, lock):
365
365
366 self.id = str(id)
366 self.id = str(id)
367 self.project_id = project_id
367 self.project_id = project_id
368 self.name = name
368 self.name = name
369 self.type = type
369 self.type = type
370 self.priority = priority
370 self.priority = priority
371 self.err_queue = err_queue
371 self.err_queue = err_queue
372 self.lock = lock
372 self.lock = lock
373 self.parmConfObjList = []
373 self.parmConfObjList = []
374
374
375 def removeParameters(self):
375 def removeParameters(self):
376
376
377 for obj in self.parmConfObjList:
377 for obj in self.parmConfObjList:
378 del obj
378 del obj
379
379
380 self.parmConfObjList = []
380 self.parmConfObjList = []
381
381
382 def addParameter(self, name, value, format='str'):
382 def addParameter(self, name, value, format='str'):
383
383
384 if value is None:
384 if value is None:
385 return None
385 return None
386 id = self.__getNewId()
386 id = self.__getNewId()
387
387
388 parmConfObj = ParameterConf()
388 parmConfObj = ParameterConf()
389 if not parmConfObj.setup(id, name, value, format):
389 if not parmConfObj.setup(id, name, value, format):
390 return None
390 return None
391
391
392 self.parmConfObjList.append(parmConfObj)
392 self.parmConfObjList.append(parmConfObj)
393
393
394 return parmConfObj
394 return parmConfObj
395
395
396 def changeParameter(self, name, value, format='str'):
396 def changeParameter(self, name, value, format='str'):
397
397
398 parmConfObj = self.getParameterObj(name)
398 parmConfObj = self.getParameterObj(name)
399 parmConfObj.update(name, value, format)
399 parmConfObj.update(name, value, format)
400
400
401 return parmConfObj
401 return parmConfObj
402
402
403 def makeXml(self, procUnitElement):
403 def makeXml(self, procUnitElement):
404
404
405 opElement = SubElement(procUnitElement, self.ELEMENTNAME)
405 opElement = SubElement(procUnitElement, self.ELEMENTNAME)
406 opElement.set('id', str(self.id))
406 opElement.set('id', str(self.id))
407 opElement.set('name', self.name)
407 opElement.set('name', self.name)
408 opElement.set('type', self.type)
408 opElement.set('type', self.type)
409 opElement.set('priority', str(self.priority))
409 opElement.set('priority', str(self.priority))
410
410
411 for parmConfObj in self.parmConfObjList:
411 for parmConfObj in self.parmConfObjList:
412 parmConfObj.makeXml(opElement)
412 parmConfObj.makeXml(opElement)
413
413
414 def readXml(self, opElement, project_id):
414 def readXml(self, opElement, project_id):
415
415
416 self.id = opElement.get('id')
416 self.id = opElement.get('id')
417 self.name = opElement.get('name')
417 self.name = opElement.get('name')
418 self.type = opElement.get('type')
418 self.type = opElement.get('type')
419 self.priority = opElement.get('priority')
419 self.priority = opElement.get('priority')
420 self.project_id = str(project_id)
420 self.project_id = str(project_id)
421
421
422 # Compatible with old signal chain version
422 # Compatible with old signal chain version
423 # Use of 'run' method instead 'init'
423 # Use of 'run' method instead 'init'
424 if self.type == 'self' and self.name == 'init':
424 if self.type == 'self' and self.name == 'init':
425 self.name = 'run'
425 self.name = 'run'
426
426
427 self.parmConfObjList = []
427 self.parmConfObjList = []
428
428
429 parmElementList = opElement.iter(ParameterConf().getElementName())
429 parmElementList = opElement.iter(ParameterConf().getElementName())
430
430
431 for parmElement in parmElementList:
431 for parmElement in parmElementList:
432 parmConfObj = ParameterConf()
432 parmConfObj = ParameterConf()
433 parmConfObj.readXml(parmElement)
433 parmConfObj.readXml(parmElement)
434
434
435 # Compatible with old signal chain version
435 # Compatible with old signal chain version
436 # If an 'plot' OPERATION is found, changes name operation by the value of its type PARAMETER
436 # If an 'plot' OPERATION is found, changes name operation by the value of its type PARAMETER
437 if self.type != 'self' and self.name == 'Plot':
437 if self.type != 'self' and self.name == 'Plot':
438 if parmConfObj.format == 'str' and parmConfObj.name == 'type':
438 if parmConfObj.format == 'str' and parmConfObj.name == 'type':
439 self.name = parmConfObj.value
439 self.name = parmConfObj.value
440 continue
440 continue
441
441
442 self.parmConfObjList.append(parmConfObj)
442 self.parmConfObjList.append(parmConfObj)
443
443
444 def printattr(self):
444 def printattr(self):
445
445
446 print('%s[%s]: name = %s, type = %s, priority = %s, project_id = %s' % (self.ELEMENTNAME,
446 print('%s[%s]: name = %s, type = %s, priority = %s, project_id = %s' % (self.ELEMENTNAME,
447 self.id,
447 self.id,
448 self.name,
448 self.name,
449 self.type,
449 self.type,
450 self.priority,
450 self.priority,
451 self.project_id))
451 self.project_id))
452
452
453 for parmConfObj in self.parmConfObjList:
453 for parmConfObj in self.parmConfObjList:
454 parmConfObj.printattr()
454 parmConfObj.printattr()
455
455
456 def createObject(self):
456 def createObject(self):
457
457
458 className = eval(self.name)
458 className = eval(self.name)
459
459
460 if self.type == 'other':
460 if self.type == 'other':
461 opObj = className()
461 opObj = className()
462 elif self.type == 'external':
462 elif self.type == 'external':
463 kwargs = self.getKwargs()
463 kwargs = self.getKwargs()
464 opObj = className(self.id, self.id, self.project_id, self.err_queue, self.lock, 'Operation', **kwargs)
464 opObj = className(self.id, self.id, self.project_id, self.err_queue, self.lock, 'Operation', **kwargs)
465 opObj.start()
465 opObj.start()
466 self.opObj = opObj
466 self.opObj = opObj
467
467
468 return opObj
468 return opObj
469
469
470 class ProcUnitConf():
470 class ProcUnitConf():
471
471
472 ELEMENTNAME = 'ProcUnit'
472 ELEMENTNAME = 'ProcUnit'
473
473
474 def __init__(self):
474 def __init__(self):
475
475
476 self.id = None
476 self.id = None
477 self.datatype = None
477 self.datatype = None
478 self.name = None
478 self.name = None
479 self.inputId = None
479 self.inputId = None
480 self.opConfObjList = []
480 self.opConfObjList = []
481 self.procUnitObj = None
481 self.procUnitObj = None
482 self.opObjDict = {}
482 self.opObjDict = {}
483
483
484 def __getPriority(self):
484 def __getPriority(self):
485
485
486 return len(self.opConfObjList) + 1
486 return len(self.opConfObjList) + 1
487
487
488 def __getNewId(self):
488 def __getNewId(self):
489
489
490 return int(self.id) * 10 + len(self.opConfObjList) + 1
490 return int(self.id) * 10 + len(self.opConfObjList) + 1
491
491
492 def getElementName(self):
492 def getElementName(self):
493
493
494 return self.ELEMENTNAME
494 return self.ELEMENTNAME
495
495
496 def getId(self):
496 def getId(self):
497
497
498 return self.id
498 return self.id
499
499
500 def updateId(self, new_id):
500 def updateId(self, new_id):
501 '''
501 '''
502 new_id = int(parentId) * 10 + (int(self.id) % 10)
502 new_id = int(parentId) * 10 + (int(self.id) % 10)
503 new_inputId = int(parentId) * 10 + (int(self.inputId) % 10)
503 new_inputId = int(parentId) * 10 + (int(self.inputId) % 10)
504
504
505 # If this proc unit has not inputs
505 # If this proc unit has not inputs
506 #if self.inputId == '0':
506 #if self.inputId == '0':
507 #new_inputId = 0
507 #new_inputId = 0
508
508
509 n = 1
509 n = 1
510 for opConfObj in self.opConfObjList:
510 for opConfObj in self.opConfObjList:
511
511
512 idOp = str(int(new_id) * 10 + n)
512 idOp = str(int(new_id) * 10 + n)
513 opConfObj.updateId(idOp)
513 opConfObj.updateId(idOp)
514
514
515 n += 1
515 n += 1
516
516
517 self.parentId = str(parentId)
517 self.parentId = str(parentId)
518 self.id = str(new_id)
518 self.id = str(new_id)
519 #self.inputId = str(new_inputId)
519 #self.inputId = str(new_inputId)
520 '''
520 '''
521 n = 1
521 n = 1
522
522
523 def getInputId(self):
523 def getInputId(self):
524
524
525 return self.inputId
525 return self.inputId
526
526
527 def getOperationObjList(self):
527 def getOperationObjList(self):
528
528
529 return self.opConfObjList
529 return self.opConfObjList
530
530
531 def getOperationObj(self, name=None):
531 def getOperationObj(self, name=None):
532
532
533 for opConfObj in self.opConfObjList:
533 for opConfObj in self.opConfObjList:
534
534
535 if opConfObj.name != name:
535 if opConfObj.name != name:
536 continue
536 continue
537
537
538 return opConfObj
538 return opConfObj
539
539
540 return None
540 return None
541
541
542 def getOpObjfromParamValue(self, value=None):
542 def getOpObjfromParamValue(self, value=None):
543
543
544 for opConfObj in self.opConfObjList:
544 for opConfObj in self.opConfObjList:
545 if opConfObj.getParameterObjfromValue(parameterValue=value) != value:
545 if opConfObj.getParameterObjfromValue(parameterValue=value) != value:
546 continue
546 continue
547 return opConfObj
547 return opConfObj
548 return None
548 return None
549
549
550 def getProcUnitObj(self):
550 def getProcUnitObj(self):
551
551
552 return self.procUnitObj
552 return self.procUnitObj
553
553
554 def setup(self, project_id, id, name, datatype, inputId, err_queue, lock):
554 def setup(self, project_id, id, name, datatype, inputId, err_queue, lock):
555 '''
555 '''
556 id sera el topico a publicar
556 id sera el topico a publicar
557 inputId sera el topico a subscribirse
557 inputId sera el topico a subscribirse
558 '''
558 '''
559
559
560 # Compatible with old signal chain version
560 # Compatible with old signal chain version
561 if datatype == None and name == None:
561 if datatype == None and name == None:
562 raise ValueError('datatype or name should be defined')
562 raise ValueError('datatype or name should be defined')
563
563
564 #Definir una condicion para inputId cuando sea 0
564 #Definir una condicion para inputId cuando sea 0
565
565
566 if name == None:
566 if name == None:
567 if 'Proc' in datatype:
567 if 'Proc' in datatype:
568 name = datatype
568 name = datatype
569 else:
569 else:
570 name = '%sProc' % (datatype)
570 name = '%sProc' % (datatype)
571
571
572 if datatype == None:
572 if datatype == None:
573 datatype = name.replace('Proc', '')
573 datatype = name.replace('Proc', '')
574
574
575 self.id = str(id)
575 self.id = str(id)
576 self.project_id = project_id
576 self.project_id = project_id
577 self.name = name
577 self.name = name
578 self.datatype = datatype
578 self.datatype = datatype
579 self.inputId = inputId
579 self.inputId = inputId
580 self.err_queue = err_queue
580 self.err_queue = err_queue
581 self.lock = lock
581 self.lock = lock
582 self.opConfObjList = []
582 self.opConfObjList = []
583
583
584 self.addOperation(name='run', optype='self')
584 self.addOperation(name='run', optype='self')
585
585
586 def removeOperations(self):
586 def removeOperations(self):
587
587
588 for obj in self.opConfObjList:
588 for obj in self.opConfObjList:
589 del obj
589 del obj
590
590
591 self.opConfObjList = []
591 self.opConfObjList = []
592 self.addOperation(name='run')
592 self.addOperation(name='run')
593
593
594 def addParameter(self, **kwargs):
594 def addParameter(self, **kwargs):
595 '''
595 '''
596 Add parameters to 'run' operation
596 Add parameters to 'run' operation
597 '''
597 '''
598 opObj = self.opConfObjList[0]
598 opObj = self.opConfObjList[0]
599
599
600 opObj.addParameter(**kwargs)
600 opObj.addParameter(**kwargs)
601
601
602 return opObj
602 return opObj
603
603
604 def addOperation(self, name, optype='self'):
604 def addOperation(self, name, optype='self'):
605 '''
605 '''
606 Actualizacion - > proceso comunicacion
606 Actualizacion - > proceso comunicacion
607 En el caso de optype='self', elminar. DEfinir comuncacion IPC -> Topic
607 En el caso de optype='self', elminar. DEfinir comuncacion IPC -> Topic
608 definir el tipoc de socket o comunicacion ipc++
608 definir el tipoc de socket o comunicacion ipc++
609
609
610 '''
610 '''
611
611
612 id = self.__getNewId()
612 id = self.__getNewId()
613 priority = self.__getPriority() # Sin mucho sentido, pero puede usarse
613 priority = self.__getPriority() # Sin mucho sentido, pero puede usarse
614 opConfObj = OperationConf()
614 opConfObj = OperationConf()
615 opConfObj.setup(id, name=name, priority=priority, type=optype, project_id=self.project_id, err_queue=self.err_queue, lock=self.lock)
615 opConfObj.setup(id, name=name, priority=priority, type=optype, project_id=self.project_id, err_queue=self.err_queue, lock=self.lock)
616 self.opConfObjList.append(opConfObj)
616 self.opConfObjList.append(opConfObj)
617
617
618 return opConfObj
618 return opConfObj
619
619
620 def makeXml(self, projectElement):
620 def makeXml(self, projectElement):
621
621
622 procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
622 procUnitElement = SubElement(projectElement, self.ELEMENTNAME)
623 procUnitElement.set('id', str(self.id))
623 procUnitElement.set('id', str(self.id))
624 procUnitElement.set('name', self.name)
624 procUnitElement.set('name', self.name)
625 procUnitElement.set('datatype', self.datatype)
625 procUnitElement.set('datatype', self.datatype)
626 procUnitElement.set('inputId', str(self.inputId))
626 procUnitElement.set('inputId', str(self.inputId))
627
627
628 for opConfObj in self.opConfObjList:
628 for opConfObj in self.opConfObjList:
629 opConfObj.makeXml(procUnitElement)
629 opConfObj.makeXml(procUnitElement)
630
630
631 def readXml(self, upElement, project_id):
631 def readXml(self, upElement, project_id):
632
632
633 self.id = upElement.get('id')
633 self.id = upElement.get('id')
634 self.name = upElement.get('name')
634 self.name = upElement.get('name')
635 self.datatype = upElement.get('datatype')
635 self.datatype = upElement.get('datatype')
636 self.inputId = upElement.get('inputId')
636 self.inputId = upElement.get('inputId')
637 self.project_id = str(project_id)
637 self.project_id = str(project_id)
638
638
639 if self.ELEMENTNAME == 'ReadUnit':
639 if self.ELEMENTNAME == 'ReadUnit':
640 self.datatype = self.datatype.replace('Reader', '')
640 self.datatype = self.datatype.replace('Reader', '')
641
641
642 if self.ELEMENTNAME == 'ProcUnit':
642 if self.ELEMENTNAME == 'ProcUnit':
643 self.datatype = self.datatype.replace('Proc', '')
643 self.datatype = self.datatype.replace('Proc', '')
644
644
645 if self.inputId == 'None':
645 if self.inputId == 'None':
646 self.inputId = '0'
646 self.inputId = '0'
647
647
648 self.opConfObjList = []
648 self.opConfObjList = []
649
649
650 opElementList = upElement.iter(OperationConf().getElementName())
650 opElementList = upElement.iter(OperationConf().getElementName())
651
651
652 for opElement in opElementList:
652 for opElement in opElementList:
653 opConfObj = OperationConf()
653 opConfObj = OperationConf()
654 opConfObj.readXml(opElement, project_id)
654 opConfObj.readXml(opElement, project_id)
655 self.opConfObjList.append(opConfObj)
655 self.opConfObjList.append(opConfObj)
656
656
657 def printattr(self):
657 def printattr(self):
658
658
659 print('%s[%s]: name = %s, datatype = %s, inputId = %s, project_id = %s' % (self.ELEMENTNAME,
659 print('%s[%s]: name = %s, datatype = %s, inputId = %s, project_id = %s' % (self.ELEMENTNAME,
660 self.id,
660 self.id,
661 self.name,
661 self.name,
662 self.datatype,
662 self.datatype,
663 self.inputId,
663 self.inputId,
664 self.project_id))
664 self.project_id))
665
665
666 for opConfObj in self.opConfObjList:
666 for opConfObj in self.opConfObjList:
667 opConfObj.printattr()
667 opConfObj.printattr()
668
668
669 def getKwargs(self):
669 def getKwargs(self):
670
670
671 opObj = self.opConfObjList[0]
671 opObj = self.opConfObjList[0]
672 kwargs = opObj.getKwargs()
672 kwargs = opObj.getKwargs()
673
673
674 return kwargs
674 return kwargs
675
675
676 def createObjects(self):
676 def createObjects(self):
677 '''
677 '''
678 Instancia de unidades de procesamiento.
678 Instancia de unidades de procesamiento.
679 '''
679 '''
680
680
681 className = eval(self.name)
681 className = eval(self.name)
682 #print(self.name)
682 kwargs = self.getKwargs()
683 kwargs = self.getKwargs()
684 #print(kwargs)
685 #print("mark_a")
683 procUnitObj = className(self.id, self.inputId, self.project_id, self.err_queue, self.lock, 'ProcUnit', **kwargs)
686 procUnitObj = className(self.id, self.inputId, self.project_id, self.err_queue, self.lock, 'ProcUnit', **kwargs)
687 #print("mark_b")
684 log.success('creating process...', self.name)
688 log.success('creating process...', self.name)
685
689
686 for opConfObj in self.opConfObjList:
690 for opConfObj in self.opConfObjList:
687
691
688 if opConfObj.type == 'self' and opConfObj.name == 'run':
692 if opConfObj.type == 'self' and opConfObj.name == 'run':
689 continue
693 continue
690 elif opConfObj.type == 'self':
694 elif opConfObj.type == 'self':
691 opObj = getattr(procUnitObj, opConfObj.name)
695 opObj = getattr(procUnitObj, opConfObj.name)
692 else:
696 else:
693 opObj = opConfObj.createObject()
697 opObj = opConfObj.createObject()
694
698
695 log.success('adding operation: {}, type:{}'.format(
699 log.success('adding operation: {}, type:{}'.format(
696 opConfObj.name,
700 opConfObj.name,
697 opConfObj.type), self.name)
701 opConfObj.type), self.name)
698
702
699 procUnitObj.addOperation(opConfObj, opObj)
703 procUnitObj.addOperation(opConfObj, opObj)
700
704
701 procUnitObj.start()
705 procUnitObj.start()
702 self.procUnitObj = procUnitObj
706 self.procUnitObj = procUnitObj
703
707
704 def close(self):
708 def close(self):
705
709
706 for opConfObj in self.opConfObjList:
710 for opConfObj in self.opConfObjList:
707 if opConfObj.type == 'self':
711 if opConfObj.type == 'self':
708 continue
712 continue
709
713
710 opObj = self.procUnitObj.getOperationObj(opConfObj.id)
714 opObj = self.procUnitObj.getOperationObj(opConfObj.id)
711 opObj.close()
715 opObj.close()
712
716
713 self.procUnitObj.close()
717 self.procUnitObj.close()
714
718
715 return
719 return
716
720
717
721
718 class ReadUnitConf(ProcUnitConf):
722 class ReadUnitConf(ProcUnitConf):
719
723
720 ELEMENTNAME = 'ReadUnit'
724 ELEMENTNAME = 'ReadUnit'
721
725
722 def __init__(self):
726 def __init__(self):
723
727
724 self.id = None
728 self.id = None
725 self.datatype = None
729 self.datatype = None
726 self.name = None
730 self.name = None
727 self.inputId = None
731 self.inputId = None
728 self.opConfObjList = []
732 self.opConfObjList = []
729 self.lock = Event()
733 self.lock = Event()
730 self.lock.set()
734 self.lock.set()
731 self.lock.n = Value('d', 0)
735 self.lock.n = Value('d', 0)
732
736
733 def getElementName(self):
737 def getElementName(self):
734
738
735 return self.ELEMENTNAME
739 return self.ELEMENTNAME
736
740
737 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
741 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
738 startTime='', endTime='', server=None, **kwargs):
742 startTime='', endTime='', server=None, **kwargs):
739
743
740
744
741 '''
745 '''
742 *****el id del proceso sera el Topico
746 *****el id del proceso sera el Topico
743
747
744 Adicion de {topic}, si no esta presente -> error
748 Adicion de {topic}, si no esta presente -> error
745 kwargs deben ser trasmitidos en la instanciacion
749 kwargs deben ser trasmitidos en la instanciacion
746
750
747 '''
751 '''
748
752
749 # Compatible with old signal chain version
753 # Compatible with old signal chain version
750 if datatype == None and name == None:
754 if datatype == None and name == None:
751 raise ValueError('datatype or name should be defined')
755 raise ValueError('datatype or name should be defined')
752 if name == None:
756 if name == None:
753 if 'Reader' in datatype:
757 if 'Reader' in datatype:
754 name = datatype
758 name = datatype
755 datatype = name.replace('Reader','')
759 datatype = name.replace('Reader','')
756 else:
760 else:
757 name = '{}Reader'.format(datatype)
761 name = '{}Reader'.format(datatype)
758 if datatype == None:
762 if datatype == None:
759 if 'Reader' in name:
763 if 'Reader' in name:
760 datatype = name.replace('Reader','')
764 datatype = name.replace('Reader','')
761 else:
765 else:
762 datatype = name
766 datatype = name
763 name = '{}Reader'.format(name)
767 name = '{}Reader'.format(name)
764
768
765 self.id = id
769 self.id = id
766 self.project_id = project_id
770 self.project_id = project_id
767 self.name = name
771 self.name = name
768 self.datatype = datatype
772 self.datatype = datatype
769 if path != '':
773 if path != '':
770 self.path = os.path.abspath(path)
774 self.path = os.path.abspath(path)
775 print (self.path)
771 self.startDate = startDate
776 self.startDate = startDate
772 self.endDate = endDate
777 self.endDate = endDate
773 self.startTime = startTime
778 self.startTime = startTime
774 self.endTime = endTime
779 self.endTime = endTime
775 self.server = server
780 self.server = server
776 self.err_queue = err_queue
781 self.err_queue = err_queue
777 self.addRunOperation(**kwargs)
782 self.addRunOperation(**kwargs)
778
783
779 def update(self, **kwargs):
784 def update(self, **kwargs):
780
785
781 if 'datatype' in kwargs:
786 if 'datatype' in kwargs:
782 datatype = kwargs.pop('datatype')
787 datatype = kwargs.pop('datatype')
783 if 'Reader' in datatype:
788 if 'Reader' in datatype:
784 self.name = datatype
789 self.name = datatype
785 else:
790 else:
786 self.name = '%sReader' % (datatype)
791 self.name = '%sReader' % (datatype)
787 self.datatype = self.name.replace('Reader', '')
792 self.datatype = self.name.replace('Reader', '')
788
793
789 attrs = ('path', 'startDate', 'endDate',
794 attrs = ('path', 'startDate', 'endDate',
790 'startTime', 'endTime')
795 'startTime', 'endTime')
791
796
792 for attr in attrs:
797 for attr in attrs:
793 if attr in kwargs:
798 if attr in kwargs:
794 setattr(self, attr, kwargs.pop(attr))
799 setattr(self, attr, kwargs.pop(attr))
795
800
796 self.updateRunOperation(**kwargs)
801 self.updateRunOperation(**kwargs)
797
802
798 def removeOperations(self):
803 def removeOperations(self):
799
804
800 for obj in self.opConfObjList:
805 for obj in self.opConfObjList:
801 del obj
806 del obj
802
807
803 self.opConfObjList = []
808 self.opConfObjList = []
804
809
805 def addRunOperation(self, **kwargs):
810 def addRunOperation(self, **kwargs):
806
811
807 opObj = self.addOperation(name='run', optype='self')
812 opObj = self.addOperation(name='run', optype='self')
808
813
809 if self.server is None:
814 if self.server is None:
810 opObj.addParameter(
815 opObj.addParameter(
811 name='datatype', value=self.datatype, format='str')
816 name='datatype', value=self.datatype, format='str')
812 opObj.addParameter(name='path', value=self.path, format='str')
817 opObj.addParameter(name='path', value=self.path, format='str')
813 opObj.addParameter(
818 opObj.addParameter(
814 name='startDate', value=self.startDate, format='date')
819 name='startDate', value=self.startDate, format='date')
815 opObj.addParameter(
820 opObj.addParameter(
816 name='endDate', value=self.endDate, format='date')
821 name='endDate', value=self.endDate, format='date')
817 opObj.addParameter(
822 opObj.addParameter(
818 name='startTime', value=self.startTime, format='time')
823 name='startTime', value=self.startTime, format='time')
819 opObj.addParameter(
824 opObj.addParameter(
820 name='endTime', value=self.endTime, format='time')
825 name='endTime', value=self.endTime, format='time')
821
826
822 for key, value in list(kwargs.items()):
827 for key, value in list(kwargs.items()):
823 opObj.addParameter(name=key, value=value,
828 opObj.addParameter(name=key, value=value,
824 format=type(value).__name__)
829 format=type(value).__name__)
825 else:
830 else:
826 opObj.addParameter(name='server', value=self.server, format='str')
831 opObj.addParameter(name='server', value=self.server, format='str')
827
832
828 return opObj
833 return opObj
829
834
830 def updateRunOperation(self, **kwargs):
835 def updateRunOperation(self, **kwargs):
831
836
832 opObj = self.getOperationObj(name='run')
837 opObj = self.getOperationObj(name='run')
833 opObj.removeParameters()
838 opObj.removeParameters()
834
839
835 opObj.addParameter(name='datatype', value=self.datatype, format='str')
840 opObj.addParameter(name='datatype', value=self.datatype, format='str')
836 opObj.addParameter(name='path', value=self.path, format='str')
841 opObj.addParameter(name='path', value=self.path, format='str')
837 opObj.addParameter(
842 opObj.addParameter(
838 name='startDate', value=self.startDate, format='date')
843 name='startDate', value=self.startDate, format='date')
839 opObj.addParameter(name='endDate', value=self.endDate, format='date')
844 opObj.addParameter(name='endDate', value=self.endDate, format='date')
840 opObj.addParameter(
845 opObj.addParameter(
841 name='startTime', value=self.startTime, format='time')
846 name='startTime', value=self.startTime, format='time')
842 opObj.addParameter(name='endTime', value=self.endTime, format='time')
847 opObj.addParameter(name='endTime', value=self.endTime, format='time')
843
848
844 for key, value in list(kwargs.items()):
849 for key, value in list(kwargs.items()):
845 opObj.addParameter(name=key, value=value,
850 opObj.addParameter(name=key, value=value,
846 format=type(value).__name__)
851 format=type(value).__name__)
847
852
848 return opObj
853 return opObj
849
854
850 def readXml(self, upElement, project_id):
855 def readXml(self, upElement, project_id):
851
856
852 self.id = upElement.get('id')
857 self.id = upElement.get('id')
853 self.name = upElement.get('name')
858 self.name = upElement.get('name')
854 self.datatype = upElement.get('datatype')
859 self.datatype = upElement.get('datatype')
855 self.project_id = str(project_id) #yong
860 self.project_id = str(project_id) #yong
856
861
857 if self.ELEMENTNAME == 'ReadUnit':
862 if self.ELEMENTNAME == 'ReadUnit':
858 self.datatype = self.datatype.replace('Reader', '')
863 self.datatype = self.datatype.replace('Reader', '')
859
864
860 self.opConfObjList = []
865 self.opConfObjList = []
861
866
862 opElementList = upElement.iter(OperationConf().getElementName())
867 opElementList = upElement.iter(OperationConf().getElementName())
863
868
864 for opElement in opElementList:
869 for opElement in opElementList:
865 opConfObj = OperationConf()
870 opConfObj = OperationConf()
866 opConfObj.readXml(opElement, project_id)
871 opConfObj.readXml(opElement, project_id)
867 self.opConfObjList.append(opConfObj)
872 self.opConfObjList.append(opConfObj)
868
873
869 if opConfObj.name == 'run':
874 if opConfObj.name == 'run':
870 self.path = opConfObj.getParameterValue('path')
875 self.path = opConfObj.getParameterValue('path')
871 self.startDate = opConfObj.getParameterValue('startDate')
876 self.startDate = opConfObj.getParameterValue('startDate')
872 self.endDate = opConfObj.getParameterValue('endDate')
877 self.endDate = opConfObj.getParameterValue('endDate')
873 self.startTime = opConfObj.getParameterValue('startTime')
878 self.startTime = opConfObj.getParameterValue('startTime')
874 self.endTime = opConfObj.getParameterValue('endTime')
879 self.endTime = opConfObj.getParameterValue('endTime')
875
880
876
881
877 class Project(Process):
882 class Project(Process):
878
883
879 ELEMENTNAME = 'Project'
884 ELEMENTNAME = 'Project'
880
885
881 def __init__(self):
886 def __init__(self):
882
887
883 Process.__init__(self)
888 Process.__init__(self)
884 self.id = None
889 self.id = None
885 self.filename = None
890 self.filename = None
886 self.description = None
891 self.description = None
887 self.email = None
892 self.email = None
888 self.alarm = None
893 self.alarm = None
889 self.procUnitConfObjDict = {}
894 self.procUnitConfObjDict = {}
890 self.err_queue = Queue()
895 self.err_queue = Queue()
891
896
892 def __getNewId(self):
897 def __getNewId(self):
893
898
894 idList = list(self.procUnitConfObjDict.keys())
899 idList = list(self.procUnitConfObjDict.keys())
895 id = int(self.id) * 10
900 id = int(self.id) * 10
896
901
897 while True:
902 while True:
898 id += 1
903 id += 1
899
904
900 if str(id) in idList:
905 if str(id) in idList:
901 continue
906 continue
902
907
903 break
908 break
904
909
905 return str(id)
910 return str(id)
906
911
907 def getElementName(self):
912 def getElementName(self):
908
913
909 return self.ELEMENTNAME
914 return self.ELEMENTNAME
910
915
911 def getId(self):
916 def getId(self):
912
917
913 return self.id
918 return self.id
914
919
915 def updateId(self, new_id):
920 def updateId(self, new_id):
916
921
917 self.id = str(new_id)
922 self.id = str(new_id)
918
923
919 keyList = list(self.procUnitConfObjDict.keys())
924 keyList = list(self.procUnitConfObjDict.keys())
920 keyList.sort()
925 keyList.sort()
921
926
922 n = 1
927 n = 1
923 newProcUnitConfObjDict = {}
928 newProcUnitConfObjDict = {}
924
929
925 for procKey in keyList:
930 for procKey in keyList:
926
931
927 procUnitConfObj = self.procUnitConfObjDict[procKey]
932 procUnitConfObj = self.procUnitConfObjDict[procKey]
928 idProcUnit = str(int(self.id) * 10 + n)
933 idProcUnit = str(int(self.id) * 10 + n)
929 procUnitConfObj.updateId(idProcUnit)
934 procUnitConfObj.updateId(idProcUnit)
930 newProcUnitConfObjDict[idProcUnit] = procUnitConfObj
935 newProcUnitConfObjDict[idProcUnit] = procUnitConfObj
931 n += 1
936 n += 1
932
937
933 self.procUnitConfObjDict = newProcUnitConfObjDict
938 self.procUnitConfObjDict = newProcUnitConfObjDict
934
939
935 def setup(self, id=1, name='', description='', email=None, alarm=[]):
940 def setup(self, id=1, name='', description='', email=None, alarm=[]):
936
941
937 print(' ')
942 print(' ')
938 print('*' * 60)
943 print('*' * 60)
939 print('* Starting SIGNAL CHAIN PROCESSING (Multiprocessing) v%s *' % schainpy.__version__)
944 print('* Starting SIGNAL CHAIN PROCESSING (Multiprocessing) v%s *' % schainpy.__version__)
940 print('*' * 60)
945 print('*' * 60)
941 print("* Python " + python_version() + " *")
946 print("* Python " + python_version() + " *")
942 print('*' * 19)
947 print('*' * 19)
943 print(' ')
948 print(' ')
944 self.id = str(id)
949 self.id = str(id)
945 self.description = description
950 self.description = description
946 self.email = email
951 self.email = email
947 self.alarm = alarm
952 self.alarm = alarm
948 if name:
953 if name:
949 self.name = '{} ({})'.format(Process.__name__, name)
954 self.name = '{} ({})'.format(Process.__name__, name)
950
955
951 def update(self, **kwargs):
956 def update(self, **kwargs):
952
957
953 for key, value in list(kwargs.items()):
958 for key, value in list(kwargs.items()):
954 setattr(self, key, value)
959 setattr(self, key, value)
955
960
956 def clone(self):
961 def clone(self):
957
962
958 p = Project()
963 p = Project()
959 p.procUnitConfObjDict = self.procUnitConfObjDict
964 p.procUnitConfObjDict = self.procUnitConfObjDict
960 return p
965 return p
961
966
962 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
967 def addReadUnit(self, id=None, datatype=None, name=None, **kwargs):
963
968
964 '''
969 '''
965 Actualizacion:
970 Actualizacion:
966 Se agrego un nuevo argumento: topic -relativo a la forma de comunicar los procesos simultaneos
971 Se agrego un nuevo argumento: topic -relativo a la forma de comunicar los procesos simultaneos
967
972
968 * El id del proceso sera el topico al que se deben subscribir los procUnits para recibir la informacion(data)
973 * El id del proceso sera el topico al que se deben subscribir los procUnits para recibir la informacion(data)
969
974
970 '''
975 '''
971
976
972 if id is None:
977 if id is None:
973 idReadUnit = self.__getNewId()
978 idReadUnit = self.__getNewId()
974 else:
979 else:
975 idReadUnit = str(id)
980 idReadUnit = str(id)
976
981
977 readUnitConfObj = ReadUnitConf()
982 readUnitConfObj = ReadUnitConf()
978 readUnitConfObj.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
983 readUnitConfObj.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
979 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
984 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
980
985
981 return readUnitConfObj
986 return readUnitConfObj
982
987
983 def addProcUnit(self, inputId='0', datatype=None, name=None):
988 def addProcUnit(self, inputId='0', datatype=None, name=None):
984
989
985 '''
990 '''
986 Actualizacion:
991 Actualizacion:
987 Se agrego dos nuevos argumentos: topic_read (lee data de otro procUnit) y topic_write(escribe o envia data a otro procUnit)
992 Se agrego dos nuevos argumentos: topic_read (lee data de otro procUnit) y topic_write(escribe o envia data a otro procUnit)
988 Deberia reemplazar a "inputId"
993 Deberia reemplazar a "inputId"
989
994
990 ** A fin de mantener el inputID, este sera la representaacion del topicoal que deben subscribirse. El ID propio de la intancia
995 ** A fin de mantener el inputID, este sera la representaacion del topicoal que deben subscribirse. El ID propio de la intancia
991 (proceso) sera el topico de la publicacion, todo sera asignado de manera dinamica.
996 (proceso) sera el topico de la publicacion, todo sera asignado de manera dinamica.
992
997
993 '''
998 '''
994
999
995 idProcUnit = self.__getNewId()
1000 idProcUnit = self.__getNewId()
996 procUnitConfObj = ProcUnitConf()
1001 procUnitConfObj = ProcUnitConf()
997 input_proc = self.procUnitConfObjDict[inputId]
1002 input_proc = self.procUnitConfObjDict[inputId]
998 procUnitConfObj.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue, input_proc.lock)
1003 procUnitConfObj.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue, input_proc.lock)
999 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1004 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1000
1005
1001 return procUnitConfObj
1006 return procUnitConfObj
1002
1007
1003 def removeProcUnit(self, id):
1008 def removeProcUnit(self, id):
1004
1009
1005 if id in list(self.procUnitConfObjDict.keys()):
1010 if id in list(self.procUnitConfObjDict.keys()):
1006 self.procUnitConfObjDict.pop(id)
1011 self.procUnitConfObjDict.pop(id)
1007
1012
1008 def getReadUnitId(self):
1013 def getReadUnitId(self):
1009
1014
1010 readUnitConfObj = self.getReadUnitObj()
1015 readUnitConfObj = self.getReadUnitObj()
1011
1016
1012 return readUnitConfObj.id
1017 return readUnitConfObj.id
1013
1018
1014 def getReadUnitObj(self):
1019 def getReadUnitObj(self):
1015
1020
1016 for obj in list(self.procUnitConfObjDict.values()):
1021 for obj in list(self.procUnitConfObjDict.values()):
1017 if obj.getElementName() == 'ReadUnit':
1022 if obj.getElementName() == 'ReadUnit':
1018 return obj
1023 return obj
1019
1024
1020 return None
1025 return None
1021
1026
1022 def getProcUnitObj(self, id=None, name=None):
1027 def getProcUnitObj(self, id=None, name=None):
1023
1028
1024 if id != None:
1029 if id != None:
1025 return self.procUnitConfObjDict[id]
1030 return self.procUnitConfObjDict[id]
1026
1031
1027 if name != None:
1032 if name != None:
1028 return self.getProcUnitObjByName(name)
1033 return self.getProcUnitObjByName(name)
1029
1034
1030 return None
1035 return None
1031
1036
1032 def getProcUnitObjByName(self, name):
1037 def getProcUnitObjByName(self, name):
1033
1038
1034 for obj in list(self.procUnitConfObjDict.values()):
1039 for obj in list(self.procUnitConfObjDict.values()):
1035 if obj.name == name:
1040 if obj.name == name:
1036 return obj
1041 return obj
1037
1042
1038 return None
1043 return None
1039
1044
1040 def procUnitItems(self):
1045 def procUnitItems(self):
1041
1046
1042 return list(self.procUnitConfObjDict.items())
1047 return list(self.procUnitConfObjDict.items())
1043
1048
1044 def makeXml(self):
1049 def makeXml(self):
1045
1050
1046 projectElement = Element('Project')
1051 projectElement = Element('Project')
1047 projectElement.set('id', str(self.id))
1052 projectElement.set('id', str(self.id))
1048 projectElement.set('name', self.name)
1053 projectElement.set('name', self.name)
1049 projectElement.set('description', self.description)
1054 projectElement.set('description', self.description)
1050
1055
1051 for procUnitConfObj in list(self.procUnitConfObjDict.values()):
1056 for procUnitConfObj in list(self.procUnitConfObjDict.values()):
1052 procUnitConfObj.makeXml(projectElement)
1057 procUnitConfObj.makeXml(projectElement)
1053
1058
1054 self.projectElement = projectElement
1059 self.projectElement = projectElement
1055
1060
1056 def writeXml(self, filename=None):
1061 def writeXml(self, filename=None):
1057
1062
1058 if filename == None:
1063 if filename == None:
1059 if self.filename:
1064 if self.filename:
1060 filename = self.filename
1065 filename = self.filename
1061 else:
1066 else:
1062 filename = 'schain.xml'
1067 filename = 'schain.xml'
1063
1068
1064 if not filename:
1069 if not filename:
1065 print('filename has not been defined. Use setFilename(filename) for do it.')
1070 print('filename has not been defined. Use setFilename(filename) for do it.')
1066 return 0
1071 return 0
1067
1072
1068 abs_file = os.path.abspath(filename)
1073 abs_file = os.path.abspath(filename)
1069
1074
1070 if not os.access(os.path.dirname(abs_file), os.W_OK):
1075 if not os.access(os.path.dirname(abs_file), os.W_OK):
1071 print('No write permission on %s' % os.path.dirname(abs_file))
1076 print('No write permission on %s' % os.path.dirname(abs_file))
1072 return 0
1077 return 0
1073
1078
1074 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
1079 if os.path.isfile(abs_file) and not(os.access(abs_file, os.W_OK)):
1075 print('File %s already exists and it could not be overwriten' % abs_file)
1080 print('File %s already exists and it could not be overwriten' % abs_file)
1076 return 0
1081 return 0
1077
1082
1078 self.makeXml()
1083 self.makeXml()
1079
1084
1080 ElementTree(self.projectElement).write(abs_file, method='xml')
1085 ElementTree(self.projectElement).write(abs_file, method='xml')
1081
1086
1082 self.filename = abs_file
1087 self.filename = abs_file
1083
1088
1084 return 1
1089 return 1
1085
1090
1086 def readXml(self, filename=None):
1091 def readXml(self, filename=None):
1087
1092
1088 if not filename:
1093 if not filename:
1089 print('filename is not defined')
1094 print('filename is not defined')
1090 return 0
1095 return 0
1091
1096
1092 abs_file = os.path.abspath(filename)
1097 abs_file = os.path.abspath(filename)
1093
1098
1094 if not os.path.isfile(abs_file):
1099 if not os.path.isfile(abs_file):
1095 print('%s file does not exist' % abs_file)
1100 print('%s file does not exist' % abs_file)
1096 return 0
1101 return 0
1097
1102
1098 self.projectElement = None
1103 self.projectElement = None
1099 self.procUnitConfObjDict = {}
1104 self.procUnitConfObjDict = {}
1100
1105
1101 try:
1106 try:
1102 self.projectElement = ElementTree().parse(abs_file)
1107 self.projectElement = ElementTree().parse(abs_file)
1103 except:
1108 except:
1104 print('Error reading %s, verify file format' % filename)
1109 print('Error reading %s, verify file format' % filename)
1105 return 0
1110 return 0
1106
1111
1107 self.project = self.projectElement.tag
1112 self.project = self.projectElement.tag
1108
1113
1109 self.id = self.projectElement.get('id')
1114 self.id = self.projectElement.get('id')
1110 self.name = self.projectElement.get('name')
1115 self.name = self.projectElement.get('name')
1111 self.description = self.projectElement.get('description')
1116 self.description = self.projectElement.get('description')
1112
1117
1113 readUnitElementList = self.projectElement.iter(
1118 readUnitElementList = self.projectElement.iter(
1114 ReadUnitConf().getElementName())
1119 ReadUnitConf().getElementName())
1115
1120
1116 for readUnitElement in readUnitElementList:
1121 for readUnitElement in readUnitElementList:
1117 readUnitConfObj = ReadUnitConf()
1122 readUnitConfObj = ReadUnitConf()
1118 readUnitConfObj.readXml(readUnitElement, self.id)
1123 readUnitConfObj.readXml(readUnitElement, self.id)
1119 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
1124 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
1120
1125
1121 procUnitElementList = self.projectElement.iter(
1126 procUnitElementList = self.projectElement.iter(
1122 ProcUnitConf().getElementName())
1127 ProcUnitConf().getElementName())
1123
1128
1124 for procUnitElement in procUnitElementList:
1129 for procUnitElement in procUnitElementList:
1125 procUnitConfObj = ProcUnitConf()
1130 procUnitConfObj = ProcUnitConf()
1126 procUnitConfObj.readXml(procUnitElement, self.id)
1131 procUnitConfObj.readXml(procUnitElement, self.id)
1127 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1132 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1128
1133
1129 self.filename = abs_file
1134 self.filename = abs_file
1130
1135
1131 return 1
1136 return 1
1132
1137
1133 def __str__(self):
1138 def __str__(self):
1134
1139
1135 print('Project: name = %s, description = %s, id = %s' % (
1140 print('Project: name = %s, description = %s, id = %s' % (
1136 self.name,
1141 self.name,
1137 self.description,
1142 self.description,
1138 self.id))
1143 self.id))
1139
1144
1140 for procUnitConfObj in self.procUnitConfObjDict.values():
1145 for procUnitConfObj in self.procUnitConfObjDict.values():
1141 print(procUnitConfObj)
1146 print(procUnitConfObj)
1142
1147
1143 def createObjects(self):
1148 def createObjects(self):
1144
1149
1145
1150
1146 keys = list(self.procUnitConfObjDict.keys())
1151 keys = list(self.procUnitConfObjDict.keys())
1147 keys.sort()
1152 keys.sort()
1148 for key in keys:
1153 for key in keys:
1149 self.procUnitConfObjDict[key].createObjects()
1154 self.procUnitConfObjDict[key].createObjects()
1150
1155
1151 def monitor(self):
1156 def monitor(self):
1152
1157
1153 t = Thread(target=self.__monitor, args=(self.err_queue, self.ctx))
1158 t = Thread(target=self.__monitor, args=(self.err_queue, self.ctx))
1154 t.start()
1159 t.start()
1155
1160
1156 def __monitor(self, queue, ctx):
1161 def __monitor(self, queue, ctx):
1157
1162
1158 import socket
1163 import socket
1159
1164
1160 procs = 0
1165 procs = 0
1161 err_msg = ''
1166 err_msg = ''
1162
1167
1163 while True:
1168 while True:
1164 msg = queue.get()
1169 msg = queue.get()
1165 if '#_start_#' in msg:
1170 if '#_start_#' in msg:
1166 procs += 1
1171 procs += 1
1167 elif '#_end_#' in msg:
1172 elif '#_end_#' in msg:
1168 procs -=1
1173 procs -=1
1169 else:
1174 else:
1170 err_msg = msg
1175 err_msg = msg
1171
1176
1172 if procs == 0 or 'Traceback' in err_msg:
1177 if procs == 0 or 'Traceback' in err_msg:
1173 break
1178 break
1174 time.sleep(0.1)
1179 time.sleep(0.1)
1175
1180
1176 if '|' in err_msg:
1181 if '|' in err_msg:
1177 name, err = err_msg.split('|')
1182 name, err = err_msg.split('|')
1178 if 'SchainWarning' in err:
1183 if 'SchainWarning' in err:
1179 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
1184 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), name)
1180 elif 'SchainError' in err:
1185 elif 'SchainError' in err:
1181 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
1186 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
1182 else:
1187 else:
1183 log.error(err, name)
1188 log.error(err, name)
1184 else:
1189 else:
1185 name, err = self.name, err_msg
1190 name, err = self.name, err_msg
1186
1191
1187 time.sleep(2)
1192 time.sleep(2)
1188
1193
1189 for conf in self.procUnitConfObjDict.values():
1194 for conf in self.procUnitConfObjDict.values():
1190 for confop in conf.opConfObjList:
1195 for confop in conf.opConfObjList:
1191 if confop.type == 'external':
1196 if confop.type == 'external':
1192 confop.opObj.terminate()
1197 confop.opObj.terminate()
1193 conf.procUnitObj.terminate()
1198 conf.procUnitObj.terminate()
1194
1199
1195 ctx.term()
1200 ctx.term()
1196
1201
1197 message = ''.join(err)
1202 message = ''.join(err)
1198
1203
1199 if err_msg:
1204 if err_msg:
1200 subject = 'SChain v%s: Error running %s\n' % (
1205 subject = 'SChain v%s: Error running %s\n' % (
1201 schainpy.__version__, self.name)
1206 schainpy.__version__, self.name)
1202
1207
1203 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
1208 subtitle = 'Hostname: %s\n' % socket.gethostbyname(
1204 socket.gethostname())
1209 socket.gethostname())
1205 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
1210 subtitle += 'Working directory: %s\n' % os.path.abspath('./')
1206 subtitle += 'Configuration file: %s\n' % self.filename
1211 subtitle += 'Configuration file: %s\n' % self.filename
1207 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
1212 subtitle += 'Time: %s\n' % str(datetime.datetime.now())
1208
1213
1209 readUnitConfObj = self.getReadUnitObj()
1214 readUnitConfObj = self.getReadUnitObj()
1210 if readUnitConfObj:
1215 if readUnitConfObj:
1211 subtitle += '\nInput parameters:\n'
1216 subtitle += '\nInput parameters:\n'
1212 subtitle += '[Data path = %s]\n' % readUnitConfObj.path
1217 subtitle += '[Data path = %s]\n' % readUnitConfObj.path
1213 subtitle += '[Data type = %s]\n' % readUnitConfObj.datatype
1218 subtitle += '[Data type = %s]\n' % readUnitConfObj.datatype
1214 subtitle += '[Start date = %s]\n' % readUnitConfObj.startDate
1219 subtitle += '[Start date = %s]\n' % readUnitConfObj.startDate
1215 subtitle += '[End date = %s]\n' % readUnitConfObj.endDate
1220 subtitle += '[End date = %s]\n' % readUnitConfObj.endDate
1216 subtitle += '[Start time = %s]\n' % readUnitConfObj.startTime
1221 subtitle += '[Start time = %s]\n' % readUnitConfObj.startTime
1217 subtitle += '[End time = %s]\n' % readUnitConfObj.endTime
1222 subtitle += '[End time = %s]\n' % readUnitConfObj.endTime
1218
1223
1219 a = Alarm(
1224 a = Alarm(
1220 modes=self.alarm,
1225 modes=self.alarm,
1221 email=self.email,
1226 email=self.email,
1222 message=message,
1227 message=message,
1223 subject=subject,
1228 subject=subject,
1224 subtitle=subtitle,
1229 subtitle=subtitle,
1225 filename=self.filename
1230 filename=self.filename
1226 )
1231 )
1227
1232
1228 a.start()
1233 a.start()
1229
1234
1230 def isPaused(self):
1235 def isPaused(self):
1231 return 0
1236 return 0
1232
1237
1233 def isStopped(self):
1238 def isStopped(self):
1234 return 0
1239 return 0
1235
1240
1236 def runController(self):
1241 def runController(self):
1237 '''
1242 '''
1238 returns 0 when this process has been stopped, 1 otherwise
1243 returns 0 when this process has been stopped, 1 otherwise
1239 '''
1244 '''
1240
1245
1241 if self.isPaused():
1246 if self.isPaused():
1242 print('Process suspended')
1247 print('Process suspended')
1243
1248
1244 while True:
1249 while True:
1245 time.sleep(0.1)
1250 time.sleep(0.1)
1246
1251
1247 if not self.isPaused():
1252 if not self.isPaused():
1248 break
1253 break
1249
1254
1250 if self.isStopped():
1255 if self.isStopped():
1251 break
1256 break
1252
1257
1253 print('Process reinitialized')
1258 print('Process reinitialized')
1254
1259
1255 if self.isStopped():
1260 if self.isStopped():
1256 print('Process stopped')
1261 print('Process stopped')
1257 return 0
1262 return 0
1258
1263
1259 return 1
1264 return 1
1260
1265
1261 def setFilename(self, filename):
1266 def setFilename(self, filename):
1262
1267
1263 self.filename = filename
1268 self.filename = filename
1264
1269
1265 def setProxy(self):
1270 def setProxy(self):
1266
1271
1267 if not os.path.exists('/tmp/schain'):
1272 if not os.path.exists('/tmp/schain'):
1268 os.mkdir('/tmp/schain')
1273 os.mkdir('/tmp/schain')
1269
1274
1270 self.ctx = zmq.Context()
1275 self.ctx = zmq.Context()
1271 xpub = self.ctx.socket(zmq.XPUB)
1276 xpub = self.ctx.socket(zmq.XPUB)
1272 xpub.bind('ipc:///tmp/schain/{}_pub'.format(self.id))
1277 xpub.bind('ipc:///tmp/schain/{}_pub'.format(self.id))
1273 xsub = self.ctx.socket(zmq.XSUB)
1278 xsub = self.ctx.socket(zmq.XSUB)
1274 xsub.bind('ipc:///tmp/schain/{}_sub'.format(self.id))
1279 xsub.bind('ipc:///tmp/schain/{}_sub'.format(self.id))
1275 self.monitor()
1280 self.monitor()
1276 try:
1281 try:
1277 zmq.proxy(xpub, xsub)
1282 zmq.proxy(xpub, xsub)
1278 except zmq.ContextTerminated:
1283 except zmq.ContextTerminated:
1279 xpub.close()
1284 xpub.close()
1280 xsub.close()
1285 xsub.close()
1281
1286
1282 def run(self):
1287 def run(self):
1283
1288
1284 log.success('Starting {}: {}'.format(self.name, self.id), tag='')
1289 log.success('Starting {}: {}'.format(self.name, self.id), tag='')
1285 self.start_time = time.time()
1290 self.start_time = time.time()
1286 self.createObjects()
1291 self.createObjects()
1287 self.setProxy()
1292 self.setProxy()
1288 log.success('{} Done (Time: {}s)'.format(
1293 log.success('{} Done (Time: {}s)'.format(
1289 self.name,
1294 self.name,
1290 time.time()-self.start_time), '')
1295 time.time()-self.start_time), '')
1 NO CONTENT: modified file
NO CONTENT: modified file
1 NO CONTENT: modified file
NO CONTENT: modified file
@@ -1,810 +1,808
1
1
2 import os
2 import os
3 import sys
3 import sys
4 import zmq
4 import zmq
5 import time
5 import time
6 import numpy
6 import numpy
7 import datetime
7 import datetime
8 from functools import wraps
8 from functools import wraps
9 from threading import Thread
9 from threading import Thread
10 import matplotlib
10 import matplotlib
11
11
12 if 'BACKEND' in os.environ:
12 if 'BACKEND' in os.environ:
13 matplotlib.use(os.environ['BACKEND'])
13 matplotlib.use(os.environ['BACKEND'])
14 elif 'linux' in sys.platform:
14 elif 'linux' in sys.platform:
15 matplotlib.use("TkAgg")
15 matplotlib.use("TkAgg")
16 elif 'darwin' in sys.platform:
16 elif 'darwin' in sys.platform:
17 matplotlib.use('WxAgg')
17 matplotlib.use('WxAgg')
18 else:
18 else:
19 from schainpy.utils import log
19 from schainpy.utils import log
20 log.warning('Using default Backend="Agg"', 'INFO')
20 log.warning('Using default Backend="Agg"', 'INFO')
21 matplotlib.use('Agg')
21 matplotlib.use('Agg')
22
22
23 import matplotlib.pyplot as plt
23 import matplotlib.pyplot as plt
24 from matplotlib.patches import Polygon
24 from matplotlib.patches import Polygon
25 from mpl_toolkits.axes_grid1 import make_axes_locatable
25 from mpl_toolkits.axes_grid1 import make_axes_locatable
26 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
26 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
27
27
28 from schainpy.model.data.jrodata import PlotterData
28 from schainpy.model.data.jrodata import PlotterData
29 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
29 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
30 from schainpy.utils import log
30 from schainpy.utils import log
31
31
32 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
32 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
33 blu_values = matplotlib.pyplot.get_cmap(
33 blu_values = matplotlib.pyplot.get_cmap(
34 'seismic_r', 20)(numpy.arange(20))[10:15]
34 'seismic_r', 20)(numpy.arange(20))[10:15]
35 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
35 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
36 'jro', numpy.vstack((blu_values, jet_values)))
36 'jro', numpy.vstack((blu_values, jet_values)))
37 matplotlib.pyplot.register_cmap(cmap=ncmap)
37 matplotlib.pyplot.register_cmap(cmap=ncmap)
38
38
39 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
39 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
40 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
40 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
41
41
42 EARTH_RADIUS = 6.3710e3
42 EARTH_RADIUS = 6.3710e3
43
43
44 def ll2xy(lat1, lon1, lat2, lon2):
44 def ll2xy(lat1, lon1, lat2, lon2):
45
45
46 p = 0.017453292519943295
46 p = 0.017453292519943295
47 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
47 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
48 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
48 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
49 r = 12742 * numpy.arcsin(numpy.sqrt(a))
49 r = 12742 * numpy.arcsin(numpy.sqrt(a))
50 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
50 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
51 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
51 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
52 theta = -theta + numpy.pi/2
52 theta = -theta + numpy.pi/2
53 return r*numpy.cos(theta), r*numpy.sin(theta)
53 return r*numpy.cos(theta), r*numpy.sin(theta)
54
54
55
55
56 def km2deg(km):
56 def km2deg(km):
57 '''
57 '''
58 Convert distance in km to degrees
58 Convert distance in km to degrees
59 '''
59 '''
60
60
61 return numpy.rad2deg(km/EARTH_RADIUS)
61 return numpy.rad2deg(km/EARTH_RADIUS)
62
62
63
63
64 def figpause(interval):
64 def figpause(interval):
65 backend = plt.rcParams['backend']
65 backend = plt.rcParams['backend']
66 if backend in matplotlib.rcsetup.interactive_bk:
66 if backend in matplotlib.rcsetup.interactive_bk:
67 figManager = matplotlib._pylab_helpers.Gcf.get_active()
67 figManager = matplotlib._pylab_helpers.Gcf.get_active()
68 if figManager is not None:
68 if figManager is not None:
69 canvas = figManager.canvas
69 canvas = figManager.canvas
70 if canvas.figure.stale:
70 if canvas.figure.stale:
71 canvas.draw()
71 canvas.draw()
72 try:
72 try:
73 canvas.start_event_loop(interval)
73 canvas.start_event_loop(interval)
74 except:
74 except:
75 pass
75 pass
76 return
76 return
77
77
78
78
79 def popup(message):
79 def popup(message):
80 '''
80 '''
81 '''
81 '''
82
82
83 fig = plt.figure(figsize=(12, 8), facecolor='r')
83 fig = plt.figure(figsize=(12, 8), facecolor='r')
84 text = '\n'.join([s.strip() for s in message.split(':')])
84 text = '\n'.join([s.strip() for s in message.split(':')])
85 fig.text(0.01, 0.5, text, ha='left', va='center',
85 fig.text(0.01, 0.5, text, ha='left', va='center',
86 size='20', weight='heavy', color='w')
86 size='20', weight='heavy', color='w')
87 fig.show()
87 fig.show()
88 figpause(1000)
88 figpause(1000)
89
89
90
90
91 class Throttle(object):
91 class Throttle(object):
92 '''
92 '''
93 Decorator that prevents a function from being called more than once every
93 Decorator that prevents a function from being called more than once every
94 time period.
94 time period.
95 To create a function that cannot be called more than once a minute, but
95 To create a function that cannot be called more than once a minute, but
96 will sleep until it can be called:
96 will sleep until it can be called:
97 @Throttle(minutes=1)
97 @Throttle(minutes=1)
98 def foo():
98 def foo():
99 pass
99 pass
100
100
101 for i in range(10):
101 for i in range(10):
102 foo()
102 foo()
103 print "This function has run %s times." % i
103 print "This function has run %s times." % i
104 '''
104 '''
105
105
106 def __init__(self, seconds=0, minutes=0, hours=0):
106 def __init__(self, seconds=0, minutes=0, hours=0):
107 self.throttle_period = datetime.timedelta(
107 self.throttle_period = datetime.timedelta(
108 seconds=seconds, minutes=minutes, hours=hours
108 seconds=seconds, minutes=minutes, hours=hours
109 )
109 )
110
110
111 self.time_of_last_call = datetime.datetime.min
111 self.time_of_last_call = datetime.datetime.min
112
112
113 def __call__(self, fn):
113 def __call__(self, fn):
114 @wraps(fn)
114 @wraps(fn)
115 def wrapper(*args, **kwargs):
115 def wrapper(*args, **kwargs):
116 coerce = kwargs.pop('coerce', None)
116 coerce = kwargs.pop('coerce', None)
117 if coerce:
117 if coerce:
118 self.time_of_last_call = datetime.datetime.now()
118 self.time_of_last_call = datetime.datetime.now()
119 return fn(*args, **kwargs)
119 return fn(*args, **kwargs)
120 else:
120 else:
121 now = datetime.datetime.now()
121 now = datetime.datetime.now()
122 time_since_last_call = now - self.time_of_last_call
122 time_since_last_call = now - self.time_of_last_call
123 time_left = self.throttle_period - time_since_last_call
123 time_left = self.throttle_period - time_since_last_call
124
124
125 if time_left > datetime.timedelta(seconds=0):
125 if time_left > datetime.timedelta(seconds=0):
126 return
126 return
127
127
128 self.time_of_last_call = datetime.datetime.now()
128 self.time_of_last_call = datetime.datetime.now()
129 return fn(*args, **kwargs)
129 return fn(*args, **kwargs)
130
130
131 return wrapper
131 return wrapper
132
132
133 def apply_throttle(value):
133 def apply_throttle(value):
134
134
135 @Throttle(seconds=value)
135 @Throttle(seconds=value)
136 def fnThrottled(fn):
136 def fnThrottled(fn):
137 fn()
137 fn()
138
138
139 return fnThrottled
139 return fnThrottled
140
140
141
141
142 @MPDecorator
142 @MPDecorator
143 class Plot(Operation):
143 class Plot(Operation):
144 '''
144 '''
145 Base class for Schain plotting operations
145 Base class for Schain plotting operations
146 '''
146 '''
147
147
148 CODE = 'Figure'
148 CODE = 'Figure'
149 colormap = 'jet'
149 colormap = 'jet'
150 bgcolor = 'white'
150 bgcolor = 'white'
151 __missing = 1E30
151 __missing = 1E30
152
152
153 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
153 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
154 'zlimits', 'xlabel', 'ylabel', 'xaxis', 'cb_label', 'title',
154 'zlimits', 'xlabel', 'ylabel', 'xaxis', 'cb_label', 'title',
155 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
155 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
156 'showprofile', 'decimation', 'pause']
156 'showprofile', 'decimation', 'pause']
157
157
158 def __init__(self):
158 def __init__(self):
159
159
160 Operation.__init__(self)
160 Operation.__init__(self)
161 self.isConfig = False
161 self.isConfig = False
162 self.isPlotConfig = False
162 self.isPlotConfig = False
163 self.save_counter = 1
163 self.save_counter = 1
164 self.sender_counter = 1
164 self.sender_counter = 1
165 self.data = None
165 self.data = None
166
166
167 def __fmtTime(self, x, pos):
167 def __fmtTime(self, x, pos):
168 '''
168 '''
169 '''
169 '''
170
170
171 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
171 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
172
172
173 def __setup(self, **kwargs):
173 def __setup(self, **kwargs):
174 '''
174 '''
175 Initialize variables
175 Initialize variables
176 '''
176 '''
177
177
178 self.figures = []
178 self.figures = []
179 self.axes = []
179 self.axes = []
180 self.cb_axes = []
180 self.cb_axes = []
181 self.localtime = kwargs.pop('localtime', True)
181 self.localtime = kwargs.pop('localtime', True)
182 self.show = kwargs.get('show', True)
182 self.show = kwargs.get('show', True)
183 self.save = kwargs.get('save', False)
183 self.save = kwargs.get('save', False)
184 self.save_period = kwargs.get('save_period', 1)
184 self.save_period = kwargs.get('save_period', 1)
185 self.ftp = kwargs.get('ftp', False)
185 self.ftp = kwargs.get('ftp', False)
186 self.colormap = kwargs.get('colormap', self.colormap)
186 self.colormap = kwargs.get('colormap', self.colormap)
187 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
187 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
188 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
188 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
189 self.colormaps = kwargs.get('colormaps', None)
189 self.colormaps = kwargs.get('colormaps', None)
190 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
190 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
191 self.showprofile = kwargs.get('showprofile', False)
191 self.showprofile = kwargs.get('showprofile', False)
192 self.title = kwargs.get('wintitle', self.CODE.upper())
192 self.title = kwargs.get('wintitle', self.CODE.upper())
193 self.cb_label = kwargs.get('cb_label', None)
193 self.cb_label = kwargs.get('cb_label', None)
194 self.cb_labels = kwargs.get('cb_labels', None)
194 self.cb_labels = kwargs.get('cb_labels', None)
195 self.labels = kwargs.get('labels', None)
195 self.labels = kwargs.get('labels', None)
196 self.xaxis = kwargs.get('xaxis', 'frequency')
196 self.xaxis = kwargs.get('xaxis', 'frequency')
197 self.zmin = kwargs.get('zmin', None)
197 self.zmin = kwargs.get('zmin', None)
198 self.zmax = kwargs.get('zmax', None)
198 self.zmax = kwargs.get('zmax', None)
199 self.zlimits = kwargs.get('zlimits', None)
199 self.zlimits = kwargs.get('zlimits', None)
200 self.xmin = kwargs.get('xmin', None)
200 self.xmin = kwargs.get('xmin', None)
201 self.xmax = kwargs.get('xmax', None)
201 self.xmax = kwargs.get('xmax', None)
202 self.xrange = kwargs.get('xrange', 24)
202 self.xrange = kwargs.get('xrange', 24)
203 self.xscale = kwargs.get('xscale', None)
203 self.xscale = kwargs.get('xscale', None)
204 self.ymin = kwargs.get('ymin', None)
204 self.ymin = kwargs.get('ymin', None)
205 self.ymax = kwargs.get('ymax', None)
205 self.ymax = kwargs.get('ymax', None)
206 self.yscale = kwargs.get('yscale', None)
206 self.yscale = kwargs.get('yscale', None)
207 self.xlabel = kwargs.get('xlabel', None)
207 self.xlabel = kwargs.get('xlabel', None)
208 self.decimation = kwargs.get('decimation', None)
208 self.decimation = kwargs.get('decimation', None)
209 self.showSNR = kwargs.get('showSNR', False)
209 self.showSNR = kwargs.get('showSNR', False)
210 self.oneFigure = kwargs.get('oneFigure', True)
210 self.oneFigure = kwargs.get('oneFigure', True)
211 self.width = kwargs.get('width', None)
211 self.width = kwargs.get('width', None)
212 self.height = kwargs.get('height', None)
212 self.height = kwargs.get('height', None)
213 self.colorbar = kwargs.get('colorbar', True)
213 self.colorbar = kwargs.get('colorbar', True)
214 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
214 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
215 self.channels = kwargs.get('channels', None)
215 self.channels = kwargs.get('channels', None)
216 self.titles = kwargs.get('titles', [])
216 self.titles = kwargs.get('titles', [])
217 self.polar = False
217 self.polar = False
218 self.type = kwargs.get('type', 'iq')
218 self.type = kwargs.get('type', 'iq')
219 self.grid = kwargs.get('grid', False)
219 self.grid = kwargs.get('grid', False)
220 self.pause = kwargs.get('pause', False)
220 self.pause = kwargs.get('pause', False)
221 self.save_labels = kwargs.get('save_labels', None)
221 self.save_labels = kwargs.get('save_labels', None)
222 self.realtime = kwargs.get('realtime', True)
222 self.realtime = kwargs.get('realtime', True)
223 self.buffering = kwargs.get('buffering', True)
223 self.buffering = kwargs.get('buffering', True)
224 self.throttle = kwargs.get('throttle', 2)
224 self.throttle = kwargs.get('throttle', 2)
225 self.exp_code = kwargs.get('exp_code', None)
225 self.exp_code = kwargs.get('exp_code', None)
226 self.plot_server = kwargs.get('plot_server', False)
226 self.plot_server = kwargs.get('plot_server', False)
227 self.sender_period = kwargs.get('sender_period', 1)
227 self.sender_period = kwargs.get('sender_period', 1)
228 self.__throttle_plot = apply_throttle(self.throttle)
228 self.__throttle_plot = apply_throttle(self.throttle)
229 self.data = PlotterData(
229 self.data = PlotterData(
230 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
230 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
231
231
232 if self.plot_server:
232 if self.plot_server:
233 if not self.plot_server.startswith('tcp://'):
233 if not self.plot_server.startswith('tcp://'):
234 self.plot_server = 'tcp://{}'.format(self.plot_server)
234 self.plot_server = 'tcp://{}'.format(self.plot_server)
235 log.success(
235 log.success(
236 'Sending to server: {}'.format(self.plot_server),
236 'Sending to server: {}'.format(self.plot_server),
237 self.name
237 self.name
238 )
238 )
239 if 'plot_name' in kwargs:
239 if 'plot_name' in kwargs:
240 self.plot_name = kwargs['plot_name']
240 self.plot_name = kwargs['plot_name']
241
241
242 def __setup_plot(self):
242 def __setup_plot(self):
243 '''
243 '''
244 Common setup for all figures, here figures and axes are created
244 Common setup for all figures, here figures and axes are created
245 '''
245 '''
246
246
247 self.setup()
247 self.setup()
248
248
249 self.time_label = 'LT' if self.localtime else 'UTC'
249 self.time_label = 'LT' if self.localtime else 'UTC'
250
250
251 if self.width is None:
251 if self.width is None:
252 self.width = 8
252 self.width = 8
253
253
254 self.figures = []
254 self.figures = []
255 self.axes = []
255 self.axes = []
256 self.cb_axes = []
256 self.cb_axes = []
257 self.pf_axes = []
257 self.pf_axes = []
258 self.cmaps = []
258 self.cmaps = []
259
259
260 size = '15%' if self.ncols == 1 else '30%'
260 size = '15%' if self.ncols == 1 else '30%'
261 pad = '4%' if self.ncols == 1 else '8%'
261 pad = '4%' if self.ncols == 1 else '8%'
262
262
263 if self.oneFigure:
263 if self.oneFigure:
264 if self.height is None:
264 if self.height is None:
265 self.height = 1.4 * self.nrows + 1
265 self.height = 1.4 * self.nrows + 1
266 fig = plt.figure(figsize=(self.width, self.height),
266 fig = plt.figure(figsize=(self.width, self.height),
267 edgecolor='k',
267 edgecolor='k',
268 facecolor='w')
268 facecolor='w')
269 self.figures.append(fig)
269 self.figures.append(fig)
270 for n in range(self.nplots):
270 for n in range(self.nplots):
271 ax = fig.add_subplot(self.nrows, self.ncols,
271 ax = fig.add_subplot(self.nrows, self.ncols,
272 n + 1, polar=self.polar)
272 n + 1, polar=self.polar)
273 ax.tick_params(labelsize=8)
273 ax.tick_params(labelsize=8)
274 ax.firsttime = True
274 ax.firsttime = True
275 ax.index = 0
275 ax.index = 0
276 ax.press = None
276 ax.press = None
277 self.axes.append(ax)
277 self.axes.append(ax)
278 if self.showprofile:
278 if self.showprofile:
279 cax = self.__add_axes(ax, size=size, pad=pad)
279 cax = self.__add_axes(ax, size=size, pad=pad)
280 cax.tick_params(labelsize=8)
280 cax.tick_params(labelsize=8)
281 self.pf_axes.append(cax)
281 self.pf_axes.append(cax)
282 else:
282 else:
283 if self.height is None:
283 if self.height is None:
284 self.height = 3
284 self.height = 3
285 for n in range(self.nplots):
285 for n in range(self.nplots):
286 fig = plt.figure(figsize=(self.width, self.height),
286 fig = plt.figure(figsize=(self.width, self.height),
287 edgecolor='k',
287 edgecolor='k',
288 facecolor='w')
288 facecolor='w')
289 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
289 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
290 ax.tick_params(labelsize=8)
290 ax.tick_params(labelsize=8)
291 ax.firsttime = True
291 ax.firsttime = True
292 ax.index = 0
292 ax.index = 0
293 ax.press = None
293 ax.press = None
294 self.figures.append(fig)
294 self.figures.append(fig)
295 self.axes.append(ax)
295 self.axes.append(ax)
296 if self.showprofile:
296 if self.showprofile:
297 cax = self.__add_axes(ax, size=size, pad=pad)
297 cax = self.__add_axes(ax, size=size, pad=pad)
298 cax.tick_params(labelsize=8)
298 cax.tick_params(labelsize=8)
299 self.pf_axes.append(cax)
299 self.pf_axes.append(cax)
300
300
301 for n in range(self.nrows):
301 for n in range(self.nrows):
302 if self.colormaps is not None:
302 if self.colormaps is not None:
303 cmap = plt.get_cmap(self.colormaps[n])
303 cmap = plt.get_cmap(self.colormaps[n])
304 else:
304 else:
305 cmap = plt.get_cmap(self.colormap)
305 cmap = plt.get_cmap(self.colormap)
306 cmap.set_bad(self.bgcolor, 1.)
306 cmap.set_bad(self.bgcolor, 1.)
307 self.cmaps.append(cmap)
307 self.cmaps.append(cmap)
308
308
309 for fig in self.figures:
309 for fig in self.figures:
310 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
310 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
311 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
311 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
312 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
312 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
313 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
313 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
314 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
314 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
315
315
316 def OnKeyPress(self, event):
316 def OnKeyPress(self, event):
317 '''
317 '''
318 Event for pressing keys (up, down) change colormap
318 Event for pressing keys (up, down) change colormap
319 '''
319 '''
320 ax = event.inaxes
320 ax = event.inaxes
321 if ax in self.axes:
321 if ax in self.axes:
322 if event.key == 'down':
322 if event.key == 'down':
323 ax.index += 1
323 ax.index += 1
324 elif event.key == 'up':
324 elif event.key == 'up':
325 ax.index -= 1
325 ax.index -= 1
326 if ax.index < 0:
326 if ax.index < 0:
327 ax.index = len(CMAPS) - 1
327 ax.index = len(CMAPS) - 1
328 elif ax.index == len(CMAPS):
328 elif ax.index == len(CMAPS):
329 ax.index = 0
329 ax.index = 0
330 cmap = CMAPS[ax.index]
330 cmap = CMAPS[ax.index]
331 ax.cbar.set_cmap(cmap)
331 ax.cbar.set_cmap(cmap)
332 ax.cbar.draw_all()
332 ax.cbar.draw_all()
333 ax.plt.set_cmap(cmap)
333 ax.plt.set_cmap(cmap)
334 ax.cbar.patch.figure.canvas.draw()
334 ax.cbar.patch.figure.canvas.draw()
335 self.colormap = cmap.name
335 self.colormap = cmap.name
336
336
337 def OnBtnScroll(self, event):
337 def OnBtnScroll(self, event):
338 '''
338 '''
339 Event for scrolling, scale figure
339 Event for scrolling, scale figure
340 '''
340 '''
341 cb_ax = event.inaxes
341 cb_ax = event.inaxes
342 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
342 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
343 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
343 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
344 pt = ax.cbar.ax.bbox.get_points()[:, 1]
344 pt = ax.cbar.ax.bbox.get_points()[:, 1]
345 nrm = ax.cbar.norm
345 nrm = ax.cbar.norm
346 vmin, vmax, p0, p1, pS = (
346 vmin, vmax, p0, p1, pS = (
347 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
347 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
348 scale = 2 if event.step == 1 else 0.5
348 scale = 2 if event.step == 1 else 0.5
349 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
349 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
350 ax.cbar.norm.vmin = point - scale * (point - vmin)
350 ax.cbar.norm.vmin = point - scale * (point - vmin)
351 ax.cbar.norm.vmax = point - scale * (point - vmax)
351 ax.cbar.norm.vmax = point - scale * (point - vmax)
352 ax.plt.set_norm(ax.cbar.norm)
352 ax.plt.set_norm(ax.cbar.norm)
353 ax.cbar.draw_all()
353 ax.cbar.draw_all()
354 ax.cbar.patch.figure.canvas.draw()
354 ax.cbar.patch.figure.canvas.draw()
355
355
356 def onBtnPress(self, event):
356 def onBtnPress(self, event):
357 '''
357 '''
358 Event for mouse button press
358 Event for mouse button press
359 '''
359 '''
360 cb_ax = event.inaxes
360 cb_ax = event.inaxes
361 if cb_ax is None:
361 if cb_ax is None:
362 return
362 return
363
363
364 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
364 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
365 cb_ax.press = event.x, event.y
365 cb_ax.press = event.x, event.y
366 else:
366 else:
367 cb_ax.press = None
367 cb_ax.press = None
368
368
369 def onMotion(self, event):
369 def onMotion(self, event):
370 '''
370 '''
371 Event for move inside colorbar
371 Event for move inside colorbar
372 '''
372 '''
373 cb_ax = event.inaxes
373 cb_ax = event.inaxes
374 if cb_ax is None:
374 if cb_ax is None:
375 return
375 return
376 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
376 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
377 return
377 return
378 if cb_ax.press is None:
378 if cb_ax.press is None:
379 return
379 return
380
380
381 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
381 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
382 xprev, yprev = cb_ax.press
382 xprev, yprev = cb_ax.press
383 dx = event.x - xprev
383 dx = event.x - xprev
384 dy = event.y - yprev
384 dy = event.y - yprev
385 cb_ax.press = event.x, event.y
385 cb_ax.press = event.x, event.y
386 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
386 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
387 perc = 0.03
387 perc = 0.03
388
388
389 if event.button == 1:
389 if event.button == 1:
390 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
390 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
391 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
391 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
392 elif event.button == 3:
392 elif event.button == 3:
393 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
393 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
394 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
394 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
395
395
396 ax.cbar.draw_all()
396 ax.cbar.draw_all()
397 ax.plt.set_norm(ax.cbar.norm)
397 ax.plt.set_norm(ax.cbar.norm)
398 ax.cbar.patch.figure.canvas.draw()
398 ax.cbar.patch.figure.canvas.draw()
399
399
400 def onBtnRelease(self, event):
400 def onBtnRelease(self, event):
401 '''
401 '''
402 Event for mouse button release
402 Event for mouse button release
403 '''
403 '''
404 cb_ax = event.inaxes
404 cb_ax = event.inaxes
405 if cb_ax is not None:
405 if cb_ax is not None:
406 cb_ax.press = None
406 cb_ax.press = None
407
407
408 def __add_axes(self, ax, size='30%', pad='8%'):
408 def __add_axes(self, ax, size='30%', pad='8%'):
409 '''
409 '''
410 Add new axes to the given figure
410 Add new axes to the given figure
411 '''
411 '''
412 divider = make_axes_locatable(ax)
412 divider = make_axes_locatable(ax)
413 nax = divider.new_horizontal(size=size, pad=pad)
413 nax = divider.new_horizontal(size=size, pad=pad)
414 ax.figure.add_axes(nax)
414 ax.figure.add_axes(nax)
415 return nax
415 return nax
416
416
417 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
417 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
418 '''
418 '''
419 Create a masked array for missing data
419 Create a masked array for missing data
420 '''
420 '''
421 if x_buffer.shape[0] < 2:
421 if x_buffer.shape[0] < 2:
422 return x_buffer, y_buffer, z_buffer
422 return x_buffer, y_buffer, z_buffer
423
423
424 deltas = x_buffer[1:] - x_buffer[0:-1]
424 deltas = x_buffer[1:] - x_buffer[0:-1]
425 x_median = numpy.median(deltas)
425 x_median = numpy.median(deltas)
426
426
427 index = numpy.where(deltas > 5 * x_median)
427 index = numpy.where(deltas > 5 * x_median)
428
428
429 if len(index[0]) != 0:
429 if len(index[0]) != 0:
430 z_buffer[::, index[0], ::] = self.__missing
430 z_buffer[::, index[0], ::] = self.__missing
431 z_buffer = numpy.ma.masked_inside(z_buffer,
431 z_buffer = numpy.ma.masked_inside(z_buffer,
432 0.99 * self.__missing,
432 0.99 * self.__missing,
433 1.01 * self.__missing)
433 1.01 * self.__missing)
434
434
435 return x_buffer, y_buffer, z_buffer
435 return x_buffer, y_buffer, z_buffer
436
436
437 def decimate(self):
437 def decimate(self):
438
438
439 # dx = int(len(self.x)/self.__MAXNUMX) + 1
439 # dx = int(len(self.x)/self.__MAXNUMX) + 1
440 dy = int(len(self.y) / self.decimation) + 1
440 dy = int(len(self.y) / self.decimation) + 1
441
441
442 # x = self.x[::dx]
442 # x = self.x[::dx]
443 x = self.x
443 x = self.x
444 y = self.y[::dy]
444 y = self.y[::dy]
445 z = self.z[::, ::, ::dy]
445 z = self.z[::, ::, ::dy]
446
446
447 return x, y, z
447 return x, y, z
448
448
449 def format(self):
449 def format(self):
450 '''
450 '''
451 Set min and max values, labels, ticks and titles
451 Set min and max values, labels, ticks and titles
452 '''
452 '''
453
453
454 if self.xmin is None:
454 if self.xmin is None:
455 xmin = self.data.min_time
455 xmin = self.data.min_time
456 else:
456 else:
457 if self.xaxis is 'time':
457 if self.xaxis is 'time':
458 dt = self.getDateTime(self.data.min_time)
458 dt = self.getDateTime(self.data.min_time)
459 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
459 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
460 datetime.datetime(1970, 1, 1)).total_seconds()
460 datetime.datetime(1970, 1, 1)).total_seconds()
461 if self.data.localtime:
461 if self.data.localtime:
462 xmin += time.timezone
462 xmin += time.timezone
463 else:
463 else:
464 xmin = self.xmin
464 xmin = self.xmin
465
465
466 if self.xmax is None:
466 if self.xmax is None:
467 xmax = xmin + self.xrange * 60 * 60
467 xmax = xmin + self.xrange * 60 * 60
468 else:
468 else:
469 if self.xaxis is 'time':
469 if self.xaxis is 'time':
470 dt = self.getDateTime(self.data.max_time)
470 dt = self.getDateTime(self.data.max_time)
471 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
471 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
472 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
472 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
473 if self.data.localtime:
473 if self.data.localtime:
474 xmax += time.timezone
474 xmax += time.timezone
475 else:
475 else:
476 xmax = self.xmax
476 xmax = self.xmax
477
477
478 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
478 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
479 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
479 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
480 #Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000])
480 #Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000])
481
481
482 #i = 1 if numpy.where(
482 #i = 1 if numpy.where(
483 # abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
483 # abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
484 #ystep = Y[i] / 10.
484 #ystep = Y[i] / 10.
485 dig = int(numpy.log10(ymax))
485 dig = int(numpy.log10(ymax))
486 if dig == 0:
486 if dig == 0:
487 digD = len(str(ymax)) - 2
487 digD = len(str(ymax)) - 2
488 ydec = ymax*(10**digD)
488 ydec = ymax*(10**digD)
489
489
490 dig = int(numpy.log10(ydec))
490 dig = int(numpy.log10(ydec))
491 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
491 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
492 ystep = ystep/5
492 ystep = ystep/5
493 ystep = ystep/(10**digD)
493 ystep = ystep/(10**digD)
494
494
495 else:
495 else:
496 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
496 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
497 ystep = ystep/5
497 ystep = ystep/5
498
498
499 if self.xaxis is not 'time':
499 if self.xaxis is not 'time':
500
500
501 dig = int(numpy.log10(xmax))
501 dig = int(numpy.log10(xmax))
502
502
503 if dig <= 0:
503 if dig <= 0:
504 digD = len(str(xmax)) - 2
504 digD = len(str(xmax)) - 2
505 xdec = xmax*(10**digD)
505 xdec = xmax*(10**digD)
506
506
507 dig = int(numpy.log10(xdec))
507 dig = int(numpy.log10(xdec))
508 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
508 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
509 xstep = xstep*0.5
509 xstep = xstep*0.5
510 xstep = xstep/(10**digD)
510 xstep = xstep/(10**digD)
511
511
512 else:
512 else:
513 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
513 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
514 xstep = xstep/5
514 xstep = xstep/5
515
515
516 for n, ax in enumerate(self.axes):
516 for n, ax in enumerate(self.axes):
517 if ax.firsttime:
517 if ax.firsttime:
518 ax.set_facecolor(self.bgcolor)
518 ax.set_facecolor(self.bgcolor)
519 ax.yaxis.set_major_locator(MultipleLocator(ystep))
519 ax.yaxis.set_major_locator(MultipleLocator(ystep))
520 if self.xscale:
520 if self.xscale:
521 ax.xaxis.set_major_formatter(FuncFormatter(
521 ax.xaxis.set_major_formatter(FuncFormatter(
522 lambda x, pos: '{0:g}'.format(x*self.xscale)))
522 lambda x, pos: '{0:g}'.format(x*self.xscale)))
523 if self.xscale:
523 if self.xscale:
524 ax.yaxis.set_major_formatter(FuncFormatter(
524 ax.yaxis.set_major_formatter(FuncFormatter(
525 lambda x, pos: '{0:g}'.format(x*self.yscale)))
525 lambda x, pos: '{0:g}'.format(x*self.yscale)))
526 if self.xaxis is 'time':
526 if self.xaxis is 'time':
527 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
527 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
528 ax.xaxis.set_major_locator(LinearLocator(9))
528 ax.xaxis.set_major_locator(LinearLocator(9))
529 else:
529 else:
530 ax.xaxis.set_major_locator(MultipleLocator(xstep))
530 ax.xaxis.set_major_locator(MultipleLocator(xstep))
531 if self.xlabel is not None:
531 if self.xlabel is not None:
532 ax.set_xlabel(self.xlabel)
532 ax.set_xlabel(self.xlabel)
533 ax.set_ylabel(self.ylabel)
533 ax.set_ylabel(self.ylabel)
534 ax.firsttime = False
534 ax.firsttime = False
535 if self.showprofile:
535 if self.showprofile:
536 self.pf_axes[n].set_ylim(ymin, ymax)
536 self.pf_axes[n].set_ylim(ymin, ymax)
537 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
537 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
538 self.pf_axes[n].set_xlabel('dB')
538 self.pf_axes[n].set_xlabel('dB')
539 self.pf_axes[n].grid(b=True, axis='x')
539 self.pf_axes[n].grid(b=True, axis='x')
540 [tick.set_visible(False)
540 [tick.set_visible(False)
541 for tick in self.pf_axes[n].get_yticklabels()]
541 for tick in self.pf_axes[n].get_yticklabels()]
542 if self.colorbar:
542 if self.colorbar:
543 ax.cbar = plt.colorbar(
543 ax.cbar = plt.colorbar(
544 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
544 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
545 ax.cbar.ax.tick_params(labelsize=8)
545 ax.cbar.ax.tick_params(labelsize=8)
546 ax.cbar.ax.press = None
546 ax.cbar.ax.press = None
547 if self.cb_label:
547 if self.cb_label:
548 ax.cbar.set_label(self.cb_label, size=8)
548 ax.cbar.set_label(self.cb_label, size=8)
549 elif self.cb_labels:
549 elif self.cb_labels:
550 ax.cbar.set_label(self.cb_labels[n], size=8)
550 ax.cbar.set_label(self.cb_labels[n], size=8)
551 else:
551 else:
552 ax.cbar = None
552 ax.cbar = None
553 if self.grid:
553 if self.grid:
554 ax.grid(True)
554 ax.grid(True)
555
555
556 if not self.polar:
556 if not self.polar:
557 ax.set_xlim(xmin, xmax)
557 ax.set_xlim(xmin, xmax)
558 ax.set_ylim(ymin, ymax)
558 ax.set_ylim(ymin, ymax)
559 ax.set_title('{} {} {}'.format(
559 ax.set_title('{} {} {}'.format(
560 self.titles[n],
560 self.titles[n],
561 self.getDateTime(self.data.max_time).strftime(
561 self.getDateTime(self.data.max_time).strftime(
562 '%Y-%m-%d %H:%M:%S'),
562 '%Y-%m-%d %H:%M:%S'),
563 self.time_label),
563 self.time_label),
564 size=8)
564 size=8)
565 else:
565 else:
566 ax.set_title('{}'.format(self.titles[n]), size=8)
566 ax.set_title('{}'.format(self.titles[n]), size=8)
567 ax.set_ylim(0, 90)
567 ax.set_ylim(0, 90)
568 ax.set_yticks(numpy.arange(0, 90, 20))
568 ax.set_yticks(numpy.arange(0, 90, 20))
569 ax.yaxis.labelpad = 40
569 ax.yaxis.labelpad = 40
570
570
571 def clear_figures(self):
571 def clear_figures(self):
572 '''
572 '''
573 Reset axes for redraw plots
573 Reset axes for redraw plots
574 '''
574 '''
575
575
576 for ax in self.axes:
576 for ax in self.axes:
577 ax.clear()
577 ax.clear()
578 ax.firsttime = True
578 ax.firsttime = True
579 if ax.cbar:
579 if ax.cbar:
580 ax.cbar.remove()
580 ax.cbar.remove()
581
581
582 def __plot(self):
582 def __plot(self):
583 '''
583 '''
584 Main function to plot, format and save figures
584 Main function to plot, format and save figures
585 '''
585 '''
586
586
587 try:
587 try:
588 self.plot()
588 self.plot()
589 self.format()
589 self.format()
590 except Exception as e:
590 except Exception as e:
591 log.warning('{} Plot could not be updated... check data'.format(
591 log.warning('{} Plot could not be updated... check data'.format(
592 self.CODE), self.name)
592 self.CODE), self.name)
593 log.error(str(e), '')
593 log.error(str(e), '')
594 return
594 return
595
595
596 for n, fig in enumerate(self.figures):
596 for n, fig in enumerate(self.figures):
597 if self.nrows == 0 or self.nplots == 0:
597 if self.nrows == 0 or self.nplots == 0:
598 log.warning('No data', self.name)
598 log.warning('No data', self.name)
599 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
599 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
600 fig.canvas.manager.set_window_title(self.CODE)
600 fig.canvas.manager.set_window_title(self.CODE)
601 continue
601 continue
602
602
603 fig.tight_layout()
603 fig.tight_layout()
604 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
604 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
605 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
605 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
606 fig.canvas.draw()
606 fig.canvas.draw()
607 if self.show:
607 if self.show:
608 fig.show()
608 fig.show()
609 figpause(0.1)
609 figpause(0.1)
610
610
611 if self.save:
611 if self.save:
612 self.save_figure(n)
612 self.save_figure(n)
613
613
614 if self.plot_server:
614 if self.plot_server:
615 self.send_to_server()
615 self.send_to_server()
616 # t = Thread(target=self.send_to_server)
616 # t = Thread(target=self.send_to_server)
617 # t.start()
617 # t.start()
618
618
619 def save_figure(self, n):
619 def save_figure(self, n):
620 '''
620 '''
621 '''
621 '''
622
622
623 if self.save_counter < self.save_period:
623 if self.save_counter < self.save_period:
624 self.save_counter += 1
624 self.save_counter += 1
625 return
625 return
626
626
627 self.save_counter = 1
627 self.save_counter = 1
628
628
629 fig = self.figures[n]
629 fig = self.figures[n]
630
630
631 if self.save_labels:
631 if self.save_labels:
632 labels = self.save_labels
632 labels = self.save_labels
633 else:
633 else:
634 labels = list(range(self.nrows))
634 labels = list(range(self.nrows))
635
635
636 if self.oneFigure:
636 if self.oneFigure:
637 label = ''
637 label = ''
638 else:
638 else:
639 label = '-{}'.format(labels[n])
639 label = '-{}'.format(labels[n])
640 figname = os.path.join(
640 figname = os.path.join(
641 self.save,
641 self.save,
642 self.CODE,
642 self.CODE,
643 '{}{}_{}.png'.format(
643 '{}{}_{}.png'.format(
644 self.CODE,
644 self.CODE,
645 label,
645 label,
646 self.getDateTime(self.data.max_time).strftime(
646 self.getDateTime(self.data.max_time).strftime('%Y%m%d_%H%M%S'),
647 '%Y%m%d_%H%M%S'
648 ),
649 )
647 )
650 )
648 )
649
651 log.log('Saving figure: {}'.format(figname), self.name)
650 log.log('Saving figure: {}'.format(figname), self.name)
652 if not os.path.isdir(os.path.dirname(figname)):
651 if not os.path.isdir(os.path.dirname(figname)):
653 os.makedirs(os.path.dirname(figname))
652 os.makedirs(os.path.dirname(figname))
654 fig.savefig(figname)
653 fig.savefig(figname)
655
654
656 if self.realtime:
655 if self.realtime:
657 figname = os.path.join(
656 figname = os.path.join(
658 self.save,
657 self.save,
659 '{}{}_{}.png'.format(
658 '{}{}_{}.png'.format(
660 self.CODE,
659 self.CODE,
661 label,
660 label,
662 self.getDateTime(self.data.min_time).strftime(
661 self.getDateTime(self.data.min_time).strftime(
663 '%Y%m%d'
662 '%Y%m%d'
664 ),
663 ),
665 )
664 )
666 )
665 )
667 fig.savefig(figname)
666 fig.savefig(figname)
668
667
669 def send_to_server(self):
668 def send_to_server(self):
670 '''
669 '''
671 '''
670 '''
672
671
673 if self.sender_counter < self.sender_period:
672 if self.sender_counter < self.sender_period:
674 self.sender_counter += 1
673 self.sender_counter += 1
675 return
674 return
676
675
677 self.sender_counter = 1
676 self.sender_counter = 1
678 self.data.meta['titles'] = self.titles
677 self.data.meta['titles'] = self.titles
679 retries = 2
678 retries = 2
680 while True:
679 while True:
681 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
680 self.socket.send_string(self.data.jsonify(self.plot_name, self.plot_type))
682 socks = dict(self.poll.poll(5000))
681 socks = dict(self.poll.poll(5000))
683 if socks.get(self.socket) == zmq.POLLIN:
682 if socks.get(self.socket) == zmq.POLLIN:
684 reply = self.socket.recv_string()
683 reply = self.socket.recv_string()
685 if reply == 'ok':
684 if reply == 'ok':
686 log.log("Response from server ok", self.name)
685 log.log("Response from server ok", self.name)
687 break
686 break
688 else:
687 else:
689 log.warning(
688 log.warning(
690 "Malformed reply from server: {}".format(reply), self.name)
689 "Malformed reply from server: {}".format(reply), self.name)
691
690
692 else:
691 else:
693 log.warning(
692 log.warning(
694 "No response from server, retrying...", self.name)
693 "No response from server, retrying...", self.name)
695 self.socket.setsockopt(zmq.LINGER, 0)
694 self.socket.setsockopt(zmq.LINGER, 0)
696 self.socket.close()
695 self.socket.close()
697 self.poll.unregister(self.socket)
696 self.poll.unregister(self.socket)
698 retries -= 1
697 retries -= 1
699 if retries == 0:
698 if retries == 0:
700 log.error(
699 log.error(
701 "Server seems to be offline, abandoning", self.name)
700 "Server seems to be offline, abandoning", self.name)
702 self.socket = self.context.socket(zmq.REQ)
701 self.socket = self.context.socket(zmq.REQ)
703 self.socket.connect(self.plot_server)
702 self.socket.connect(self.plot_server)
704 self.poll.register(self.socket, zmq.POLLIN)
703 self.poll.register(self.socket, zmq.POLLIN)
705 time.sleep(1)
704 time.sleep(1)
706 break
705 break
707 self.socket = self.context.socket(zmq.REQ)
706 self.socket = self.context.socket(zmq.REQ)
708 self.socket.connect(self.plot_server)
707 self.socket.connect(self.plot_server)
709 self.poll.register(self.socket, zmq.POLLIN)
708 self.poll.register(self.socket, zmq.POLLIN)
710 time.sleep(0.5)
709 time.sleep(0.5)
711
710
712 def setup(self):
711 def setup(self):
713 '''
712 '''
714 This method should be implemented in the child class, the following
713 This method should be implemented in the child class, the following
715 attributes should be set:
714 attributes should be set:
716
715
717 self.nrows: number of rows
716 self.nrows: number of rows
718 self.ncols: number of cols
717 self.ncols: number of cols
719 self.nplots: number of plots (channels or pairs)
718 self.nplots: number of plots (channels or pairs)
720 self.ylabel: label for Y axes
719 self.ylabel: label for Y axes
721 self.titles: list of axes title
720 self.titles: list of axes title
722
721
723 '''
722 '''
724 raise NotImplementedError
723 raise NotImplementedError
725
724
726 def plot(self):
725 def plot(self):
727 '''
726 '''
728 Must be defined in the child class
727 Must be defined in the child class
729 '''
728 '''
730 raise NotImplementedError
729 raise NotImplementedError
731
730
732 def run(self, dataOut, **kwargs):
731 def run(self, dataOut, **kwargs):
733 '''
732 '''
734 Main plotting routine
733 Main plotting routine
735 '''
734 '''
736
735
737 if self.isConfig is False:
736 if self.isConfig is False:
738 self.__setup(**kwargs)
737 self.__setup(**kwargs)
739 if dataOut.type == 'Parameters':
738 if dataOut.type == 'Parameters':
740 t = dataOut.utctimeInit
739 t = dataOut.utctimeInit
741 else:
740 else:
742 t = dataOut.utctime
741 t = dataOut.utctime
743
742
744 if dataOut.useLocalTime:
743 if dataOut.useLocalTime:
745 self.getDateTime = datetime.datetime.fromtimestamp
744 self.getDateTime = datetime.datetime.fromtimestamp
746 if not self.localtime:
745 if not self.localtime:
747 t += time.timezone
746 t += time.timezone
748 else:
747 else:
749 self.getDateTime = datetime.datetime.utcfromtimestamp
748 self.getDateTime = datetime.datetime.utcfromtimestamp
750 if self.localtime:
749 if self.localtime:
751 t -= time.timezone
750 t -= time.timezone
752
751
753 if 'buffer' in self.plot_type:
752 if 'buffer' in self.plot_type:
754 if self.xmin is None:
753 if self.xmin is None:
755 self.tmin = t
754 self.tmin = t
756 else:
755 else:
757 self.tmin = (
756 self.tmin = (
758 self.getDateTime(t).replace(
757 self.getDateTime(t).replace(
759 hour=self.xmin,
758 hour=self.xmin,
760 minute=0,
759 minute=0,
761 second=0) - self.getDateTime(0)).total_seconds()
760 second=0) - self.getDateTime(0)).total_seconds()
762
761
763 self.data.setup()
762 self.data.setup()
764 self.isConfig = True
763 self.isConfig = True
765 if self.plot_server:
764 if self.plot_server:
766 self.context = zmq.Context()
765 self.context = zmq.Context()
767 self.socket = self.context.socket(zmq.REQ)
766 self.socket = self.context.socket(zmq.REQ)
768 self.socket.connect(self.plot_server)
767 self.socket.connect(self.plot_server)
769 self.poll = zmq.Poller()
768 self.poll = zmq.Poller()
770 self.poll.register(self.socket, zmq.POLLIN)
769 self.poll.register(self.socket, zmq.POLLIN)
771
770
772 if dataOut.type == 'Parameters':
771 if dataOut.type == 'Parameters':
773 tm = dataOut.utctimeInit
772 tm = dataOut.utctimeInit
774 else:
773 else:
775 tm = dataOut.utctime
774 tm = dataOut.utctime
776
775
777 if not dataOut.useLocalTime and self.localtime:
776 if not dataOut.useLocalTime and self.localtime:
778 tm -= time.timezone
777 tm -= time.timezone
779 if dataOut.useLocalTime and not self.localtime:
778 if dataOut.useLocalTime and not self.localtime:
780 tm += time.timezone
779 tm += time.timezone
781
780
782 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
781 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
783 self.save_counter = self.save_period
782 self.save_counter = self.save_period
784 self.__plot()
783 self.__plot()
785 self.xmin += self.xrange
784 self.xmin += self.xrange
786 if self.xmin >= 24:
785 if self.xmin >= 24:
787 self.xmin -= 24
786 self.xmin -= 24
788 self.tmin += self.xrange*60*60
787 self.tmin += self.xrange*60*60
789 self.data.setup()
788 self.data.setup()
790 self.clear_figures()
789 self.clear_figures()
791
790
792 self.data.update(dataOut, tm)
791 self.data.update(dataOut, tm)
793
792
794 if self.isPlotConfig is False:
793 if self.isPlotConfig is False:
795 self.__setup_plot()
794 self.__setup_plot()
796 self.isPlotConfig = True
795 self.isPlotConfig = True
797
796
798 if self.realtime:
797 if self.realtime:
799 self.__plot()
798 self.__plot()
800 else:
799 else:
801 self.__throttle_plot(self.__plot)#, coerce=coerce)
800 self.__throttle_plot(self.__plot)#, coerce=coerce)
802
801
803 def close(self):
802 def close(self):
804
803
805 if self.data:
804 if self.data:
806 self.save_counter = self.save_period
805 self.save_counter = self.save_period
807 self.__plot()
806 self.__plot()
808 if self.data and self.pause:
807 if self.data and self.pause:
809 figpause(10)
808 figpause(10)
810
@@ -1,629 +1,649
1 '''
1 '''
2 Created on Set 9, 2015
2 Created on Set 9, 2015
3
3
4 @author: roj-idl71 Karim Kuyeng
4 @author: roj-idl71 Karim Kuyeng
5 '''
5 '''
6
6
7 import os
7 import os
8 import sys
8 import sys
9 import glob
9 import glob
10 import fnmatch
10 import fnmatch
11 import datetime
11 import datetime
12 import time
12 import time
13 import re
13 import re
14 import h5py
14 import h5py
15 import numpy
15 import numpy
16
16
17 try:
17 try:
18 from gevent import sleep
18 from gevent import sleep
19 except:
19 except:
20 from time import sleep
20 from time import sleep
21
21
22 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
22 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
23 from schainpy.model.data.jrodata import Voltage
23 from schainpy.model.data.jrodata import Voltage
24 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
24 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
25 from numpy import imag
25 from numpy import imag
26
26
27 @MPDecorator
27 class AMISRReader(ProcessingUnit):
28 class AMISRReader(ProcessingUnit):
28 '''
29 '''
29 classdocs
30 classdocs
30 '''
31 '''
31
32
32 def __init__(self):
33 def __init__(self):
33 '''
34 '''
34 Constructor
35 Constructor
35 '''
36 '''
36
37
37 ProcessingUnit.__init__(self)
38 ProcessingUnit.__init__(self)
38
39
39 self.set = None
40 self.set = None
40 self.subset = None
41 self.subset = None
41 self.extension_file = '.h5'
42 self.extension_file = '.h5'
42 self.dtc_str = 'dtc'
43 self.dtc_str = 'dtc'
43 self.dtc_id = 0
44 self.dtc_id = 0
44 self.status = True
45 self.status = True
45 self.isConfig = False
46 self.isConfig = False
46 self.dirnameList = []
47 self.dirnameList = []
47 self.filenameList = []
48 self.filenameList = []
48 self.fileIndex = None
49 self.fileIndex = None
49 self.flagNoMoreFiles = False
50 self.flagNoMoreFiles = False
50 self.flagIsNewFile = 0
51 self.flagIsNewFile = 0
51 self.filename = ''
52 self.filename = ''
52 self.amisrFilePointer = None
53 self.amisrFilePointer = None
53
54
54
55
55 self.dataset = None
56 #self.dataset = None
56
57
57
58
58
59
59
60
60 self.profileIndex = 0
61 self.profileIndex = 0
61
62
62
63
63 self.beamCodeByFrame = None
64 self.beamCodeByFrame = None
64 self.radacTimeByFrame = None
65 self.radacTimeByFrame = None
65
66
66 self.dataset = None
67 self.dataset = None
67
68
68
69
69
70
70
71
71 self.__firstFile = True
72 self.__firstFile = True
72
73
73 self.buffer = None
74 self.buffer = None
74
75
75
76
76 self.timezone = 'ut'
77 self.timezone = 'ut'
77
78
78 self.__waitForNewFile = 20
79 self.__waitForNewFile = 20
79 self.__filename_online = None
80 self.__filename_online = None
80 #Is really necessary create the output object in the initializer
81 #Is really necessary create the output object in the initializer
81 self.dataOut = Voltage()
82 self.dataOut = Voltage()
83 self.dataOut.error=False
82
84
83 def setup(self,path=None,
85 def setup(self,path=None,
84 startDate=None,
86 startDate=None,
85 endDate=None,
87 endDate=None,
86 startTime=None,
88 startTime=None,
87 endTime=None,
89 endTime=None,
88 walk=True,
90 walk=True,
89 timezone='ut',
91 timezone='ut',
90 all=0,
92 all=0,
91 code = None,
93 code = None,
92 nCode = 0,
94 nCode = 0,
93 nBaud = 0,
95 nBaud = 0,
94 online=False):
96 online=False):
95
97
98 #print ("T",path)
99
96 self.timezone = timezone
100 self.timezone = timezone
97 self.all = all
101 self.all = all
98 self.online = online
102 self.online = online
99
103
100 self.code = code
104 self.code = code
101 self.nCode = int(nCode)
105 self.nCode = int(nCode)
102 self.nBaud = int(nBaud)
106 self.nBaud = int(nBaud)
103
107
104
108
105
109
106 #self.findFiles()
110 #self.findFiles()
107 if not(online):
111 if not(online):
108 #Busqueda de archivos offline
112 #Busqueda de archivos offline
109 self.searchFilesOffLine(path, startDate, endDate, startTime, endTime, walk)
113 self.searchFilesOffLine(path, startDate, endDate, startTime, endTime, walk)
110 else:
114 else:
111 self.searchFilesOnLine(path, startDate, endDate, startTime,endTime,walk)
115 self.searchFilesOnLine(path, startDate, endDate, startTime,endTime,walk)
112
116
113 if not(self.filenameList):
117 if not(self.filenameList):
114 print("There is no files into the folder: %s"%(path))
118 print("There is no files into the folder: %s"%(path))
115
116 sys.exit(-1)
119 sys.exit(-1)
117
120
118 self.fileIndex = -1
121 self.fileIndex = -1
119
122
120 self.readNextFile(online)
123 self.readNextFile(online)
121
124
122 '''
125 '''
123 Add code
126 Add code
124 '''
127 '''
125 self.isConfig = True
128 self.isConfig = True
126
129
127 pass
130 pass
128
131
129
132
130 def readAMISRHeader(self,fp):
133 def readAMISRHeader(self,fp):
131 header = 'Raw11/Data/RadacHeader'
134 header = 'Raw11/Data/RadacHeader'
132 self.beamCodeByPulse = fp.get(header+'/BeamCode') # LIST OF BEAMS PER PROFILE, TO BE USED ON REARRANGE
135 self.beamCodeByPulse = fp.get(header+'/BeamCode') # LIST OF BEAMS PER PROFILE, TO BE USED ON REARRANGE
133 self.beamCode = fp.get('Raw11/Data/Beamcodes') # NUMBER OF CHANNELS AND IDENTIFY POSITION TO CREATE A FILE WITH THAT INFO
136 self.beamCode = fp.get('Raw11/Data/Beamcodes') # NUMBER OF CHANNELS AND IDENTIFY POSITION TO CREATE A FILE WITH THAT INFO
134 #self.code = fp.get(header+'/Code') # NOT USE FOR THIS
137 #self.code = fp.get(header+'/Code') # NOT USE FOR THIS
135 self.frameCount = fp.get(header+'/FrameCount')# NOT USE FOR THIS
138 self.frameCount = fp.get(header+'/FrameCount')# NOT USE FOR THIS
136 self.modeGroup = fp.get(header+'/ModeGroup')# NOT USE FOR THIS
139 self.modeGroup = fp.get(header+'/ModeGroup')# NOT USE FOR THIS
137 self.nsamplesPulse = fp.get(header+'/NSamplesPulse')# TO GET NSA OR USING DATA FOR THAT
140 self.nsamplesPulse = fp.get(header+'/NSamplesPulse')# TO GET NSA OR USING DATA FOR THAT
138 self.pulseCount = fp.get(header+'/PulseCount')# NOT USE FOR THIS
141 self.pulseCount = fp.get(header+'/PulseCount')# NOT USE FOR THIS
139 self.radacTime = fp.get(header+'/RadacTime')# 1st TIME ON FILE ANDE CALCULATE THE REST WITH IPP*nindexprofile
142 self.radacTime = fp.get(header+'/RadacTime')# 1st TIME ON FILE ANDE CALCULATE THE REST WITH IPP*nindexprofile
140 self.timeCount = fp.get(header+'/TimeCount')# NOT USE FOR THIS
143 self.timeCount = fp.get(header+'/TimeCount')# NOT USE FOR THIS
141 self.timeStatus = fp.get(header+'/TimeStatus')# NOT USE FOR THIS
144 self.timeStatus = fp.get(header+'/TimeStatus')# NOT USE FOR THIS
142 self.rangeFromFile = fp.get('Raw11/Data/Samples/Range')
145 self.rangeFromFile = fp.get('Raw11/Data/Samples/Range')
143 self.frequency = fp.get('Rx/Frequency')
146 self.frequency = fp.get('Rx/Frequency')
144 txAus = fp.get('Raw11/Data/Pulsewidth')
147 txAus = fp.get('Raw11/Data/Pulsewidth')
145
148
146
149
147 self.nblocks = self.pulseCount.shape[0] #nblocks
150 self.nblocks = self.pulseCount.shape[0] #nblocks
148
151
149 self.nprofiles = self.pulseCount.shape[1] #nprofile
152 self.nprofiles = self.pulseCount.shape[1] #nprofile
150 self.nsa = self.nsamplesPulse[0,0] #ngates
153 self.nsa = self.nsamplesPulse[0,0] #ngates
151 self.nchannels = self.beamCode.shape[1]
154 self.nchannels = self.beamCode.shape[1]
152 self.ippSeconds = (self.radacTime[0][1] -self.radacTime[0][0]) #Ipp in seconds
155 self.ippSeconds = (self.radacTime[0][1] -self.radacTime[0][0]) #Ipp in seconds
153 #self.__waitForNewFile = self.nblocks # wait depending on the number of blocks since each block is 1 sec
156 #self.__waitForNewFile = self.nblocks # wait depending on the number of blocks since each block is 1 sec
154 self.__waitForNewFile = self.nblocks * self.nprofiles * self.ippSeconds # wait until new file is created
157 self.__waitForNewFile = self.nblocks * self.nprofiles * self.ippSeconds # wait until new file is created
155
158
156 #filling radar controller header parameters
159 #filling radar controller header parameters
157 self.__ippKm = self.ippSeconds *.15*1e6 # in km
160 self.__ippKm = self.ippSeconds *.15*1e6 # in km
158 self.__txA = (txAus.value)*.15 #(ipp[us]*.15km/1us) in km
161 self.__txA = (txAus.value)*.15 #(ipp[us]*.15km/1us) in km
159 self.__txB = 0
162 self.__txB = 0
160 nWindows=1
163 nWindows=1
161 self.__nSamples = self.nsa
164 self.__nSamples = self.nsa
162 self.__firstHeight = self.rangeFromFile[0][0]/1000 #in km
165 self.__firstHeight = self.rangeFromFile[0][0]/1000 #in km
163 self.__deltaHeight = (self.rangeFromFile[0][1] - self.rangeFromFile[0][0])/1000
166 self.__deltaHeight = (self.rangeFromFile[0][1] - self.rangeFromFile[0][0])/1000
164
167
165 #for now until understand why the code saved is different (code included even though code not in tuf file)
168 #for now until understand why the code saved is different (code included even though code not in tuf file)
166 #self.__codeType = 0
169 #self.__codeType = 0
167 # self.__nCode = None
170 # self.__nCode = None
168 # self.__nBaud = None
171 # self.__nBaud = None
169 self.__code = self.code
172 self.__code = self.code
170 self.__codeType = 0
173 self.__codeType = 0
171 if self.code != None:
174 if self.code != None:
172 self.__codeType = 1
175 self.__codeType = 1
173 self.__nCode = self.nCode
176 self.__nCode = self.nCode
174 self.__nBaud = self.nBaud
177 self.__nBaud = self.nBaud
175 #self.__code = 0
178 #self.__code = 0
176
179
177 #filling system header parameters
180 #filling system header parameters
178 self.__nSamples = self.nsa
181 self.__nSamples = self.nsa
179 self.newProfiles = self.nprofiles/self.nchannels
182 self.newProfiles = self.nprofiles/self.nchannels
180 self.__channelList = list(range(self.nchannels))
183 self.__channelList = list(range(self.nchannels))
181
184
182 self.__frequency = self.frequency[0][0]
185 self.__frequency = self.frequency[0][0]
183
186
184
187
185
188
186 def createBuffers(self):
189 def createBuffers(self):
187
190
188 pass
191 pass
189
192
190 def __setParameters(self,path='', startDate='',endDate='',startTime='', endTime='', walk=''):
193 def __setParameters(self,path='', startDate='',endDate='',startTime='', endTime='', walk=''):
191 self.path = path
194 self.path = path
192 self.startDate = startDate
195 self.startDate = startDate
193 self.endDate = endDate
196 self.endDate = endDate
194 self.startTime = startTime
197 self.startTime = startTime
195 self.endTime = endTime
198 self.endTime = endTime
196 self.walk = walk
199 self.walk = walk
197
200
198 def __checkPath(self):
201 def __checkPath(self):
199 if os.path.exists(self.path):
202 if os.path.exists(self.path):
200 self.status = 1
203 self.status = 1
201 else:
204 else:
202 self.status = 0
205 self.status = 0
203 print('Path:%s does not exists'%self.path)
206 print('Path:%s does not exists'%self.path)
204
207
205 return
208 return
206
209
207
210
208 def __selDates(self, amisr_dirname_format):
211 def __selDates(self, amisr_dirname_format):
209 try:
212 try:
210 year = int(amisr_dirname_format[0:4])
213 year = int(amisr_dirname_format[0:4])
211 month = int(amisr_dirname_format[4:6])
214 month = int(amisr_dirname_format[4:6])
212 dom = int(amisr_dirname_format[6:8])
215 dom = int(amisr_dirname_format[6:8])
213 thisDate = datetime.date(year,month,dom)
216 thisDate = datetime.date(year,month,dom)
214
217
215 if (thisDate>=self.startDate and thisDate <= self.endDate):
218 if (thisDate>=self.startDate and thisDate <= self.endDate):
216 return amisr_dirname_format
219 return amisr_dirname_format
217 except:
220 except:
218 return None
221 return None
219
222
220
223
221 def __findDataForDates(self,online=False):
224 def __findDataForDates(self,online=False):
222
225
223 if not(self.status):
226 if not(self.status):
224 return None
227 return None
225
228
226 pat = '\d+.\d+'
229 pat = '\d+.\d+'
227 dirnameList = [re.search(pat,x) for x in os.listdir(self.path)]
230 dirnameList = [re.search(pat,x) for x in os.listdir(self.path)]
228 dirnameList = [x for x in dirnameList if x!=None]
231 dirnameList = [x for x in dirnameList if x!=None]
229 dirnameList = [x.string for x in dirnameList]
232 dirnameList = [x.string for x in dirnameList]
230 if not(online):
233 if not(online):
231 dirnameList = [self.__selDates(x) for x in dirnameList]
234 dirnameList = [self.__selDates(x) for x in dirnameList]
232 dirnameList = [x for x in dirnameList if x!=None]
235 dirnameList = [x for x in dirnameList if x!=None]
233 if len(dirnameList)>0:
236 if len(dirnameList)>0:
234 self.status = 1
237 self.status = 1
235 self.dirnameList = dirnameList
238 self.dirnameList = dirnameList
236 self.dirnameList.sort()
239 self.dirnameList.sort()
237 else:
240 else:
238 self.status = 0
241 self.status = 0
239 return None
242 return None
240
243
241 def __getTimeFromData(self):
244 def __getTimeFromData(self):
242 startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime)
245 startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime)
243 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
246 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
244
247
245 print('Filtering Files from %s to %s'%(startDateTime_Reader, endDateTime_Reader))
248 print('Filtering Files from %s to %s'%(startDateTime_Reader, endDateTime_Reader))
246 print('........................................')
249 print('........................................')
247 filter_filenameList = []
250 filter_filenameList = []
248 self.filenameList.sort()
251 self.filenameList.sort()
249 #for i in range(len(self.filenameList)-1):
252 #for i in range(len(self.filenameList)-1):
250 for i in range(len(self.filenameList)):
253 for i in range(len(self.filenameList)):
251 filename = self.filenameList[i]
254 filename = self.filenameList[i]
252 fp = h5py.File(filename,'r')
255 fp = h5py.File(filename,'r')
253 time_str = fp.get('Time/RadacTimeString')
256 time_str = fp.get('Time/RadacTimeString')
254
257
255 startDateTimeStr_File = time_str[0][0].split('.')[0]
258 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
259 #startDateTimeStr_File = "2019-12-16 09:21:11"
256 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
260 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
257 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
261 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
258
262
259 endDateTimeStr_File = time_str[-1][-1].split('.')[0]
263 #endDateTimeStr_File = "2019-12-16 11:10:11"
264 endDateTimeStr_File = time_str[-1][-1].decode('UTF-8').split('.')[0]
260 junk = time.strptime(endDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
265 junk = time.strptime(endDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
261 endDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
266 endDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
262
267
263 fp.close()
268 fp.close()
264
269
270 #print("check time", startDateTime_File)
265 if self.timezone == 'lt':
271 if self.timezone == 'lt':
266 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
272 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
267 endDateTime_File = endDateTime_File - datetime.timedelta(minutes = 300)
273 endDateTime_File = endDateTime_File - datetime.timedelta(minutes = 300)
268
269 if (endDateTime_File>=startDateTime_Reader and endDateTime_File<endDateTime_Reader):
274 if (endDateTime_File>=startDateTime_Reader and endDateTime_File<endDateTime_Reader):
270 #self.filenameList.remove(filename)
275 #self.filenameList.remove(filename)
271 filter_filenameList.append(filename)
276 filter_filenameList.append(filename)
272
277
273 if (endDateTime_File>=endDateTime_Reader):
278 if (endDateTime_File>=endDateTime_Reader):
274 break
279 break
275
280
276
281
277 filter_filenameList.sort()
282 filter_filenameList.sort()
278 self.filenameList = filter_filenameList
283 self.filenameList = filter_filenameList
279 return 1
284 return 1
280
285
281 def __filterByGlob1(self, dirName):
286 def __filterByGlob1(self, dirName):
282 filter_files = glob.glob1(dirName, '*.*%s'%self.extension_file)
287 filter_files = glob.glob1(dirName, '*.*%s'%self.extension_file)
283 filter_files.sort()
288 filter_files.sort()
284 filterDict = {}
289 filterDict = {}
285 filterDict.setdefault(dirName)
290 filterDict.setdefault(dirName)
286 filterDict[dirName] = filter_files
291 filterDict[dirName] = filter_files
287 return filterDict
292 return filterDict
288
293
289 def __getFilenameList(self, fileListInKeys, dirList):
294 def __getFilenameList(self, fileListInKeys, dirList):
290 for value in fileListInKeys:
295 for value in fileListInKeys:
291 dirName = list(value.keys())[0]
296 dirName = list(value.keys())[0]
292 for file in value[dirName]:
297 for file in value[dirName]:
293 filename = os.path.join(dirName, file)
298 filename = os.path.join(dirName, file)
294 self.filenameList.append(filename)
299 self.filenameList.append(filename)
295
300
296
301
297 def __selectDataForTimes(self, online=False):
302 def __selectDataForTimes(self, online=False):
298 #aun no esta implementado el filtro for tiempo
303 #aun no esta implementado el filtro for tiempo
299 if not(self.status):
304 if not(self.status):
300 return None
305 return None
301
306
302 dirList = [os.path.join(self.path,x) for x in self.dirnameList]
307 dirList = [os.path.join(self.path,x) for x in self.dirnameList]
303
308
304 fileListInKeys = [self.__filterByGlob1(x) for x in dirList]
309 fileListInKeys = [self.__filterByGlob1(x) for x in dirList]
305
310
306 self.__getFilenameList(fileListInKeys, dirList)
311 self.__getFilenameList(fileListInKeys, dirList)
307 if not(online):
312 if not(online):
308 #filtro por tiempo
313 #filtro por tiempo
309 if not(self.all):
314 if not(self.all):
310 self.__getTimeFromData()
315 self.__getTimeFromData()
311
316
312 if len(self.filenameList)>0:
317 if len(self.filenameList)>0:
313 self.status = 1
318 self.status = 1
314 self.filenameList.sort()
319 self.filenameList.sort()
315 else:
320 else:
316 self.status = 0
321 self.status = 0
317 return None
322 return None
318
323
319 else:
324 else:
320 #get the last file - 1
325 #get the last file - 1
321 self.filenameList = [self.filenameList[-2]]
326 self.filenameList = [self.filenameList[-2]]
322
327
323 new_dirnameList = []
328 new_dirnameList = []
324 for dirname in self.dirnameList:
329 for dirname in self.dirnameList:
325 junk = numpy.array([dirname in x for x in self.filenameList])
330 junk = numpy.array([dirname in x for x in self.filenameList])
326 junk_sum = junk.sum()
331 junk_sum = junk.sum()
327 if junk_sum > 0:
332 if junk_sum > 0:
328 new_dirnameList.append(dirname)
333 new_dirnameList.append(dirname)
329 self.dirnameList = new_dirnameList
334 self.dirnameList = new_dirnameList
330 return 1
335 return 1
331
336
332 def searchFilesOnLine(self, path, startDate, endDate, startTime=datetime.time(0,0,0),
337 def searchFilesOnLine(self, path, startDate, endDate, startTime=datetime.time(0,0,0),
333 endTime=datetime.time(23,59,59),walk=True):
338 endTime=datetime.time(23,59,59),walk=True):
334
339
335 if endDate ==None:
340 if endDate ==None:
336 startDate = datetime.datetime.utcnow().date()
341 startDate = datetime.datetime.utcnow().date()
337 endDate = datetime.datetime.utcnow().date()
342 endDate = datetime.datetime.utcnow().date()
338
343
339 self.__setParameters(path=path, startDate=startDate, endDate=endDate,startTime = startTime,endTime=endTime, walk=walk)
344 self.__setParameters(path=path, startDate=startDate, endDate=endDate,startTime = startTime,endTime=endTime, walk=walk)
340
345
341 self.__checkPath()
346 self.__checkPath()
342
347
343 self.__findDataForDates(online=True)
348 self.__findDataForDates(online=True)
344
349
345 self.dirnameList = [self.dirnameList[-1]]
350 self.dirnameList = [self.dirnameList[-1]]
346
351
347 self.__selectDataForTimes(online=True)
352 self.__selectDataForTimes(online=True)
348
353
349 return
354 return
350
355
351
356
352 def searchFilesOffLine(self,
357 def searchFilesOffLine(self,
353 path,
358 path,
354 startDate,
359 startDate,
355 endDate,
360 endDate,
356 startTime=datetime.time(0,0,0),
361 startTime=datetime.time(0,0,0),
357 endTime=datetime.time(23,59,59),
362 endTime=datetime.time(23,59,59),
358 walk=True):
363 walk=True):
359
364
360 self.__setParameters(path, startDate, endDate, startTime, endTime, walk)
365 self.__setParameters(path, startDate, endDate, startTime, endTime, walk)
361
366
362 self.__checkPath()
367 self.__checkPath()
363
368
364 self.__findDataForDates()
369 self.__findDataForDates()
365
370
366 self.__selectDataForTimes()
371 self.__selectDataForTimes()
367
372
368 for i in range(len(self.filenameList)):
373 for i in range(len(self.filenameList)):
369 print("%s" %(self.filenameList[i]))
374 print("%s" %(self.filenameList[i]))
370
375
371 return
376 return
372
377
373 def __setNextFileOffline(self):
378 def __setNextFileOffline(self):
374 idFile = self.fileIndex
379 idFile = self.fileIndex
375
380
376 while (True):
381 while (True):
377 idFile += 1
382 idFile += 1
378 if not(idFile < len(self.filenameList)):
383 if not(idFile < len(self.filenameList)):
379 self.flagNoMoreFiles = 1
384 self.flagNoMoreFiles = 1
380 print("No more Files")
385 print("No more Files")
386 self.dataOut.error = True
381 return 0
387 return 0
382
388
383 filename = self.filenameList[idFile]
389 filename = self.filenameList[idFile]
384
390
385 amisrFilePointer = h5py.File(filename,'r')
391 amisrFilePointer = h5py.File(filename,'r')
386
392
387 break
393 break
388
394
389 self.flagIsNewFile = 1
395 self.flagIsNewFile = 1
390 self.fileIndex = idFile
396 self.fileIndex = idFile
391 self.filename = filename
397 self.filename = filename
392
398
393 self.amisrFilePointer = amisrFilePointer
399 self.amisrFilePointer = amisrFilePointer
394
400
395 print("Setting the file: %s"%self.filename)
401 print("Setting the file: %s"%self.filename)
396
402
397 return 1
403 return 1
398
404
399
405
400 def __setNextFileOnline(self):
406 def __setNextFileOnline(self):
401 filename = self.filenameList[0]
407 filename = self.filenameList[0]
402 if self.__filename_online != None:
408 if self.__filename_online != None:
403 self.__selectDataForTimes(online=True)
409 self.__selectDataForTimes(online=True)
404 filename = self.filenameList[0]
410 filename = self.filenameList[0]
405 wait = 0
411 wait = 0
406 while self.__filename_online == filename:
412 while self.__filename_online == filename:
407 print('waiting %d seconds to get a new file...'%(self.__waitForNewFile))
413 print('waiting %d seconds to get a new file...'%(self.__waitForNewFile))
408 if wait == 5:
414 if wait == 5:
409 return 0
415 return 0
410 sleep(self.__waitForNewFile)
416 sleep(self.__waitForNewFile)
411 self.__selectDataForTimes(online=True)
417 self.__selectDataForTimes(online=True)
412 filename = self.filenameList[0]
418 filename = self.filenameList[0]
413 wait += 1
419 wait += 1
414
420
415 self.__filename_online = filename
421 self.__filename_online = filename
416
422
417 self.amisrFilePointer = h5py.File(filename,'r')
423 self.amisrFilePointer = h5py.File(filename,'r')
418 self.flagIsNewFile = 1
424 self.flagIsNewFile = 1
419 self.filename = filename
425 self.filename = filename
420 print("Setting the file: %s"%self.filename)
426 print("Setting the file: %s"%self.filename)
421 return 1
427 return 1
422
428
423
429
424 def readData(self):
430 def readData(self):
425 buffer = self.amisrFilePointer.get('Raw11/Data/Samples/Data')
431 buffer = self.amisrFilePointer.get('Raw11/Data/Samples/Data')
426 re = buffer[:,:,:,0]
432 re = buffer[:,:,:,0]
427 im = buffer[:,:,:,1]
433 im = buffer[:,:,:,1]
428 dataset = re + im*1j
434 dataset = re + im*1j
435
429 self.radacTime = self.amisrFilePointer.get('Raw11/Data/RadacHeader/RadacTime')
436 self.radacTime = self.amisrFilePointer.get('Raw11/Data/RadacHeader/RadacTime')
430 timeset = self.radacTime[:,0]
437 timeset = self.radacTime[:,0]
438
431 return dataset,timeset
439 return dataset,timeset
432
440
433 def reshapeData(self):
441 def reshapeData(self):
434 #self.beamCodeByPulse, self.beamCode, self.nblocks, self.nprofiles, self.nsa,
442 #self.beamCodeByPulse, self.beamCode, self.nblocks, self.nprofiles, self.nsa,
435 channels = self.beamCodeByPulse[0,:]
443 channels = self.beamCodeByPulse[0,:]
436 nchan = self.nchannels
444 nchan = self.nchannels
437 #self.newProfiles = self.nprofiles/nchan #must be defined on filljroheader
445 #self.newProfiles = self.nprofiles/nchan #must be defined on filljroheader
438 nblocks = self.nblocks
446 nblocks = self.nblocks
439 nsamples = self.nsa
447 nsamples = self.nsa
440
448
441 #Dimensions : nChannels, nProfiles, nSamples
449 #Dimensions : nChannels, nProfiles, nSamples
442 new_block = numpy.empty((nblocks, nchan, self.newProfiles, nsamples), dtype="complex64")
450 new_block = numpy.empty((nblocks, nchan, numpy.int_(self.newProfiles), nsamples), dtype="complex64")
443 ############################################
451 ############################################
444
452
445 for thisChannel in range(nchan):
453 for thisChannel in range(nchan):
446 new_block[:,thisChannel,:,:] = self.dataset[:,numpy.where(channels==self.beamCode[0][thisChannel])[0],:]
454 new_block[:,thisChannel,:,:] = self.dataset[:,numpy.where(channels==self.beamCode[0][thisChannel])[0],:]
447
455
448
456
449 new_block = numpy.transpose(new_block, (1,0,2,3))
457 new_block = numpy.transpose(new_block, (1,0,2,3))
450 new_block = numpy.reshape(new_block, (nchan,-1, nsamples))
458 new_block = numpy.reshape(new_block, (nchan,-1, nsamples))
451
459
452 return new_block
460 return new_block
453
461
454 def updateIndexes(self):
462 def updateIndexes(self):
455
463
456 pass
464 pass
457
465
458 def fillJROHeader(self):
466 def fillJROHeader(self):
459
467
460 #fill radar controller header
468 #fill radar controller header
461 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ippKm=self.__ippKm,
469 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ipp=self.__ippKm,
462 txA=self.__txA,
470 txA=self.__txA,
463 txB=0,
471 txB=0,
464 nWindows=1,
472 nWindows=1,
465 nHeights=self.__nSamples,
473 nHeights=self.__nSamples,
466 firstHeight=self.__firstHeight,
474 firstHeight=self.__firstHeight,
467 deltaHeight=self.__deltaHeight,
475 deltaHeight=self.__deltaHeight,
468 codeType=self.__codeType,
476 codeType=self.__codeType,
469 nCode=self.__nCode, nBaud=self.__nBaud,
477 nCode=self.__nCode, nBaud=self.__nBaud,
470 code = self.__code,
478 code = self.__code,
471 fClock=1)
479 fClock=1)
472
480
473
474
475 #fill system header
481 #fill system header
476 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
482 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
477 nProfiles=self.newProfiles,
483 nProfiles=self.newProfiles,
478 nChannels=len(self.__channelList),
484 nChannels=len(self.__channelList),
479 adcResolution=14,
485 adcResolution=14,
480 pciDioBusWith=32)
486 pciDioBusWidth=32)
481
487
482 self.dataOut.type = "Voltage"
488 self.dataOut.type = "Voltage"
483
489
484 self.dataOut.data = None
490 self.dataOut.data = None
485
491
486 self.dataOut.dtype = numpy.dtype([('real','<i8'),('imag','<i8')])
492 self.dataOut.dtype = numpy.dtype([('real','<i8'),('imag','<i8')])
487
493
488 # self.dataOut.nChannels = 0
494 # self.dataOut.nChannels = 0
489
495
490 # self.dataOut.nHeights = 0
496 # self.dataOut.nHeights = 0
491
497
492 self.dataOut.nProfiles = self.newProfiles*self.nblocks
498 self.dataOut.nProfiles = self.newProfiles*self.nblocks
493
499
494 #self.dataOut.heightList = self.__firstHeigth + numpy.arange(self.__nSamples, dtype = numpy.float)*self.__deltaHeigth
500 #self.dataOut.heightList = self.__firstHeigth + numpy.arange(self.__nSamples, dtype = numpy.float)*self.__deltaHeigth
495 ranges = numpy.reshape(self.rangeFromFile.value,(-1))
501 ranges = numpy.reshape(self.rangeFromFile.value,(-1))
496 self.dataOut.heightList = ranges/1000.0 #km
502 self.dataOut.heightList = ranges/1000.0 #km
497
503
498
504
499 self.dataOut.channelList = self.__channelList
505 self.dataOut.channelList = self.__channelList
500
506
501 self.dataOut.blocksize = self.dataOut.getNChannels() * self.dataOut.getNHeights()
507 self.dataOut.blocksize = self.dataOut.getNChannels() * self.dataOut.getNHeights()
502
508
503 # self.dataOut.channelIndexList = None
509 # self.dataOut.channelIndexList = None
504
510
505 self.dataOut.flagNoData = True
511 self.dataOut.flagNoData = True
506
512
507 #Set to TRUE if the data is discontinuous
513 #Set to TRUE if the data is discontinuous
508 self.dataOut.flagDiscontinuousBlock = False
514 self.dataOut.flagDiscontinuousBlock = False
509
515
510 self.dataOut.utctime = None
516 self.dataOut.utctime = None
511
517
512 #self.dataOut.timeZone = -5 #self.__timezone/60 #timezone like jroheader, difference in minutes between UTC and localtime
518 #self.dataOut.timeZone = -5 #self.__timezone/60 #timezone like jroheader, difference in minutes between UTC and localtime
513 if self.timezone == 'lt':
519 if self.timezone == 'lt':
514 self.dataOut.timeZone = time.timezone / 60. #get the timezone in minutes
520 self.dataOut.timeZone = time.timezone / 60. #get the timezone in minutes
515 else:
521 else:
516 self.dataOut.timeZone = 0 #by default time is UTC
522 self.dataOut.timeZone = 0 #by default time is UTC
517
523
518 self.dataOut.dstFlag = 0
524 self.dataOut.dstFlag = 0
519
525
520 self.dataOut.errorCount = 0
526 self.dataOut.errorCount = 0
521
527
522 self.dataOut.nCohInt = 1
528 self.dataOut.nCohInt = 1
523
529
524 self.dataOut.flagDecodeData = False #asumo que la data esta decodificada
530 self.dataOut.flagDecodeData = False #asumo que la data esta decodificada
525
531
526 self.dataOut.flagDeflipData = False #asumo que la data esta sin flip
532 self.dataOut.flagDeflipData = False #asumo que la data esta sin flip
527
533
528 self.dataOut.flagShiftFFT = False
534 self.dataOut.flagShiftFFT = False
529
535
530 self.dataOut.ippSeconds = self.ippSeconds
536 self.dataOut.ippSeconds = self.ippSeconds
531
537
532 #Time interval between profiles
538 #Time interval between profiles
533 #self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
539 #self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
534
540
535 self.dataOut.frequency = self.__frequency
541 self.dataOut.frequency = self.__frequency
536
537 self.dataOut.realtime = self.online
542 self.dataOut.realtime = self.online
538 pass
543 pass
539
544
540 def readNextFile(self,online=False):
545 def readNextFile(self,online=False):
541
546
542 if not(online):
547 if not(online):
543 newFile = self.__setNextFileOffline()
548 newFile = self.__setNextFileOffline()
544 else:
549 else:
545 newFile = self.__setNextFileOnline()
550 newFile = self.__setNextFileOnline()
546
551
547 if not(newFile):
552 if not(newFile):
548 return 0
553 return 0
549
550 #if self.__firstFile:
554 #if self.__firstFile:
551 self.readAMISRHeader(self.amisrFilePointer)
555 self.readAMISRHeader(self.amisrFilePointer)
556
552 self.createBuffers()
557 self.createBuffers()
558
553 self.fillJROHeader()
559 self.fillJROHeader()
560
554 #self.__firstFile = False
561 #self.__firstFile = False
555
562
556
563
557
564
558 self.dataset,self.timeset = self.readData()
565 self.dataset,self.timeset = self.readData()
559
566
560 if self.endDate!=None:
567 if self.endDate!=None:
561 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
568 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
562 time_str = self.amisrFilePointer.get('Time/RadacTimeString')
569 time_str = self.amisrFilePointer.get('Time/RadacTimeString')
563 startDateTimeStr_File = time_str[0][0].split('.')[0]
570 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
564 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
571 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
565 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
572 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
566 if self.timezone == 'lt':
573 if self.timezone == 'lt':
567 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
574 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
568 if (startDateTime_File>endDateTime_Reader):
575 if (startDateTime_File>endDateTime_Reader):
569 return 0
576 return 0
570
577
571 self.jrodataset = self.reshapeData()
578 self.jrodataset = self.reshapeData()
572 #----self.updateIndexes()
579 #----self.updateIndexes()
573 self.profileIndex = 0
580 self.profileIndex = 0
574
581
575 return 1
582 return 1
576
583
577
584
578 def __hasNotDataInBuffer(self):
585 def __hasNotDataInBuffer(self):
579 if self.profileIndex >= (self.newProfiles*self.nblocks):
586 if self.profileIndex >= (self.newProfiles*self.nblocks):
580 return 1
587 return 1
581 return 0
588 return 0
582
589
583
590
584 def getData(self):
591 def getData(self):
585
592
586 if self.flagNoMoreFiles:
593 if self.flagNoMoreFiles:
587 self.dataOut.flagNoData = True
594 self.dataOut.flagNoData = True
588 return 0
595 return 0
589
596
590 if self.__hasNotDataInBuffer():
597 if self.__hasNotDataInBuffer():
591 if not (self.readNextFile(self.online)):
598 if not (self.readNextFile(self.online)):
592 return 0
599 return 0
593
600
594
601
595 if self.dataset is None: # setear esta condicion cuando no hayan datos por leers
602 if self.dataset is None: # setear esta condicion cuando no hayan datos por leer
596 self.dataOut.flagNoData = True
603 self.dataOut.flagNoData = True
597 return 0
604 return 0
598
605
599 #self.dataOut.data = numpy.reshape(self.jrodataset[self.profileIndex,:],(1,-1))
606 #self.dataOut.data = numpy.reshape(self.jrodataset[self.profileIndex,:],(1,-1))
600
607
601 self.dataOut.data = self.jrodataset[:,self.profileIndex,:]
608 self.dataOut.data = self.jrodataset[:,self.profileIndex,:]
602
609
610 #print("R_t",self.timeset)
611
603 #self.dataOut.utctime = self.jrotimeset[self.profileIndex]
612 #self.dataOut.utctime = self.jrotimeset[self.profileIndex]
604 #verificar basic header de jro data y ver si es compatible con este valor
613 #verificar basic header de jro data y ver si es compatible con este valor
605 #self.dataOut.utctime = self.timeset + (self.profileIndex * self.ippSeconds * self.nchannels)
614 #self.dataOut.utctime = self.timeset + (self.profileIndex * self.ippSeconds * self.nchannels)
606 indexprof = numpy.mod(self.profileIndex, self.newProfiles)
615 indexprof = numpy.mod(self.profileIndex, self.newProfiles)
607 indexblock = self.profileIndex/self.newProfiles
616 indexblock = self.profileIndex/self.newProfiles
608 #print indexblock, indexprof
617 #print (indexblock, indexprof)
609 self.dataOut.utctime = self.timeset[indexblock] + (indexprof * self.ippSeconds * self.nchannels)
618 diffUTC = 1.8e4 #UTC diference from peru in seconds --Joab
619 diffUTC = 0
620 t_comp = (indexprof * self.ippSeconds * self.nchannels) + diffUTC #
621 #cambio posible 18/02/2020
622
623
624
625 #print("utc :",indexblock," __ ",t_comp)
626 #print(numpy.shape(self.timeset))
627 self.dataOut.utctime = self.timeset[numpy.int_(indexblock)] + t_comp
628 #self.dataOut.utctime = self.timeset[self.profileIndex] + t_comp
629 #print(self.dataOut.utctime)
610 self.dataOut.profileIndex = self.profileIndex
630 self.dataOut.profileIndex = self.profileIndex
611 self.dataOut.flagNoData = False
631 self.dataOut.flagNoData = False
612 # if indexprof == 0:
632 # if indexprof == 0:
613 # print self.dataOut.utctime
633 # print self.dataOut.utctime
614
634
615 self.profileIndex += 1
635 self.profileIndex += 1
616
636
617 return self.dataOut.data
637 return self.dataOut.data
618
638
619
639
620 def run(self, **kwargs):
640 def run(self, **kwargs):
621 '''
641 '''
622 This method will be called many times so here you should put all your code
642 This method will be called many times so here you should put all your code
623 '''
643 '''
624
644
625 if not self.isConfig:
645 if not self.isConfig:
626 self.setup(**kwargs)
646 self.setup(**kwargs)
627 self.isConfig = True
647 self.isConfig = True
628
648
629 self.getData()
649 self.getData()
@@ -1,1435 +1,1435
1 import numpy
1 import numpy
2 import time
2 import time
3 import os
3 import os
4 import h5py
4 import h5py
5 import re
5 import re
6 import datetime
6 import datetime
7
7
8 import schainpy.admin
8 import schainpy.admin
9 from schainpy.model.data.jrodata import *
9 from schainpy.model.data.jrodata import *
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 from schainpy.model.io.jroIO_base import *
11 from schainpy.model.io.jroIO_base import *
12 from schainpy.utils import log
12 from schainpy.utils import log
13
13
14 @MPDecorator
14 @MPDecorator
15 class ParamReader(JRODataReader,ProcessingUnit):
15 class ParamReader(JRODataReader,ProcessingUnit):
16 '''
16 '''
17 Reads HDF5 format files
17 Reads HDF5 format files
18 path
18 path
19 startDate
19 startDate
20 endDate
20 endDate
21 startTime
21 startTime
22 endTime
22 endTime
23 '''
23 '''
24
24
25 ext = ".hdf5"
25 ext = ".hdf5"
26 optchar = "D"
26 optchar = "D"
27 timezone = None
27 timezone = None
28 startTime = None
28 startTime = None
29 endTime = None
29 endTime = None
30 fileIndex = None
30 fileIndex = None
31 utcList = None #To select data in the utctime list
31 utcList = None #To select data in the utctime list
32 blockList = None #List to blocks to be read from the file
32 blockList = None #List to blocks to be read from the file
33 blocksPerFile = None #Number of blocks to be read
33 blocksPerFile = None #Number of blocks to be read
34 blockIndex = None
34 blockIndex = None
35 path = None
35 path = None
36 #List of Files
36 #List of Files
37 filenameList = None
37 filenameList = None
38 datetimeList = None
38 datetimeList = None
39 #Hdf5 File
39 #Hdf5 File
40 listMetaname = None
40 listMetaname = None
41 listMeta = None
41 listMeta = None
42 listDataname = None
42 listDataname = None
43 listData = None
43 listData = None
44 listShapes = None
44 listShapes = None
45 fp = None
45 fp = None
46 #dataOut reconstruction
46 #dataOut reconstruction
47 dataOut = None
47 dataOut = None
48
48
49 def __init__(self):#, **kwargs):
49 def __init__(self):#, **kwargs):
50 ProcessingUnit.__init__(self) #, **kwargs)
50 ProcessingUnit.__init__(self) #, **kwargs)
51 self.dataOut = Parameters()
51 self.dataOut = Parameters()
52 return
52 return
53
53
54 def setup(self, **kwargs):
54 def setup(self, **kwargs):
55
55
56 path = kwargs['path']
56 path = kwargs['path']
57 startDate = kwargs['startDate']
57 startDate = kwargs['startDate']
58 endDate = kwargs['endDate']
58 endDate = kwargs['endDate']
59 startTime = kwargs['startTime']
59 startTime = kwargs['startTime']
60 endTime = kwargs['endTime']
60 endTime = kwargs['endTime']
61 walk = kwargs['walk']
61 walk = kwargs['walk']
62 if 'ext' in kwargs:
62 if 'ext' in kwargs:
63 ext = kwargs['ext']
63 ext = kwargs['ext']
64 else:
64 else:
65 ext = '.hdf5'
65 ext = '.hdf5'
66 if 'timezone' in kwargs:
66 if 'timezone' in kwargs:
67 self.timezone = kwargs['timezone']
67 self.timezone = kwargs['timezone']
68 else:
68 else:
69 self.timezone = 'lt'
69 self.timezone = 'lt'
70
70
71 print("[Reading] Searching files in offline mode ...")
71 print("[Reading] Searching files in offline mode ...")
72 pathList, filenameList = self.searchFilesOffLine(path, startDate=startDate, endDate=endDate,
72 pathList, filenameList = self.searchFilesOffLine(path, startDate=startDate, endDate=endDate,
73 startTime=startTime, endTime=endTime,
73 startTime=startTime, endTime=endTime,
74 ext=ext, walk=walk)
74 ext=ext, walk=walk)
75
75
76 if not(filenameList):
76 if not(filenameList):
77 print("There is no files into the folder: %s"%(path))
77 print("There is no files into the folder: %s"%(path))
78 sys.exit(-1)
78 sys.exit(-1)
79
79
80 self.fileIndex = -1
80 self.fileIndex = -1
81 self.startTime = startTime
81 self.startTime = startTime
82 self.endTime = endTime
82 self.endTime = endTime
83
83
84 self.__readMetadata()
84 self.__readMetadata()
85
85
86 self.__setNextFileOffline()
86 self.__setNextFileOffline()
87
87
88 return
88 return
89
89
90 def searchFilesOffLine(self,
90 def searchFilesOffLine(self,
91 path,
91 path,
92 startDate=None,
92 startDate=None,
93 endDate=None,
93 endDate=None,
94 startTime=datetime.time(0,0,0),
94 startTime=datetime.time(0,0,0),
95 endTime=datetime.time(23,59,59),
95 endTime=datetime.time(23,59,59),
96 ext='.hdf5',
96 ext='.hdf5',
97 walk=True):
97 walk=True):
98
98
99 expLabel = ''
99 expLabel = ''
100 self.filenameList = []
100 self.filenameList = []
101 self.datetimeList = []
101 self.datetimeList = []
102
102
103 pathList = []
103 pathList = []
104
104
105 JRODataObj = JRODataReader()
105 JRODataObj = JRODataReader()
106 dateList, pathList = JRODataObj.findDatafiles(path, startDate, endDate, expLabel, ext, walk, include_path=True)
106 dateList, pathList = JRODataObj.findDatafiles(path, startDate, endDate, expLabel, ext, walk, include_path=True)
107
107
108 if dateList == []:
108 if dateList == []:
109 print("[Reading] No *%s files in %s from %s to %s)"%(ext, path,
109 print("[Reading] No *%s files in %s from %s to %s)"%(ext, path,
110 datetime.datetime.combine(startDate,startTime).ctime(),
110 datetime.datetime.combine(startDate,startTime).ctime(),
111 datetime.datetime.combine(endDate,endTime).ctime()))
111 datetime.datetime.combine(endDate,endTime).ctime()))
112
112
113 return None, None
113 return None, None
114
114
115 if len(dateList) > 1:
115 if len(dateList) > 1:
116 print("[Reading] %d days were found in date range: %s - %s" %(len(dateList), startDate, endDate))
116 print("[Reading] %d days were found in date range: %s - %s" %(len(dateList), startDate, endDate))
117 else:
117 else:
118 print("[Reading] data was found for the date %s" %(dateList[0]))
118 print("[Reading] data was found for the date %s" %(dateList[0]))
119
119
120 filenameList = []
120 filenameList = []
121 datetimeList = []
121 datetimeList = []
122
122
123 #----------------------------------------------------------------------------------
123 #----------------------------------------------------------------------------------
124
124
125 for thisPath in pathList:
125 for thisPath in pathList:
126
126
127 fileList = glob.glob1(thisPath, "*%s" %ext)
127 fileList = glob.glob1(thisPath, "*%s" %ext)
128 fileList.sort()
128 fileList.sort()
129
129
130 for file in fileList:
130 for file in fileList:
131
131
132 filename = os.path.join(thisPath,file)
132 filename = os.path.join(thisPath,file)
133
133
134 if not isFileInDateRange(filename, startDate, endDate):
134 if not isFileInDateRange(filename, startDate, endDate):
135 continue
135 continue
136
136
137 thisDatetime = self.__isFileInTimeRange(filename, startDate, endDate, startTime, endTime)
137 thisDatetime = self.__isFileInTimeRange(filename, startDate, endDate, startTime, endTime)
138
138
139 if not(thisDatetime):
139 if not(thisDatetime):
140 continue
140 continue
141
141
142 filenameList.append(filename)
142 filenameList.append(filename)
143 datetimeList.append(thisDatetime)
143 datetimeList.append(thisDatetime)
144
144
145 if not(filenameList):
145 if not(filenameList):
146 print("[Reading] Any file was found int time range %s - %s" %(datetime.datetime.combine(startDate,startTime).ctime(), datetime.datetime.combine(endDate,endTime).ctime()))
146 print("[Reading] Any file was found int time range %s - %s" %(datetime.datetime.combine(startDate,startTime).ctime(), datetime.datetime.combine(endDate,endTime).ctime()))
147 return None, None
147 return None, None
148
148
149 print("[Reading] %d file(s) was(were) found in time range: %s - %s" %(len(filenameList), startTime, endTime))
149 print("[Reading] %d file(s) was(were) found in time range: %s - %s" %(len(filenameList), startTime, endTime))
150 print()
150 print()
151
151
152 self.filenameList = filenameList
152 self.filenameList = filenameList
153 self.datetimeList = datetimeList
153 self.datetimeList = datetimeList
154
154
155 return pathList, filenameList
155 return pathList, filenameList
156
156
157 def __isFileInTimeRange(self,filename, startDate, endDate, startTime, endTime):
157 def __isFileInTimeRange(self,filename, startDate, endDate, startTime, endTime):
158
158
159 """
159 """
160 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
160 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
161
161
162 Inputs:
162 Inputs:
163 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
163 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
164 startDate : fecha inicial del rango seleccionado en formato datetime.date
164 startDate : fecha inicial del rango seleccionado en formato datetime.date
165 endDate : fecha final del rango seleccionado en formato datetime.date
165 endDate : fecha final del rango seleccionado en formato datetime.date
166 startTime : tiempo inicial del rango seleccionado en formato datetime.time
166 startTime : tiempo inicial del rango seleccionado en formato datetime.time
167 endTime : tiempo final del rango seleccionado en formato datetime.time
167 endTime : tiempo final del rango seleccionado en formato datetime.time
168
168
169 Return:
169 Return:
170 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
170 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
171 fecha especificado, de lo contrario retorna False.
171 fecha especificado, de lo contrario retorna False.
172
172
173 Excepciones:
173 Excepciones:
174 Si el archivo no existe o no puede ser abierto
174 Si el archivo no existe o no puede ser abierto
175 Si la cabecera no puede ser leida.
175 Si la cabecera no puede ser leida.
176
176
177 """
177 """
178
178
179 try:
179 try:
180 fp = h5py.File(filename,'r')
180 fp = h5py.File(filename,'r')
181 grp1 = fp['Data']
181 grp1 = fp['Data']
182
182
183 except IOError:
183 except IOError:
184 traceback.print_exc()
184 traceback.print_exc()
185 raise IOError("The file %s can't be opened" %(filename))
185 raise IOError("The file %s can't be opened" %(filename))
186
186
187 #In case has utctime attribute
187 #In case has utctime attribute
188 grp2 = grp1['utctime']
188 grp2 = grp1['utctime']
189 # thisUtcTime = grp2.value[0] - 5*3600 #To convert to local time
189 # thisUtcTime = grp2.value[0] - 5*3600 #To convert to local time
190 thisUtcTime = grp2.value[0]
190 thisUtcTime = grp2.value[0]
191
191
192 fp.close()
192 fp.close()
193
193
194 if self.timezone == 'lt':
194 if self.timezone == 'lt':
195 thisUtcTime -= 5*3600
195 thisUtcTime -= 5*3600
196
196
197 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
197 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
198 thisDate = thisDatetime.date()
198 thisDate = thisDatetime.date()
199 thisTime = thisDatetime.time()
199 thisTime = thisDatetime.time()
200
200
201 startUtcTime = (datetime.datetime.combine(thisDate,startTime)- datetime.datetime(1970, 1, 1)).total_seconds()
201 startUtcTime = (datetime.datetime.combine(thisDate,startTime)- datetime.datetime(1970, 1, 1)).total_seconds()
202 endUtcTime = (datetime.datetime.combine(thisDate,endTime)- datetime.datetime(1970, 1, 1)).total_seconds()
202 endUtcTime = (datetime.datetime.combine(thisDate,endTime)- datetime.datetime(1970, 1, 1)).total_seconds()
203
203
204 #General case
204 #General case
205 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
205 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
206 #-----------o----------------------------o-----------
206 #-----------o----------------------------o-----------
207 # startTime endTime
207 # startTime endTime
208
208
209 if endTime >= startTime:
209 if endTime >= startTime:
210 thisUtcLog = numpy.logical_and(thisUtcTime > startUtcTime, thisUtcTime < endUtcTime)
210 thisUtcLog = numpy.logical_and(thisUtcTime > startUtcTime, thisUtcTime < endUtcTime)
211 if numpy.any(thisUtcLog): #If there is one block between the hours mentioned
211 if numpy.any(thisUtcLog): #If there is one block between the hours mentioned
212 return thisDatetime
212 return thisDatetime
213 return None
213 return None
214
214
215 #If endTime < startTime then endTime belongs to the next day
215 #If endTime < startTime then endTime belongs to the next day
216 #<<<<<<<<<<<o o>>>>>>>>>>>
216 #<<<<<<<<<<<o o>>>>>>>>>>>
217 #-----------o----------------------------o-----------
217 #-----------o----------------------------o-----------
218 # endTime startTime
218 # endTime startTime
219
219
220 if (thisDate == startDate) and numpy.all(thisUtcTime < startUtcTime):
220 if (thisDate == startDate) and numpy.all(thisUtcTime < startUtcTime):
221 return None
221 return None
222
222
223 if (thisDate == endDate) and numpy.all(thisUtcTime > endUtcTime):
223 if (thisDate == endDate) and numpy.all(thisUtcTime > endUtcTime):
224 return None
224 return None
225
225
226 if numpy.all(thisUtcTime < startUtcTime) and numpy.all(thisUtcTime > endUtcTime):
226 if numpy.all(thisUtcTime < startUtcTime) and numpy.all(thisUtcTime > endUtcTime):
227 return None
227 return None
228
228
229 return thisDatetime
229 return thisDatetime
230
230
231 def __setNextFileOffline(self):
231 def __setNextFileOffline(self):
232
232
233 self.fileIndex += 1
233 self.fileIndex += 1
234 idFile = self.fileIndex
234 idFile = self.fileIndex
235
235
236 if not(idFile < len(self.filenameList)):
236 if not(idFile < len(self.filenameList)):
237 raise schainpy.admin.SchainError("No more Files")
237 raise schainpy.admin.SchainError("No more Files")
238 return 0
238 return 0
239
239
240 filename = self.filenameList[idFile]
240 filename = self.filenameList[idFile]
241 filePointer = h5py.File(filename,'r')
241 filePointer = h5py.File(filename,'r')
242 self.filename = filename
242 self.filename = filename
243 self.fp = filePointer
243 self.fp = filePointer
244
244
245 print("Setting the file: %s"%self.filename)
245 print("Setting the file: %s"%self.filename)
246
246
247 self.__setBlockList()
247 self.__setBlockList()
248 self.__readData()
248 self.__readData()
249 self.blockIndex = 0
249 self.blockIndex = 0
250 return 1
250 return 1
251
251
252 def __setBlockList(self):
252 def __setBlockList(self):
253 '''
253 '''
254 Selects the data within the times defined
254 Selects the data within the times defined
255
255
256 self.fp
256 self.fp
257 self.startTime
257 self.startTime
258 self.endTime
258 self.endTime
259
259
260 self.blockList
260 self.blockList
261 self.blocksPerFile
261 self.blocksPerFile
262
262
263 '''
263 '''
264 fp = self.fp
264 fp = self.fp
265 startTime = self.startTime
265 startTime = self.startTime
266 endTime = self.endTime
266 endTime = self.endTime
267
267
268 grp = fp['Data']
268 grp = fp['Data']
269 thisUtcTime = grp['utctime'].value.astype(numpy.float)[0]
269 thisUtcTime = grp['utctime'].value.astype(numpy.float)[0]
270
270
271 #ERROOOOR
271 #ERROOOOR
272 if self.timezone == 'lt':
272 if self.timezone == 'lt':
273 thisUtcTime -= 5*3600
273 thisUtcTime -= 5*3600
274
274
275 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
275 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
276
276
277 thisDate = thisDatetime.date()
277 thisDate = thisDatetime.date()
278 thisTime = thisDatetime.time()
278 thisTime = thisDatetime.time()
279
279
280 startUtcTime = (datetime.datetime.combine(thisDate,startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
280 startUtcTime = (datetime.datetime.combine(thisDate,startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
281 endUtcTime = (datetime.datetime.combine(thisDate,endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
281 endUtcTime = (datetime.datetime.combine(thisDate,endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
282
282
283 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
283 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
284
284
285 self.blockList = ind
285 self.blockList = ind
286 self.blocksPerFile = len(ind)
286 self.blocksPerFile = len(ind)
287
287
288 return
288 return
289
289
290 def __readMetadata(self):
290 def __readMetadata(self):
291 '''
291 '''
292 Reads Metadata
292 Reads Metadata
293
293
294 self.pathMeta
294 self.pathMeta
295 self.listShapes
295 self.listShapes
296 self.listMetaname
296 self.listMetaname
297 self.listMeta
297 self.listMeta
298
298
299 '''
299 '''
300
300
301 filename = self.filenameList[0]
301 filename = self.filenameList[0]
302 fp = h5py.File(filename,'r')
302 fp = h5py.File(filename,'r')
303 gp = fp['Metadata']
303 gp = fp['Metadata']
304
304
305 listMetaname = []
305 listMetaname = []
306 listMetadata = []
306 listMetadata = []
307 for item in list(gp.items()):
307 for item in list(gp.items()):
308 name = item[0]
308 name = item[0]
309
309
310 if name=='array dimensions':
310 if name=='array dimensions':
311 table = gp[name][:]
311 table = gp[name][:]
312 listShapes = {}
312 listShapes = {}
313 for shapes in table:
313 for shapes in table:
314 listShapes[shapes[0]] = numpy.array([shapes[1],shapes[2],shapes[3],shapes[4],shapes[5]])
314 listShapes[shapes[0]] = numpy.array([shapes[1],shapes[2],shapes[3],shapes[4],shapes[5]])
315 else:
315 else:
316 data = gp[name].value
316 data = gp[name].value
317 listMetaname.append(name)
317 listMetaname.append(name)
318 listMetadata.append(data)
318 listMetadata.append(data)
319
319
320 self.listShapes = listShapes
320 self.listShapes = listShapes
321 self.listMetaname = listMetaname
321 self.listMetaname = listMetaname
322 self.listMeta = listMetadata
322 self.listMeta = listMetadata
323
323
324 fp.close()
324 fp.close()
325 return
325 return
326
326
327 def __readData(self):
327 def __readData(self):
328 grp = self.fp['Data']
328 grp = self.fp['Data']
329 listdataname = []
329 listdataname = []
330 listdata = []
330 listdata = []
331
331
332 for item in list(grp.items()):
332 for item in list(grp.items()):
333 name = item[0]
333 name = item[0]
334 listdataname.append(name)
334 listdataname.append(name)
335
335
336 array = self.__setDataArray(grp[name],self.listShapes[name])
336 array = self.__setDataArray(grp[name],self.listShapes[name])
337 listdata.append(array)
337 listdata.append(array)
338
338
339 self.listDataname = listdataname
339 self.listDataname = listdataname
340 self.listData = listdata
340 self.listData = listdata
341 return
341 return
342
342
343 def __setDataArray(self, dataset, shapes):
343 def __setDataArray(self, dataset, shapes):
344
344
345 nDims = shapes[0]
345 nDims = shapes[0]
346 nDim2 = shapes[1] #Dimension 0
346 nDim2 = shapes[1] #Dimension 0
347 nDim1 = shapes[2] #Dimension 1, number of Points or Parameters
347 nDim1 = shapes[2] #Dimension 1, number of Points or Parameters
348 nDim0 = shapes[3] #Dimension 2, number of samples or ranges
348 nDim0 = shapes[3] #Dimension 2, number of samples or ranges
349 mode = shapes[4] #Mode of storing
349 mode = shapes[4] #Mode of storing
350 blockList = self.blockList
350 blockList = self.blockList
351 blocksPerFile = self.blocksPerFile
351 blocksPerFile = self.blocksPerFile
352
352
353 #Depending on what mode the data was stored
353 #Depending on what mode the data was stored
354 if mode == 0: #Divided in channels
354 if mode == 0: #Divided in channels
355 arrayData = dataset.value.astype(numpy.float)[0][blockList]
355 arrayData = dataset.value.astype(numpy.float)[0][blockList]
356 if mode == 1: #Divided in parameter
356 if mode == 1: #Divided in parameter
357 strds = 'table'
357 strds = 'table'
358 nDatas = nDim1
358 nDatas = nDim1
359 newShapes = (blocksPerFile,nDim2,nDim0)
359 newShapes = (blocksPerFile,nDim2,nDim0)
360 elif mode==2: #Concatenated in a table
360 elif mode==2: #Concatenated in a table
361 strds = 'table0'
361 strds = 'table0'
362 arrayData = dataset[strds].value
362 arrayData = dataset[strds].value
363 #Selecting part of the dataset
363 #Selecting part of the dataset
364 utctime = arrayData[:,0]
364 utctime = arrayData[:,0]
365 u, indices = numpy.unique(utctime, return_index=True)
365 u, indices = numpy.unique(utctime, return_index=True)
366
366
367 if blockList.size != indices.size:
367 if blockList.size != indices.size:
368 indMin = indices[blockList[0]]
368 indMin = indices[blockList[0]]
369 if blockList[1] + 1 >= indices.size:
369 if blockList[1] + 1 >= indices.size:
370 arrayData = arrayData[indMin:,:]
370 arrayData = arrayData[indMin:,:]
371 else:
371 else:
372 indMax = indices[blockList[1] + 1]
372 indMax = indices[blockList[1] + 1]
373 arrayData = arrayData[indMin:indMax,:]
373 arrayData = arrayData[indMin:indMax,:]
374 return arrayData
374 return arrayData
375
375
376 # One dimension
376 # One dimension
377 if nDims == 0:
377 if nDims == 0:
378 arrayData = dataset.value.astype(numpy.float)[0][blockList]
378 arrayData = dataset.value.astype(numpy.float)[0][blockList]
379
379
380 # Two dimensions
380 # Two dimensions
381 elif nDims == 2:
381 elif nDims == 2:
382 arrayData = numpy.zeros((blocksPerFile,nDim1,nDim0))
382 arrayData = numpy.zeros((blocksPerFile,nDim1,nDim0))
383 newShapes = (blocksPerFile,nDim0)
383 newShapes = (blocksPerFile,nDim0)
384 nDatas = nDim1
384 nDatas = nDim1
385
385
386 for i in range(nDatas):
386 for i in range(nDatas):
387 data = dataset[strds + str(i)].value
387 data = dataset[strds + str(i)].value
388 arrayData[:,i,:] = data[blockList,:]
388 arrayData[:,i,:] = data[blockList,:]
389
389
390 # Three dimensions
390 # Three dimensions
391 else:
391 else:
392 arrayData = numpy.zeros((blocksPerFile,nDim2,nDim1,nDim0))
392 arrayData = numpy.zeros((blocksPerFile,nDim2,nDim1,nDim0))
393 for i in range(nDatas):
393 for i in range(nDatas):
394
394
395 data = dataset[strds + str(i)].value
395 data = dataset[strds + str(i)].value
396
396
397 for b in range(blockList.size):
397 for b in range(blockList.size):
398 arrayData[b,:,i,:] = data[:,:,blockList[b]]
398 arrayData[b,:,i,:] = data[:,:,blockList[b]]
399
399
400 return arrayData
400 return arrayData
401
401
402 def __setDataOut(self):
402 def __setDataOut(self):
403 listMeta = self.listMeta
403 listMeta = self.listMeta
404 listMetaname = self.listMetaname
404 listMetaname = self.listMetaname
405 listDataname = self.listDataname
405 listDataname = self.listDataname
406 listData = self.listData
406 listData = self.listData
407 listShapes = self.listShapes
407 listShapes = self.listShapes
408
408
409 blockIndex = self.blockIndex
409 blockIndex = self.blockIndex
410 # blockList = self.blockList
410 # blockList = self.blockList
411
411
412 for i in range(len(listMeta)):
412 for i in range(len(listMeta)):
413 setattr(self.dataOut,listMetaname[i],listMeta[i])
413 setattr(self.dataOut,listMetaname[i],listMeta[i])
414
414
415 for j in range(len(listData)):
415 for j in range(len(listData)):
416 nShapes = listShapes[listDataname[j]][0]
416 nShapes = listShapes[listDataname[j]][0]
417 mode = listShapes[listDataname[j]][4]
417 mode = listShapes[listDataname[j]][4]
418 if nShapes == 1:
418 if nShapes == 1:
419 setattr(self.dataOut,listDataname[j],listData[j][blockIndex])
419 setattr(self.dataOut,listDataname[j],listData[j][blockIndex])
420 elif nShapes > 1:
420 elif nShapes > 1:
421 setattr(self.dataOut,listDataname[j],listData[j][blockIndex,:])
421 setattr(self.dataOut,listDataname[j],listData[j][blockIndex,:])
422 elif mode==0:
422 elif mode==0:
423 setattr(self.dataOut,listDataname[j],listData[j][blockIndex])
423 setattr(self.dataOut,listDataname[j],listData[j][blockIndex])
424 #Mode Meteors
424 #Mode Meteors
425 elif mode ==2:
425 elif mode ==2:
426 selectedData = self.__selectDataMode2(listData[j], blockIndex)
426 selectedData = self.__selectDataMode2(listData[j], blockIndex)
427 setattr(self.dataOut, listDataname[j], selectedData)
427 setattr(self.dataOut, listDataname[j], selectedData)
428 return
428 return
429
429
430 def __selectDataMode2(self, data, blockIndex):
430 def __selectDataMode2(self, data, blockIndex):
431 utctime = data[:,0]
431 utctime = data[:,0]
432 aux, indices = numpy.unique(utctime, return_inverse=True)
432 aux, indices = numpy.unique(utctime, return_inverse=True)
433 selInd = numpy.where(indices == blockIndex)[0]
433 selInd = numpy.where(indices == blockIndex)[0]
434 selData = data[selInd,:]
434 selData = data[selInd,:]
435
435
436 return selData
436 return selData
437
437
438 def getData(self):
438 def getData(self):
439
439
440 if self.blockIndex==self.blocksPerFile:
440 if self.blockIndex==self.blocksPerFile:
441 if not( self.__setNextFileOffline() ):
441 if not( self.__setNextFileOffline() ):
442 self.dataOut.flagNoData = True
442 self.dataOut.flagNoData = True
443 return 0
443 return 0
444
444
445 self.__setDataOut()
445 self.__setDataOut()
446 self.dataOut.flagNoData = False
446 self.dataOut.flagNoData = False
447
447
448 self.blockIndex += 1
448 self.blockIndex += 1
449
449
450 return
450 return
451
451
452 def run(self, **kwargs):
452 def run(self, **kwargs):
453
453
454 if not(self.isConfig):
454 if not(self.isConfig):
455 self.setup(**kwargs)
455 self.setup(**kwargs)
456 self.isConfig = True
456 self.isConfig = True
457
457
458 self.getData()
458 self.getData()
459
459
460 return
460 return
461
461
462 @MPDecorator
462 @MPDecorator
463 class ParamWriter(Operation):
463 class ParamWriter(Operation):
464 '''
464 '''
465 HDF5 Writer, stores parameters data in HDF5 format files
465 HDF5 Writer, stores parameters data in HDF5 format files
466
466
467 path: path where the files will be stored
467 path: path where the files will be stored
468 blocksPerFile: number of blocks that will be saved in per HDF5 format file
468 blocksPerFile: number of blocks that will be saved in per HDF5 format file
469 mode: selects the data stacking mode: '0' channels, '1' parameters, '3' table (for meteors)
469 mode: selects the data stacking mode: '0' channels, '1' parameters, '3' table (for meteors)
470 metadataList: list of attributes that will be stored as metadata
470 metadataList: list of attributes that will be stored as metadata
471 dataList: list of attributes that will be stores as data
471 dataList: list of attributes that will be stores as data
472 '''
472 '''
473
473
474 ext = ".hdf5"
474 ext = ".hdf5"
475 optchar = "D"
475 optchar = "D"
476 metaoptchar = "M"
476 metaoptchar = "M"
477 metaFile = None
477 metaFile = None
478 filename = None
478 filename = None
479 path = None
479 path = None
480 setFile = None
480 setFile = None
481 fp = None
481 fp = None
482 grp = None
482 grp = None
483 ds = None
483 ds = None
484 firsttime = True
484 firsttime = True
485 #Configurations
485 #Configurations
486 blocksPerFile = None
486 blocksPerFile = None
487 blockIndex = None
487 blockIndex = None
488 dataOut = None
488 dataOut = None
489 #Data Arrays
489 #Data Arrays
490 dataList = None
490 dataList = None
491 metadataList = None
491 metadataList = None
492 dsList = None #List of dictionaries with dataset properties
492 dsList = None #List of dictionaries with dataset properties
493 tableDim = None
493 tableDim = None
494 dtype = [('arrayName', 'S20'),('nDimensions', 'i'), ('dim2', 'i'), ('dim1', 'i'),('dim0', 'i'),('mode', 'b')]
494 dtype = [('arrayName', 'S20'),('nDimensions', 'i'), ('dim2', 'i'), ('dim1', 'i'),('dim0', 'i'),('mode', 'b')]
495 currentDay = None
495 currentDay = None
496 lastTime = None
496 lastTime = None
497 setType = None
497 setType = None
498
498
499 def __init__(self):
499 def __init__(self):
500
500
501 Operation.__init__(self)
501 Operation.__init__(self)
502 return
502 return
503
503
504 def setup(self, dataOut, path=None, blocksPerFile=10, metadataList=None, dataList=None, mode=None, setType=None):
504 def setup(self, dataOut, path=None, blocksPerFile=10, metadataList=None, dataList=None, mode=None, setType=None):
505 self.path = path
505 self.path = path
506 self.blocksPerFile = blocksPerFile
506 self.blocksPerFile = blocksPerFile
507 self.metadataList = metadataList
507 self.metadataList = metadataList
508 self.dataList = dataList
508 self.dataList = dataList
509 self.dataOut = dataOut
509 self.dataOut = dataOut
510 self.mode = mode
510 self.mode = mode
511 if self.mode is not None:
511 if self.mode is not None:
512 self.mode = numpy.zeros(len(self.dataList)) + mode
512 self.mode = numpy.zeros(len(self.dataList)) + mode
513 else:
513 else:
514 self.mode = numpy.ones(len(self.dataList))
514 self.mode = numpy.ones(len(self.dataList))
515
515
516 self.setType = setType
516 self.setType = setType
517
517
518 arrayDim = numpy.zeros((len(self.dataList),5))
518 arrayDim = numpy.zeros((len(self.dataList),5))
519
519
520 #Table dimensions
520 #Table dimensions
521 dtype0 = self.dtype
521 dtype0 = self.dtype
522 tableList = []
522 tableList = []
523
523
524 #Dictionary and list of tables
524 #Dictionary and list of tables
525 dsList = []
525 dsList = []
526
526
527 for i in range(len(self.dataList)):
527 for i in range(len(self.dataList)):
528 dsDict = {}
528 dsDict = {}
529 dataAux = getattr(self.dataOut, self.dataList[i])
529 dataAux = getattr(self.dataOut, self.dataList[i])
530 dsDict['variable'] = self.dataList[i]
530 dsDict['variable'] = self.dataList[i]
531 #--------------------- Conditionals ------------------------
531 #--------------------- Conditionals ------------------------
532 #There is no data
532 #There is no data
533
533
534 if dataAux is None:
534 if dataAux is None:
535
535
536 return 0
536 return 0
537
537
538 if isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
538 if isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
539 dsDict['mode'] = 0
539 dsDict['mode'] = 0
540 dsDict['nDim'] = 0
540 dsDict['nDim'] = 0
541 arrayDim[i,0] = 0
541 arrayDim[i,0] = 0
542 dsList.append(dsDict)
542 dsList.append(dsDict)
543
543
544 #Mode 2: meteors
544 #Mode 2: meteors
545 elif self.mode[i] == 2:
545 elif self.mode[i] == 2:
546 dsDict['dsName'] = 'table0'
546 dsDict['dsName'] = 'table0'
547 dsDict['mode'] = 2 # Mode meteors
547 dsDict['mode'] = 2 # Mode meteors
548 dsDict['shape'] = dataAux.shape[-1]
548 dsDict['shape'] = dataAux.shape[-1]
549 dsDict['nDim'] = 0
549 dsDict['nDim'] = 0
550 dsDict['dsNumber'] = 1
550 dsDict['dsNumber'] = 1
551 arrayDim[i,3] = dataAux.shape[-1]
551 arrayDim[i,3] = dataAux.shape[-1]
552 arrayDim[i,4] = self.mode[i] #Mode the data was stored
552 arrayDim[i,4] = self.mode[i] #Mode the data was stored
553 dsList.append(dsDict)
553 dsList.append(dsDict)
554
554
555 #Mode 1
555 #Mode 1
556 else:
556 else:
557 arrayDim0 = dataAux.shape #Data dimensions
557 arrayDim0 = dataAux.shape #Data dimensions
558 arrayDim[i,0] = len(arrayDim0) #Number of array dimensions
558 arrayDim[i,0] = len(arrayDim0) #Number of array dimensions
559 arrayDim[i,4] = self.mode[i] #Mode the data was stored
559 arrayDim[i,4] = self.mode[i] #Mode the data was stored
560 strtable = 'table'
560 strtable = 'table'
561 dsDict['mode'] = 1 # Mode parameters
561 dsDict['mode'] = 1 # Mode parameters
562
562
563 # Three-dimension arrays
563 # Three-dimension arrays
564 if len(arrayDim0) == 3:
564 if len(arrayDim0) == 3:
565 arrayDim[i,1:-1] = numpy.array(arrayDim0)
565 arrayDim[i,1:-1] = numpy.array(arrayDim0)
566 nTables = int(arrayDim[i,2])
566 nTables = int(arrayDim[i,2])
567 dsDict['dsNumber'] = nTables
567 dsDict['dsNumber'] = nTables
568 dsDict['shape'] = arrayDim[i,2:4]
568 dsDict['shape'] = arrayDim[i,2:4]
569 dsDict['nDim'] = 3
569 dsDict['nDim'] = 3
570
570
571 for j in range(nTables):
571 for j in range(nTables):
572 dsDict = dsDict.copy()
572 dsDict = dsDict.copy()
573 dsDict['dsName'] = strtable + str(j)
573 dsDict['dsName'] = strtable + str(j)
574 dsList.append(dsDict)
574 dsList.append(dsDict)
575
575
576 # Two-dimension arrays
576 # Two-dimension arrays
577 elif len(arrayDim0) == 2:
577 elif len(arrayDim0) == 2:
578 arrayDim[i,2:-1] = numpy.array(arrayDim0)
578 arrayDim[i,2:-1] = numpy.array(arrayDim0)
579 nTables = int(arrayDim[i,2])
579 nTables = int(arrayDim[i,2])
580 dsDict['dsNumber'] = nTables
580 dsDict['dsNumber'] = nTables
581 dsDict['shape'] = arrayDim[i,3]
581 dsDict['shape'] = arrayDim[i,3]
582 dsDict['nDim'] = 2
582 dsDict['nDim'] = 2
583
583
584 for j in range(nTables):
584 for j in range(nTables):
585 dsDict = dsDict.copy()
585 dsDict = dsDict.copy()
586 dsDict['dsName'] = strtable + str(j)
586 dsDict['dsName'] = strtable + str(j)
587 dsList.append(dsDict)
587 dsList.append(dsDict)
588
588
589 # One-dimension arrays
589 # One-dimension arrays
590 elif len(arrayDim0) == 1:
590 elif len(arrayDim0) == 1:
591 arrayDim[i,3] = arrayDim0[0]
591 arrayDim[i,3] = arrayDim0[0]
592 dsDict['shape'] = arrayDim0[0]
592 dsDict['shape'] = arrayDim0[0]
593 dsDict['dsNumber'] = 1
593 dsDict['dsNumber'] = 1
594 dsDict['dsName'] = strtable + str(0)
594 dsDict['dsName'] = strtable + str(0)
595 dsDict['nDim'] = 1
595 dsDict['nDim'] = 1
596 dsList.append(dsDict)
596 dsList.append(dsDict)
597
597
598 table = numpy.array((self.dataList[i],) + tuple(arrayDim[i,:]),dtype = dtype0)
598 table = numpy.array((self.dataList[i],) + tuple(arrayDim[i,:]),dtype = dtype0)
599 tableList.append(table)
599 tableList.append(table)
600
600
601 self.dsList = dsList
601 self.dsList = dsList
602 self.tableDim = numpy.array(tableList, dtype = dtype0)
602 self.tableDim = numpy.array(tableList, dtype = dtype0)
603 self.blockIndex = 0
603 self.blockIndex = 0
604 timeTuple = time.localtime(dataOut.utctime)
604 timeTuple = time.localtime(dataOut.utctime)
605 self.currentDay = timeTuple.tm_yday
605 self.currentDay = timeTuple.tm_yday
606
606
607 def putMetadata(self):
607 def putMetadata(self):
608
608
609 fp = self.createMetadataFile()
609 fp = self.createMetadataFile()
610 self.writeMetadata(fp)
610 self.writeMetadata(fp)
611 fp.close()
611 fp.close()
612 return
612 return
613
613
614 def createMetadataFile(self):
614 def createMetadataFile(self):
615 ext = self.ext
615 ext = self.ext
616 path = self.path
616 path = self.path
617 setFile = self.setFile
617 setFile = self.setFile
618
618
619 timeTuple = time.localtime(self.dataOut.utctime)
619 timeTuple = time.localtime(self.dataOut.utctime)
620
620
621 subfolder = ''
621 subfolder = ''
622 fullpath = os.path.join( path, subfolder )
622 fullpath = os.path.join( path, subfolder )
623
623
624 if not( os.path.exists(fullpath) ):
624 if not( os.path.exists(fullpath) ):
625 os.mkdir(fullpath)
625 os.mkdir(fullpath)
626 setFile = -1 #inicializo mi contador de seteo
626 setFile = -1 #inicializo mi contador de seteo
627
627
628 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
628 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
629 fullpath = os.path.join( path, subfolder )
629 fullpath = os.path.join( path, subfolder )
630
630
631 if not( os.path.exists(fullpath) ):
631 if not( os.path.exists(fullpath) ):
632 os.mkdir(fullpath)
632 os.mkdir(fullpath)
633 setFile = -1 #inicializo mi contador de seteo
633 setFile = -1 #inicializo mi contador de seteo
634
634
635 else:
635 else:
636 filesList = os.listdir( fullpath )
636 filesList = os.listdir( fullpath )
637 filesList = sorted( filesList, key=str.lower )
637 filesList = sorted( filesList, key=str.lower )
638 if len( filesList ) > 0:
638 if len( filesList ) > 0:
639 filesList = [k for k in filesList if k.startswith(self.metaoptchar)]
639 filesList = [k for k in filesList if k.startswith(self.metaoptchar)]
640 filen = filesList[-1]
640 filen = filesList[-1]
641 # el filename debera tener el siguiente formato
641 # el filename debera tener el siguiente formato
642 # 0 1234 567 89A BCDE (hex)
642 # 0 1234 567 89A BCDE (hex)
643 # x YYYY DDD SSS .ext
643 # x YYYY DDD SSS .ext
644 if isNumber( filen[8:11] ):
644 if isNumber( filen[8:11] ):
645 setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file
645 setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file
646 else:
646 else:
647 setFile = -1
647 setFile = -1
648 else:
648 else:
649 setFile = -1 #inicializo mi contador de seteo
649 setFile = -1 #inicializo mi contador de seteo
650
650
651 if self.setType is None:
651 if self.setType is None:
652 setFile += 1
652 setFile += 1
653 file = '%s%4.4d%3.3d%03d%s' % (self.metaoptchar,
653 file = '%s%4.4d%3.3d%03d%s' % (self.metaoptchar,
654 timeTuple.tm_year,
654 timeTuple.tm_year,
655 timeTuple.tm_yday,
655 timeTuple.tm_yday,
656 setFile,
656 setFile,
657 ext )
657 ext )
658 else:
658 else:
659 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
659 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
660 file = '%s%4.4d%3.3d%04d%s' % (self.metaoptchar,
660 file = '%s%4.4d%3.3d%04d%s' % (self.metaoptchar,
661 timeTuple.tm_year,
661 timeTuple.tm_year,
662 timeTuple.tm_yday,
662 timeTuple.tm_yday,
663 setFile,
663 setFile,
664 ext )
664 ext )
665
665
666 filename = os.path.join( path, subfolder, file )
666 filename = os.path.join( path, subfolder, file )
667 self.metaFile = file
667 self.metaFile = file
668 #Setting HDF5 File
668 #Setting HDF5 File
669 fp = h5py.File(filename,'w')
669 fp = h5py.File(filename,'w')
670
670
671 return fp
671 return fp
672
672
673 def writeMetadata(self, fp):
673 def writeMetadata(self, fp):
674
674
675 grp = fp.create_group("Metadata")
675 grp = fp.create_group("Metadata")
676 grp.create_dataset('array dimensions', data = self.tableDim, dtype = self.dtype)
676 grp.create_dataset('array dimensions', data = self.tableDim, dtype = self.dtype)
677
677
678 for i in range(len(self.metadataList)):
678 for i in range(len(self.metadataList)):
679 grp.create_dataset(self.metadataList[i], data=getattr(self.dataOut, self.metadataList[i]))
679 grp.create_dataset(self.metadataList[i], data=getattr(self.dataOut, self.metadataList[i]))
680 return
680 return
681
681
682 def timeFlag(self):
682 def timeFlag(self):
683 currentTime = self.dataOut.utctime
683 currentTime = self.dataOut.utctime
684
684
685 if self.lastTime is None:
685 if self.lastTime is None:
686 self.lastTime = currentTime
686 self.lastTime = currentTime
687
687
688 #Day
688 #Day
689 timeTuple = time.localtime(currentTime)
689 timeTuple = time.localtime(currentTime)
690 dataDay = timeTuple.tm_yday
690 dataDay = timeTuple.tm_yday
691
691
692 #Time
692 #Time
693 timeDiff = currentTime - self.lastTime
693 timeDiff = currentTime - self.lastTime
694
694
695 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
695 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
696 if dataDay != self.currentDay:
696 if dataDay != self.currentDay:
697 self.currentDay = dataDay
697 self.currentDay = dataDay
698 return True
698 return True
699 elif timeDiff > 3*60*60:
699 elif timeDiff > 3*60*60:
700 self.lastTime = currentTime
700 self.lastTime = currentTime
701 return True
701 return True
702 else:
702 else:
703 self.lastTime = currentTime
703 self.lastTime = currentTime
704 return False
704 return False
705
705
706 def setNextFile(self):
706 def setNextFile(self):
707
707
708 ext = self.ext
708 ext = self.ext
709 path = self.path
709 path = self.path
710 setFile = self.setFile
710 setFile = self.setFile
711 mode = self.mode
711 mode = self.mode
712
712
713 timeTuple = time.localtime(self.dataOut.utctime)
713 timeTuple = time.localtime(self.dataOut.utctime)
714 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
714 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
715
715
716 fullpath = os.path.join( path, subfolder )
716 fullpath = os.path.join( path, subfolder )
717
717
718 if os.path.exists(fullpath):
718 if os.path.exists(fullpath):
719 filesList = os.listdir( fullpath )
719 filesList = os.listdir( fullpath )
720 filesList = [k for k in filesList if 'M' in k]
720 ##filesList = [k for k in filesList if 'M' in k]
721 if len( filesList ) > 0:
721 if len( filesList ) > 0:
722 filesList = sorted( filesList, key=str.lower )
722 filesList = sorted( filesList, key=str.lower )
723 filen = filesList[-1]
723 filen = filesList[-1]
724 # el filename debera tener el siguiente formato
724 # el filename debera tener el siguiente formato
725 # 0 1234 567 89A BCDE (hex)
725 # 0 1234 567 89A BCDE (hex)
726 # x YYYY DDD SSS .ext
726 # x YYYY DDD SSS .ext
727 if isNumber( filen[8:11] ):
727 if isNumber( filen[8:11] ):
728 setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file
728 setFile = int( filen[8:11] ) #inicializo mi contador de seteo al seteo del ultimo file
729 else:
729 else:
730 setFile = -1
730 setFile = -1
731 else:
731 else:
732 setFile = -1 #inicializo mi contador de seteo
732 setFile = -1 #inicializo mi contador de seteo
733 else:
733 else:
734 os.makedirs(fullpath)
734 os.makedirs(fullpath)
735 setFile = -1 #inicializo mi contador de seteo
735 setFile = -1 #inicializo mi contador de seteo
736
736
737 if self.setType is None:
737 if self.setType is None:
738 setFile += 1
738 setFile += 1
739 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
739 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
740 timeTuple.tm_year,
740 timeTuple.tm_year,
741 timeTuple.tm_yday,
741 timeTuple.tm_yday,
742 setFile,
742 setFile,
743 ext )
743 ext )
744 else:
744 else:
745 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
745 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
746 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
746 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
747 timeTuple.tm_year,
747 timeTuple.tm_year,
748 timeTuple.tm_yday,
748 timeTuple.tm_yday,
749 setFile,
749 setFile,
750 ext )
750 ext )
751
751
752 filename = os.path.join( path, subfolder, file )
752 filename = os.path.join( path, subfolder, file )
753
753
754 #Setting HDF5 File
754 #Setting HDF5 File
755 fp = h5py.File(filename,'w')
755 fp = h5py.File(filename,'w')
756 #write metadata
756 #write metadata
757 self.writeMetadata(fp)
757 self.writeMetadata(fp)
758 #Write data
758 #Write data
759 grp = fp.create_group("Data")
759 grp = fp.create_group("Data")
760 ds = []
760 ds = []
761 data = []
761 data = []
762 dsList = self.dsList
762 dsList = self.dsList
763 i = 0
763 i = 0
764 while i < len(dsList):
764 while i < len(dsList):
765 dsInfo = dsList[i]
765 dsInfo = dsList[i]
766 #One-dimension data
766 #One-dimension data
767 if dsInfo['mode'] == 0:
767 if dsInfo['mode'] == 0:
768 ds0 = grp.create_dataset(dsInfo['variable'], (1,1), maxshape=(1,self.blocksPerFile) , chunks = True, dtype=numpy.float64)
768 ds0 = grp.create_dataset(dsInfo['variable'], (1,1), maxshape=(1,self.blocksPerFile) , chunks = True, dtype=numpy.float64)
769 ds.append(ds0)
769 ds.append(ds0)
770 data.append([])
770 data.append([])
771 i += 1
771 i += 1
772 continue
772 continue
773
773
774 elif dsInfo['mode'] == 2:
774 elif dsInfo['mode'] == 2:
775 grp0 = grp.create_group(dsInfo['variable'])
775 grp0 = grp.create_group(dsInfo['variable'])
776 ds0 = grp0.create_dataset(dsInfo['dsName'], (1,dsInfo['shape']), data = numpy.zeros((1,dsInfo['shape'])) , maxshape=(None,dsInfo['shape']), chunks=True)
776 ds0 = grp0.create_dataset(dsInfo['dsName'], (1,dsInfo['shape']), data = numpy.zeros((1,dsInfo['shape'])) , maxshape=(None,dsInfo['shape']), chunks=True)
777 ds.append(ds0)
777 ds.append(ds0)
778 data.append([])
778 data.append([])
779 i += 1
779 i += 1
780 continue
780 continue
781
781
782 elif dsInfo['mode'] == 1:
782 elif dsInfo['mode'] == 1:
783 grp0 = grp.create_group(dsInfo['variable'])
783 grp0 = grp.create_group(dsInfo['variable'])
784
784
785 for j in range(dsInfo['dsNumber']):
785 for j in range(dsInfo['dsNumber']):
786 dsInfo = dsList[i]
786 dsInfo = dsList[i]
787 tableName = dsInfo['dsName']
787 tableName = dsInfo['dsName']
788
788
789
789
790 if dsInfo['nDim'] == 3:
790 if dsInfo['nDim'] == 3:
791 shape = dsInfo['shape'].astype(int)
791 shape = dsInfo['shape'].astype(int)
792 ds0 = grp0.create_dataset(tableName, (shape[0],shape[1],1) , data = numpy.zeros((shape[0],shape[1],1)), maxshape = (None,shape[1],None), chunks=True)
792 ds0 = grp0.create_dataset(tableName, (shape[0],shape[1],1) , data = numpy.zeros((shape[0],shape[1],1)), maxshape = (None,shape[1],None), chunks=True)
793 else:
793 else:
794 shape = int(dsInfo['shape'])
794 shape = int(dsInfo['shape'])
795 ds0 = grp0.create_dataset(tableName, (1,shape), data = numpy.zeros((1,shape)) , maxshape=(None,shape), chunks=True)
795 ds0 = grp0.create_dataset(tableName, (1,shape), data = numpy.zeros((1,shape)) , maxshape=(None,shape), chunks=True)
796
796
797 ds.append(ds0)
797 ds.append(ds0)
798 data.append([])
798 data.append([])
799 i += 1
799 i += 1
800
800
801 fp.flush()
801 fp.flush()
802 fp.close()
802 fp.close()
803
803
804 log.log('creating file: {}'.format(filename), 'Writing')
804 log.log('creating file: {}'.format(filename), 'Writing')
805 self.filename = filename
805 self.filename = filename
806 self.ds = ds
806 self.ds = ds
807 self.data = data
807 self.data = data
808 self.firsttime = True
808 self.firsttime = True
809 self.blockIndex = 0
809 self.blockIndex = 0
810 return
810 return
811
811
812 def putData(self):
812 def putData(self):
813
813
814 if self.blockIndex == self.blocksPerFile or self.timeFlag():
814 if self.blockIndex == self.blocksPerFile or self.timeFlag():
815 self.setNextFile()
815 self.setNextFile()
816
816
817 self.readBlock()
817 self.readBlock()
818 self.setBlock() #Prepare data to be written
818 self.setBlock() #Prepare data to be written
819 self.writeBlock() #Write data
819 self.writeBlock() #Write data
820
820
821 return
821 return
822
822
823 def readBlock(self):
823 def readBlock(self):
824
824
825 '''
825 '''
826 data Array configured
826 data Array configured
827
827
828
828
829 self.data
829 self.data
830 '''
830 '''
831 dsList = self.dsList
831 dsList = self.dsList
832 ds = self.ds
832 ds = self.ds
833 #Setting HDF5 File
833 #Setting HDF5 File
834 fp = h5py.File(self.filename,'r+')
834 fp = h5py.File(self.filename,'r+')
835 grp = fp["Data"]
835 grp = fp["Data"]
836 ind = 0
836 ind = 0
837
837
838 while ind < len(dsList):
838 while ind < len(dsList):
839 dsInfo = dsList[ind]
839 dsInfo = dsList[ind]
840
840
841 if dsInfo['mode'] == 0:
841 if dsInfo['mode'] == 0:
842 ds0 = grp[dsInfo['variable']]
842 ds0 = grp[dsInfo['variable']]
843 ds[ind] = ds0
843 ds[ind] = ds0
844 ind += 1
844 ind += 1
845 else:
845 else:
846
846
847 grp0 = grp[dsInfo['variable']]
847 grp0 = grp[dsInfo['variable']]
848
848
849 for j in range(dsInfo['dsNumber']):
849 for j in range(dsInfo['dsNumber']):
850 dsInfo = dsList[ind]
850 dsInfo = dsList[ind]
851 ds0 = grp0[dsInfo['dsName']]
851 ds0 = grp0[dsInfo['dsName']]
852 ds[ind] = ds0
852 ds[ind] = ds0
853 ind += 1
853 ind += 1
854
854
855 self.fp = fp
855 self.fp = fp
856 self.grp = grp
856 self.grp = grp
857 self.ds = ds
857 self.ds = ds
858
858
859 return
859 return
860
860
861 def setBlock(self):
861 def setBlock(self):
862 '''
862 '''
863 data Array configured
863 data Array configured
864
864
865
865
866 self.data
866 self.data
867 '''
867 '''
868 #Creating Arrays
868 #Creating Arrays
869 dsList = self.dsList
869 dsList = self.dsList
870 data = self.data
870 data = self.data
871 ind = 0
871 ind = 0
872
872
873 while ind < len(dsList):
873 while ind < len(dsList):
874 dsInfo = dsList[ind]
874 dsInfo = dsList[ind]
875 dataAux = getattr(self.dataOut, dsInfo['variable'])
875 dataAux = getattr(self.dataOut, dsInfo['variable'])
876
876
877 mode = dsInfo['mode']
877 mode = dsInfo['mode']
878 nDim = dsInfo['nDim']
878 nDim = dsInfo['nDim']
879
879
880 if mode == 0 or mode == 2 or nDim == 1:
880 if mode == 0 or mode == 2 or nDim == 1:
881 data[ind] = dataAux
881 data[ind] = dataAux
882 ind += 1
882 ind += 1
883 # elif nDim == 1:
883 # elif nDim == 1:
884 # data[ind] = numpy.reshape(dataAux,(numpy.size(dataAux),1))
884 # data[ind] = numpy.reshape(dataAux,(numpy.size(dataAux),1))
885 # ind += 1
885 # ind += 1
886 elif nDim == 2:
886 elif nDim == 2:
887 for j in range(dsInfo['dsNumber']):
887 for j in range(dsInfo['dsNumber']):
888 data[ind] = dataAux[j,:]
888 data[ind] = dataAux[j,:]
889 ind += 1
889 ind += 1
890 elif nDim == 3:
890 elif nDim == 3:
891 for j in range(dsInfo['dsNumber']):
891 for j in range(dsInfo['dsNumber']):
892 data[ind] = dataAux[:,j,:]
892 data[ind] = dataAux[:,j,:]
893 ind += 1
893 ind += 1
894
894
895 self.data = data
895 self.data = data
896 return
896 return
897
897
898 def writeBlock(self):
898 def writeBlock(self):
899 '''
899 '''
900 Saves the block in the HDF5 file
900 Saves the block in the HDF5 file
901 '''
901 '''
902 dsList = self.dsList
902 dsList = self.dsList
903
903
904 for i in range(len(self.ds)):
904 for i in range(len(self.ds)):
905 dsInfo = dsList[i]
905 dsInfo = dsList[i]
906 nDim = dsInfo['nDim']
906 nDim = dsInfo['nDim']
907 mode = dsInfo['mode']
907 mode = dsInfo['mode']
908
908
909 # First time
909 # First time
910 if self.firsttime:
910 if self.firsttime:
911 if type(self.data[i]) == numpy.ndarray:
911 if type(self.data[i]) == numpy.ndarray:
912
912
913 if nDim == 3:
913 if nDim == 3:
914 self.data[i] = self.data[i].reshape((self.data[i].shape[0],self.data[i].shape[1],1))
914 self.data[i] = self.data[i].reshape((self.data[i].shape[0],self.data[i].shape[1],1))
915 self.ds[i].resize(self.data[i].shape)
915 self.ds[i].resize(self.data[i].shape)
916 if mode == 2:
916 if mode == 2:
917 self.ds[i].resize(self.data[i].shape)
917 self.ds[i].resize(self.data[i].shape)
918 self.ds[i][:] = self.data[i]
918 self.ds[i][:] = self.data[i]
919 else:
919 else:
920
920
921 # From second time
921 # From second time
922 # Meteors!
922 # Meteors!
923 if mode == 2:
923 if mode == 2:
924 dataShape = self.data[i].shape
924 dataShape = self.data[i].shape
925 dsShape = self.ds[i].shape
925 dsShape = self.ds[i].shape
926 self.ds[i].resize((self.ds[i].shape[0] + dataShape[0],self.ds[i].shape[1]))
926 self.ds[i].resize((self.ds[i].shape[0] + dataShape[0],self.ds[i].shape[1]))
927 self.ds[i][dsShape[0]:,:] = self.data[i]
927 self.ds[i][dsShape[0]:,:] = self.data[i]
928 # No dimension
928 # No dimension
929 elif mode == 0:
929 elif mode == 0:
930 self.ds[i].resize((self.ds[i].shape[0], self.ds[i].shape[1] + 1))
930 self.ds[i].resize((self.ds[i].shape[0], self.ds[i].shape[1] + 1))
931 self.ds[i][0,-1] = self.data[i]
931 self.ds[i][0,-1] = self.data[i]
932 # One dimension
932 # One dimension
933 elif nDim == 1:
933 elif nDim == 1:
934 self.ds[i].resize((self.ds[i].shape[0] + 1, self.ds[i].shape[1]))
934 self.ds[i].resize((self.ds[i].shape[0] + 1, self.ds[i].shape[1]))
935 self.ds[i][-1,:] = self.data[i]
935 self.ds[i][-1,:] = self.data[i]
936 # Two dimension
936 # Two dimension
937 elif nDim == 2:
937 elif nDim == 2:
938 self.ds[i].resize((self.ds[i].shape[0] + 1,self.ds[i].shape[1]))
938 self.ds[i].resize((self.ds[i].shape[0] + 1,self.ds[i].shape[1]))
939 self.ds[i][self.blockIndex,:] = self.data[i]
939 self.ds[i][self.blockIndex,:] = self.data[i]
940 # Three dimensions
940 # Three dimensions
941 elif nDim == 3:
941 elif nDim == 3:
942 self.ds[i].resize((self.ds[i].shape[0],self.ds[i].shape[1],self.ds[i].shape[2]+1))
942 self.ds[i].resize((self.ds[i].shape[0],self.ds[i].shape[1],self.ds[i].shape[2]+1))
943 self.ds[i][:,:,-1] = self.data[i]
943 self.ds[i][:,:,-1] = self.data[i]
944
944
945 self.firsttime = False
945 self.firsttime = False
946 self.blockIndex += 1
946 self.blockIndex += 1
947
947
948 #Close to save changes
948 #Close to save changes
949 self.fp.flush()
949 self.fp.flush()
950 self.fp.close()
950 self.fp.close()
951 return
951 return
952
952
953 def run(self, dataOut, path, blocksPerFile=10, metadataList=None, dataList=None, mode=None, setType=None):
953 def run(self, dataOut, path, blocksPerFile=10, metadataList=None, dataList=None, mode=None, setType=None):
954
954
955 self.dataOut = dataOut
955 self.dataOut = dataOut
956 if not(self.isConfig):
956 if not(self.isConfig):
957 self.setup(dataOut, path=path, blocksPerFile=blocksPerFile,
957 self.setup(dataOut, path=path, blocksPerFile=blocksPerFile,
958 metadataList=metadataList, dataList=dataList, mode=mode,
958 metadataList=metadataList, dataList=dataList, mode=mode,
959 setType=setType)
959 setType=setType)
960
960
961 self.isConfig = True
961 self.isConfig = True
962 self.setNextFile()
962 self.setNextFile()
963
963
964 self.putData()
964 self.putData()
965 return
965 return
966
966
967
967
968 @MPDecorator
968 @MPDecorator
969 class ParameterReader(Reader, ProcessingUnit):
969 class ParameterReader(Reader, ProcessingUnit):
970 '''
970 '''
971 Reads HDF5 format files
971 Reads HDF5 format files
972 '''
972 '''
973
973
974 def __init__(self):
974 def __init__(self):
975 ProcessingUnit.__init__(self)
975 ProcessingUnit.__init__(self)
976 self.dataOut = Parameters()
976 self.dataOut = Parameters()
977 self.ext = ".hdf5"
977 self.ext = ".hdf5"
978 self.optchar = "D"
978 self.optchar = "D"
979 self.timezone = "lt"
979 self.timezone = "lt"
980 self.listMetaname = []
980 self.listMetaname = []
981 self.listMeta = []
981 self.listMeta = []
982 self.listDataname = []
982 self.listDataname = []
983 self.listData = []
983 self.listData = []
984 self.listShapes = []
984 self.listShapes = []
985 self.open_file = h5py.File
985 self.open_file = h5py.File
986 self.open_mode = 'r'
986 self.open_mode = 'r'
987 self.metadata = False
987 self.metadata = False
988 self.filefmt = "*%Y%j***"
988 self.filefmt = "*%Y%j***"
989 self.folderfmt = "*%Y%j"
989 self.folderfmt = "*%Y%j"
990
990
991 def setup(self, **kwargs):
991 def setup(self, **kwargs):
992
992
993 self.set_kwargs(**kwargs)
993 self.set_kwargs(**kwargs)
994 if not self.ext.startswith('.'):
994 if not self.ext.startswith('.'):
995 self.ext = '.{}'.format(self.ext)
995 self.ext = '.{}'.format(self.ext)
996
996
997 if self.online:
997 if self.online:
998 log.log("Searching files in online mode...", self.name)
998 log.log("Searching files in online mode...", self.name)
999
999
1000 for nTries in range(self.nTries):
1000 for nTries in range(self.nTries):
1001 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1001 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1002 self.endDate, self.expLabel, self.ext, self.walk,
1002 self.endDate, self.expLabel, self.ext, self.walk,
1003 self.filefmt, self.folderfmt)
1003 self.filefmt, self.folderfmt)
1004
1004
1005 try:
1005 try:
1006 fullpath = next(fullpath)
1006 fullpath = next(fullpath)
1007 except:
1007 except:
1008 fullpath = None
1008 fullpath = None
1009
1009
1010 if fullpath:
1010 if fullpath:
1011 break
1011 break
1012
1012
1013 log.warning(
1013 log.warning(
1014 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1014 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1015 self.delay, self.path, nTries + 1),
1015 self.delay, self.path, nTries + 1),
1016 self.name)
1016 self.name)
1017 time.sleep(self.delay)
1017 time.sleep(self.delay)
1018
1018
1019 if not(fullpath):
1019 if not(fullpath):
1020 raise schainpy.admin.SchainError(
1020 raise schainpy.admin.SchainError(
1021 'There isn\'t any valid file in {}'.format(self.path))
1021 'There isn\'t any valid file in {}'.format(self.path))
1022
1022
1023 pathname, filename = os.path.split(fullpath)
1023 pathname, filename = os.path.split(fullpath)
1024 self.year = int(filename[1:5])
1024 self.year = int(filename[1:5])
1025 self.doy = int(filename[5:8])
1025 self.doy = int(filename[5:8])
1026 self.set = int(filename[8:11]) - 1
1026 self.set = int(filename[8:11]) - 1
1027 else:
1027 else:
1028 log.log("Searching files in {}".format(self.path), self.name)
1028 log.log("Searching files in {}".format(self.path), self.name)
1029 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1029 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1030 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1030 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1031
1031
1032 self.setNextFile()
1032 self.setNextFile()
1033
1033
1034 return
1034 return
1035
1035
1036 def readFirstHeader(self):
1036 def readFirstHeader(self):
1037 '''Read metadata and data'''
1037 '''Read metadata and data'''
1038
1038
1039 self.__readMetadata()
1039 self.__readMetadata()
1040 self.__readData()
1040 self.__readData()
1041 self.__setBlockList()
1041 self.__setBlockList()
1042 self.blockIndex = 0
1042 self.blockIndex = 0
1043
1043
1044 return
1044 return
1045
1045
1046 def __setBlockList(self):
1046 def __setBlockList(self):
1047 '''
1047 '''
1048 Selects the data within the times defined
1048 Selects the data within the times defined
1049
1049
1050 self.fp
1050 self.fp
1051 self.startTime
1051 self.startTime
1052 self.endTime
1052 self.endTime
1053 self.blockList
1053 self.blockList
1054 self.blocksPerFile
1054 self.blocksPerFile
1055
1055
1056 '''
1056 '''
1057
1057
1058 startTime = self.startTime
1058 startTime = self.startTime
1059 endTime = self.endTime
1059 endTime = self.endTime
1060
1060
1061 index = self.listDataname.index('utctime')
1061 index = self.listDataname.index('utctime')
1062 thisUtcTime = self.listData[index]
1062 thisUtcTime = self.listData[index]
1063 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
1063 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
1064
1064
1065 if self.timezone == 'lt':
1065 if self.timezone == 'lt':
1066 thisUtcTime -= 5*3600
1066 thisUtcTime -= 5*3600
1067
1067
1068 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
1068 thisDatetime = datetime.datetime.fromtimestamp(thisUtcTime[0] + 5*3600)
1069
1069
1070 thisDate = thisDatetime.date()
1070 thisDate = thisDatetime.date()
1071 thisTime = thisDatetime.time()
1071 thisTime = thisDatetime.time()
1072
1072
1073 startUtcTime = (datetime.datetime.combine(thisDate,startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
1073 startUtcTime = (datetime.datetime.combine(thisDate,startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
1074 endUtcTime = (datetime.datetime.combine(thisDate,endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
1074 endUtcTime = (datetime.datetime.combine(thisDate,endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
1075
1075
1076 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
1076 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
1077
1077
1078 self.blockList = ind
1078 self.blockList = ind
1079 self.blocksPerFile = len(ind)
1079 self.blocksPerFile = len(ind)
1080 return
1080 return
1081
1081
1082 def __readMetadata(self):
1082 def __readMetadata(self):
1083 '''
1083 '''
1084 Reads Metadata
1084 Reads Metadata
1085 '''
1085 '''
1086
1086
1087 listMetaname = []
1087 listMetaname = []
1088 listMetadata = []
1088 listMetadata = []
1089 if 'Metadata' in self.fp:
1089 if 'Metadata' in self.fp:
1090 gp = self.fp['Metadata']
1090 gp = self.fp['Metadata']
1091 for item in list(gp.items()):
1091 for item in list(gp.items()):
1092 name = item[0]
1092 name = item[0]
1093
1093
1094 if name=='variables':
1094 if name=='variables':
1095 table = gp[name][:]
1095 table = gp[name][:]
1096 listShapes = {}
1096 listShapes = {}
1097 for shapes in table:
1097 for shapes in table:
1098 listShapes[shapes[0].decode()] = numpy.array([shapes[1]])
1098 listShapes[shapes[0].decode()] = numpy.array([shapes[1]])
1099 else:
1099 else:
1100 data = gp[name].value
1100 data = gp[name].value
1101 listMetaname.append(name)
1101 listMetaname.append(name)
1102 listMetadata.append(data)
1102 listMetadata.append(data)
1103 elif self.metadata:
1103 elif self.metadata:
1104 metadata = json.loads(self.metadata)
1104 metadata = json.loads(self.metadata)
1105 listShapes = {}
1105 listShapes = {}
1106 for tup in metadata:
1106 for tup in metadata:
1107 name, values, dim = tup
1107 name, values, dim = tup
1108 if dim == -1:
1108 if dim == -1:
1109 listMetaname.append(name)
1109 listMetaname.append(name)
1110 listMetadata.append(self.fp[values].value)
1110 listMetadata.append(self.fp[values].value)
1111 else:
1111 else:
1112 listShapes[name] = numpy.array([dim])
1112 listShapes[name] = numpy.array([dim])
1113 else:
1113 else:
1114 raise IOError('Missing Metadata group in file or metadata info')
1114 raise IOError('Missing Metadata group in file or metadata info')
1115
1115
1116 self.listShapes = listShapes
1116 self.listShapes = listShapes
1117 self.listMetaname = listMetaname
1117 self.listMetaname = listMetaname
1118 self.listMeta = listMetadata
1118 self.listMeta = listMetadata
1119
1119
1120 return
1120 return
1121
1121
1122 def __readData(self):
1122 def __readData(self):
1123
1123
1124 listdataname = []
1124 listdataname = []
1125 listdata = []
1125 listdata = []
1126
1126
1127 if 'Data' in self.fp:
1127 if 'Data' in self.fp:
1128 grp = self.fp['Data']
1128 grp = self.fp['Data']
1129 for item in list(grp.items()):
1129 for item in list(grp.items()):
1130 name = item[0]
1130 name = item[0]
1131 listdataname.append(name)
1131 listdataname.append(name)
1132 dim = self.listShapes[name][0]
1132 dim = self.listShapes[name][0]
1133 if dim == 0:
1133 if dim == 0:
1134 array = grp[name].value
1134 array = grp[name].value
1135 else:
1135 else:
1136 array = []
1136 array = []
1137 for i in range(dim):
1137 for i in range(dim):
1138 array.append(grp[name]['table{:02d}'.format(i)].value)
1138 array.append(grp[name]['table{:02d}'.format(i)].value)
1139 array = numpy.array(array)
1139 array = numpy.array(array)
1140
1140
1141 listdata.append(array)
1141 listdata.append(array)
1142 elif self.metadata:
1142 elif self.metadata:
1143 metadata = json.loads(self.metadata)
1143 metadata = json.loads(self.metadata)
1144 for tup in metadata:
1144 for tup in metadata:
1145 name, values, dim = tup
1145 name, values, dim = tup
1146 listdataname.append(name)
1146 listdataname.append(name)
1147 if dim == -1:
1147 if dim == -1:
1148 continue
1148 continue
1149 elif dim == 0:
1149 elif dim == 0:
1150 array = self.fp[values].value
1150 array = self.fp[values].value
1151 else:
1151 else:
1152 array = []
1152 array = []
1153 for var in values:
1153 for var in values:
1154 array.append(self.fp[var].value)
1154 array.append(self.fp[var].value)
1155 array = numpy.array(array)
1155 array = numpy.array(array)
1156 listdata.append(array)
1156 listdata.append(array)
1157 else:
1157 else:
1158 raise IOError('Missing Data group in file or metadata info')
1158 raise IOError('Missing Data group in file or metadata info')
1159
1159
1160 self.listDataname = listdataname
1160 self.listDataname = listdataname
1161 self.listData = listdata
1161 self.listData = listdata
1162 return
1162 return
1163
1163
1164 def getData(self):
1164 def getData(self):
1165
1165
1166 for i in range(len(self.listMeta)):
1166 for i in range(len(self.listMeta)):
1167 setattr(self.dataOut, self.listMetaname[i], self.listMeta[i])
1167 setattr(self.dataOut, self.listMetaname[i], self.listMeta[i])
1168
1168
1169 for j in range(len(self.listData)):
1169 for j in range(len(self.listData)):
1170 dim = self.listShapes[self.listDataname[j]][0]
1170 dim = self.listShapes[self.listDataname[j]][0]
1171 if dim == 0:
1171 if dim == 0:
1172 setattr(self.dataOut, self.listDataname[j], self.listData[j][self.blockIndex])
1172 setattr(self.dataOut, self.listDataname[j], self.listData[j][self.blockIndex])
1173 else:
1173 else:
1174 setattr(self.dataOut, self.listDataname[j], self.listData[j][:,self.blockIndex])
1174 setattr(self.dataOut, self.listDataname[j], self.listData[j][:,self.blockIndex])
1175
1175
1176 self.dataOut.paramInterval = self.interval
1176 self.dataOut.paramInterval = self.interval
1177 self.dataOut.flagNoData = False
1177 self.dataOut.flagNoData = False
1178 self.blockIndex += 1
1178 self.blockIndex += 1
1179
1179
1180 return
1180 return
1181
1181
1182 def run(self, **kwargs):
1182 def run(self, **kwargs):
1183
1183
1184 if not(self.isConfig):
1184 if not(self.isConfig):
1185 self.setup(**kwargs)
1185 self.setup(**kwargs)
1186 self.isConfig = True
1186 self.isConfig = True
1187
1187
1188 if self.blockIndex == self.blocksPerFile:
1188 if self.blockIndex == self.blocksPerFile:
1189 self.setNextFile()
1189 self.setNextFile()
1190
1190
1191 self.getData()
1191 self.getData()
1192
1192
1193 return
1193 return
1194
1194
1195 @MPDecorator
1195 @MPDecorator
1196 class ParameterWriter(Operation):
1196 class ParameterWriter(Operation):
1197 '''
1197 '''
1198 HDF5 Writer, stores parameters data in HDF5 format files
1198 HDF5 Writer, stores parameters data in HDF5 format files
1199
1199
1200 path: path where the files will be stored
1200 path: path where the files will be stored
1201 blocksPerFile: number of blocks that will be saved in per HDF5 format file
1201 blocksPerFile: number of blocks that will be saved in per HDF5 format file
1202 mode: selects the data stacking mode: '0' channels, '1' parameters, '3' table (for meteors)
1202 mode: selects the data stacking mode: '0' channels, '1' parameters, '3' table (for meteors)
1203 metadataList: list of attributes that will be stored as metadata
1203 metadataList: list of attributes that will be stored as metadata
1204 dataList: list of attributes that will be stores as data
1204 dataList: list of attributes that will be stores as data
1205 '''
1205 '''
1206
1206
1207
1207
1208 ext = ".hdf5"
1208 ext = ".hdf5"
1209 optchar = "D"
1209 optchar = "D"
1210 metaoptchar = "M"
1210 metaoptchar = "M"
1211 metaFile = None
1211 metaFile = None
1212 filename = None
1212 filename = None
1213 path = None
1213 path = None
1214 setFile = None
1214 setFile = None
1215 fp = None
1215 fp = None
1216 grp = None
1216 grp = None
1217 ds = None
1217 ds = None
1218 firsttime = True
1218 firsttime = True
1219 #Configurations
1219 #Configurations
1220 blocksPerFile = None
1220 blocksPerFile = None
1221 blockIndex = None
1221 blockIndex = None
1222 dataOut = None
1222 dataOut = None
1223 #Data Arrays
1223 #Data Arrays
1224 dataList = None
1224 dataList = None
1225 metadataList = None
1225 metadataList = None
1226 dsList = None #List of dictionaries with dataset properties
1226 dsList = None #List of dictionaries with dataset properties
1227 tableDim = None
1227 tableDim = None
1228 dtype = [('name', 'S20'),('nDim', 'i')]
1228 dtype = [('name', 'S20'),('nDim', 'i')]
1229 currentDay = None
1229 currentDay = None
1230 lastTime = None
1230 lastTime = None
1231
1231
1232 def __init__(self):
1232 def __init__(self):
1233
1233
1234 Operation.__init__(self)
1234 Operation.__init__(self)
1235 return
1235 return
1236
1236
1237 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None):
1237 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None):
1238 self.path = path
1238 self.path = path
1239 self.blocksPerFile = blocksPerFile
1239 self.blocksPerFile = blocksPerFile
1240 self.metadataList = metadataList
1240 self.metadataList = metadataList
1241 self.dataList = dataList
1241 self.dataList = dataList
1242 self.setType = setType
1242 self.setType = setType
1243
1243
1244 tableList = []
1244 tableList = []
1245 dsList = []
1245 dsList = []
1246
1246
1247 for i in range(len(self.dataList)):
1247 for i in range(len(self.dataList)):
1248 dsDict = {}
1248 dsDict = {}
1249 dataAux = getattr(self.dataOut, self.dataList[i])
1249 dataAux = getattr(self.dataOut, self.dataList[i])
1250 dsDict['variable'] = self.dataList[i]
1250 dsDict['variable'] = self.dataList[i]
1251
1251
1252 if dataAux is None:
1252 if dataAux is None:
1253 continue
1253 continue
1254 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
1254 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
1255 dsDict['nDim'] = 0
1255 dsDict['nDim'] = 0
1256 else:
1256 else:
1257 dsDict['nDim'] = len(dataAux.shape)
1257 dsDict['nDim'] = len(dataAux.shape)
1258 dsDict['shape'] = dataAux.shape
1258 dsDict['shape'] = dataAux.shape
1259 dsDict['dsNumber'] = dataAux.shape[0]
1259 dsDict['dsNumber'] = dataAux.shape[0]
1260
1260
1261 dsList.append(dsDict)
1261 dsList.append(dsDict)
1262 tableList.append((self.dataList[i], dsDict['nDim']))
1262 tableList.append((self.dataList[i], dsDict['nDim']))
1263
1263
1264 self.dsList = dsList
1264 self.dsList = dsList
1265 self.tableDim = numpy.array(tableList, dtype=self.dtype)
1265 self.tableDim = numpy.array(tableList, dtype=self.dtype)
1266 self.currentDay = self.dataOut.datatime.date()
1266 self.currentDay = self.dataOut.datatime.date()
1267
1267
1268 def timeFlag(self):
1268 def timeFlag(self):
1269 currentTime = self.dataOut.utctime
1269 currentTime = self.dataOut.utctime
1270 timeTuple = time.localtime(currentTime)
1270 timeTuple = time.localtime(currentTime)
1271 dataDay = timeTuple.tm_yday
1271 dataDay = timeTuple.tm_yday
1272
1272
1273 if self.lastTime is None:
1273 if self.lastTime is None:
1274 self.lastTime = currentTime
1274 self.lastTime = currentTime
1275 self.currentDay = dataDay
1275 self.currentDay = dataDay
1276 return False
1276 return False
1277
1277
1278 timeDiff = currentTime - self.lastTime
1278 timeDiff = currentTime - self.lastTime
1279
1279
1280 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
1280 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
1281 if dataDay != self.currentDay:
1281 if dataDay != self.currentDay:
1282 self.currentDay = dataDay
1282 self.currentDay = dataDay
1283 return True
1283 return True
1284 elif timeDiff > 3*60*60:
1284 elif timeDiff > 3*60*60:
1285 self.lastTime = currentTime
1285 self.lastTime = currentTime
1286 return True
1286 return True
1287 else:
1287 else:
1288 self.lastTime = currentTime
1288 self.lastTime = currentTime
1289 return False
1289 return False
1290
1290
1291 def run(self, dataOut, path, blocksPerFile=10, metadataList=None, dataList=None, setType=None):
1291 def run(self, dataOut, path, blocksPerFile=10, metadataList=None, dataList=None, setType=None):
1292
1292
1293 self.dataOut = dataOut
1293 self.dataOut = dataOut
1294 if not(self.isConfig):
1294 if not(self.isConfig):
1295 self.setup(path=path, blocksPerFile=blocksPerFile,
1295 self.setup(path=path, blocksPerFile=blocksPerFile,
1296 metadataList=metadataList, dataList=dataList,
1296 metadataList=metadataList, dataList=dataList,
1297 setType=setType)
1297 setType=setType)
1298
1298
1299 self.isConfig = True
1299 self.isConfig = True
1300 self.setNextFile()
1300 self.setNextFile()
1301
1301
1302 self.putData()
1302 self.putData()
1303 return
1303 return
1304
1304
1305 def setNextFile(self):
1305 def setNextFile(self):
1306
1306
1307 ext = self.ext
1307 ext = self.ext
1308 path = self.path
1308 path = self.path
1309 setFile = self.setFile
1309 setFile = self.setFile
1310
1310
1311 timeTuple = time.localtime(self.dataOut.utctime)
1311 timeTuple = time.localtime(self.dataOut.utctime)
1312 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
1312 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
1313 fullpath = os.path.join(path, subfolder)
1313 fullpath = os.path.join(path, subfolder)
1314
1314
1315 if os.path.exists(fullpath):
1315 if os.path.exists(fullpath):
1316 filesList = os.listdir(fullpath)
1316 filesList = os.listdir(fullpath)
1317 filesList = [k for k in filesList if k.startswith(self.optchar)]
1317 filesList = [k for k in filesList if k.startswith(self.optchar)]
1318 if len( filesList ) > 0:
1318 if len( filesList ) > 0:
1319 filesList = sorted(filesList, key=str.lower)
1319 filesList = sorted(filesList, key=str.lower)
1320 filen = filesList[-1]
1320 filen = filesList[-1]
1321 # el filename debera tener el siguiente formato
1321 # el filename debera tener el siguiente formato
1322 # 0 1234 567 89A BCDE (hex)
1322 # 0 1234 567 89A BCDE (hex)
1323 # x YYYY DDD SSS .ext
1323 # x YYYY DDD SSS .ext
1324 if isNumber(filen[8:11]):
1324 if isNumber(filen[8:11]):
1325 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
1325 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
1326 else:
1326 else:
1327 setFile = -1
1327 setFile = -1
1328 else:
1328 else:
1329 setFile = -1 #inicializo mi contador de seteo
1329 setFile = -1 #inicializo mi contador de seteo
1330 else:
1330 else:
1331 os.makedirs(fullpath)
1331 os.makedirs(fullpath)
1332 setFile = -1 #inicializo mi contador de seteo
1332 setFile = -1 #inicializo mi contador de seteo
1333
1333
1334 if self.setType is None:
1334 if self.setType is None:
1335 setFile += 1
1335 setFile += 1
1336 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
1336 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
1337 timeTuple.tm_year,
1337 timeTuple.tm_year,
1338 timeTuple.tm_yday,
1338 timeTuple.tm_yday,
1339 setFile,
1339 setFile,
1340 ext )
1340 ext )
1341 else:
1341 else:
1342 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
1342 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
1343 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
1343 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
1344 timeTuple.tm_year,
1344 timeTuple.tm_year,
1345 timeTuple.tm_yday,
1345 timeTuple.tm_yday,
1346 setFile,
1346 setFile,
1347 ext )
1347 ext )
1348
1348
1349 self.filename = os.path.join( path, subfolder, file )
1349 self.filename = os.path.join( path, subfolder, file )
1350
1350
1351 #Setting HDF5 File
1351 #Setting HDF5 File
1352 self.fp = h5py.File(self.filename, 'w')
1352 self.fp = h5py.File(self.filename, 'w')
1353 #write metadata
1353 #write metadata
1354 self.writeMetadata(self.fp)
1354 self.writeMetadata(self.fp)
1355 #Write data
1355 #Write data
1356 self.writeData(self.fp)
1356 self.writeData(self.fp)
1357
1357
1358 def writeMetadata(self, fp):
1358 def writeMetadata(self, fp):
1359
1359
1360 grp = fp.create_group("Metadata")
1360 grp = fp.create_group("Metadata")
1361 grp.create_dataset('variables', data=self.tableDim, dtype=self.dtype)
1361 grp.create_dataset('variables', data=self.tableDim, dtype=self.dtype)
1362
1362
1363 for i in range(len(self.metadataList)):
1363 for i in range(len(self.metadataList)):
1364 if not hasattr(self.dataOut, self.metadataList[i]):
1364 if not hasattr(self.dataOut, self.metadataList[i]):
1365 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
1365 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
1366 continue
1366 continue
1367 value = getattr(self.dataOut, self.metadataList[i])
1367 value = getattr(self.dataOut, self.metadataList[i])
1368 grp.create_dataset(self.metadataList[i], data=value)
1368 grp.create_dataset(self.metadataList[i], data=value)
1369 return
1369 return
1370
1370
1371 def writeData(self, fp):
1371 def writeData(self, fp):
1372
1372
1373 grp = fp.create_group("Data")
1373 grp = fp.create_group("Data")
1374 dtsets = []
1374 dtsets = []
1375 data = []
1375 data = []
1376
1376
1377 for dsInfo in self.dsList:
1377 for dsInfo in self.dsList:
1378 if dsInfo['nDim'] == 0:
1378 if dsInfo['nDim'] == 0:
1379 ds = grp.create_dataset(
1379 ds = grp.create_dataset(
1380 dsInfo['variable'],
1380 dsInfo['variable'],
1381 (self.blocksPerFile, ),
1381 (self.blocksPerFile, ),
1382 chunks=True,
1382 chunks=True,
1383 dtype=numpy.float64)
1383 dtype=numpy.float64)
1384 dtsets.append(ds)
1384 dtsets.append(ds)
1385 data.append((dsInfo['variable'], -1))
1385 data.append((dsInfo['variable'], -1))
1386 else:
1386 else:
1387 sgrp = grp.create_group(dsInfo['variable'])
1387 sgrp = grp.create_group(dsInfo['variable'])
1388 for i in range(dsInfo['dsNumber']):
1388 for i in range(dsInfo['dsNumber']):
1389 ds = sgrp.create_dataset(
1389 ds = sgrp.create_dataset(
1390 'table{:02d}'.format(i),
1390 'table{:02d}'.format(i),
1391 (self.blocksPerFile, ) + dsInfo['shape'][1:],
1391 (self.blocksPerFile, ) + dsInfo['shape'][1:],
1392 chunks=True)
1392 chunks=True)
1393 dtsets.append(ds)
1393 dtsets.append(ds)
1394 data.append((dsInfo['variable'], i))
1394 data.append((dsInfo['variable'], i))
1395 fp.flush()
1395 fp.flush()
1396
1396
1397 log.log('Creating file: {}'.format(fp.filename), self.name)
1397 log.log('Creating file: {}'.format(fp.filename), self.name)
1398
1398
1399 self.ds = dtsets
1399 self.ds = dtsets
1400 self.data = data
1400 self.data = data
1401 self.firsttime = True
1401 self.firsttime = True
1402 self.blockIndex = 0
1402 self.blockIndex = 0
1403 return
1403 return
1404
1404
1405 def putData(self):
1405 def putData(self):
1406
1406
1407 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
1407 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
1408 self.closeFile()
1408 self.closeFile()
1409 self.setNextFile()
1409 self.setNextFile()
1410
1410
1411 for i, ds in enumerate(self.ds):
1411 for i, ds in enumerate(self.ds):
1412 attr, ch = self.data[i]
1412 attr, ch = self.data[i]
1413 if ch == -1:
1413 if ch == -1:
1414 ds[self.blockIndex] = getattr(self.dataOut, attr)
1414 ds[self.blockIndex] = getattr(self.dataOut, attr)
1415 else:
1415 else:
1416 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
1416 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
1417
1417
1418 self.fp.flush()
1418 self.fp.flush()
1419 self.blockIndex += 1
1419 self.blockIndex += 1
1420 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
1420 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
1421
1421
1422 return
1422 return
1423
1423
1424 def closeFile(self):
1424 def closeFile(self):
1425
1425
1426 if self.blockIndex != self.blocksPerFile:
1426 if self.blockIndex != self.blocksPerFile:
1427 for ds in self.ds:
1427 for ds in self.ds:
1428 ds.resize(self.blockIndex, axis=0)
1428 ds.resize(self.blockIndex, axis=0)
1429
1429
1430 self.fp.flush()
1430 self.fp.flush()
1431 self.fp.close()
1431 self.fp.close()
1432
1432
1433 def close(self):
1433 def close(self):
1434
1434
1435 self.closeFile()
1435 self.closeFile()
@@ -1,429 +1,426
1 '''
1 '''
2 Updated for multiprocessing
2 Updated for multiprocessing
3 Author : Sergio Cortez
3 Author : Sergio Cortez
4 Jan 2018
4 Jan 2018
5 Abstract:
5 Abstract:
6 Base class for processing units and operations. A decorator provides multiprocessing features and interconnect the processes created.
6 Base class for processing units and operations. A decorator provides multiprocessing features and interconnect the processes created.
7 The argument (kwargs) sent from the controller is parsed and filtered via the decorator for each processing unit or operation instantiated.
7 The argument (kwargs) sent from the controller is parsed and filtered via the decorator for each processing unit or operation instantiated.
8 The decorator handle also the methods inside the processing unit to be called from the main script (not as operations) (OPERATION -> type ='self').
8 The decorator handle also the methods inside the processing unit to be called from the main script (not as operations) (OPERATION -> type ='self').
9
9
10 Based on:
10 Based on:
11 $Author: murco $
11 $Author: murco $
12 $Id: jroproc_base.py 1 2012-11-12 18:56:07Z murco $
12 $Id: jroproc_base.py 1 2012-11-12 18:56:07Z murco $
13 '''
13 '''
14
14
15 import os
15 import os
16 import sys
16 import sys
17 import inspect
17 import inspect
18 import zmq
18 import zmq
19 import time
19 import time
20 import pickle
20 import pickle
21 import traceback
21 import traceback
22 try:
22 try:
23 from queue import Queue
23 from queue import Queue
24 except:
24 except:
25 from Queue import Queue
25 from Queue import Queue
26 from threading import Thread
26 from threading import Thread
27 from multiprocessing import Process
27 from multiprocessing import Process
28
28
29 from schainpy.utils import log
29 from schainpy.utils import log
30
30
31
31
32 class ProcessingUnit(object):
32 class ProcessingUnit(object):
33
33
34 """
34 """
35 Update - Jan 2018 - MULTIPROCESSING
35 Update - Jan 2018 - MULTIPROCESSING
36 All the "call" methods present in the previous base were removed.
36 All the "call" methods present in the previous base were removed.
37 The majority of operations are independant processes, thus
37 The majority of operations are independant processes, thus
38 the decorator is in charge of communicate the operation processes
38 the decorator is in charge of communicate the operation processes
39 with the proccessing unit via IPC.
39 with the proccessing unit via IPC.
40
40
41 The constructor does not receive any argument. The remaining methods
41 The constructor does not receive any argument. The remaining methods
42 are related with the operations to execute.
42 are related with the operations to execute.
43
43
44
44
45 """
45 """
46 proc_type = 'processing'
46 proc_type = 'processing'
47 __attrs__ = []
47 __attrs__ = []
48
48
49 def __init__(self):
49 def __init__(self):
50
50
51 self.dataIn = None
51 self.dataIn = None
52 self.dataOut = None
52 self.dataOut = None
53 self.isConfig = False
53 self.isConfig = False
54 self.operations = []
54 self.operations = []
55 self.plots = []
55 self.plots = []
56
56
57 def getAllowedArgs(self):
57 def getAllowedArgs(self):
58 if hasattr(self, '__attrs__'):
58 if hasattr(self, '__attrs__'):
59 return self.__attrs__
59 return self.__attrs__
60 else:
60 else:
61 return inspect.getargspec(self.run).args
61 return inspect.getargspec(self.run).args
62
62
63 def addOperation(self, conf, operation):
63 def addOperation(self, conf, operation):
64 """
64 """
65 This method is used in the controller, and update the dictionary containing the operations to execute. The dict
65 This method is used in the controller, and update the dictionary containing the operations to execute. The dict
66 posses the id of the operation process (IPC purposes)
66 posses the id of the operation process (IPC purposes)
67
67
68 Agrega un objeto del tipo "Operation" (opObj) a la lista de objetos "self.objectList" y retorna el
68 Agrega un objeto del tipo "Operation" (opObj) a la lista de objetos "self.objectList" y retorna el
69 identificador asociado a este objeto.
69 identificador asociado a este objeto.
70
70
71 Input:
71 Input:
72
72
73 object : objeto de la clase "Operation"
73 object : objeto de la clase "Operation"
74
74
75 Return:
75 Return:
76
76
77 objId : identificador del objeto, necesario para comunicar con master(procUnit)
77 objId : identificador del objeto, necesario para comunicar con master(procUnit)
78 """
78 """
79
79
80 self.operations.append(
80 self.operations.append(
81 (operation, conf.type, conf.id, conf.getKwargs()))
81 (operation, conf.type, conf.id, conf.getKwargs()))
82
82
83 if 'plot' in self.name.lower():
83 if 'plot' in self.name.lower():
84 self.plots.append(operation.CODE)
84 self.plots.append(operation.CODE)
85
85
86 def getOperationObj(self, objId):
86 def getOperationObj(self, objId):
87
87
88 if objId not in list(self.operations.keys()):
88 if objId not in list(self.operations.keys()):
89 return None
89 return None
90
90
91 return self.operations[objId]
91 return self.operations[objId]
92
92
93 def operation(self, **kwargs):
93 def operation(self, **kwargs):
94 """
94 """
95 Operacion directa sobre la data (dataOut.data). Es necesario actualizar los valores de los
95 Operacion directa sobre la data (dataOut.data). Es necesario actualizar los valores de los
96 atributos del objeto dataOut
96 atributos del objeto dataOut
97
97
98 Input:
98 Input:
99
99
100 **kwargs : Diccionario de argumentos de la funcion a ejecutar
100 **kwargs : Diccionario de argumentos de la funcion a ejecutar
101 """
101 """
102
102
103 raise NotImplementedError
103 raise NotImplementedError
104
104
105 def setup(self):
105 def setup(self):
106
106
107 raise NotImplementedError
107 raise NotImplementedError
108
108
109 def run(self):
109 def run(self):
110
110
111 raise NotImplementedError
111 raise NotImplementedError
112
112
113 def close(self):
113 def close(self):
114
114
115 return
115 return
116
116
117
117
118 class Operation(object):
118 class Operation(object):
119
119
120 """
120 """
121 Update - Jan 2018 - MULTIPROCESSING
121 Update - Jan 2018 - MULTIPROCESSING
122
122
123 Most of the methods remained the same. The decorator parse the arguments and executed the run() method for each process.
123 Most of the methods remained the same. The decorator parse the arguments and executed the run() method for each process.
124 The constructor doe snot receive any argument, neither the baseclass.
124 The constructor doe snot receive any argument, neither the baseclass.
125
125
126
126
127 Clase base para definir las operaciones adicionales que se pueden agregar a la clase ProcessingUnit
127 Clase base para definir las operaciones adicionales que se pueden agregar a la clase ProcessingUnit
128 y necesiten acumular informacion previa de los datos a procesar. De preferencia usar un buffer de
128 y necesiten acumular informacion previa de los datos a procesar. De preferencia usar un buffer de
129 acumulacion dentro de esta clase
129 acumulacion dentro de esta clase
130
130
131 Ejemplo: Integraciones coherentes, necesita la informacion previa de los n perfiles anteriores (bufffer)
131 Ejemplo: Integraciones coherentes, necesita la informacion previa de los n perfiles anteriores (bufffer)
132
132
133 """
133 """
134 proc_type = 'operation'
134 proc_type = 'operation'
135 __attrs__ = []
135 __attrs__ = []
136
136
137 def __init__(self):
137 def __init__(self):
138
138
139 self.id = None
139 self.id = None
140 self.isConfig = False
140 self.isConfig = False
141
141
142 if not hasattr(self, 'name'):
142 if not hasattr(self, 'name'):
143 self.name = self.__class__.__name__
143 self.name = self.__class__.__name__
144
144
145 def getAllowedArgs(self):
145 def getAllowedArgs(self):
146 if hasattr(self, '__attrs__'):
146 if hasattr(self, '__attrs__'):
147 return self.__attrs__
147 return self.__attrs__
148 else:
148 else:
149 return inspect.getargspec(self.run).args
149 return inspect.getargspec(self.run).args
150
150
151 def setup(self):
151 def setup(self):
152
152
153 self.isConfig = True
153 self.isConfig = True
154
154
155 raise NotImplementedError
155 raise NotImplementedError
156
156
157 def run(self, dataIn, **kwargs):
157 def run(self, dataIn, **kwargs):
158 """
158 """
159 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
159 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
160 atributos del objeto dataIn.
160 atributos del objeto dataIn.
161
161
162 Input:
162 Input:
163
163
164 dataIn : objeto del tipo JROData
164 dataIn : objeto del tipo JROData
165
165
166 Return:
166 Return:
167
167
168 None
168 None
169
169
170 Affected:
170 Affected:
171 __buffer : buffer de recepcion de datos.
171 __buffer : buffer de recepcion de datos.
172
172
173 """
173 """
174 if not self.isConfig:
174 if not self.isConfig:
175 self.setup(**kwargs)
175 self.setup(**kwargs)
176
176
177 raise NotImplementedError
177 raise NotImplementedError
178
178
179 def close(self):
179 def close(self):
180
180
181 return
181 return
182
182
183 class InputQueue(Thread):
183 class InputQueue(Thread):
184
184
185 '''
185 '''
186 Class to hold input data for Proccessing Units and external Operations,
186 Class to hold input data for Proccessing Units and external Operations,
187 '''
187 '''
188
188
189 def __init__(self, project_id, inputId, lock=None):
189 def __init__(self, project_id, inputId, lock=None):
190
190
191 Thread.__init__(self)
191 Thread.__init__(self)
192 self.queue = Queue()
192 self.queue = Queue()
193 self.project_id = project_id
193 self.project_id = project_id
194 self.inputId = inputId
194 self.inputId = inputId
195 self.lock = lock
195 self.lock = lock
196 self.islocked = False
196 self.islocked = False
197 self.size = 0
197 self.size = 0
198
198
199 def run(self):
199 def run(self):
200
200
201 c = zmq.Context()
201 c = zmq.Context()
202 self.receiver = c.socket(zmq.SUB)
202 self.receiver = c.socket(zmq.SUB)
203 self.receiver.connect(
203 self.receiver.connect(
204 'ipc:///tmp/schain/{}_pub'.format(self.project_id))
204 'ipc:///tmp/schain/{}_pub'.format(self.project_id))
205 self.receiver.setsockopt(zmq.SUBSCRIBE, self.inputId.encode())
205 self.receiver.setsockopt(zmq.SUBSCRIBE, self.inputId.encode())
206
206
207 while True:
207 while True:
208 obj = self.receiver.recv_multipart()[1]
208 obj = self.receiver.recv_multipart()[1]
209 self.size += sys.getsizeof(obj)
209 self.size += sys.getsizeof(obj)
210 self.queue.put(obj)
210 self.queue.put(obj)
211
211
212 def get(self):
212 def get(self):
213
213
214 if not self.islocked and self.size/1000000 > 512:
214 if not self.islocked and self.size/1000000 > 512:
215 self.lock.n.value += 1
215 self.lock.n.value += 1
216 self.islocked = True
216 self.islocked = True
217 self.lock.clear()
217 self.lock.clear()
218 elif self.islocked and self.size/1000000 <= 512:
218 elif self.islocked and self.size/1000000 <= 512:
219 self.islocked = False
219 self.islocked = False
220 self.lock.n.value -= 1
220 self.lock.n.value -= 1
221 if self.lock.n.value == 0:
221 if self.lock.n.value == 0:
222 self.lock.set()
222 self.lock.set()
223
223
224 obj = self.queue.get()
224 obj = self.queue.get()
225 self.size -= sys.getsizeof(obj)
225 self.size -= sys.getsizeof(obj)
226 return pickle.loads(obj)
226 return pickle.loads(obj)
227
227
228
228
229 def MPDecorator(BaseClass):
229 def MPDecorator(BaseClass):
230 """
230 """
231 Multiprocessing class decorator
231 Multiprocessing class decorator
232
232
233 This function add multiprocessing features to a BaseClass. Also, it handle
233 This function add multiprocessing features to a BaseClass. Also, it handle
234 the communication beetween processes (readers, procUnits and operations).
234 the communication beetween processes (readers, procUnits and operations).
235 """
235 """
236
236
237 class MPClass(BaseClass, Process):
237 class MPClass(BaseClass, Process):
238
238
239 def __init__(self, *args, **kwargs):
239 def __init__(self, *args, **kwargs):
240 super(MPClass, self).__init__()
240 super(MPClass, self).__init__()
241 Process.__init__(self)
241 Process.__init__(self)
242 self.operationKwargs = {}
242 self.operationKwargs = {}
243 self.args = args
243 self.args = args
244 self.kwargs = kwargs
244 self.kwargs = kwargs
245 self.sender = None
245 self.sender = None
246 self.receiver = None
246 self.receiver = None
247 self.i = 0
247 self.i = 0
248 self.t = time.time()
248 self.t = time.time()
249 self.name = BaseClass.__name__
249 self.name = BaseClass.__name__
250 self.__doc__ = BaseClass.__doc__
250 self.__doc__ = BaseClass.__doc__
251
251
252 if 'plot' in self.name.lower() and not self.name.endswith('_'):
252 if 'plot' in self.name.lower() and not self.name.endswith('_'):
253 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
253 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
254
254
255 self.start_time = time.time()
255 self.start_time = time.time()
256 self.id = args[0]
256 self.id = args[0]
257 self.inputId = args[1]
257 self.inputId = args[1]
258 self.project_id = args[2]
258 self.project_id = args[2]
259 self.err_queue = args[3]
259 self.err_queue = args[3]
260 self.lock = args[4]
260 self.lock = args[4]
261 self.typeProc = args[5]
261 self.typeProc = args[5]
262 self.err_queue.put('#_start_#')
262 self.err_queue.put('#_start_#')
263 if self.inputId is not None:
263 if self.inputId is not None:
264 self.queue = InputQueue(self.project_id, self.inputId, self.lock)
264 self.queue = InputQueue(self.project_id, self.inputId, self.lock)
265
265
266 def subscribe(self):
266 def subscribe(self):
267 '''
267 '''
268 Start the zmq socket receiver and subcribe to input ID.
268 Start the zmq socket receiver and subcribe to input ID.
269 '''
269 '''
270
270
271 self.queue.start()
271 self.queue.start()
272
272
273 def listen(self):
273 def listen(self):
274 '''
274 '''
275 This function waits for objects
275 This function waits for objects
276 '''
276 '''
277
277
278 return self.queue.get()
278 return self.queue.get()
279
279
280 def set_publisher(self):
280 def set_publisher(self):
281 '''
281 '''
282 This function create a zmq socket for publishing objects.
282 This function create a zmq socket for publishing objects.
283 '''
283 '''
284
284
285 time.sleep(0.5)
285 time.sleep(0.5)
286
286
287 c = zmq.Context()
287 c = zmq.Context()
288 self.sender = c.socket(zmq.PUB)
288 self.sender = c.socket(zmq.PUB)
289 self.sender.connect(
289 self.sender.connect(
290 'ipc:///tmp/schain/{}_sub'.format(self.project_id))
290 'ipc:///tmp/schain/{}_sub'.format(self.project_id))
291
291
292 def publish(self, data, id):
292 def publish(self, data, id):
293 '''
293 '''
294 This function publish an object, to an specific topic.
294 This function publish an object, to an specific topic.
295 It blocks publishing when receiver queue is full to avoid data loss
295 It blocks publishing when receiver queue is full to avoid data loss
296 '''
296 '''
297
297
298 if self.inputId is None:
298 if self.inputId is None:
299 self.lock.wait()
299 self.lock.wait()
300 self.sender.send_multipart([str(id).encode(), pickle.dumps(data)])
300 self.sender.send_multipart([str(id).encode(), pickle.dumps(data)])
301
302 def runReader(self):
301 def runReader(self):
303 '''
302 '''
304 Run fuction for read units
303 Run fuction for read units
305 '''
304 '''
306 while True:
305 while True:
307
306
308 try:
307 try:
309 BaseClass.run(self, **self.kwargs)
308 BaseClass.run(self, **self.kwargs)
310 except:
309 except:
311 err = traceback.format_exc()
310 err = traceback.format_exc()
312 if 'No more files' in err:
311 if 'No more files' in err:
313 log.warning('No more files to read', self.name)
312 log.warning('No more files to read', self.name)
314 else:
313 else:
315 self.err_queue.put('{}|{}'.format(self.name, err))
314 self.err_queue.put('{}|{}'.format(self.name, err))
316 self.dataOut.error = True
315 self.dataOut.error = True
317
316
318 for op, optype, opId, kwargs in self.operations:
317 for op, optype, opId, kwargs in self.operations:
319 if optype == 'self' and not self.dataOut.flagNoData:
318 if optype == 'self' and not self.dataOut.flagNoData:
320 op(**kwargs)
319 op(**kwargs)
321 elif optype == 'other' and not self.dataOut.flagNoData:
320 elif optype == 'other' and not self.dataOut.flagNoData:
322 self.dataOut = op.run(self.dataOut, **self.kwargs)
321 self.dataOut = op.run(self.dataOut, **self.kwargs)
323 elif optype == 'external':
322 elif optype == 'external':
324 self.publish(self.dataOut, opId)
323 self.publish(self.dataOut, opId)
325
324
326 if self.dataOut.flagNoData and not self.dataOut.error:
325 if self.dataOut.flagNoData and not self.dataOut.error:
327 continue
326 continue
328
327
329 self.publish(self.dataOut, self.id)
328 self.publish(self.dataOut, self.id)
330
331 if self.dataOut.error:
329 if self.dataOut.error:
332 break
330 break
333
331
334 time.sleep(0.5)
332 time.sleep(0.5)
335
333
336 def runProc(self):
334 def runProc(self):
337 '''
335 '''
338 Run function for proccessing units
336 Run function for proccessing units
339 '''
337 '''
340
338
341 while True:
339 while True:
342 self.dataIn = self.listen()
340 self.dataIn = self.listen()
343
341
344 if self.dataIn.flagNoData and self.dataIn.error is None:
342 if self.dataIn.flagNoData and self.dataIn.error is None:
345 continue
343 continue
346 elif not self.dataIn.error:
344 elif not self.dataIn.error:
347 try:
345 try:
348 BaseClass.run(self, **self.kwargs)
346 BaseClass.run(self, **self.kwargs)
349 except:
347 except:
350 self.err_queue.put('{}|{}'.format(self.name, traceback.format_exc()))
348 self.err_queue.put('{}|{}'.format(self.name, traceback.format_exc()))
351 self.dataOut.error = True
349 self.dataOut.error = True
352 elif self.dataIn.error:
350 elif self.dataIn.error:
353 self.dataOut.error = self.dataIn.error
351 self.dataOut.error = self.dataIn.error
354 self.dataOut.flagNoData = True
352 self.dataOut.flagNoData = True
355
353
356 for op, optype, opId, kwargs in self.operations:
354 for op, optype, opId, kwargs in self.operations:
357 if optype == 'self' and not self.dataOut.flagNoData:
355 if optype == 'self' and not self.dataOut.flagNoData:
358 op(**kwargs)
356 op(**kwargs)
359 elif optype == 'other' and not self.dataOut.flagNoData:
357 elif optype == 'other' and not self.dataOut.flagNoData:
360 self.dataOut = op.run(self.dataOut, **kwargs)
358 self.dataOut = op.run(self.dataOut, **kwargs)
361 elif optype == 'external' and not self.dataOut.flagNoData:
359 elif optype == 'external' and not self.dataOut.flagNoData:
362 self.publish(self.dataOut, opId)
360 self.publish(self.dataOut, opId)
363
361
364 self.publish(self.dataOut, self.id)
362 self.publish(self.dataOut, self.id)
365 for op, optype, opId, kwargs in self.operations:
363 for op, optype, opId, kwargs in self.operations:
366 if optype == 'external' and self.dataOut.error:
364 if optype == 'external' and self.dataOut.error:
367 self.publish(self.dataOut, opId)
365 self.publish(self.dataOut, opId)
368
366
369 if self.dataOut.error:
367 if self.dataOut.error:
370 break
368 break
371
369
372 time.sleep(0.5)
370 time.sleep(0.5)
373
371
374 def runOp(self):
372 def runOp(self):
375 '''
373 '''
376 Run function for external operations (this operations just receive data
374 Run function for external operations (this operations just receive data
377 ex: plots, writers, publishers)
375 ex: plots, writers, publishers)
378 '''
376 '''
379
377
380 while True:
378 while True:
381
379
382 dataOut = self.listen()
380 dataOut = self.listen()
383
381
384 if not dataOut.error:
382 if not dataOut.error:
385 try:
383 try:
386 BaseClass.run(self, dataOut, **self.kwargs)
384 BaseClass.run(self, dataOut, **self.kwargs)
387 except:
385 except:
388 self.err_queue.put('{}|{}'.format(self.name, traceback.format_exc()))
386 self.err_queue.put('{}|{}'.format(self.name, traceback.format_exc()))
389 dataOut.error = True
387 dataOut.error = True
390 else:
388 else:
391 break
389 break
392
390
393 def run(self):
391 def run(self):
394 if self.typeProc is "ProcUnit":
392 if self.typeProc is "ProcUnit":
395
393
396 if self.inputId is not None:
394 if self.inputId is not None:
397 self.subscribe()
395 self.subscribe()
398
396
399 self.set_publisher()
397 self.set_publisher()
400
398
401 if 'Reader' not in BaseClass.__name__:
399 if 'Reader' not in BaseClass.__name__:
402 self.runProc()
400 self.runProc()
403 else:
401 else:
404 self.runReader()
402 self.runReader()
405
406 elif self.typeProc is "Operation":
403 elif self.typeProc is "Operation":
407
404
408 self.subscribe()
405 self.subscribe()
409 self.runOp()
406 self.runOp()
410
407
411 else:
408 else:
412 raise ValueError("Unknown type")
409 raise ValueError("Unknown type")
413
410
414 self.close()
411 self.close()
415
412
416 def close(self):
413 def close(self):
417
414
418 BaseClass.close(self)
415 BaseClass.close(self)
419 self.err_queue.put('#_end_#')
416 self.err_queue.put('#_end_#')
420
417
421 if self.sender:
418 if self.sender:
422 self.sender.close()
419 self.sender.close()
423
420
424 if self.receiver:
421 if self.receiver:
425 self.receiver.close()
422 self.receiver.close()
426
423
427 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
424 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
428
425
429 return MPClass
426 return MPClass
@@ -1,3857 +1,3857
1 import numpy
1 import numpy
2 import math
2 import math
3 from scipy import optimize, interpolate, signal, stats, ndimage
3 from scipy import optimize, interpolate, signal, stats, ndimage
4 import scipy
4 import scipy
5 import re
5 import re
6 import datetime
6 import datetime
7 import copy
7 import copy
8 import sys
8 import sys
9 import importlib
9 import importlib
10 import itertools
10 import itertools
11 from multiprocessing import Pool, TimeoutError
11 from multiprocessing import Pool, TimeoutError
12 from multiprocessing.pool import ThreadPool
12 from multiprocessing.pool import ThreadPool
13 import time
13 import time
14
14
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 from scipy import asarray as ar,exp
18 from scipy import asarray as ar,exp
19 from scipy.optimize import curve_fit
19 from scipy.optimize import curve_fit
20 from schainpy.utils import log
20 from schainpy.utils import log
21 import warnings
21 import warnings
22 from numpy import NaN
22 from numpy import NaN
23 from scipy.optimize.optimize import OptimizeWarning
23 from scipy.optimize.optimize import OptimizeWarning
24 warnings.filterwarnings('ignore')
24 warnings.filterwarnings('ignore')
25
25
26
26
27 SPEED_OF_LIGHT = 299792458
27 SPEED_OF_LIGHT = 299792458
28
28
29
29
30 '''solving pickling issue'''
30 '''solving pickling issue'''
31
31
32 def _pickle_method(method):
32 def _pickle_method(method):
33 func_name = method.__func__.__name__
33 func_name = method.__func__.__name__
34 obj = method.__self__
34 obj = method.__self__
35 cls = method.__self__.__class__
35 cls = method.__self__.__class__
36 return _unpickle_method, (func_name, obj, cls)
36 return _unpickle_method, (func_name, obj, cls)
37
37
38 def _unpickle_method(func_name, obj, cls):
38 def _unpickle_method(func_name, obj, cls):
39 for cls in cls.mro():
39 for cls in cls.mro():
40 try:
40 try:
41 func = cls.__dict__[func_name]
41 func = cls.__dict__[func_name]
42 except KeyError:
42 except KeyError:
43 pass
43 pass
44 else:
44 else:
45 break
45 break
46 return func.__get__(obj, cls)
46 return func.__get__(obj, cls)
47
47
48 @MPDecorator
48 @MPDecorator
49 class ParametersProc(ProcessingUnit):
49 class ParametersProc(ProcessingUnit):
50
50
51 METHODS = {}
51 METHODS = {}
52 nSeconds = None
52 nSeconds = None
53
53
54 def __init__(self):
54 def __init__(self):
55 ProcessingUnit.__init__(self)
55 ProcessingUnit.__init__(self)
56
56
57 # self.objectDict = {}
57 # self.objectDict = {}
58 self.buffer = None
58 self.buffer = None
59 self.firstdatatime = None
59 self.firstdatatime = None
60 self.profIndex = 0
60 self.profIndex = 0
61 self.dataOut = Parameters()
61 self.dataOut = Parameters()
62 self.setupReq = False #Agregar a todas las unidades de proc
62 self.setupReq = False #Agregar a todas las unidades de proc
63
63
64 def __updateObjFromInput(self):
64 def __updateObjFromInput(self):
65
65
66 self.dataOut.inputUnit = self.dataIn.type
66 self.dataOut.inputUnit = self.dataIn.type
67
67
68 self.dataOut.timeZone = self.dataIn.timeZone
68 self.dataOut.timeZone = self.dataIn.timeZone
69 self.dataOut.dstFlag = self.dataIn.dstFlag
69 self.dataOut.dstFlag = self.dataIn.dstFlag
70 self.dataOut.errorCount = self.dataIn.errorCount
70 self.dataOut.errorCount = self.dataIn.errorCount
71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
72
72
73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
75 self.dataOut.channelList = self.dataIn.channelList
75 self.dataOut.channelList = self.dataIn.channelList
76 self.dataOut.heightList = self.dataIn.heightList
76 self.dataOut.heightList = self.dataIn.heightList
77 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
77 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
78 # self.dataOut.nHeights = self.dataIn.nHeights
78 # self.dataOut.nHeights = self.dataIn.nHeights
79 # self.dataOut.nChannels = self.dataIn.nChannels
79 # self.dataOut.nChannels = self.dataIn.nChannels
80 self.dataOut.nBaud = self.dataIn.nBaud
80 self.dataOut.nBaud = self.dataIn.nBaud
81 self.dataOut.nCode = self.dataIn.nCode
81 self.dataOut.nCode = self.dataIn.nCode
82 self.dataOut.code = self.dataIn.code
82 self.dataOut.code = self.dataIn.code
83 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
83 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
84 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
84 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
85 # self.dataOut.utctime = self.firstdatatime
85 # self.dataOut.utctime = self.firstdatatime
86 self.dataOut.utctime = self.dataIn.utctime
86 self.dataOut.utctime = self.dataIn.utctime
87 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
87 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
88 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
88 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
89 self.dataOut.nCohInt = self.dataIn.nCohInt
89 self.dataOut.nCohInt = self.dataIn.nCohInt
90 # self.dataOut.nIncohInt = 1
90 # self.dataOut.nIncohInt = 1
91 self.dataOut.ippSeconds = self.dataIn.ippSeconds
91 self.dataOut.ippSeconds = self.dataIn.ippSeconds
92 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
92 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
93 self.dataOut.timeInterval1 = self.dataIn.timeInterval
93 self.dataOut.timeInterval1 = self.dataIn.timeInterval
94 self.dataOut.heightList = self.dataIn.getHeiRange()
94 self.dataOut.heightList = self.dataIn.getHeiRange()
95 self.dataOut.frequency = self.dataIn.frequency
95 self.dataOut.frequency = self.dataIn.frequency
96 # self.dataOut.noise = self.dataIn.noise
96 # self.dataOut.noise = self.dataIn.noise
97
97
98 def run(self):
98 def run(self):
99
99
100
100
101
101
102 #---------------------- Voltage Data ---------------------------
102 #---------------------- Voltage Data ---------------------------
103
103
104 if self.dataIn.type == "Voltage":
104 if self.dataIn.type == "Voltage":
105
105
106 self.__updateObjFromInput()
106 self.__updateObjFromInput()
107 self.dataOut.data_pre = self.dataIn.data.copy()
107 self.dataOut.data_pre = self.dataIn.data.copy()
108 self.dataOut.flagNoData = False
108 self.dataOut.flagNoData = False
109 self.dataOut.utctimeInit = self.dataIn.utctime
109 self.dataOut.utctimeInit = self.dataIn.utctime
110 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
110 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
111 return
111 return
112
112
113 #---------------------- Spectra Data ---------------------------
113 #---------------------- Spectra Data ---------------------------
114
114
115 if self.dataIn.type == "Spectra":
115 if self.dataIn.type == "Spectra":
116
116
117 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
117 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
118 self.dataOut.data_spc = self.dataIn.data_spc
118 self.dataOut.data_spc = self.dataIn.data_spc
119 self.dataOut.data_cspc = self.dataIn.data_cspc
119 self.dataOut.data_cspc = self.dataIn.data_cspc
120 self.dataOut.nProfiles = self.dataIn.nProfiles
120 self.dataOut.nProfiles = self.dataIn.nProfiles
121 self.dataOut.nIncohInt = self.dataIn.nIncohInt
121 self.dataOut.nIncohInt = self.dataIn.nIncohInt
122 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
122 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
123 self.dataOut.ippFactor = self.dataIn.ippFactor
123 self.dataOut.ippFactor = self.dataIn.ippFactor
124 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
124 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
125 self.dataOut.spc_noise = self.dataIn.getNoise()
125 self.dataOut.spc_noise = self.dataIn.getNoise()
126 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
126 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
127 # self.dataOut.normFactor = self.dataIn.normFactor
127 # self.dataOut.normFactor = self.dataIn.normFactor
128 self.dataOut.pairsList = self.dataIn.pairsList
128 self.dataOut.pairsList = self.dataIn.pairsList
129 self.dataOut.groupList = self.dataIn.pairsList
129 self.dataOut.groupList = self.dataIn.pairsList
130 self.dataOut.flagNoData = False
130 self.dataOut.flagNoData = False
131
131
132 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
132 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
133 self.dataOut.ChanDist = self.dataIn.ChanDist
133 self.dataOut.ChanDist = self.dataIn.ChanDist
134 else: self.dataOut.ChanDist = None
134 else: self.dataOut.ChanDist = None
135
135
136 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
136 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
137 # self.dataOut.VelRange = self.dataIn.VelRange
137 # self.dataOut.VelRange = self.dataIn.VelRange
138 #else: self.dataOut.VelRange = None
138 #else: self.dataOut.VelRange = None
139
139
140 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
140 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
141 self.dataOut.RadarConst = self.dataIn.RadarConst
141 self.dataOut.RadarConst = self.dataIn.RadarConst
142
142
143 if hasattr(self.dataIn, 'NPW'): #NPW
143 if hasattr(self.dataIn, 'NPW'): #NPW
144 self.dataOut.NPW = self.dataIn.NPW
144 self.dataOut.NPW = self.dataIn.NPW
145
145
146 if hasattr(self.dataIn, 'COFA'): #COFA
146 if hasattr(self.dataIn, 'COFA'): #COFA
147 self.dataOut.COFA = self.dataIn.COFA
147 self.dataOut.COFA = self.dataIn.COFA
148
148
149
149
150
150
151 #---------------------- Correlation Data ---------------------------
151 #---------------------- Correlation Data ---------------------------
152
152
153 if self.dataIn.type == "Correlation":
153 if self.dataIn.type == "Correlation":
154 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
154 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
155
155
156 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
156 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
157 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
157 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
158 self.dataOut.groupList = (acf_pairs, ccf_pairs)
158 self.dataOut.groupList = (acf_pairs, ccf_pairs)
159
159
160 self.dataOut.abscissaList = self.dataIn.lagRange
160 self.dataOut.abscissaList = self.dataIn.lagRange
161 self.dataOut.noise = self.dataIn.noise
161 self.dataOut.noise = self.dataIn.noise
162 self.dataOut.data_SNR = self.dataIn.SNR
162 self.dataOut.data_SNR = self.dataIn.SNR
163 self.dataOut.flagNoData = False
163 self.dataOut.flagNoData = False
164 self.dataOut.nAvg = self.dataIn.nAvg
164 self.dataOut.nAvg = self.dataIn.nAvg
165
165
166 #---------------------- Parameters Data ---------------------------
166 #---------------------- Parameters Data ---------------------------
167
167
168 if self.dataIn.type == "Parameters":
168 if self.dataIn.type == "Parameters":
169 self.dataOut.copy(self.dataIn)
169 self.dataOut.copy(self.dataIn)
170 self.dataOut.flagNoData = False
170 self.dataOut.flagNoData = False
171
171
172 return True
172 return True
173
173
174 self.__updateObjFromInput()
174 self.__updateObjFromInput()
175 self.dataOut.utctimeInit = self.dataIn.utctime
175 self.dataOut.utctimeInit = self.dataIn.utctime
176 self.dataOut.paramInterval = self.dataIn.timeInterval
176 self.dataOut.paramInterval = self.dataIn.timeInterval
177
177
178
178 return
179 return
179
180
180
181
181 def target(tups):
182 def target(tups):
182
183
183 obj, args = tups
184 obj, args = tups
184
185
185 return obj.FitGau(args)
186 return obj.FitGau(args)
186
187
187
188
188 class SpectralFilters(Operation):
189 class SpectralFilters(Operation):
189
190
190 '''This class allows the Rainfall / Wind Selection for CLAIRE RADAR
191 '''This class allows the Rainfall / Wind Selection for CLAIRE RADAR
191
192
192 LimitR : It is the limit in m/s of Rainfall
193 LimitR : It is the limit in m/s of Rainfall
193 LimitW : It is the limit in m/s for Winds
194 LimitW : It is the limit in m/s for Winds
194
195
195 Input:
196 Input:
196
197
197 self.dataOut.data_pre : SPC and CSPC
198 self.dataOut.data_pre : SPC and CSPC
198 self.dataOut.spc_range : To select wind and rainfall velocities
199 self.dataOut.spc_range : To select wind and rainfall velocities
199
200
200 Affected:
201 Affected:
201
202
202 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
203 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
203 self.dataOut.spcparam_range : Used in SpcParamPlot
204 self.dataOut.spcparam_range : Used in SpcParamPlot
204 self.dataOut.SPCparam : Used in PrecipitationProc
205 self.dataOut.SPCparam : Used in PrecipitationProc
205
206
206
207
207 '''
208 '''
208
209
209 def __init__(self):
210 def __init__(self):
210 Operation.__init__(self)
211 Operation.__init__(self)
211 self.i=0
212 self.i=0
212
213
213 def run(self, dataOut, PositiveLimit=1.5, NegativeLimit=2.5):
214 def run(self, dataOut, PositiveLimit=1.5, NegativeLimit=2.5):
214
215
215
216
216 #Limite de vientos
217 #Limite de vientos
217 LimitR = PositiveLimit
218 LimitR = PositiveLimit
218 LimitN = NegativeLimit
219 LimitN = NegativeLimit
219
220
220 self.spc = dataOut.data_pre[0].copy()
221 self.spc = dataOut.data_pre[0].copy()
221 self.cspc = dataOut.data_pre[1].copy()
222 self.cspc = dataOut.data_pre[1].copy()
222
223
223 self.Num_Hei = self.spc.shape[2]
224 self.Num_Hei = self.spc.shape[2]
224 self.Num_Bin = self.spc.shape[1]
225 self.Num_Bin = self.spc.shape[1]
225 self.Num_Chn = self.spc.shape[0]
226 self.Num_Chn = self.spc.shape[0]
226
227
227 VelRange = dataOut.spc_range[2]
228 VelRange = dataOut.spc_range[2]
228 TimeRange = dataOut.spc_range[1]
229 TimeRange = dataOut.spc_range[1]
229 FrecRange = dataOut.spc_range[0]
230 FrecRange = dataOut.spc_range[0]
230
231
231 Vmax= 2*numpy.max(dataOut.spc_range[2])
232 Vmax= 2*numpy.max(dataOut.spc_range[2])
232 Tmax= 2*numpy.max(dataOut.spc_range[1])
233 Tmax= 2*numpy.max(dataOut.spc_range[1])
233 Fmax= 2*numpy.max(dataOut.spc_range[0])
234 Fmax= 2*numpy.max(dataOut.spc_range[0])
234
235
235 Breaker1R=VelRange[numpy.abs(VelRange-(-LimitN)).argmin()]
236 Breaker1R=VelRange[numpy.abs(VelRange-(-LimitN)).argmin()]
236 Breaker1R=numpy.where(VelRange == Breaker1R)
237 Breaker1R=numpy.where(VelRange == Breaker1R)
237
238
238 Delta = self.Num_Bin/2 - Breaker1R[0]
239 Delta = self.Num_Bin/2 - Breaker1R[0]
239
240
240
241
241 '''Reacomodando SPCrange'''
242 '''Reacomodando SPCrange'''
242
243
243 VelRange=numpy.roll(VelRange,-(int(self.Num_Bin/2)) ,axis=0)
244 VelRange=numpy.roll(VelRange,-(int(self.Num_Bin/2)) ,axis=0)
244
245
245 VelRange[-(int(self.Num_Bin/2)):]+= Vmax
246 VelRange[-(int(self.Num_Bin/2)):]+= Vmax
246
247
247 FrecRange=numpy.roll(FrecRange,-(int(self.Num_Bin/2)),axis=0)
248 FrecRange=numpy.roll(FrecRange,-(int(self.Num_Bin/2)),axis=0)
248
249
249 FrecRange[-(int(self.Num_Bin/2)):]+= Fmax
250 FrecRange[-(int(self.Num_Bin/2)):]+= Fmax
250
251
251 TimeRange=numpy.roll(TimeRange,-(int(self.Num_Bin/2)),axis=0)
252 TimeRange=numpy.roll(TimeRange,-(int(self.Num_Bin/2)),axis=0)
252
253
253 TimeRange[-(int(self.Num_Bin/2)):]+= Tmax
254 TimeRange[-(int(self.Num_Bin/2)):]+= Tmax
254
255
255 ''' ------------------ '''
256 ''' ------------------ '''
256
257
257 Breaker2R=VelRange[numpy.abs(VelRange-(LimitR)).argmin()]
258 Breaker2R=VelRange[numpy.abs(VelRange-(LimitR)).argmin()]
258 Breaker2R=numpy.where(VelRange == Breaker2R)
259 Breaker2R=numpy.where(VelRange == Breaker2R)
259
260
260
261
261 SPCroll = numpy.roll(self.spc,-(int(self.Num_Bin/2)) ,axis=1)
262 SPCroll = numpy.roll(self.spc,-(int(self.Num_Bin/2)) ,axis=1)
262
263
263 SPCcut = SPCroll.copy()
264 SPCcut = SPCroll.copy()
264 for i in range(self.Num_Chn):
265 for i in range(self.Num_Chn):
265
266
266 SPCcut[i,0:int(Breaker2R[0]),:] = dataOut.noise[i]
267 SPCcut[i,0:int(Breaker2R[0]),:] = dataOut.noise[i]
267 SPCcut[i,-int(Delta):,:] = dataOut.noise[i]
268 SPCcut[i,-int(Delta):,:] = dataOut.noise[i]
268
269
269 SPCcut[i]=SPCcut[i]- dataOut.noise[i]
270 SPCcut[i]=SPCcut[i]- dataOut.noise[i]
270 SPCcut[ numpy.where( SPCcut<0 ) ] = 1e-20
271 SPCcut[ numpy.where( SPCcut<0 ) ] = 1e-20
271
272
272 SPCroll[i]=SPCroll[i]-dataOut.noise[i]
273 SPCroll[i]=SPCroll[i]-dataOut.noise[i]
273 SPCroll[ numpy.where( SPCroll<0 ) ] = 1e-20
274 SPCroll[ numpy.where( SPCroll<0 ) ] = 1e-20
274
275
275 SPC_ch1 = SPCroll
276 SPC_ch1 = SPCroll
276
277
277 SPC_ch2 = SPCcut
278 SPC_ch2 = SPCcut
278
279
279 SPCparam = (SPC_ch1, SPC_ch2, self.spc)
280 SPCparam = (SPC_ch1, SPC_ch2, self.spc)
280 dataOut.SPCparam = numpy.asarray(SPCparam)
281 dataOut.SPCparam = numpy.asarray(SPCparam)
281
282
282
283
283 dataOut.spcparam_range=numpy.zeros([self.Num_Chn,self.Num_Bin+1])
284 dataOut.spcparam_range=numpy.zeros([self.Num_Chn,self.Num_Bin+1])
284
285
285 dataOut.spcparam_range[2]=VelRange
286 dataOut.spcparam_range[2]=VelRange
286 dataOut.spcparam_range[1]=TimeRange
287 dataOut.spcparam_range[1]=TimeRange
287 dataOut.spcparam_range[0]=FrecRange
288 dataOut.spcparam_range[0]=FrecRange
288 return dataOut
289 return dataOut
289
290
290 class GaussianFit(Operation):
291 class GaussianFit(Operation):
291
292
292 '''
293 '''
293 Function that fit of one and two generalized gaussians (gg) based
294 Function that fit of one and two generalized gaussians (gg) based
294 on the PSD shape across an "power band" identified from a cumsum of
295 on the PSD shape across an "power band" identified from a cumsum of
295 the measured spectrum - noise.
296 the measured spectrum - noise.
296
297
297 Input:
298 Input:
298 self.dataOut.data_pre : SelfSpectra
299 self.dataOut.data_pre : SelfSpectra
299
300
300 Output:
301 Output:
301 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
302 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
302
303
303 '''
304 '''
304 def __init__(self):
305 def __init__(self):
305 Operation.__init__(self)
306 Operation.__init__(self)
306 self.i=0
307 self.i=0
307
308
308
309
309 def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
310 def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
310 """This routine will find a couple of generalized Gaussians to a power spectrum
311 """This routine will find a couple of generalized Gaussians to a power spectrum
311 input: spc
312 input: spc
312 output:
313 output:
313 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
314 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
314 """
315 """
315
316
316 self.spc = dataOut.data_pre[0].copy()
317 self.spc = dataOut.data_pre[0].copy()
317 self.Num_Hei = self.spc.shape[2]
318 self.Num_Hei = self.spc.shape[2]
318 self.Num_Bin = self.spc.shape[1]
319 self.Num_Bin = self.spc.shape[1]
319 self.Num_Chn = self.spc.shape[0]
320 self.Num_Chn = self.spc.shape[0]
320 Vrange = dataOut.abscissaList
321 Vrange = dataOut.abscissaList
321
322
322 GauSPC = numpy.empty([self.Num_Chn,self.Num_Bin,self.Num_Hei])
323 GauSPC = numpy.empty([self.Num_Chn,self.Num_Bin,self.Num_Hei])
323 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
324 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
324 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
325 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
325 SPC_ch1[:] = numpy.NaN
326 SPC_ch1[:] = numpy.NaN
326 SPC_ch2[:] = numpy.NaN
327 SPC_ch2[:] = numpy.NaN
327
328
328
329
329 start_time = time.time()
330 start_time = time.time()
330
331
331 noise_ = dataOut.spc_noise[0].copy()
332 noise_ = dataOut.spc_noise[0].copy()
332
333
333
334
334 pool = Pool(processes=self.Num_Chn)
335 pool = Pool(processes=self.Num_Chn)
335 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
336 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
336 objs = [self for __ in range(self.Num_Chn)]
337 objs = [self for __ in range(self.Num_Chn)]
337 attrs = list(zip(objs, args))
338 attrs = list(zip(objs, args))
338 gauSPC = pool.map(target, attrs)
339 gauSPC = pool.map(target, attrs)
339 dataOut.SPCparam = numpy.asarray(SPCparam)
340 dataOut.SPCparam = numpy.asarray(SPCparam)
340
341
341 ''' Parameters:
342 ''' Parameters:
342 1. Amplitude
343 1. Amplitude
343 2. Shift
344 2. Shift
344 3. Width
345 3. Width
345 4. Power
346 4. Power
346 '''
347 '''
347
348
348 def FitGau(self, X):
349 def FitGau(self, X):
349
350
350 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
351 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
351
352
352 SPCparam = []
353 SPCparam = []
353 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
354 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
354 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
355 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
355 SPC_ch1[:] = 0#numpy.NaN
356 SPC_ch1[:] = 0#numpy.NaN
356 SPC_ch2[:] = 0#numpy.NaN
357 SPC_ch2[:] = 0#numpy.NaN
357
358
358
359
359
360
360 for ht in range(self.Num_Hei):
361 for ht in range(self.Num_Hei):
361
362
362
363
363 spc = numpy.asarray(self.spc)[ch,:,ht]
364 spc = numpy.asarray(self.spc)[ch,:,ht]
364
365
365 #############################################
366 #############################################
366 # normalizing spc and noise
367 # normalizing spc and noise
367 # This part differs from gg1
368 # This part differs from gg1
368 spc_norm_max = max(spc)
369 spc_norm_max = max(spc)
369 #spc = spc / spc_norm_max
370 #spc = spc / spc_norm_max
370 pnoise = pnoise #/ spc_norm_max
371 pnoise = pnoise #/ spc_norm_max
371 #############################################
372 #############################################
372
373
373 fatspectra=1.0
374 fatspectra=1.0
374
375
375 wnoise = noise_ #/ spc_norm_max
376 wnoise = noise_ #/ spc_norm_max
376 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
377 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
377 #if wnoise>1.1*pnoise: # to be tested later
378 #if wnoise>1.1*pnoise: # to be tested later
378 # wnoise=pnoise
379 # wnoise=pnoise
379 noisebl=wnoise*0.9;
380 noisebl=wnoise*0.9;
380 noisebh=wnoise*1.1
381 noisebh=wnoise*1.1
381 spc=spc-wnoise
382 spc=spc-wnoise
382
383
383 minx=numpy.argmin(spc)
384 minx=numpy.argmin(spc)
384 #spcs=spc.copy()
385 #spcs=spc.copy()
385 spcs=numpy.roll(spc,-minx)
386 spcs=numpy.roll(spc,-minx)
386 cum=numpy.cumsum(spcs)
387 cum=numpy.cumsum(spcs)
387 tot_noise=wnoise * self.Num_Bin #64;
388 tot_noise=wnoise * self.Num_Bin #64;
388
389
389 snr = sum(spcs)/tot_noise
390 snr = sum(spcs)/tot_noise
390 snrdB=10.*numpy.log10(snr)
391 snrdB=10.*numpy.log10(snr)
391
392
392 if snrdB < SNRlimit :
393 if snrdB < SNRlimit :
393 snr = numpy.NaN
394 snr = numpy.NaN
394 SPC_ch1[:,ht] = 0#numpy.NaN
395 SPC_ch1[:,ht] = 0#numpy.NaN
395 SPC_ch1[:,ht] = 0#numpy.NaN
396 SPC_ch1[:,ht] = 0#numpy.NaN
396 SPCparam = (SPC_ch1,SPC_ch2)
397 SPCparam = (SPC_ch1,SPC_ch2)
397 continue
398 continue
398
399
399
400
400 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
401 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
401 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
402 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
402
403
403 cummax=max(cum);
404 cummax=max(cum);
404 epsi=0.08*fatspectra # cumsum to narrow down the energy region
405 epsi=0.08*fatspectra # cumsum to narrow down the energy region
405 cumlo=cummax*epsi;
406 cumlo=cummax*epsi;
406 cumhi=cummax*(1-epsi)
407 cumhi=cummax*(1-epsi)
407 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
408 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
408
409
409
410
410 if len(powerindex) < 1:# case for powerindex 0
411 if len(powerindex) < 1:# case for powerindex 0
411 continue
412 continue
412 powerlo=powerindex[0]
413 powerlo=powerindex[0]
413 powerhi=powerindex[-1]
414 powerhi=powerindex[-1]
414 powerwidth=powerhi-powerlo
415 powerwidth=powerhi-powerlo
415
416
416 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
417 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
417 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
418 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
418 midpeak=(firstpeak+secondpeak)/2.
419 midpeak=(firstpeak+secondpeak)/2.
419 firstamp=spcs[int(firstpeak)]
420 firstamp=spcs[int(firstpeak)]
420 secondamp=spcs[int(secondpeak)]
421 secondamp=spcs[int(secondpeak)]
421 midamp=spcs[int(midpeak)]
422 midamp=spcs[int(midpeak)]
422
423
423 x=numpy.arange( self.Num_Bin )
424 x=numpy.arange( self.Num_Bin )
424 y_data=spc+wnoise
425 y_data=spc+wnoise
425
426
426 ''' single Gaussian '''
427 ''' single Gaussian '''
427 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
428 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
428 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
429 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
429 power0=2.
430 power0=2.
430 amplitude0=midamp
431 amplitude0=midamp
431 state0=[shift0,width0,amplitude0,power0,wnoise]
432 state0=[shift0,width0,amplitude0,power0,wnoise]
432 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
433 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
433 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
434 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
434
435
435 chiSq1=lsq1[1];
436 chiSq1=lsq1[1];
436
437
437
438
438 if fatspectra<1.0 and powerwidth<4:
439 if fatspectra<1.0 and powerwidth<4:
439 choice=0
440 choice=0
440 Amplitude0=lsq1[0][2]
441 Amplitude0=lsq1[0][2]
441 shift0=lsq1[0][0]
442 shift0=lsq1[0][0]
442 width0=lsq1[0][1]
443 width0=lsq1[0][1]
443 p0=lsq1[0][3]
444 p0=lsq1[0][3]
444 Amplitude1=0.
445 Amplitude1=0.
445 shift1=0.
446 shift1=0.
446 width1=0.
447 width1=0.
447 p1=0.
448 p1=0.
448 noise=lsq1[0][4]
449 noise=lsq1[0][4]
449 #return (numpy.array([shift0,width0,Amplitude0,p0]),
450 #return (numpy.array([shift0,width0,Amplitude0,p0]),
450 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
451 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
451
452
452 ''' two gaussians '''
453 ''' two gaussians '''
453 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
454 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
454 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
455 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
455 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
456 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
456 width0=powerwidth/6.;
457 width0=powerwidth/6.;
457 width1=width0
458 width1=width0
458 power0=2.;
459 power0=2.;
459 power1=power0
460 power1=power0
460 amplitude0=firstamp;
461 amplitude0=firstamp;
461 amplitude1=secondamp
462 amplitude1=secondamp
462 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
463 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
463 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
464 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
464 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
465 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
465 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
466 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
466
467
467 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
468 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
468
469
469
470
470 chiSq2=lsq2[1];
471 chiSq2=lsq2[1];
471
472
472
473
473
474
474 oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
475 oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
475
476
476 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
477 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
477 if oneG:
478 if oneG:
478 choice=0
479 choice=0
479 else:
480 else:
480 w1=lsq2[0][1]; w2=lsq2[0][5]
481 w1=lsq2[0][1]; w2=lsq2[0][5]
481 a1=lsq2[0][2]; a2=lsq2[0][6]
482 a1=lsq2[0][2]; a2=lsq2[0][6]
482 p1=lsq2[0][3]; p2=lsq2[0][7]
483 p1=lsq2[0][3]; p2=lsq2[0][7]
483 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
484 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
484 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
485 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
485 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
486 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
486
487
487 if gp1>gp2:
488 if gp1>gp2:
488 if a1>0.7*a2:
489 if a1>0.7*a2:
489 choice=1
490 choice=1
490 else:
491 else:
491 choice=2
492 choice=2
492 elif gp2>gp1:
493 elif gp2>gp1:
493 if a2>0.7*a1:
494 if a2>0.7*a1:
494 choice=2
495 choice=2
495 else:
496 else:
496 choice=1
497 choice=1
497 else:
498 else:
498 choice=numpy.argmax([a1,a2])+1
499 choice=numpy.argmax([a1,a2])+1
499 #else:
500 #else:
500 #choice=argmin([std2a,std2b])+1
501 #choice=argmin([std2a,std2b])+1
501
502
502 else: # with low SNR go to the most energetic peak
503 else: # with low SNR go to the most energetic peak
503 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
504 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
504
505
505
506
506 shift0=lsq2[0][0];
507 shift0=lsq2[0][0];
507 vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
508 vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
508 shift1=lsq2[0][4];
509 shift1=lsq2[0][4];
509 vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
510 vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
510
511
511 max_vel = 1.0
512 max_vel = 1.0
512
513
513 #first peak will be 0, second peak will be 1
514 #first peak will be 0, second peak will be 1
514 if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range
515 if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range
515 shift0=lsq2[0][0]
516 shift0=lsq2[0][0]
516 width0=lsq2[0][1]
517 width0=lsq2[0][1]
517 Amplitude0=lsq2[0][2]
518 Amplitude0=lsq2[0][2]
518 p0=lsq2[0][3]
519 p0=lsq2[0][3]
519
520
520 shift1=lsq2[0][4]
521 shift1=lsq2[0][4]
521 width1=lsq2[0][5]
522 width1=lsq2[0][5]
522 Amplitude1=lsq2[0][6]
523 Amplitude1=lsq2[0][6]
523 p1=lsq2[0][7]
524 p1=lsq2[0][7]
524 noise=lsq2[0][8]
525 noise=lsq2[0][8]
525 else:
526 else:
526 shift1=lsq2[0][0]
527 shift1=lsq2[0][0]
527 width1=lsq2[0][1]
528 width1=lsq2[0][1]
528 Amplitude1=lsq2[0][2]
529 Amplitude1=lsq2[0][2]
529 p1=lsq2[0][3]
530 p1=lsq2[0][3]
530
531
531 shift0=lsq2[0][4]
532 shift0=lsq2[0][4]
532 width0=lsq2[0][5]
533 width0=lsq2[0][5]
533 Amplitude0=lsq2[0][6]
534 Amplitude0=lsq2[0][6]
534 p0=lsq2[0][7]
535 p0=lsq2[0][7]
535 noise=lsq2[0][8]
536 noise=lsq2[0][8]
536
537
537 if Amplitude0<0.05: # in case the peak is noise
538 if Amplitude0<0.05: # in case the peak is noise
538 shift0,width0,Amplitude0,p0 = [0,0,0,0]#4*[numpy.NaN]
539 shift0,width0,Amplitude0,p0 = [0,0,0,0]#4*[numpy.NaN]
539 if Amplitude1<0.05:
540 if Amplitude1<0.05:
540 shift1,width1,Amplitude1,p1 = [0,0,0,0]#4*[numpy.NaN]
541 shift1,width1,Amplitude1,p1 = [0,0,0,0]#4*[numpy.NaN]
541
542
542
543
543 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
544 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
544 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
545 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
545 SPCparam = (SPC_ch1,SPC_ch2)
546 SPCparam = (SPC_ch1,SPC_ch2)
546
547
547
548
548 return GauSPC
549 return GauSPC
549
550
550 def y_model1(self,x,state):
551 def y_model1(self,x,state):
551 shift0,width0,amplitude0,power0,noise=state
552 shift0,width0,amplitude0,power0,noise=state
552 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
553 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
553
554
554 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
555 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
555
556
556 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
557 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
557 return model0+model0u+model0d+noise
558 return model0+model0u+model0d+noise
558
559
559 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
560 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
560 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
561 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
561 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
562 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
562
563
563 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
564 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
564
565
565 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
566 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
566 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
567 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
567
568
568 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
569 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
569
570
570 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
571 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
571 return model0+model0u+model0d+model1+model1u+model1d+noise
572 return model0+model0u+model0d+model1+model1u+model1d+noise
572
573
573 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
574 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
574
575
575 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
576 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
576
577
577 def misfit2(self,state,y_data,x,num_intg):
578 def misfit2(self,state,y_data,x,num_intg):
578 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
579 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
579
580
580
581
581
582
582 class PrecipitationProc(Operation):
583 class PrecipitationProc(Operation):
583
584
584 '''
585 '''
585 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
586 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
586
587
587 Input:
588 Input:
588 self.dataOut.data_pre : SelfSpectra
589 self.dataOut.data_pre : SelfSpectra
589
590
590 Output:
591 Output:
591
592
592 self.dataOut.data_output : Reflectivity factor, rainfall Rate
593 self.dataOut.data_output : Reflectivity factor, rainfall Rate
593
594
594
595
595 Parameters affected:
596 Parameters affected:
596 '''
597 '''
597
598
598 def __init__(self):
599 def __init__(self):
599 Operation.__init__(self)
600 Operation.__init__(self)
600 self.i=0
601 self.i=0
601
602
602
603
603 def gaus(self,xSamples,Amp,Mu,Sigma):
604 def gaus(self,xSamples,Amp,Mu,Sigma):
604 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
605 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
605
606
606
607
607
608
608 def Moments(self, ySamples, xSamples):
609 def Moments(self, ySamples, xSamples):
609 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
610 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
610 yNorm = ySamples / Pot
611 yNorm = ySamples / Pot
611
612
612 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
613 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
613 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
614 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
614 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
615 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
615
616
616 return numpy.array([Pot, Vr, Desv])
617 return numpy.array([Pot, Vr, Desv])
617
618
618 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
619 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
619 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km = 0.93, Altitude=3350):
620 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km = 0.93, Altitude=3350):
620
621
621
622
622 Velrange = dataOut.spcparam_range[2]
623 Velrange = dataOut.spcparam_range[2]
623 FrecRange = dataOut.spcparam_range[0]
624 FrecRange = dataOut.spcparam_range[0]
624
625
625 dV= Velrange[1]-Velrange[0]
626 dV= Velrange[1]-Velrange[0]
626 dF= FrecRange[1]-FrecRange[0]
627 dF= FrecRange[1]-FrecRange[0]
627
628
628 if radar == "MIRA35C" :
629 if radar == "MIRA35C" :
629
630
630 self.spc = dataOut.data_pre[0].copy()
631 self.spc = dataOut.data_pre[0].copy()
631 self.Num_Hei = self.spc.shape[2]
632 self.Num_Hei = self.spc.shape[2]
632 self.Num_Bin = self.spc.shape[1]
633 self.Num_Bin = self.spc.shape[1]
633 self.Num_Chn = self.spc.shape[0]
634 self.Num_Chn = self.spc.shape[0]
634 Ze = self.dBZeMODE2(dataOut)
635 Ze = self.dBZeMODE2(dataOut)
635
636
636 else:
637 else:
637
638
638 self.spc = dataOut.SPCparam[1].copy() #dataOut.data_pre[0].copy() #
639 self.spc = dataOut.SPCparam[1].copy() #dataOut.data_pre[0].copy() #
639
640
640 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
641 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
641
642
642 self.spc[:,:,0:7]= numpy.NaN
643 self.spc[:,:,0:7]= numpy.NaN
643
644
644 """##########################################"""
645 """##########################################"""
645
646
646 self.Num_Hei = self.spc.shape[2]
647 self.Num_Hei = self.spc.shape[2]
647 self.Num_Bin = self.spc.shape[1]
648 self.Num_Bin = self.spc.shape[1]
648 self.Num_Chn = self.spc.shape[0]
649 self.Num_Chn = self.spc.shape[0]
649
650
650 ''' Se obtiene la constante del RADAR '''
651 ''' Se obtiene la constante del RADAR '''
651
652
652 self.Pt = Pt
653 self.Pt = Pt
653 self.Gt = Gt
654 self.Gt = Gt
654 self.Gr = Gr
655 self.Gr = Gr
655 self.Lambda = Lambda
656 self.Lambda = Lambda
656 self.aL = aL
657 self.aL = aL
657 self.tauW = tauW
658 self.tauW = tauW
658 self.ThetaT = ThetaT
659 self.ThetaT = ThetaT
659 self.ThetaR = ThetaR
660 self.ThetaR = ThetaR
660
661
661 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
662 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
662 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
663 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
663 RadarConstant = 10e-26 * Numerator / Denominator #
664 RadarConstant = 10e-26 * Numerator / Denominator #
664
665
665 ''' ============================= '''
666 ''' ============================= '''
666
667
667 self.spc[0] = (self.spc[0]-dataOut.noise[0])
668 self.spc[0] = (self.spc[0]-dataOut.noise[0])
668 self.spc[1] = (self.spc[1]-dataOut.noise[1])
669 self.spc[1] = (self.spc[1]-dataOut.noise[1])
669 self.spc[2] = (self.spc[2]-dataOut.noise[2])
670 self.spc[2] = (self.spc[2]-dataOut.noise[2])
670
671
671 self.spc[ numpy.where(self.spc < 0)] = 0
672 self.spc[ numpy.where(self.spc < 0)] = 0
672
673
673 SPCmean = (numpy.mean(self.spc,0) - numpy.mean(dataOut.noise))
674 SPCmean = (numpy.mean(self.spc,0) - numpy.mean(dataOut.noise))
674 SPCmean[ numpy.where(SPCmean < 0)] = 0
675 SPCmean[ numpy.where(SPCmean < 0)] = 0
675
676
676 ETAn = numpy.zeros([self.Num_Bin,self.Num_Hei])
677 ETAn = numpy.zeros([self.Num_Bin,self.Num_Hei])
677 ETAv = numpy.zeros([self.Num_Bin,self.Num_Hei])
678 ETAv = numpy.zeros([self.Num_Bin,self.Num_Hei])
678 ETAd = numpy.zeros([self.Num_Bin,self.Num_Hei])
679 ETAd = numpy.zeros([self.Num_Bin,self.Num_Hei])
679
680
680 Pr = SPCmean[:,:]
681 Pr = SPCmean[:,:]
681
682
682 VelMeteoro = numpy.mean(SPCmean,axis=0)
683 VelMeteoro = numpy.mean(SPCmean,axis=0)
683
684
684 D_range = numpy.zeros([self.Num_Bin,self.Num_Hei])
685 D_range = numpy.zeros([self.Num_Bin,self.Num_Hei])
685 SIGMA = numpy.zeros([self.Num_Bin,self.Num_Hei])
686 SIGMA = numpy.zeros([self.Num_Bin,self.Num_Hei])
686 N_dist = numpy.zeros([self.Num_Bin,self.Num_Hei])
687 N_dist = numpy.zeros([self.Num_Bin,self.Num_Hei])
687 V_mean = numpy.zeros(self.Num_Hei)
688 V_mean = numpy.zeros(self.Num_Hei)
688 del_V = numpy.zeros(self.Num_Hei)
689 del_V = numpy.zeros(self.Num_Hei)
689 Z = numpy.zeros(self.Num_Hei)
690 Z = numpy.zeros(self.Num_Hei)
690 Ze = numpy.zeros(self.Num_Hei)
691 Ze = numpy.zeros(self.Num_Hei)
691 RR = numpy.zeros(self.Num_Hei)
692 RR = numpy.zeros(self.Num_Hei)
692
693
693 Range = dataOut.heightList*1000.
694 Range = dataOut.heightList*1000.
694
695
695 for R in range(self.Num_Hei):
696 for R in range(self.Num_Hei):
696
697
697 h = Range[R] + Altitude #Range from ground to radar pulse altitude
698 h = Range[R] + Altitude #Range from ground to radar pulse altitude
698 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
699 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
699
700
700 D_range[:,R] = numpy.log( (9.65 - (Velrange[0:self.Num_Bin] / del_V[R])) / 10.3 ) / -0.6 #Diameter range [m]x10**-3
701 D_range[:,R] = numpy.log( (9.65 - (Velrange[0:self.Num_Bin] / del_V[R])) / 10.3 ) / -0.6 #Diameter range [m]x10**-3
701
702
702 '''NOTA: ETA(n) dn = ETA(f) df
703 '''NOTA: ETA(n) dn = ETA(f) df
703
704
704 dn = 1 Diferencial de muestreo
705 dn = 1 Diferencial de muestreo
705 df = ETA(n) / ETA(f)
706 df = ETA(n) / ETA(f)
706
707
707 '''
708 '''
708
709
709 ETAn[:,R] = RadarConstant * Pr[:,R] * (Range[R] )**2 #Reflectivity (ETA)
710 ETAn[:,R] = RadarConstant * Pr[:,R] * (Range[R] )**2 #Reflectivity (ETA)
710
711
711 ETAv[:,R]=ETAn[:,R]/dV
712 ETAv[:,R]=ETAn[:,R]/dV
712
713
713 ETAd[:,R]=ETAv[:,R]*6.18*exp(-0.6*D_range[:,R])
714 ETAd[:,R]=ETAv[:,R]*6.18*exp(-0.6*D_range[:,R])
714
715
715 SIGMA[:,R] = Km * (D_range[:,R] * 1e-3 )**6 * numpy.pi**5 / Lambda**4 #Equivalent Section of drops (sigma)
716 SIGMA[:,R] = Km * (D_range[:,R] * 1e-3 )**6 * numpy.pi**5 / Lambda**4 #Equivalent Section of drops (sigma)
716
717
717 N_dist[:,R] = ETAn[:,R] / SIGMA[:,R]
718 N_dist[:,R] = ETAn[:,R] / SIGMA[:,R]
718
719
719 DMoments = self.Moments(Pr[:,R], Velrange[0:self.Num_Bin])
720 DMoments = self.Moments(Pr[:,R], Velrange[0:self.Num_Bin])
720
721
721 try:
722 try:
722 popt01,pcov = curve_fit(self.gaus, Velrange[0:self.Num_Bin] , Pr[:,R] , p0=DMoments)
723 popt01,pcov = curve_fit(self.gaus, Velrange[0:self.Num_Bin] , Pr[:,R] , p0=DMoments)
723 except:
724 except:
724 popt01=numpy.zeros(3)
725 popt01=numpy.zeros(3)
725 popt01[1]= DMoments[1]
726 popt01[1]= DMoments[1]
726
727
727 if popt01[1]<0 or popt01[1]>20:
728 if popt01[1]<0 or popt01[1]>20:
728 popt01[1]=numpy.NaN
729 popt01[1]=numpy.NaN
729
730
730
731
731 V_mean[R]=popt01[1]
732 V_mean[R]=popt01[1]
732
733
733 Z[R] = numpy.nansum( N_dist[:,R] * (D_range[:,R])**6 )#*10**-18
734 Z[R] = numpy.nansum( N_dist[:,R] * (D_range[:,R])**6 )#*10**-18
734
735
735 RR[R] = 0.0006*numpy.pi * numpy.nansum( D_range[:,R]**3 * N_dist[:,R] * Velrange[0:self.Num_Bin] ) #Rainfall rate
736 RR[R] = 0.0006*numpy.pi * numpy.nansum( D_range[:,R]**3 * N_dist[:,R] * Velrange[0:self.Num_Bin] ) #Rainfall rate
736
737
737 Ze[R] = (numpy.nansum( ETAn[:,R]) * Lambda**4) / ( 10**-18*numpy.pi**5 * Km)
738 Ze[R] = (numpy.nansum( ETAn[:,R]) * Lambda**4) / ( 10**-18*numpy.pi**5 * Km)
738
739
739
740
740
741
741 RR2 = (Z/200)**(1/1.6)
742 RR2 = (Z/200)**(1/1.6)
742 dBRR = 10*numpy.log10(RR)
743 dBRR = 10*numpy.log10(RR)
743 dBRR2 = 10*numpy.log10(RR2)
744 dBRR2 = 10*numpy.log10(RR2)
744
745
745 dBZe = 10*numpy.log10(Ze)
746 dBZe = 10*numpy.log10(Ze)
746 dBZ = 10*numpy.log10(Z)
747 dBZ = 10*numpy.log10(Z)
747
748
748 dataOut.data_output = RR[8]
749 dataOut.data_output = RR[8]
749 dataOut.data_param = numpy.ones([3,self.Num_Hei])
750 dataOut.data_param = numpy.ones([3,self.Num_Hei])
750 dataOut.channelList = [0,1,2]
751 dataOut.channelList = [0,1,2]
751
752
752 dataOut.data_param[0]=dBZ
753 dataOut.data_param[0]=dBZ
753 dataOut.data_param[1]=V_mean
754 dataOut.data_param[1]=V_mean
754 dataOut.data_param[2]=RR
755 dataOut.data_param[2]=RR
755
756
756 return dataOut
757 return dataOut
757
758
758 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
759 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
759
760
760 NPW = dataOut.NPW
761 NPW = dataOut.NPW
761 COFA = dataOut.COFA
762 COFA = dataOut.COFA
762
763
763 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
764 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
764 RadarConst = dataOut.RadarConst
765 RadarConst = dataOut.RadarConst
765 #frequency = 34.85*10**9
766 #frequency = 34.85*10**9
766
767
767 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
768 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
768 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
769 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
769
770
770 ETA = numpy.sum(SNR,1)
771 ETA = numpy.sum(SNR,1)
771
772
772 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
773 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
773
774
774 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
775 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
775
776
776 for r in range(self.Num_Hei):
777 for r in range(self.Num_Hei):
777
778
778 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
779 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
779 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
780 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
780
781
781 return Ze
782 return Ze
782
783
783 # def GetRadarConstant(self):
784 # def GetRadarConstant(self):
784 #
785 #
785 # """
786 # """
786 # Constants:
787 # Constants:
787 #
788 #
788 # Pt: Transmission Power dB 5kW 5000
789 # Pt: Transmission Power dB 5kW 5000
789 # Gt: Transmission Gain dB 24.7 dB 295.1209
790 # Gt: Transmission Gain dB 24.7 dB 295.1209
790 # Gr: Reception Gain dB 18.5 dB 70.7945
791 # Gr: Reception Gain dB 18.5 dB 70.7945
791 # Lambda: Wavelenght m 0.6741 m 0.6741
792 # Lambda: Wavelenght m 0.6741 m 0.6741
792 # aL: Attenuation loses dB 4dB 2.5118
793 # aL: Attenuation loses dB 4dB 2.5118
793 # tauW: Width of transmission pulse s 4us 4e-6
794 # tauW: Width of transmission pulse s 4us 4e-6
794 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
795 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
795 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
796 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
796 #
797 #
797 # """
798 # """
798 #
799 #
799 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
800 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
800 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
801 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
801 # RadarConstant = Numerator / Denominator
802 # RadarConstant = Numerator / Denominator
802 #
803 #
803 # return RadarConstant
804 # return RadarConstant
804
805
805
806
806
807
807 class FullSpectralAnalysis(Operation):
808 class FullSpectralAnalysis(Operation):
808
809
809 """
810 """
810 Function that implements Full Spectral Analisys technique.
811 Function that implements Full Spectral Analisys technique.
811
812
812 Input:
813 Input:
813 self.dataOut.data_pre : SelfSpectra and CrossSPectra data
814 self.dataOut.data_pre : SelfSpectra and CrossSPectra data
814 self.dataOut.groupList : Pairlist of channels
815 self.dataOut.groupList : Pairlist of channels
815 self.dataOut.ChanDist : Physical distance between receivers
816 self.dataOut.ChanDist : Physical distance between receivers
816
817
817
818
818 Output:
819 Output:
819
820
820 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
821 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
821
822
822
823
823 Parameters affected: Winds, height range, SNR
824 Parameters affected: Winds, height range, SNR
824
825
825 """
826 """
826 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRlimit=7):
827 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRlimit=7):
827
828
828 self.indice=int(numpy.random.rand()*1000)
829 self.indice=int(numpy.random.rand()*1000)
829
830
830 spc = dataOut.data_pre[0].copy()
831 spc = dataOut.data_pre[0].copy()
831 cspc = dataOut.data_pre[1]
832 cspc = dataOut.data_pre[1]
832
833
833 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
834 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
834
835
835 SNRspc = spc.copy()
836 SNRspc = spc.copy()
836 SNRspc[:,:,0:7]= numpy.NaN
837 SNRspc[:,:,0:7]= numpy.NaN
837
838
838 """##########################################"""
839 """##########################################"""
839
840
840
841
841 nChannel = spc.shape[0]
842 nChannel = spc.shape[0]
842 nProfiles = spc.shape[1]
843 nProfiles = spc.shape[1]
843 nHeights = spc.shape[2]
844 nHeights = spc.shape[2]
844
845
845 pairsList = dataOut.groupList
846 pairsList = dataOut.groupList
846 if dataOut.ChanDist is not None :
847 if dataOut.ChanDist is not None :
847 ChanDist = dataOut.ChanDist
848 ChanDist = dataOut.ChanDist
848 else:
849 else:
849 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
850 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
850
851
851 FrecRange = dataOut.spc_range[0]
852 FrecRange = dataOut.spc_range[0]
852
853
853 ySamples=numpy.ones([nChannel,nProfiles])
854 ySamples=numpy.ones([nChannel,nProfiles])
854 phase=numpy.ones([nChannel,nProfiles])
855 phase=numpy.ones([nChannel,nProfiles])
855 CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_)
856 CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_)
856 coherence=numpy.ones([nChannel,nProfiles])
857 coherence=numpy.ones([nChannel,nProfiles])
857 PhaseSlope=numpy.ones(nChannel)
858 PhaseSlope=numpy.ones(nChannel)
858 PhaseInter=numpy.ones(nChannel)
859 PhaseInter=numpy.ones(nChannel)
859 data_SNR=numpy.zeros([nProfiles])
860 data_SNR=numpy.zeros([nProfiles])
860
861
861 data = dataOut.data_pre
862 data = dataOut.data_pre
862 noise = dataOut.noise
863 noise = dataOut.noise
863
864
864 dataOut.data_SNR = (numpy.mean(SNRspc,axis=1)- noise[0]) / noise[0]
865 dataOut.data_SNR = (numpy.mean(SNRspc,axis=1)- noise[0]) / noise[0]
865
866
866 dataOut.data_SNR[numpy.where( dataOut.data_SNR <0 )] = 1e-20
867 dataOut.data_SNR[numpy.where( dataOut.data_SNR <0 )] = 1e-20
867
868
868
869
869 data_output=numpy.ones([spc.shape[0],spc.shape[2]])*numpy.NaN
870 data_output=numpy.ones([spc.shape[0],spc.shape[2]])*numpy.NaN
870
871
871 velocityX=[]
872 velocityX=[]
872 velocityY=[]
873 velocityY=[]
873 velocityV=[]
874 velocityV=[]
874 PhaseLine=[]
875 PhaseLine=[]
875
876
876 dbSNR = 10*numpy.log10(dataOut.data_SNR)
877 dbSNR = 10*numpy.log10(dataOut.data_SNR)
877 dbSNR = numpy.average(dbSNR,0)
878 dbSNR = numpy.average(dbSNR,0)
878
879
879 for Height in range(nHeights):
880 for Height in range(nHeights):
880
881
881 [Vzon,Vmer,Vver, GaussCenter, PhaseSlope, FitGaussCSPC]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, dataOut.spc_range, dbSNR[Height], SNRlimit)
882 [Vzon,Vmer,Vver, GaussCenter, PhaseSlope, FitGaussCSPC]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, dataOut.spc_range, dbSNR[Height], SNRlimit)
882 PhaseLine = numpy.append(PhaseLine, PhaseSlope)
883 PhaseLine = numpy.append(PhaseLine, PhaseSlope)
883
884
884 if abs(Vzon)<100. and abs(Vzon)> 0.:
885 if abs(Vzon)<100. and abs(Vzon)> 0.:
885 velocityX=numpy.append(velocityX, Vzon)#Vmag
886 velocityX=numpy.append(velocityX, Vzon)#Vmag
886
887
887 else:
888 else:
888 velocityX=numpy.append(velocityX, numpy.NaN)
889 velocityX=numpy.append(velocityX, numpy.NaN)
889
890
890 if abs(Vmer)<100. and abs(Vmer) > 0.:
891 if abs(Vmer)<100. and abs(Vmer) > 0.:
891 velocityY=numpy.append(velocityY, -Vmer)#Vang
892 velocityY=numpy.append(velocityY, -Vmer)#Vang
892
893
893 else:
894 else:
894 velocityY=numpy.append(velocityY, numpy.NaN)
895 velocityY=numpy.append(velocityY, numpy.NaN)
895
896
896 if dbSNR[Height] > SNRlimit:
897 if dbSNR[Height] > SNRlimit:
897 velocityV=numpy.append(velocityV, -Vver)#FirstMoment[Height])
898 velocityV=numpy.append(velocityV, -Vver)#FirstMoment[Height])
898 else:
899 else:
899 velocityV=numpy.append(velocityV, numpy.NaN)
900 velocityV=numpy.append(velocityV, numpy.NaN)
900
901
901
902
902
903
903 '''Nota: Cambiar el signo de numpy.array(velocityX) cuando se intente procesar datos de BLTR'''
904 '''Nota: Cambiar el signo de numpy.array(velocityX) cuando se intente procesar datos de BLTR'''
904 data_output[0] = numpy.array(velocityX) #self.moving_average(numpy.array(velocityX) , N=1)
905 data_output[0] = numpy.array(velocityX) #self.moving_average(numpy.array(velocityX) , N=1)
905 data_output[1] = numpy.array(velocityY) #self.moving_average(numpy.array(velocityY) , N=1)
906 data_output[1] = numpy.array(velocityY) #self.moving_average(numpy.array(velocityY) , N=1)
906 data_output[2] = velocityV#FirstMoment
907 data_output[2] = velocityV#FirstMoment
907
908
908 xFrec=FrecRange[0:spc.shape[1]]
909 xFrec=FrecRange[0:spc.shape[1]]
909
910
910 dataOut.data_output=data_output
911 dataOut.data_output=data_output
911
912
912 return dataOut
913 return dataOut
913
914
914
915
915 def moving_average(self,x, N=2):
916 def moving_average(self,x, N=2):
916 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
917 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
917
918
918 def gaus(self,xSamples,Amp,Mu,Sigma):
919 def gaus(self,xSamples,Amp,Mu,Sigma):
919 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
920 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
920
921
921
922
922
923
923 def Moments(self, ySamples, xSamples):
924 def Moments(self, ySamples, xSamples):
924 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
925 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
925 yNorm = ySamples / Pot
926 yNorm = ySamples / Pot
926 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
927 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
927 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
928 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
928 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
929 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
929
930
930 return numpy.array([Pot, Vr, Desv])
931 return numpy.array([Pot, Vr, Desv])
931
932
932 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit):
933 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit):
933
934
934
935
935
936
936 ySamples=numpy.ones([spc.shape[0],spc.shape[1]])
937 ySamples=numpy.ones([spc.shape[0],spc.shape[1]])
937 phase=numpy.ones([spc.shape[0],spc.shape[1]])
938 phase=numpy.ones([spc.shape[0],spc.shape[1]])
938 CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_)
939 CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_)
939 coherence=numpy.ones([spc.shape[0],spc.shape[1]])
940 coherence=numpy.ones([spc.shape[0],spc.shape[1]])
940 PhaseSlope=numpy.zeros(spc.shape[0])
941 PhaseSlope=numpy.zeros(spc.shape[0])
941 PhaseInter=numpy.ones(spc.shape[0])
942 PhaseInter=numpy.ones(spc.shape[0])
942 xFrec=AbbsisaRange[0][0:spc.shape[1]]
943 xFrec=AbbsisaRange[0][0:spc.shape[1]]
943 xVel =AbbsisaRange[2][0:spc.shape[1]]
944 xVel =AbbsisaRange[2][0:spc.shape[1]]
944 Vv=numpy.empty(spc.shape[2])*0
945 Vv=numpy.empty(spc.shape[2])*0
945 SPCav = numpy.average(spc, axis=0)-numpy.average(noise) #spc[0]-noise[0]#
946 SPCav = numpy.average(spc, axis=0)-numpy.average(noise) #spc[0]-noise[0]#
946
947
947 SPCmoments = self.Moments(SPCav[:,Height], xVel )
948 SPCmoments = self.Moments(SPCav[:,Height], xVel )
948 CSPCmoments = []
949 CSPCmoments = []
949 cspcNoise = numpy.empty(3)
950 cspcNoise = numpy.empty(3)
950
951
951 '''Getting Eij and Nij'''
952 '''Getting Eij and Nij'''
952
953
953 Xi01=ChanDist[0][0]
954 Xi01=ChanDist[0][0]
954 Eta01=ChanDist[0][1]
955 Eta01=ChanDist[0][1]
955
956
956 Xi02=ChanDist[1][0]
957 Xi02=ChanDist[1][0]
957 Eta02=ChanDist[1][1]
958 Eta02=ChanDist[1][1]
958
959
959 Xi12=ChanDist[2][0]
960 Xi12=ChanDist[2][0]
960 Eta12=ChanDist[2][1]
961 Eta12=ChanDist[2][1]
961
962
962 z = spc.copy()
963 z = spc.copy()
963 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
964 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
964
965
965 for i in range(spc.shape[0]):
966 for i in range(spc.shape[0]):
966
967
967 '''****** Line of Data SPC ******'''
968 '''****** Line of Data SPC ******'''
968 zline=z[i,:,Height].copy() - noise[i] # Se resta ruido
969 zline=z[i,:,Height].copy() - noise[i] # Se resta ruido
969
970
970 '''****** SPC is normalized ******'''
971 '''****** SPC is normalized ******'''
971 SmoothSPC =self.moving_average(zline.copy(),N=1) # Se suaviza el ruido
972 SmoothSPC =self.moving_average(zline.copy(),N=1) # Se suaviza el ruido
972 FactNorm = SmoothSPC/numpy.nansum(SmoothSPC) # SPC Normalizado y suavizado
973 FactNorm = SmoothSPC/numpy.nansum(SmoothSPC) # SPC Normalizado y suavizado
973
974
974 xSamples = xFrec # Se toma el rango de frecuncias
975 xSamples = xFrec # Se toma el rango de frecuncias
975 ySamples[i] = FactNorm # Se toman los valores de SPC normalizado
976 ySamples[i] = FactNorm # Se toman los valores de SPC normalizado
976
977
977 for i in range(spc.shape[0]):
978 for i in range(spc.shape[0]):
978
979
979 '''****** Line of Data CSPC ******'''
980 '''****** Line of Data CSPC ******'''
980 cspcLine = ( cspc[i,:,Height].copy())# - noise[i] ) # no! Se resta el ruido
981 cspcLine = ( cspc[i,:,Height].copy())# - noise[i] ) # no! Se resta el ruido
981 SmoothCSPC =self.moving_average(cspcLine,N=1) # Se suaviza el ruido
982 SmoothCSPC =self.moving_average(cspcLine,N=1) # Se suaviza el ruido
982 cspcNorm = SmoothCSPC/numpy.nansum(SmoothCSPC) # CSPC normalizado y suavizado
983 cspcNorm = SmoothCSPC/numpy.nansum(SmoothCSPC) # CSPC normalizado y suavizado
983
984
984 '''****** CSPC is normalized with respect to Briggs and Vincent ******'''
985 '''****** CSPC is normalized with respect to Briggs and Vincent ******'''
985 chan_index0 = pairsList[i][0]
986 chan_index0 = pairsList[i][0]
986 chan_index1 = pairsList[i][1]
987 chan_index1 = pairsList[i][1]
987
988
988 CSPCFactor= numpy.abs(numpy.nansum(ySamples[chan_index0]))**2 * numpy.abs(numpy.nansum(ySamples[chan_index1]))**2
989 CSPCFactor= numpy.abs(numpy.nansum(ySamples[chan_index0]))**2 * numpy.abs(numpy.nansum(ySamples[chan_index1]))**2
989 CSPCNorm = cspcNorm / numpy.sqrt(CSPCFactor)
990 CSPCNorm = cspcNorm / numpy.sqrt(CSPCFactor)
990
991
991 CSPCSamples[i] = CSPCNorm
992 CSPCSamples[i] = CSPCNorm
992
993
993 coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor)
994 coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor)
994
995
995 #coherence[i]= self.moving_average(coherence[i],N=1)
996 #coherence[i]= self.moving_average(coherence[i],N=1)
996
997
997 phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi
998 phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi
998
999
999 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPCSamples[0]), xSamples),
1000 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPCSamples[0]), xSamples),
1000 self.Moments(numpy.abs(CSPCSamples[1]), xSamples),
1001 self.Moments(numpy.abs(CSPCSamples[1]), xSamples),
1001 self.Moments(numpy.abs(CSPCSamples[2]), xSamples)])
1002 self.Moments(numpy.abs(CSPCSamples[2]), xSamples)])
1002
1003
1003
1004
1004 popt=[1e-10,0,1e-10]
1005 popt=[1e-10,0,1e-10]
1005 popt01, popt02, popt12 = [1e-10,1e-10,1e-10], [1e-10,1e-10,1e-10] ,[1e-10,1e-10,1e-10]
1006 popt01, popt02, popt12 = [1e-10,1e-10,1e-10], [1e-10,1e-10,1e-10] ,[1e-10,1e-10,1e-10]
1006 FitGauss01, FitGauss02, FitGauss12 = numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0
1007 FitGauss01, FitGauss02, FitGauss12 = numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0
1007
1008
1008 CSPCMask01 = numpy.abs(CSPCSamples[0])
1009 CSPCMask01 = numpy.abs(CSPCSamples[0])
1009 CSPCMask02 = numpy.abs(CSPCSamples[1])
1010 CSPCMask02 = numpy.abs(CSPCSamples[1])
1010 CSPCMask12 = numpy.abs(CSPCSamples[2])
1011 CSPCMask12 = numpy.abs(CSPCSamples[2])
1011
1012
1012 mask01 = ~numpy.isnan(CSPCMask01)
1013 mask01 = ~numpy.isnan(CSPCMask01)
1013 mask02 = ~numpy.isnan(CSPCMask02)
1014 mask02 = ~numpy.isnan(CSPCMask02)
1014 mask12 = ~numpy.isnan(CSPCMask12)
1015 mask12 = ~numpy.isnan(CSPCMask12)
1015
1016
1016 #mask = ~numpy.isnan(CSPCMask01)
1017 #mask = ~numpy.isnan(CSPCMask01)
1017 CSPCMask01 = CSPCMask01[mask01]
1018 CSPCMask01 = CSPCMask01[mask01]
1018 CSPCMask02 = CSPCMask02[mask02]
1019 CSPCMask02 = CSPCMask02[mask02]
1019 CSPCMask12 = CSPCMask12[mask12]
1020 CSPCMask12 = CSPCMask12[mask12]
1020 #CSPCMask01 = numpy.ma.masked_invalid(CSPCMask01)
1021 #CSPCMask01 = numpy.ma.masked_invalid(CSPCMask01)
1021
1022
1022
1023
1023
1024
1024 '''***Fit Gauss CSPC01***'''
1025 '''***Fit Gauss CSPC01***'''
1025 if dbSNR > SNRlimit and numpy.abs(SPCmoments[1])<3 :
1026 if dbSNR > SNRlimit and numpy.abs(SPCmoments[1])<3 :
1026 try:
1027 try:
1027 popt01,pcov = curve_fit(self.gaus,xSamples[mask01],numpy.abs(CSPCMask01),p0=CSPCmoments[0])
1028 popt01,pcov = curve_fit(self.gaus,xSamples[mask01],numpy.abs(CSPCMask01),p0=CSPCmoments[0])
1028 popt02,pcov = curve_fit(self.gaus,xSamples[mask02],numpy.abs(CSPCMask02),p0=CSPCmoments[1])
1029 popt02,pcov = curve_fit(self.gaus,xSamples[mask02],numpy.abs(CSPCMask02),p0=CSPCmoments[1])
1029 popt12,pcov = curve_fit(self.gaus,xSamples[mask12],numpy.abs(CSPCMask12),p0=CSPCmoments[2])
1030 popt12,pcov = curve_fit(self.gaus,xSamples[mask12],numpy.abs(CSPCMask12),p0=CSPCmoments[2])
1030 FitGauss01 = self.gaus(xSamples,*popt01)
1031 FitGauss01 = self.gaus(xSamples,*popt01)
1031 FitGauss02 = self.gaus(xSamples,*popt02)
1032 FitGauss02 = self.gaus(xSamples,*popt02)
1032 FitGauss12 = self.gaus(xSamples,*popt12)
1033 FitGauss12 = self.gaus(xSamples,*popt12)
1033 except:
1034 except:
1034 FitGauss01=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[0]))
1035 FitGauss01=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[0]))
1035 FitGauss02=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[1]))
1036 FitGauss02=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[1]))
1036 FitGauss12=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[2]))
1037 FitGauss12=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[2]))
1037
1038
1038
1039
1039 CSPCopt = numpy.vstack([popt01,popt02,popt12])
1040 CSPCopt = numpy.vstack([popt01,popt02,popt12])
1040
1041
1041 '''****** Getting fij width ******'''
1042 '''****** Getting fij width ******'''
1042
1043
1043 yMean = numpy.average(ySamples, axis=0) # ySamples[0]
1044 yMean = numpy.average(ySamples, axis=0) # ySamples[0]
1044
1045
1045 '''******* Getting fitting Gaussian *******'''
1046 '''******* Getting fitting Gaussian *******'''
1046 meanGauss = sum(xSamples*yMean) / len(xSamples) # Mu, velocidad radial (frecuencia)
1047 meanGauss = sum(xSamples*yMean) / len(xSamples) # Mu, velocidad radial (frecuencia)
1047 sigma2 = sum(yMean*(xSamples-meanGauss)**2) / len(xSamples) # Varianza, Ancho espectral (frecuencia)
1048 sigma2 = sum(yMean*(xSamples-meanGauss)**2) / len(xSamples) # Varianza, Ancho espectral (frecuencia)
1048
1049
1049 yMoments = self.Moments(yMean, xSamples)
1050 yMoments = self.Moments(yMean, xSamples)
1050
1051
1051 if dbSNR > SNRlimit and numpy.abs(SPCmoments[1])<3: # and abs(meanGauss/sigma2) > 0.00001:
1052 if dbSNR > SNRlimit and numpy.abs(SPCmoments[1])<3: # and abs(meanGauss/sigma2) > 0.00001:
1052 try:
1053 try:
1053 popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=yMoments)
1054 popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=yMoments)
1054 FitGauss=self.gaus(xSamples,*popt)
1055 FitGauss=self.gaus(xSamples,*popt)
1055
1056
1056 except :#RuntimeError:
1057 except :#RuntimeError:
1057 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1058 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1058
1059
1059
1060
1060 else:
1061 else:
1061 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1062 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1062
1063
1063
1064
1064
1065
1065 '''****** Getting Fij ******'''
1066 '''****** Getting Fij ******'''
1066 Fijcspc = CSPCopt[:,2]/2*3
1067 Fijcspc = CSPCopt[:,2]/2*3
1067
1068
1068
1069
1069 GaussCenter = popt[1] #xFrec[GCpos]
1070 GaussCenter = popt[1] #xFrec[GCpos]
1070 #Punto en Eje X de la Gaussiana donde se encuentra el centro
1071 #Punto en Eje X de la Gaussiana donde se encuentra el centro
1071 ClosestCenter = xSamples[numpy.abs(xSamples-GaussCenter).argmin()]
1072 ClosestCenter = xSamples[numpy.abs(xSamples-GaussCenter).argmin()]
1072 PointGauCenter = numpy.where(xSamples==ClosestCenter)[0][0]
1073 PointGauCenter = numpy.where(xSamples==ClosestCenter)[0][0]
1073
1074
1074 #Punto e^-1 hubicado en la Gaussiana
1075 #Punto e^-1 hubicado en la Gaussiana
1075 PeMinus1 = numpy.max(FitGauss)* numpy.exp(-1)
1076 PeMinus1 = numpy.max(FitGauss)* numpy.exp(-1)
1076 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # El punto mas cercano a "Peminus1" dentro de "FitGauss"
1077 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # El punto mas cercano a "Peminus1" dentro de "FitGauss"
1077 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1078 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1078
1079
1079 if xSamples[PointFij] > xSamples[PointGauCenter]:
1080 if xSamples[PointFij] > xSamples[PointGauCenter]:
1080 Fij = xSamples[PointFij] - xSamples[PointGauCenter]
1081 Fij = xSamples[PointFij] - xSamples[PointGauCenter]
1081
1082
1082 else:
1083 else:
1083 Fij = xSamples[PointGauCenter] - xSamples[PointFij]
1084 Fij = xSamples[PointGauCenter] - xSamples[PointFij]
1084
1085
1085
1086
1086 '''****** Taking frequency ranges from SPCs ******'''
1087 '''****** Taking frequency ranges from SPCs ******'''
1087
1088
1088
1089
1089 #GaussCenter = popt[1] #Primer momento 01
1090 #GaussCenter = popt[1] #Primer momento 01
1090 GauWidth = popt[2] *3/2 #Ancho de banda de Gau01
1091 GauWidth = popt[2] *3/2 #Ancho de banda de Gau01
1091 Range = numpy.empty(2)
1092 Range = numpy.empty(2)
1092 Range[0] = GaussCenter - GauWidth
1093 Range[0] = GaussCenter - GauWidth
1093 Range[1] = GaussCenter + GauWidth
1094 Range[1] = GaussCenter + GauWidth
1094 #Punto en Eje X de la Gaussiana donde se encuentra ancho de banda (min:max)
1095 #Punto en Eje X de la Gaussiana donde se encuentra ancho de banda (min:max)
1095 ClosRangeMin = xSamples[numpy.abs(xSamples-Range[0]).argmin()]
1096 ClosRangeMin = xSamples[numpy.abs(xSamples-Range[0]).argmin()]
1096 ClosRangeMax = xSamples[numpy.abs(xSamples-Range[1]).argmin()]
1097 ClosRangeMax = xSamples[numpy.abs(xSamples-Range[1]).argmin()]
1097
1098
1098 PointRangeMin = numpy.where(xSamples==ClosRangeMin)[0][0]
1099 PointRangeMin = numpy.where(xSamples==ClosRangeMin)[0][0]
1099 PointRangeMax = numpy.where(xSamples==ClosRangeMax)[0][0]
1100 PointRangeMax = numpy.where(xSamples==ClosRangeMax)[0][0]
1100
1101
1101 Range=numpy.array([ PointRangeMin, PointRangeMax ])
1102 Range=numpy.array([ PointRangeMin, PointRangeMax ])
1102
1103
1103 FrecRange = xFrec[ Range[0] : Range[1] ]
1104 FrecRange = xFrec[ Range[0] : Range[1] ]
1104 VelRange = xVel[ Range[0] : Range[1] ]
1105 VelRange = xVel[ Range[0] : Range[1] ]
1105
1106
1106
1107
1107 '''****** Getting SCPC Slope ******'''
1108 '''****** Getting SCPC Slope ******'''
1108
1109
1109 for i in range(spc.shape[0]):
1110 for i in range(spc.shape[0]):
1110
1111
1111 if len(FrecRange)>5 and len(FrecRange)<spc.shape[1]*0.3:
1112 if len(FrecRange)>5 and len(FrecRange)<spc.shape[1]*0.3:
1112 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1113 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1113
1114
1114 '''***********************VelRange******************'''
1115 '''***********************VelRange******************'''
1115
1116
1116 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1117 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1117
1118
1118 if len(FrecRange) == len(PhaseRange):
1119 if len(FrecRange) == len(PhaseRange):
1119 try:
1120 try:
1120 slope, intercept, r_value, p_value, std_err = stats.linregress(FrecRange[mask], PhaseRange[mask])
1121 slope, intercept, r_value, p_value, std_err = stats.linregress(FrecRange[mask], PhaseRange[mask])
1121 PhaseSlope[i]=slope
1122 PhaseSlope[i]=slope
1122 PhaseInter[i]=intercept
1123 PhaseInter[i]=intercept
1123 except:
1124 except:
1124 PhaseSlope[i]=0
1125 PhaseSlope[i]=0
1125 PhaseInter[i]=0
1126 PhaseInter[i]=0
1126 else:
1127 else:
1127 PhaseSlope[i]=0
1128 PhaseSlope[i]=0
1128 PhaseInter[i]=0
1129 PhaseInter[i]=0
1129 else:
1130 else:
1130 PhaseSlope[i]=0
1131 PhaseSlope[i]=0
1131 PhaseInter[i]=0
1132 PhaseInter[i]=0
1132
1133
1133
1134
1134 '''Getting constant C'''
1135 '''Getting constant C'''
1135 cC=(Fij*numpy.pi)**2
1136 cC=(Fij*numpy.pi)**2
1136
1137
1137 '''****** Getting constants F and G ******'''
1138 '''****** Getting constants F and G ******'''
1138 MijEijNij=numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1139 MijEijNij=numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1139 MijResult0=(-PhaseSlope[1]*cC) / (2*numpy.pi)
1140 MijResult0=(-PhaseSlope[1]*cC) / (2*numpy.pi)
1140 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1141 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1141 MijResults=numpy.array([MijResult0,MijResult1])
1142 MijResults=numpy.array([MijResult0,MijResult1])
1142 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1143 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1143
1144
1144 '''****** Getting constants A, B and H ******'''
1145 '''****** Getting constants A, B and H ******'''
1145 W01=numpy.nanmax( FitGauss01 ) #numpy.abs(CSPCSamples[0]))
1146 W01=numpy.nanmax( FitGauss01 ) #numpy.abs(CSPCSamples[0]))
1146 W02=numpy.nanmax( FitGauss02 ) #numpy.abs(CSPCSamples[1]))
1147 W02=numpy.nanmax( FitGauss02 ) #numpy.abs(CSPCSamples[1]))
1147 W12=numpy.nanmax( FitGauss12 ) #numpy.abs(CSPCSamples[2]))
1148 W12=numpy.nanmax( FitGauss12 ) #numpy.abs(CSPCSamples[2]))
1148
1149
1149 WijResult0=((cF*Xi01+cG*Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi/cC))
1150 WijResult0=((cF*Xi01+cG*Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi/cC))
1150 WijResult1=((cF*Xi02+cG*Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi/cC))
1151 WijResult1=((cF*Xi02+cG*Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi/cC))
1151 WijResult2=((cF*Xi12+cG*Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi/cC))
1152 WijResult2=((cF*Xi12+cG*Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi/cC))
1152
1153
1153 WijResults=numpy.array([WijResult0, WijResult1, WijResult2])
1154 WijResults=numpy.array([WijResult0, WijResult1, WijResult2])
1154
1155
1155 WijEijNij=numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1156 WijEijNij=numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1156 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1157 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1157
1158
1158 VxVy=numpy.array([[cA,cH],[cH,cB]])
1159 VxVy=numpy.array([[cA,cH],[cH,cB]])
1159 VxVyResults=numpy.array([-cF,-cG])
1160 VxVyResults=numpy.array([-cF,-cG])
1160 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1161 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1161
1162
1162 Vzon = Vy
1163 Vzon = Vy
1163 Vmer = Vx
1164 Vmer = Vx
1164 Vmag=numpy.sqrt(Vzon**2+Vmer**2)
1165 Vmag=numpy.sqrt(Vzon**2+Vmer**2)
1165 Vang=numpy.arctan2(Vmer,Vzon)
1166 Vang=numpy.arctan2(Vmer,Vzon)
1166 if numpy.abs( popt[1] ) < 3.5 and len(FrecRange)>4:
1167 if numpy.abs( popt[1] ) < 3.5 and len(FrecRange)>4:
1167 Vver=popt[1]
1168 Vver=popt[1]
1168 else:
1169 else:
1169 Vver=numpy.NaN
1170 Vver=numpy.NaN
1170 FitGaussCSPC = numpy.array([FitGauss01,FitGauss02,FitGauss12])
1171 FitGaussCSPC = numpy.array([FitGauss01,FitGauss02,FitGauss12])
1171
1172
1172
1173
1173 return Vzon, Vmer, Vver, GaussCenter, PhaseSlope, FitGaussCSPC
1174 return Vzon, Vmer, Vver, GaussCenter, PhaseSlope, FitGaussCSPC
1174
1175
1175 class SpectralMoments(Operation):
1176 class SpectralMoments(Operation):
1176
1177
1177 '''
1178 '''
1178 Function SpectralMoments()
1179 Function SpectralMoments()
1179
1180
1180 Calculates moments (power, mean, standard deviation) and SNR of the signal
1181 Calculates moments (power, mean, standard deviation) and SNR of the signal
1181
1182
1182 Type of dataIn: Spectra
1183 Type of dataIn: Spectra
1183
1184
1184 Configuration Parameters:
1185 Configuration Parameters:
1185
1186
1186 dirCosx : Cosine director in X axis
1187 dirCosx : Cosine director in X axis
1187 dirCosy : Cosine director in Y axis
1188 dirCosy : Cosine director in Y axis
1188
1189
1189 elevation :
1190 elevation :
1190 azimuth :
1191 azimuth :
1191
1192
1192 Input:
1193 Input:
1193 channelList : simple channel list to select e.g. [2,3,7]
1194 channelList : simple channel list to select e.g. [2,3,7]
1194 self.dataOut.data_pre : Spectral data
1195 self.dataOut.data_pre : Spectral data
1195 self.dataOut.abscissaList : List of frequencies
1196 self.dataOut.abscissaList : List of frequencies
1196 self.dataOut.noise : Noise level per channel
1197 self.dataOut.noise : Noise level per channel
1197
1198
1198 Affected:
1199 Affected:
1199 self.dataOut.moments : Parameters per channel
1200 self.dataOut.moments : Parameters per channel
1200 self.dataOut.data_SNR : SNR per channel
1201 self.dataOut.data_SNR : SNR per channel
1201
1202
1202 '''
1203 '''
1203
1204
1204 def run(self, dataOut):
1205 def run(self, dataOut):
1205
1206
1206 #dataOut.data_pre = dataOut.data_pre[0]
1207 #dataOut.data_pre = dataOut.data_pre[0]
1207 data = dataOut.data_pre[0]
1208 data = dataOut.data_pre[0]
1208 absc = dataOut.abscissaList[:-1]
1209 absc = dataOut.abscissaList[:-1]
1209 noise = dataOut.noise
1210 noise = dataOut.noise
1210 nChannel = data.shape[0]
1211 nChannel = data.shape[0]
1211 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1212 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1212
1213
1213 for ind in range(nChannel):
1214 for ind in range(nChannel):
1214 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1215 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1215
1216
1216 dataOut.moments = data_param[:,1:,:]
1217 dataOut.moments = data_param[:,1:,:]
1217 dataOut.data_SNR = data_param[:,0]
1218 dataOut.data_SNR = data_param[:,0]
1218 dataOut.data_POW = data_param[:,1]
1219 dataOut.data_POW = data_param[:,1]
1219 dataOut.data_DOP = data_param[:,2]
1220 dataOut.data_DOP = data_param[:,2]
1220 dataOut.data_WIDTH = data_param[:,3]
1221 dataOut.data_WIDTH = data_param[:,3]
1221 return dataOut
1222 return dataOut
1222
1223
1223 def __calculateMoments(self, oldspec, oldfreq, n0,
1224 def __calculateMoments(self, oldspec, oldfreq, n0,
1224 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1225 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1225
1226
1226 if (nicoh is None): nicoh = 1
1227 if (nicoh is None): nicoh = 1
1227 if (graph is None): graph = 0
1228 if (graph is None): graph = 0
1228 if (smooth is None): smooth = 0
1229 if (smooth is None): smooth = 0
1229 elif (self.smooth < 3): smooth = 0
1230 elif (self.smooth < 3): smooth = 0
1230
1231
1231 if (type1 is None): type1 = 0
1232 if (type1 is None): type1 = 0
1232 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1233 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1233 if (snrth is None): snrth = -3
1234 if (snrth is None): snrth = -3
1234 if (dc is None): dc = 0
1235 if (dc is None): dc = 0
1235 if (aliasing is None): aliasing = 0
1236 if (aliasing is None): aliasing = 0
1236 if (oldfd is None): oldfd = 0
1237 if (oldfd is None): oldfd = 0
1237 if (wwauto is None): wwauto = 0
1238 if (wwauto is None): wwauto = 0
1238
1239
1239 if (n0 < 1.e-20): n0 = 1.e-20
1240 if (n0 < 1.e-20): n0 = 1.e-20
1240
1241
1241 freq = oldfreq
1242 freq = oldfreq
1242 vec_power = numpy.zeros(oldspec.shape[1])
1243 vec_power = numpy.zeros(oldspec.shape[1])
1243 vec_fd = numpy.zeros(oldspec.shape[1])
1244 vec_fd = numpy.zeros(oldspec.shape[1])
1244 vec_w = numpy.zeros(oldspec.shape[1])
1245 vec_w = numpy.zeros(oldspec.shape[1])
1245 vec_snr = numpy.zeros(oldspec.shape[1])
1246 vec_snr = numpy.zeros(oldspec.shape[1])
1246
1247
1247 oldspec = numpy.ma.masked_invalid(oldspec)
1248 oldspec = numpy.ma.masked_invalid(oldspec)
1248
1249
1249 for ind in range(oldspec.shape[1]):
1250 for ind in range(oldspec.shape[1]):
1250
1251
1251 spec = oldspec[:,ind]
1252 spec = oldspec[:,ind]
1252 aux = spec*fwindow
1253 aux = spec*fwindow
1253 max_spec = aux.max()
1254 max_spec = aux.max()
1254 m = list(aux).index(max_spec)
1255 m = list(aux).index(max_spec)
1255
1256
1256 #Smooth
1257 #Smooth
1257 if (smooth == 0): spec2 = spec
1258 if (smooth == 0): spec2 = spec
1258 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1259 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1259
1260
1260 # Calculo de Momentos
1261 # Calculo de Momentos
1261 bb = spec2[list(range(m,spec2.size))]
1262 bb = spec2[list(range(m,spec2.size))]
1262 bb = (bb<n0).nonzero()
1263 bb = (bb<n0).nonzero()
1263 bb = bb[0]
1264 bb = bb[0]
1264
1265
1265 ss = spec2[list(range(0,m + 1))]
1266 ss = spec2[list(range(0,m + 1))]
1266 ss = (ss<n0).nonzero()
1267 ss = (ss<n0).nonzero()
1267 ss = ss[0]
1268 ss = ss[0]
1268
1269
1269 if (bb.size == 0):
1270 if (bb.size == 0):
1270 bb0 = spec.size - 1 - m
1271 bb0 = spec.size - 1 - m
1271 else:
1272 else:
1272 bb0 = bb[0] - 1
1273 bb0 = bb[0] - 1
1273 if (bb0 < 0):
1274 if (bb0 < 0):
1274 bb0 = 0
1275 bb0 = 0
1275
1276
1276 if (ss.size == 0): ss1 = 1
1277 if (ss.size == 0): ss1 = 1
1277 else: ss1 = max(ss) + 1
1278 else: ss1 = max(ss) + 1
1278
1279
1279 if (ss1 > m): ss1 = m
1280 if (ss1 > m): ss1 = m
1280
1281
1281 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
1282 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
1282 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
1283 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
1283 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
1284 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
1284 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1285 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1285 snr = (spec2.mean()-n0)/n0
1286 snr = (spec2.mean()-n0)/n0
1286
1287
1287 if (snr < 1.e-20) :
1288 if (snr < 1.e-20) :
1288 snr = 1.e-20
1289 snr = 1.e-20
1289
1290
1290 vec_power[ind] = power
1291 vec_power[ind] = power
1291 vec_fd[ind] = fd
1292 vec_fd[ind] = fd
1292 vec_w[ind] = w
1293 vec_w[ind] = w
1293 vec_snr[ind] = snr
1294 vec_snr[ind] = snr
1294
1295
1295 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1296 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1296 return moments
1297 return moments
1297
1298
1298 #------------------ Get SA Parameters --------------------------
1299 #------------------ Get SA Parameters --------------------------
1299
1300
1300 def GetSAParameters(self):
1301 def GetSAParameters(self):
1301 #SA en frecuencia
1302 #SA en frecuencia
1302 pairslist = self.dataOut.groupList
1303 pairslist = self.dataOut.groupList
1303 num_pairs = len(pairslist)
1304 num_pairs = len(pairslist)
1304
1305
1305 vel = self.dataOut.abscissaList
1306 vel = self.dataOut.abscissaList
1306 spectra = self.dataOut.data_pre
1307 spectra = self.dataOut.data_pre
1307 cspectra = self.dataIn.data_cspc
1308 cspectra = self.dataIn.data_cspc
1308 delta_v = vel[1] - vel[0]
1309 delta_v = vel[1] - vel[0]
1309
1310
1310 #Calculating the power spectrum
1311 #Calculating the power spectrum
1311 spc_pow = numpy.sum(spectra, 3)*delta_v
1312 spc_pow = numpy.sum(spectra, 3)*delta_v
1312 #Normalizing Spectra
1313 #Normalizing Spectra
1313 norm_spectra = spectra/spc_pow
1314 norm_spectra = spectra/spc_pow
1314 #Calculating the norm_spectra at peak
1315 #Calculating the norm_spectra at peak
1315 max_spectra = numpy.max(norm_spectra, 3)
1316 max_spectra = numpy.max(norm_spectra, 3)
1316
1317
1317 #Normalizing Cross Spectra
1318 #Normalizing Cross Spectra
1318 norm_cspectra = numpy.zeros(cspectra.shape)
1319 norm_cspectra = numpy.zeros(cspectra.shape)
1319
1320
1320 for i in range(num_chan):
1321 for i in range(num_chan):
1321 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1322 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1322
1323
1323 max_cspectra = numpy.max(norm_cspectra,2)
1324 max_cspectra = numpy.max(norm_cspectra,2)
1324 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1325 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1325
1326
1326 for i in range(num_pairs):
1327 for i in range(num_pairs):
1327 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1328 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1328 #------------------- Get Lags ----------------------------------
1329 #------------------- Get Lags ----------------------------------
1329
1330
1330 class SALags(Operation):
1331 class SALags(Operation):
1331 '''
1332 '''
1332 Function GetMoments()
1333 Function GetMoments()
1333
1334
1334 Input:
1335 Input:
1335 self.dataOut.data_pre
1336 self.dataOut.data_pre
1336 self.dataOut.abscissaList
1337 self.dataOut.abscissaList
1337 self.dataOut.noise
1338 self.dataOut.noise
1338 self.dataOut.normFactor
1339 self.dataOut.normFactor
1339 self.dataOut.data_SNR
1340 self.dataOut.data_SNR
1340 self.dataOut.groupList
1341 self.dataOut.groupList
1341 self.dataOut.nChannels
1342 self.dataOut.nChannels
1342
1343
1343 Affected:
1344 Affected:
1344 self.dataOut.data_param
1345 self.dataOut.data_param
1345
1346
1346 '''
1347 '''
1347 def run(self, dataOut):
1348 def run(self, dataOut):
1348 data_acf = dataOut.data_pre[0]
1349 data_acf = dataOut.data_pre[0]
1349 data_ccf = dataOut.data_pre[1]
1350 data_ccf = dataOut.data_pre[1]
1350 normFactor_acf = dataOut.normFactor[0]
1351 normFactor_acf = dataOut.normFactor[0]
1351 normFactor_ccf = dataOut.normFactor[1]
1352 normFactor_ccf = dataOut.normFactor[1]
1352 pairs_acf = dataOut.groupList[0]
1353 pairs_acf = dataOut.groupList[0]
1353 pairs_ccf = dataOut.groupList[1]
1354 pairs_ccf = dataOut.groupList[1]
1354
1355
1355 nHeights = dataOut.nHeights
1356 nHeights = dataOut.nHeights
1356 absc = dataOut.abscissaList
1357 absc = dataOut.abscissaList
1357 noise = dataOut.noise
1358 noise = dataOut.noise
1358 SNR = dataOut.data_SNR
1359 SNR = dataOut.data_SNR
1359 nChannels = dataOut.nChannels
1360 nChannels = dataOut.nChannels
1360 # pairsList = dataOut.groupList
1361 # pairsList = dataOut.groupList
1361 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1362 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1362
1363
1363 for l in range(len(pairs_acf)):
1364 for l in range(len(pairs_acf)):
1364 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1365 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1365
1366
1366 for l in range(len(pairs_ccf)):
1367 for l in range(len(pairs_ccf)):
1367 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1368 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1368
1369
1369 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1370 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1370 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1371 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1371 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1372 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1372 return
1373 return
1373
1374
1374 # def __getPairsAutoCorr(self, pairsList, nChannels):
1375 # def __getPairsAutoCorr(self, pairsList, nChannels):
1375 #
1376 #
1376 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1377 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1377 #
1378 #
1378 # for l in range(len(pairsList)):
1379 # for l in range(len(pairsList)):
1379 # firstChannel = pairsList[l][0]
1380 # firstChannel = pairsList[l][0]
1380 # secondChannel = pairsList[l][1]
1381 # secondChannel = pairsList[l][1]
1381 #
1382 #
1382 # #Obteniendo pares de Autocorrelacion
1383 # #Obteniendo pares de Autocorrelacion
1383 # if firstChannel == secondChannel:
1384 # if firstChannel == secondChannel:
1384 # pairsAutoCorr[firstChannel] = int(l)
1385 # pairsAutoCorr[firstChannel] = int(l)
1385 #
1386 #
1386 # pairsAutoCorr = pairsAutoCorr.astype(int)
1387 # pairsAutoCorr = pairsAutoCorr.astype(int)
1387 #
1388 #
1388 # pairsCrossCorr = range(len(pairsList))
1389 # pairsCrossCorr = range(len(pairsList))
1389 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1390 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1390 #
1391 #
1391 # return pairsAutoCorr, pairsCrossCorr
1392 # return pairsAutoCorr, pairsCrossCorr
1392
1393
1393 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1394 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1394
1395
1395 lag0 = data_acf.shape[1]/2
1396 lag0 = data_acf.shape[1]/2
1396 #Funcion de Autocorrelacion
1397 #Funcion de Autocorrelacion
1397 mean_acf = stats.nanmean(data_acf, axis = 0)
1398 mean_acf = stats.nanmean(data_acf, axis = 0)
1398
1399
1399 #Obtencion Indice de TauCross
1400 #Obtencion Indice de TauCross
1400 ind_ccf = data_ccf.argmax(axis = 1)
1401 ind_ccf = data_ccf.argmax(axis = 1)
1401 #Obtencion Indice de TauAuto
1402 #Obtencion Indice de TauAuto
1402 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1403 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1403 ccf_lag0 = data_ccf[:,lag0,:]
1404 ccf_lag0 = data_ccf[:,lag0,:]
1404
1405
1405 for i in range(ccf_lag0.shape[0]):
1406 for i in range(ccf_lag0.shape[0]):
1406 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1407 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1407
1408
1408 #Obtencion de TauCross y TauAuto
1409 #Obtencion de TauCross y TauAuto
1409 tau_ccf = lagRange[ind_ccf]
1410 tau_ccf = lagRange[ind_ccf]
1410 tau_acf = lagRange[ind_acf]
1411 tau_acf = lagRange[ind_acf]
1411
1412
1412 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1413 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1413
1414
1414 tau_ccf[Nan1,Nan2] = numpy.nan
1415 tau_ccf[Nan1,Nan2] = numpy.nan
1415 tau_acf[Nan1,Nan2] = numpy.nan
1416 tau_acf[Nan1,Nan2] = numpy.nan
1416 tau = numpy.vstack((tau_ccf,tau_acf))
1417 tau = numpy.vstack((tau_ccf,tau_acf))
1417
1418
1418 return tau
1419 return tau
1419
1420
1420 def __calculateLag1Phase(self, data, lagTRange):
1421 def __calculateLag1Phase(self, data, lagTRange):
1421 data1 = stats.nanmean(data, axis = 0)
1422 data1 = stats.nanmean(data, axis = 0)
1422 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1423 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1423
1424
1424 phase = numpy.angle(data1[lag1,:])
1425 phase = numpy.angle(data1[lag1,:])
1425
1426
1426 return phase
1427 return phase
1427
1428
1428 class SpectralFitting(Operation):
1429 class SpectralFitting(Operation):
1429 '''
1430 '''
1430 Function GetMoments()
1431 Function GetMoments()
1431
1432
1432 Input:
1433 Input:
1433 Output:
1434 Output:
1434 Variables modified:
1435 Variables modified:
1435 '''
1436 '''
1436
1437
1437 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1438 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1438
1439
1439
1440
1440 if path != None:
1441 if path != None:
1441 sys.path.append(path)
1442 sys.path.append(path)
1442 self.dataOut.library = importlib.import_module(file)
1443 self.dataOut.library = importlib.import_module(file)
1443
1444
1444 #To be inserted as a parameter
1445 #To be inserted as a parameter
1445 groupArray = numpy.array(groupList)
1446 groupArray = numpy.array(groupList)
1446 # groupArray = numpy.array([[0,1],[2,3]])
1447 # groupArray = numpy.array([[0,1],[2,3]])
1447 self.dataOut.groupList = groupArray
1448 self.dataOut.groupList = groupArray
1448
1449
1449 nGroups = groupArray.shape[0]
1450 nGroups = groupArray.shape[0]
1450 nChannels = self.dataIn.nChannels
1451 nChannels = self.dataIn.nChannels
1451 nHeights=self.dataIn.heightList.size
1452 nHeights=self.dataIn.heightList.size
1452
1453
1453 #Parameters Array
1454 #Parameters Array
1454 self.dataOut.data_param = None
1455 self.dataOut.data_param = None
1455
1456
1456 #Set constants
1457 #Set constants
1457 constants = self.dataOut.library.setConstants(self.dataIn)
1458 constants = self.dataOut.library.setConstants(self.dataIn)
1458 self.dataOut.constants = constants
1459 self.dataOut.constants = constants
1459 M = self.dataIn.normFactor
1460 M = self.dataIn.normFactor
1460 N = self.dataIn.nFFTPoints
1461 N = self.dataIn.nFFTPoints
1461 ippSeconds = self.dataIn.ippSeconds
1462 ippSeconds = self.dataIn.ippSeconds
1462 K = self.dataIn.nIncohInt
1463 K = self.dataIn.nIncohInt
1463 pairsArray = numpy.array(self.dataIn.pairsList)
1464 pairsArray = numpy.array(self.dataIn.pairsList)
1464
1465
1465 #List of possible combinations
1466 #List of possible combinations
1466 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1467 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1467 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1468 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1468
1469
1469 if getSNR:
1470 if getSNR:
1470 listChannels = groupArray.reshape((groupArray.size))
1471 listChannels = groupArray.reshape((groupArray.size))
1471 listChannels.sort()
1472 listChannels.sort()
1472 noise = self.dataIn.getNoise()
1473 noise = self.dataIn.getNoise()
1473 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1474 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1474
1475
1475 for i in range(nGroups):
1476 for i in range(nGroups):
1476 coord = groupArray[i,:]
1477 coord = groupArray[i,:]
1477
1478
1478 #Input data array
1479 #Input data array
1479 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1480 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1480 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1481 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1481
1482
1482 #Cross Spectra data array for Covariance Matrixes
1483 #Cross Spectra data array for Covariance Matrixes
1483 ind = 0
1484 ind = 0
1484 for pairs in listComb:
1485 for pairs in listComb:
1485 pairsSel = numpy.array([coord[x],coord[y]])
1486 pairsSel = numpy.array([coord[x],coord[y]])
1486 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1487 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1487 ind += 1
1488 ind += 1
1488 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1489 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1489 dataCross = dataCross**2/K
1490 dataCross = dataCross**2/K
1490
1491
1491 for h in range(nHeights):
1492 for h in range(nHeights):
1492
1493
1493 #Input
1494 #Input
1494 d = data[:,h]
1495 d = data[:,h]
1495
1496
1496 #Covariance Matrix
1497 #Covariance Matrix
1497 D = numpy.diag(d**2/K)
1498 D = numpy.diag(d**2/K)
1498 ind = 0
1499 ind = 0
1499 for pairs in listComb:
1500 for pairs in listComb:
1500 #Coordinates in Covariance Matrix
1501 #Coordinates in Covariance Matrix
1501 x = pairs[0]
1502 x = pairs[0]
1502 y = pairs[1]
1503 y = pairs[1]
1503 #Channel Index
1504 #Channel Index
1504 S12 = dataCross[ind,:,h]
1505 S12 = dataCross[ind,:,h]
1505 D12 = numpy.diag(S12)
1506 D12 = numpy.diag(S12)
1506 #Completing Covariance Matrix with Cross Spectras
1507 #Completing Covariance Matrix with Cross Spectras
1507 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1508 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1508 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1509 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1509 ind += 1
1510 ind += 1
1510 Dinv=numpy.linalg.inv(D)
1511 Dinv=numpy.linalg.inv(D)
1511 L=numpy.linalg.cholesky(Dinv)
1512 L=numpy.linalg.cholesky(Dinv)
1512 LT=L.T
1513 LT=L.T
1513
1514
1514 dp = numpy.dot(LT,d)
1515 dp = numpy.dot(LT,d)
1515
1516
1516 #Initial values
1517 #Initial values
1517 data_spc = self.dataIn.data_spc[coord,:,h]
1518 data_spc = self.dataIn.data_spc[coord,:,h]
1518
1519
1519 if (h>0)and(error1[3]<5):
1520 if (h>0)and(error1[3]<5):
1520 p0 = self.dataOut.data_param[i,:,h-1]
1521 p0 = self.dataOut.data_param[i,:,h-1]
1521 else:
1522 else:
1522 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1523 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1523
1524
1524 try:
1525 try:
1525 #Least Squares
1526 #Least Squares
1526 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1527 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1527 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1528 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1528 #Chi square error
1529 #Chi square error
1529 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1530 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1530 #Error with Jacobian
1531 #Error with Jacobian
1531 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1532 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1532 except:
1533 except:
1533 minp = p0*numpy.nan
1534 minp = p0*numpy.nan
1534 error0 = numpy.nan
1535 error0 = numpy.nan
1535 error1 = p0*numpy.nan
1536 error1 = p0*numpy.nan
1536
1537
1537 #Save
1538 #Save
1538 if self.dataOut.data_param is None:
1539 if self.dataOut.data_param is None:
1539 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1540 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1540 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1541 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1541
1542
1542 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1543 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1543 self.dataOut.data_param[i,:,h] = minp
1544 self.dataOut.data_param[i,:,h] = minp
1544 return
1545 return
1545
1546
1546 def __residFunction(self, p, dp, LT, constants):
1547 def __residFunction(self, p, dp, LT, constants):
1547
1548
1548 fm = self.dataOut.library.modelFunction(p, constants)
1549 fm = self.dataOut.library.modelFunction(p, constants)
1549 fmp=numpy.dot(LT,fm)
1550 fmp=numpy.dot(LT,fm)
1550
1551
1551 return dp-fmp
1552 return dp-fmp
1552
1553
1553 def __getSNR(self, z, noise):
1554 def __getSNR(self, z, noise):
1554
1555
1555 avg = numpy.average(z, axis=1)
1556 avg = numpy.average(z, axis=1)
1556 SNR = (avg.T-noise)/noise
1557 SNR = (avg.T-noise)/noise
1557 SNR = SNR.T
1558 SNR = SNR.T
1558 return SNR
1559 return SNR
1559
1560
1560 def __chisq(p,chindex,hindex):
1561 def __chisq(p,chindex,hindex):
1561 #similar to Resid but calculates CHI**2
1562 #similar to Resid but calculates CHI**2
1562 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1563 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1563 dp=numpy.dot(LT,d)
1564 dp=numpy.dot(LT,d)
1564 fmp=numpy.dot(LT,fm)
1565 fmp=numpy.dot(LT,fm)
1565 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1566 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1566 return chisq
1567 return chisq
1567
1568
1568 class WindProfiler(Operation):
1569 class WindProfiler(Operation):
1569
1570
1570 __isConfig = False
1571 __isConfig = False
1571
1572
1572 __initime = None
1573 __initime = None
1573 __lastdatatime = None
1574 __lastdatatime = None
1574 __integrationtime = None
1575 __integrationtime = None
1575
1576
1576 __buffer = None
1577 __buffer = None
1577
1578
1578 __dataReady = False
1579 __dataReady = False
1579
1580
1580 __firstdata = None
1581 __firstdata = None
1581
1582
1582 n = None
1583 n = None
1583
1584
1584 def __init__(self):
1585 def __init__(self):
1585 Operation.__init__(self)
1586 Operation.__init__(self)
1586
1587
1587 def __calculateCosDir(self, elev, azim):
1588 def __calculateCosDir(self, elev, azim):
1588 zen = (90 - elev)*numpy.pi/180
1589 zen = (90 - elev)*numpy.pi/180
1589 azim = azim*numpy.pi/180
1590 azim = azim*numpy.pi/180
1590 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1591 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1591 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1592 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1592
1593
1593 signX = numpy.sign(numpy.cos(azim))
1594 signX = numpy.sign(numpy.cos(azim))
1594 signY = numpy.sign(numpy.sin(azim))
1595 signY = numpy.sign(numpy.sin(azim))
1595
1596
1596 cosDirX = numpy.copysign(cosDirX, signX)
1597 cosDirX = numpy.copysign(cosDirX, signX)
1597 cosDirY = numpy.copysign(cosDirY, signY)
1598 cosDirY = numpy.copysign(cosDirY, signY)
1598 return cosDirX, cosDirY
1599 return cosDirX, cosDirY
1599
1600
1600 def __calculateAngles(self, theta_x, theta_y, azimuth):
1601 def __calculateAngles(self, theta_x, theta_y, azimuth):
1601
1602
1602 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1603 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1603 zenith_arr = numpy.arccos(dir_cosw)
1604 zenith_arr = numpy.arccos(dir_cosw)
1604 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1605 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1605
1606
1606 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1607 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1607 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1608 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1608
1609
1609 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1610 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1610
1611
1611 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1612 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1612
1613
1613 #
1614 #
1614 if horOnly:
1615 if horOnly:
1615 A = numpy.c_[dir_cosu,dir_cosv]
1616 A = numpy.c_[dir_cosu,dir_cosv]
1616 else:
1617 else:
1617 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1618 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1618 A = numpy.asmatrix(A)
1619 A = numpy.asmatrix(A)
1619 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1620 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1620
1621
1621 return A1
1622 return A1
1622
1623
1623 def __correctValues(self, heiRang, phi, velRadial, SNR):
1624 def __correctValues(self, heiRang, phi, velRadial, SNR):
1624 listPhi = phi.tolist()
1625 listPhi = phi.tolist()
1625 maxid = listPhi.index(max(listPhi))
1626 maxid = listPhi.index(max(listPhi))
1626 minid = listPhi.index(min(listPhi))
1627 minid = listPhi.index(min(listPhi))
1627
1628
1628 rango = list(range(len(phi)))
1629 rango = list(range(len(phi)))
1629 # rango = numpy.delete(rango,maxid)
1630 # rango = numpy.delete(rango,maxid)
1630
1631
1631 heiRang1 = heiRang*math.cos(phi[maxid])
1632 heiRang1 = heiRang*math.cos(phi[maxid])
1632 heiRangAux = heiRang*math.cos(phi[minid])
1633 heiRangAux = heiRang*math.cos(phi[minid])
1633 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1634 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1634 heiRang1 = numpy.delete(heiRang1,indOut)
1635 heiRang1 = numpy.delete(heiRang1,indOut)
1635
1636
1636 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1637 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1637 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1638 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1638
1639
1639 for i in rango:
1640 for i in rango:
1640 x = heiRang*math.cos(phi[i])
1641 x = heiRang*math.cos(phi[i])
1641 y1 = velRadial[i,:]
1642 y1 = velRadial[i,:]
1642 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1643 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1643
1644
1644 x1 = heiRang1
1645 x1 = heiRang1
1645 y11 = f1(x1)
1646 y11 = f1(x1)
1646
1647
1647 y2 = SNR[i,:]
1648 y2 = SNR[i,:]
1648 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1649 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1649 y21 = f2(x1)
1650 y21 = f2(x1)
1650
1651
1651 velRadial1[i,:] = y11
1652 velRadial1[i,:] = y11
1652 SNR1[i,:] = y21
1653 SNR1[i,:] = y21
1653
1654
1654 return heiRang1, velRadial1, SNR1
1655 return heiRang1, velRadial1, SNR1
1655
1656
1656 def __calculateVelUVW(self, A, velRadial):
1657 def __calculateVelUVW(self, A, velRadial):
1657
1658
1658 #Operacion Matricial
1659 #Operacion Matricial
1659 # velUVW = numpy.zeros((velRadial.shape[1],3))
1660 # velUVW = numpy.zeros((velRadial.shape[1],3))
1660 # for ind in range(velRadial.shape[1]):
1661 # for ind in range(velRadial.shape[1]):
1661 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1662 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1662 # velUVW = velUVW.transpose()
1663 # velUVW = velUVW.transpose()
1663 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1664 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1664 velUVW[:,:] = numpy.dot(A,velRadial)
1665 velUVW[:,:] = numpy.dot(A,velRadial)
1665
1666
1666
1667
1667 return velUVW
1668 return velUVW
1668
1669
1669 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1670 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1670
1671
1671 def techniqueDBS(self, kwargs):
1672 def techniqueDBS(self, kwargs):
1672 """
1673 """
1673 Function that implements Doppler Beam Swinging (DBS) technique.
1674 Function that implements Doppler Beam Swinging (DBS) technique.
1674
1675
1675 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1676 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1676 Direction correction (if necessary), Ranges and SNR
1677 Direction correction (if necessary), Ranges and SNR
1677
1678
1678 Output: Winds estimation (Zonal, Meridional and Vertical)
1679 Output: Winds estimation (Zonal, Meridional and Vertical)
1679
1680
1680 Parameters affected: Winds, height range, SNR
1681 Parameters affected: Winds, height range, SNR
1681 """
1682 """
1682 velRadial0 = kwargs['velRadial']
1683 velRadial0 = kwargs['velRadial']
1683 heiRang = kwargs['heightList']
1684 heiRang = kwargs['heightList']
1684 SNR0 = kwargs['SNR']
1685 SNR0 = kwargs['SNR']
1685
1686
1686 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1687 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1687 theta_x = numpy.array(kwargs['dirCosx'])
1688 theta_x = numpy.array(kwargs['dirCosx'])
1688 theta_y = numpy.array(kwargs['dirCosy'])
1689 theta_y = numpy.array(kwargs['dirCosy'])
1689 else:
1690 else:
1690 elev = numpy.array(kwargs['elevation'])
1691 elev = numpy.array(kwargs['elevation'])
1691 azim = numpy.array(kwargs['azimuth'])
1692 azim = numpy.array(kwargs['azimuth'])
1692 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1693 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1693 azimuth = kwargs['correctAzimuth']
1694 azimuth = kwargs['correctAzimuth']
1694 if 'horizontalOnly' in kwargs:
1695 if 'horizontalOnly' in kwargs:
1695 horizontalOnly = kwargs['horizontalOnly']
1696 horizontalOnly = kwargs['horizontalOnly']
1696 else: horizontalOnly = False
1697 else: horizontalOnly = False
1697 if 'correctFactor' in kwargs:
1698 if 'correctFactor' in kwargs:
1698 correctFactor = kwargs['correctFactor']
1699 correctFactor = kwargs['correctFactor']
1699 else: correctFactor = 1
1700 else: correctFactor = 1
1700 if 'channelList' in kwargs:
1701 if 'channelList' in kwargs:
1701 channelList = kwargs['channelList']
1702 channelList = kwargs['channelList']
1702 if len(channelList) == 2:
1703 if len(channelList) == 2:
1703 horizontalOnly = True
1704 horizontalOnly = True
1704 arrayChannel = numpy.array(channelList)
1705 arrayChannel = numpy.array(channelList)
1705 param = param[arrayChannel,:,:]
1706 param = param[arrayChannel,:,:]
1706 theta_x = theta_x[arrayChannel]
1707 theta_x = theta_x[arrayChannel]
1707 theta_y = theta_y[arrayChannel]
1708 theta_y = theta_y[arrayChannel]
1708
1709
1709 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1710 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1710 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1711 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1711 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1712 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1712
1713
1713 #Calculo de Componentes de la velocidad con DBS
1714 #Calculo de Componentes de la velocidad con DBS
1714 winds = self.__calculateVelUVW(A,velRadial1)
1715 winds = self.__calculateVelUVW(A,velRadial1)
1715
1716
1716 return winds, heiRang1, SNR1
1717 return winds, heiRang1, SNR1
1717
1718
1718 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1719 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1719
1720
1720 nPairs = len(pairs_ccf)
1721 nPairs = len(pairs_ccf)
1721 posx = numpy.asarray(posx)
1722 posx = numpy.asarray(posx)
1722 posy = numpy.asarray(posy)
1723 posy = numpy.asarray(posy)
1723
1724
1724 #Rotacion Inversa para alinear con el azimuth
1725 #Rotacion Inversa para alinear con el azimuth
1725 if azimuth!= None:
1726 if azimuth!= None:
1726 azimuth = azimuth*math.pi/180
1727 azimuth = azimuth*math.pi/180
1727 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1728 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1728 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1729 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1729 else:
1730 else:
1730 posx1 = posx
1731 posx1 = posx
1731 posy1 = posy
1732 posy1 = posy
1732
1733
1733 #Calculo de Distancias
1734 #Calculo de Distancias
1734 distx = numpy.zeros(nPairs)
1735 distx = numpy.zeros(nPairs)
1735 disty = numpy.zeros(nPairs)
1736 disty = numpy.zeros(nPairs)
1736 dist = numpy.zeros(nPairs)
1737 dist = numpy.zeros(nPairs)
1737 ang = numpy.zeros(nPairs)
1738 ang = numpy.zeros(nPairs)
1738
1739
1739 for i in range(nPairs):
1740 for i in range(nPairs):
1740 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1741 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1741 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1742 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1742 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1743 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1743 ang[i] = numpy.arctan2(disty[i],distx[i])
1744 ang[i] = numpy.arctan2(disty[i],distx[i])
1744
1745
1745 return distx, disty, dist, ang
1746 return distx, disty, dist, ang
1746 #Calculo de Matrices
1747 #Calculo de Matrices
1747 # nPairs = len(pairs)
1748 # nPairs = len(pairs)
1748 # ang1 = numpy.zeros((nPairs, 2, 1))
1749 # ang1 = numpy.zeros((nPairs, 2, 1))
1749 # dist1 = numpy.zeros((nPairs, 2, 1))
1750 # dist1 = numpy.zeros((nPairs, 2, 1))
1750 #
1751 #
1751 # for j in range(nPairs):
1752 # for j in range(nPairs):
1752 # dist1[j,0,0] = dist[pairs[j][0]]
1753 # dist1[j,0,0] = dist[pairs[j][0]]
1753 # dist1[j,1,0] = dist[pairs[j][1]]
1754 # dist1[j,1,0] = dist[pairs[j][1]]
1754 # ang1[j,0,0] = ang[pairs[j][0]]
1755 # ang1[j,0,0] = ang[pairs[j][0]]
1755 # ang1[j,1,0] = ang[pairs[j][1]]
1756 # ang1[j,1,0] = ang[pairs[j][1]]
1756 #
1757 #
1757 # return distx,disty, dist1,ang1
1758 # return distx,disty, dist1,ang1
1758
1759
1759
1760
1760 def __calculateVelVer(self, phase, lagTRange, _lambda):
1761 def __calculateVelVer(self, phase, lagTRange, _lambda):
1761
1762
1762 Ts = lagTRange[1] - lagTRange[0]
1763 Ts = lagTRange[1] - lagTRange[0]
1763 velW = -_lambda*phase/(4*math.pi*Ts)
1764 velW = -_lambda*phase/(4*math.pi*Ts)
1764
1765
1765 return velW
1766 return velW
1766
1767
1767 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1768 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1768 nPairs = tau1.shape[0]
1769 nPairs = tau1.shape[0]
1769 nHeights = tau1.shape[1]
1770 nHeights = tau1.shape[1]
1770 vel = numpy.zeros((nPairs,3,nHeights))
1771 vel = numpy.zeros((nPairs,3,nHeights))
1771 dist1 = numpy.reshape(dist, (dist.size,1))
1772 dist1 = numpy.reshape(dist, (dist.size,1))
1772
1773
1773 angCos = numpy.cos(ang)
1774 angCos = numpy.cos(ang)
1774 angSin = numpy.sin(ang)
1775 angSin = numpy.sin(ang)
1775
1776
1776 vel0 = dist1*tau1/(2*tau2**2)
1777 vel0 = dist1*tau1/(2*tau2**2)
1777 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1778 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1778 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1779 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1779
1780
1780 ind = numpy.where(numpy.isinf(vel))
1781 ind = numpy.where(numpy.isinf(vel))
1781 vel[ind] = numpy.nan
1782 vel[ind] = numpy.nan
1782
1783
1783 return vel
1784 return vel
1784
1785
1785 # def __getPairsAutoCorr(self, pairsList, nChannels):
1786 # def __getPairsAutoCorr(self, pairsList, nChannels):
1786 #
1787 #
1787 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1788 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1788 #
1789 #
1789 # for l in range(len(pairsList)):
1790 # for l in range(len(pairsList)):
1790 # firstChannel = pairsList[l][0]
1791 # firstChannel = pairsList[l][0]
1791 # secondChannel = pairsList[l][1]
1792 # secondChannel = pairsList[l][1]
1792 #
1793 #
1793 # #Obteniendo pares de Autocorrelacion
1794 # #Obteniendo pares de Autocorrelacion
1794 # if firstChannel == secondChannel:
1795 # if firstChannel == secondChannel:
1795 # pairsAutoCorr[firstChannel] = int(l)
1796 # pairsAutoCorr[firstChannel] = int(l)
1796 #
1797 #
1797 # pairsAutoCorr = pairsAutoCorr.astype(int)
1798 # pairsAutoCorr = pairsAutoCorr.astype(int)
1798 #
1799 #
1799 # pairsCrossCorr = range(len(pairsList))
1800 # pairsCrossCorr = range(len(pairsList))
1800 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1801 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1801 #
1802 #
1802 # return pairsAutoCorr, pairsCrossCorr
1803 # return pairsAutoCorr, pairsCrossCorr
1803
1804
1804 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1805 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1805 def techniqueSA(self, kwargs):
1806 def techniqueSA(self, kwargs):
1806
1807
1807 """
1808 """
1808 Function that implements Spaced Antenna (SA) technique.
1809 Function that implements Spaced Antenna (SA) technique.
1809
1810
1810 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1811 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1811 Direction correction (if necessary), Ranges and SNR
1812 Direction correction (if necessary), Ranges and SNR
1812
1813
1813 Output: Winds estimation (Zonal, Meridional and Vertical)
1814 Output: Winds estimation (Zonal, Meridional and Vertical)
1814
1815
1815 Parameters affected: Winds
1816 Parameters affected: Winds
1816 """
1817 """
1817 position_x = kwargs['positionX']
1818 position_x = kwargs['positionX']
1818 position_y = kwargs['positionY']
1819 position_y = kwargs['positionY']
1819 azimuth = kwargs['azimuth']
1820 azimuth = kwargs['azimuth']
1820
1821
1821 if 'correctFactor' in kwargs:
1822 if 'correctFactor' in kwargs:
1822 correctFactor = kwargs['correctFactor']
1823 correctFactor = kwargs['correctFactor']
1823 else:
1824 else:
1824 correctFactor = 1
1825 correctFactor = 1
1825
1826
1826 groupList = kwargs['groupList']
1827 groupList = kwargs['groupList']
1827 pairs_ccf = groupList[1]
1828 pairs_ccf = groupList[1]
1828 tau = kwargs['tau']
1829 tau = kwargs['tau']
1829 _lambda = kwargs['_lambda']
1830 _lambda = kwargs['_lambda']
1830
1831
1831 #Cross Correlation pairs obtained
1832 #Cross Correlation pairs obtained
1832 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1833 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1833 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1834 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1834 # pairsSelArray = numpy.array(pairsSelected)
1835 # pairsSelArray = numpy.array(pairsSelected)
1835 # pairs = []
1836 # pairs = []
1836 #
1837 #
1837 # #Wind estimation pairs obtained
1838 # #Wind estimation pairs obtained
1838 # for i in range(pairsSelArray.shape[0]/2):
1839 # for i in range(pairsSelArray.shape[0]/2):
1839 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1840 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1840 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1841 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1841 # pairs.append((ind1,ind2))
1842 # pairs.append((ind1,ind2))
1842
1843
1843 indtau = tau.shape[0]/2
1844 indtau = tau.shape[0]/2
1844 tau1 = tau[:indtau,:]
1845 tau1 = tau[:indtau,:]
1845 tau2 = tau[indtau:-1,:]
1846 tau2 = tau[indtau:-1,:]
1846 # tau1 = tau1[pairs,:]
1847 # tau1 = tau1[pairs,:]
1847 # tau2 = tau2[pairs,:]
1848 # tau2 = tau2[pairs,:]
1848 phase1 = tau[-1,:]
1849 phase1 = tau[-1,:]
1849
1850
1850 #---------------------------------------------------------------------
1851 #---------------------------------------------------------------------
1851 #Metodo Directo
1852 #Metodo Directo
1852 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1853 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1853 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1854 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1854 winds = stats.nanmean(winds, axis=0)
1855 winds = stats.nanmean(winds, axis=0)
1855 #---------------------------------------------------------------------
1856 #---------------------------------------------------------------------
1856 #Metodo General
1857 #Metodo General
1857 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1858 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1858 # #Calculo Coeficientes de Funcion de Correlacion
1859 # #Calculo Coeficientes de Funcion de Correlacion
1859 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1860 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1860 # #Calculo de Velocidades
1861 # #Calculo de Velocidades
1861 # winds = self.calculateVelUV(F,G,A,B,H)
1862 # winds = self.calculateVelUV(F,G,A,B,H)
1862
1863
1863 #---------------------------------------------------------------------
1864 #---------------------------------------------------------------------
1864 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1865 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1865 winds = correctFactor*winds
1866 winds = correctFactor*winds
1866 return winds
1867 return winds
1867
1868
1868 def __checkTime(self, currentTime, paramInterval, outputInterval):
1869 def __checkTime(self, currentTime, paramInterval, outputInterval):
1869
1870
1870 dataTime = currentTime + paramInterval
1871 dataTime = currentTime + paramInterval
1871 deltaTime = dataTime - self.__initime
1872 deltaTime = dataTime - self.__initime
1872
1873
1873 if deltaTime >= outputInterval or deltaTime < 0:
1874 if deltaTime >= outputInterval or deltaTime < 0:
1874 self.__dataReady = True
1875 self.__dataReady = True
1875 return
1876 return
1876
1877
1877 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1878 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1878 '''
1879 '''
1879 Function that implements winds estimation technique with detected meteors.
1880 Function that implements winds estimation technique with detected meteors.
1880
1881
1881 Input: Detected meteors, Minimum meteor quantity to wind estimation
1882 Input: Detected meteors, Minimum meteor quantity to wind estimation
1882
1883
1883 Output: Winds estimation (Zonal and Meridional)
1884 Output: Winds estimation (Zonal and Meridional)
1884
1885
1885 Parameters affected: Winds
1886 Parameters affected: Winds
1886 '''
1887 '''
1887 #Settings
1888 #Settings
1888 nInt = (heightMax - heightMin)/2
1889 nInt = (heightMax - heightMin)/2
1889 nInt = int(nInt)
1890 nInt = int(nInt)
1890 winds = numpy.zeros((2,nInt))*numpy.nan
1891 winds = numpy.zeros((2,nInt))*numpy.nan
1891
1892
1892 #Filter errors
1893 #Filter errors
1893 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1894 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1894 finalMeteor = arrayMeteor[error,:]
1895 finalMeteor = arrayMeteor[error,:]
1895
1896
1896 #Meteor Histogram
1897 #Meteor Histogram
1897 finalHeights = finalMeteor[:,2]
1898 finalHeights = finalMeteor[:,2]
1898 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1899 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1899 nMeteorsPerI = hist[0]
1900 nMeteorsPerI = hist[0]
1900 heightPerI = hist[1]
1901 heightPerI = hist[1]
1901
1902
1902 #Sort of meteors
1903 #Sort of meteors
1903 indSort = finalHeights.argsort()
1904 indSort = finalHeights.argsort()
1904 finalMeteor2 = finalMeteor[indSort,:]
1905 finalMeteor2 = finalMeteor[indSort,:]
1905
1906
1906 # Calculating winds
1907 # Calculating winds
1907 ind1 = 0
1908 ind1 = 0
1908 ind2 = 0
1909 ind2 = 0
1909
1910
1910 for i in range(nInt):
1911 for i in range(nInt):
1911 nMet = nMeteorsPerI[i]
1912 nMet = nMeteorsPerI[i]
1912 ind1 = ind2
1913 ind1 = ind2
1913 ind2 = ind1 + nMet
1914 ind2 = ind1 + nMet
1914
1915
1915 meteorAux = finalMeteor2[ind1:ind2,:]
1916 meteorAux = finalMeteor2[ind1:ind2,:]
1916
1917
1917 if meteorAux.shape[0] >= meteorThresh:
1918 if meteorAux.shape[0] >= meteorThresh:
1918 vel = meteorAux[:, 6]
1919 vel = meteorAux[:, 6]
1919 zen = meteorAux[:, 4]*numpy.pi/180
1920 zen = meteorAux[:, 4]*numpy.pi/180
1920 azim = meteorAux[:, 3]*numpy.pi/180
1921 azim = meteorAux[:, 3]*numpy.pi/180
1921
1922
1922 n = numpy.cos(zen)
1923 n = numpy.cos(zen)
1923 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1924 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1924 # l = m*numpy.tan(azim)
1925 # l = m*numpy.tan(azim)
1925 l = numpy.sin(zen)*numpy.sin(azim)
1926 l = numpy.sin(zen)*numpy.sin(azim)
1926 m = numpy.sin(zen)*numpy.cos(azim)
1927 m = numpy.sin(zen)*numpy.cos(azim)
1927
1928
1928 A = numpy.vstack((l, m)).transpose()
1929 A = numpy.vstack((l, m)).transpose()
1929 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1930 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1930 windsAux = numpy.dot(A1, vel)
1931 windsAux = numpy.dot(A1, vel)
1931
1932
1932 winds[0,i] = windsAux[0]
1933 winds[0,i] = windsAux[0]
1933 winds[1,i] = windsAux[1]
1934 winds[1,i] = windsAux[1]
1934
1935
1935 return winds, heightPerI[:-1]
1936 return winds, heightPerI[:-1]
1936
1937
1937 def techniqueNSM_SA(self, **kwargs):
1938 def techniqueNSM_SA(self, **kwargs):
1938 metArray = kwargs['metArray']
1939 metArray = kwargs['metArray']
1939 heightList = kwargs['heightList']
1940 heightList = kwargs['heightList']
1940 timeList = kwargs['timeList']
1941 timeList = kwargs['timeList']
1941
1942
1942 rx_location = kwargs['rx_location']
1943 rx_location = kwargs['rx_location']
1943 groupList = kwargs['groupList']
1944 groupList = kwargs['groupList']
1944 azimuth = kwargs['azimuth']
1945 azimuth = kwargs['azimuth']
1945 dfactor = kwargs['dfactor']
1946 dfactor = kwargs['dfactor']
1946 k = kwargs['k']
1947 k = kwargs['k']
1947
1948
1948 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1949 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1949 d = dist*dfactor
1950 d = dist*dfactor
1950 #Phase calculation
1951 #Phase calculation
1951 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1952 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1952
1953
1953 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
1954 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
1954
1955
1955 velEst = numpy.zeros((heightList.size,2))*numpy.nan
1956 velEst = numpy.zeros((heightList.size,2))*numpy.nan
1956 azimuth1 = azimuth1*numpy.pi/180
1957 azimuth1 = azimuth1*numpy.pi/180
1957
1958
1958 for i in range(heightList.size):
1959 for i in range(heightList.size):
1959 h = heightList[i]
1960 h = heightList[i]
1960 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
1961 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
1961 metHeight = metArray1[indH,:]
1962 metHeight = metArray1[indH,:]
1962 if metHeight.shape[0] >= 2:
1963 if metHeight.shape[0] >= 2:
1963 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
1964 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
1964 iazim = metHeight[:,1].astype(int)
1965 iazim = metHeight[:,1].astype(int)
1965 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
1966 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
1966 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
1967 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
1967 A = numpy.asmatrix(A)
1968 A = numpy.asmatrix(A)
1968 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
1969 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
1969 velHor = numpy.dot(A1,velAux)
1970 velHor = numpy.dot(A1,velAux)
1970
1971
1971 velEst[i,:] = numpy.squeeze(velHor)
1972 velEst[i,:] = numpy.squeeze(velHor)
1972 return velEst
1973 return velEst
1973
1974
1974 def __getPhaseSlope(self, metArray, heightList, timeList):
1975 def __getPhaseSlope(self, metArray, heightList, timeList):
1975 meteorList = []
1976 meteorList = []
1976 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
1977 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
1977 #Putting back together the meteor matrix
1978 #Putting back together the meteor matrix
1978 utctime = metArray[:,0]
1979 utctime = metArray[:,0]
1979 uniqueTime = numpy.unique(utctime)
1980 uniqueTime = numpy.unique(utctime)
1980
1981
1981 phaseDerThresh = 0.5
1982 phaseDerThresh = 0.5
1982 ippSeconds = timeList[1] - timeList[0]
1983 ippSeconds = timeList[1] - timeList[0]
1983 sec = numpy.where(timeList>1)[0][0]
1984 sec = numpy.where(timeList>1)[0][0]
1984 nPairs = metArray.shape[1] - 6
1985 nPairs = metArray.shape[1] - 6
1985 nHeights = len(heightList)
1986 nHeights = len(heightList)
1986
1987
1987 for t in uniqueTime:
1988 for t in uniqueTime:
1988 metArray1 = metArray[utctime==t,:]
1989 metArray1 = metArray[utctime==t,:]
1989 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
1990 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
1990 tmet = metArray1[:,1].astype(int)
1991 tmet = metArray1[:,1].astype(int)
1991 hmet = metArray1[:,2].astype(int)
1992 hmet = metArray1[:,2].astype(int)
1992
1993
1993 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
1994 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
1994 metPhase[:,:] = numpy.nan
1995 metPhase[:,:] = numpy.nan
1995 metPhase[:,hmet,tmet] = metArray1[:,6:].T
1996 metPhase[:,hmet,tmet] = metArray1[:,6:].T
1996
1997
1997 #Delete short trails
1998 #Delete short trails
1998 metBool = ~numpy.isnan(metPhase[0,:,:])
1999 metBool = ~numpy.isnan(metPhase[0,:,:])
1999 heightVect = numpy.sum(metBool, axis = 1)
2000 heightVect = numpy.sum(metBool, axis = 1)
2000 metBool[heightVect<sec,:] = False
2001 metBool[heightVect<sec,:] = False
2001 metPhase[:,heightVect<sec,:] = numpy.nan
2002 metPhase[:,heightVect<sec,:] = numpy.nan
2002
2003
2003 #Derivative
2004 #Derivative
2004 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2005 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2005 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2006 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2006 metPhase[phDerAux] = numpy.nan
2007 metPhase[phDerAux] = numpy.nan
2007
2008
2008 #--------------------------METEOR DETECTION -----------------------------------------
2009 #--------------------------METEOR DETECTION -----------------------------------------
2009 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2010 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2010
2011
2011 for p in numpy.arange(nPairs):
2012 for p in numpy.arange(nPairs):
2012 phase = metPhase[p,:,:]
2013 phase = metPhase[p,:,:]
2013 phDer = metDer[p,:,:]
2014 phDer = metDer[p,:,:]
2014
2015
2015 for h in indMet:
2016 for h in indMet:
2016 height = heightList[h]
2017 height = heightList[h]
2017 phase1 = phase[h,:] #82
2018 phase1 = phase[h,:] #82
2018 phDer1 = phDer[h,:]
2019 phDer1 = phDer[h,:]
2019
2020
2020 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2021 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2021
2022
2022 indValid = numpy.where(~numpy.isnan(phase1))[0]
2023 indValid = numpy.where(~numpy.isnan(phase1))[0]
2023 initMet = indValid[0]
2024 initMet = indValid[0]
2024 endMet = 0
2025 endMet = 0
2025
2026
2026 for i in range(len(indValid)-1):
2027 for i in range(len(indValid)-1):
2027
2028
2028 #Time difference
2029 #Time difference
2029 inow = indValid[i]
2030 inow = indValid[i]
2030 inext = indValid[i+1]
2031 inext = indValid[i+1]
2031 idiff = inext - inow
2032 idiff = inext - inow
2032 #Phase difference
2033 #Phase difference
2033 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2034 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2034
2035
2035 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2036 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2036 sizeTrail = inow - initMet + 1
2037 sizeTrail = inow - initMet + 1
2037 if sizeTrail>3*sec: #Too short meteors
2038 if sizeTrail>3*sec: #Too short meteors
2038 x = numpy.arange(initMet,inow+1)*ippSeconds
2039 x = numpy.arange(initMet,inow+1)*ippSeconds
2039 y = phase1[initMet:inow+1]
2040 y = phase1[initMet:inow+1]
2040 ynnan = ~numpy.isnan(y)
2041 ynnan = ~numpy.isnan(y)
2041 x = x[ynnan]
2042 x = x[ynnan]
2042 y = y[ynnan]
2043 y = y[ynnan]
2043 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2044 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2044 ylin = x*slope + intercept
2045 ylin = x*slope + intercept
2045 rsq = r_value**2
2046 rsq = r_value**2
2046 if rsq > 0.5:
2047 if rsq > 0.5:
2047 vel = slope#*height*1000/(k*d)
2048 vel = slope#*height*1000/(k*d)
2048 estAux = numpy.array([utctime,p,height, vel, rsq])
2049 estAux = numpy.array([utctime,p,height, vel, rsq])
2049 meteorList.append(estAux)
2050 meteorList.append(estAux)
2050 initMet = inext
2051 initMet = inext
2051 metArray2 = numpy.array(meteorList)
2052 metArray2 = numpy.array(meteorList)
2052
2053
2053 return metArray2
2054 return metArray2
2054
2055
2055 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2056 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2056
2057
2057 azimuth1 = numpy.zeros(len(pairslist))
2058 azimuth1 = numpy.zeros(len(pairslist))
2058 dist = numpy.zeros(len(pairslist))
2059 dist = numpy.zeros(len(pairslist))
2059
2060
2060 for i in range(len(rx_location)):
2061 for i in range(len(rx_location)):
2061 ch0 = pairslist[i][0]
2062 ch0 = pairslist[i][0]
2062 ch1 = pairslist[i][1]
2063 ch1 = pairslist[i][1]
2063
2064
2064 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2065 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2065 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2066 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2066 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2067 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2067 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2068 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2068
2069
2069 azimuth1 -= azimuth0
2070 azimuth1 -= azimuth0
2070 return azimuth1, dist
2071 return azimuth1, dist
2071
2072
2072 def techniqueNSM_DBS(self, **kwargs):
2073 def techniqueNSM_DBS(self, **kwargs):
2073 metArray = kwargs['metArray']
2074 metArray = kwargs['metArray']
2074 heightList = kwargs['heightList']
2075 heightList = kwargs['heightList']
2075 timeList = kwargs['timeList']
2076 timeList = kwargs['timeList']
2076 azimuth = kwargs['azimuth']
2077 azimuth = kwargs['azimuth']
2077 theta_x = numpy.array(kwargs['theta_x'])
2078 theta_x = numpy.array(kwargs['theta_x'])
2078 theta_y = numpy.array(kwargs['theta_y'])
2079 theta_y = numpy.array(kwargs['theta_y'])
2079
2080
2080 utctime = metArray[:,0]
2081 utctime = metArray[:,0]
2081 cmet = metArray[:,1].astype(int)
2082 cmet = metArray[:,1].astype(int)
2082 hmet = metArray[:,3].astype(int)
2083 hmet = metArray[:,3].astype(int)
2083 SNRmet = metArray[:,4]
2084 SNRmet = metArray[:,4]
2084 vmet = metArray[:,5]
2085 vmet = metArray[:,5]
2085 spcmet = metArray[:,6]
2086 spcmet = metArray[:,6]
2086
2087
2087 nChan = numpy.max(cmet) + 1
2088 nChan = numpy.max(cmet) + 1
2088 nHeights = len(heightList)
2089 nHeights = len(heightList)
2089
2090
2090 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2091 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2091 hmet = heightList[hmet]
2092 hmet = heightList[hmet]
2092 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2093 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2093
2094
2094 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2095 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2095
2096
2096 for i in range(nHeights - 1):
2097 for i in range(nHeights - 1):
2097 hmin = heightList[i]
2098 hmin = heightList[i]
2098 hmax = heightList[i + 1]
2099 hmax = heightList[i + 1]
2099
2100
2100 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2101 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2101 indthisH = numpy.where(thisH)
2102 indthisH = numpy.where(thisH)
2102
2103
2103 if numpy.size(indthisH) > 3:
2104 if numpy.size(indthisH) > 3:
2104
2105
2105 vel_aux = vmet[thisH]
2106 vel_aux = vmet[thisH]
2106 chan_aux = cmet[thisH]
2107 chan_aux = cmet[thisH]
2107 cosu_aux = dir_cosu[chan_aux]
2108 cosu_aux = dir_cosu[chan_aux]
2108 cosv_aux = dir_cosv[chan_aux]
2109 cosv_aux = dir_cosv[chan_aux]
2109 cosw_aux = dir_cosw[chan_aux]
2110 cosw_aux = dir_cosw[chan_aux]
2110
2111
2111 nch = numpy.size(numpy.unique(chan_aux))
2112 nch = numpy.size(numpy.unique(chan_aux))
2112 if nch > 1:
2113 if nch > 1:
2113 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2114 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2114 velEst[i,:] = numpy.dot(A,vel_aux)
2115 velEst[i,:] = numpy.dot(A,vel_aux)
2115
2116
2116 return velEst
2117 return velEst
2117
2118
2118 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2119 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2119
2120
2120 param = dataOut.data_param
2121 param = dataOut.data_param
2121 if dataOut.abscissaList != None:
2122 if dataOut.abscissaList != None:
2122 absc = dataOut.abscissaList[:-1]
2123 absc = dataOut.abscissaList[:-1]
2123 # noise = dataOut.noise
2124 # noise = dataOut.noise
2124 heightList = dataOut.heightList
2125 heightList = dataOut.heightList
2125 SNR = dataOut.data_SNR
2126 SNR = dataOut.data_SNR
2126
2127
2127 if technique == 'DBS':
2128 if technique == 'DBS':
2128
2129
2129 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2130 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2130 kwargs['heightList'] = heightList
2131 kwargs['heightList'] = heightList
2131 kwargs['SNR'] = SNR
2132 kwargs['SNR'] = SNR
2132
2133
2133 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
2134 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
2134 dataOut.utctimeInit = dataOut.utctime
2135 dataOut.utctimeInit = dataOut.utctime
2135 dataOut.outputInterval = dataOut.paramInterval
2136 dataOut.outputInterval = dataOut.paramInterval
2136
2137
2137 elif technique == 'SA':
2138 elif technique == 'SA':
2138
2139
2139 #Parameters
2140 #Parameters
2140 # position_x = kwargs['positionX']
2141 # position_x = kwargs['positionX']
2141 # position_y = kwargs['positionY']
2142 # position_y = kwargs['positionY']
2142 # azimuth = kwargs['azimuth']
2143 # azimuth = kwargs['azimuth']
2143 #
2144 #
2144 # if kwargs.has_key('crosspairsList'):
2145 # if kwargs.has_key('crosspairsList'):
2145 # pairs = kwargs['crosspairsList']
2146 # pairs = kwargs['crosspairsList']
2146 # else:
2147 # else:
2147 # pairs = None
2148 # pairs = None
2148 #
2149 #
2149 # if kwargs.has_key('correctFactor'):
2150 # if kwargs.has_key('correctFactor'):
2150 # correctFactor = kwargs['correctFactor']
2151 # correctFactor = kwargs['correctFactor']
2151 # else:
2152 # else:
2152 # correctFactor = 1
2153 # correctFactor = 1
2153
2154
2154 # tau = dataOut.data_param
2155 # tau = dataOut.data_param
2155 # _lambda = dataOut.C/dataOut.frequency
2156 # _lambda = dataOut.C/dataOut.frequency
2156 # pairsList = dataOut.groupList
2157 # pairsList = dataOut.groupList
2157 # nChannels = dataOut.nChannels
2158 # nChannels = dataOut.nChannels
2158
2159
2159 kwargs['groupList'] = dataOut.groupList
2160 kwargs['groupList'] = dataOut.groupList
2160 kwargs['tau'] = dataOut.data_param
2161 kwargs['tau'] = dataOut.data_param
2161 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2162 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2162 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2163 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2163 dataOut.data_output = self.techniqueSA(kwargs)
2164 dataOut.data_output = self.techniqueSA(kwargs)
2164 dataOut.utctimeInit = dataOut.utctime
2165 dataOut.utctimeInit = dataOut.utctime
2165 dataOut.outputInterval = dataOut.timeInterval
2166 dataOut.outputInterval = dataOut.timeInterval
2166
2167
2167 elif technique == 'Meteors':
2168 elif technique == 'Meteors':
2168 dataOut.flagNoData = True
2169 dataOut.flagNoData = True
2169 self.__dataReady = False
2170 self.__dataReady = False
2170
2171
2171 if 'nHours' in kwargs:
2172 if 'nHours' in kwargs:
2172 nHours = kwargs['nHours']
2173 nHours = kwargs['nHours']
2173 else:
2174 else:
2174 nHours = 1
2175 nHours = 1
2175
2176
2176 if 'meteorsPerBin' in kwargs:
2177 if 'meteorsPerBin' in kwargs:
2177 meteorThresh = kwargs['meteorsPerBin']
2178 meteorThresh = kwargs['meteorsPerBin']
2178 else:
2179 else:
2179 meteorThresh = 6
2180 meteorThresh = 6
2180
2181
2181 if 'hmin' in kwargs:
2182 if 'hmin' in kwargs:
2182 hmin = kwargs['hmin']
2183 hmin = kwargs['hmin']
2183 else: hmin = 70
2184 else: hmin = 70
2184 if 'hmax' in kwargs:
2185 if 'hmax' in kwargs:
2185 hmax = kwargs['hmax']
2186 hmax = kwargs['hmax']
2186 else: hmax = 110
2187 else: hmax = 110
2187
2188
2188 dataOut.outputInterval = nHours*3600
2189 dataOut.outputInterval = nHours*3600
2189
2190
2190 if self.__isConfig == False:
2191 if self.__isConfig == False:
2191 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2192 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2192 #Get Initial LTC time
2193 #Get Initial LTC time
2193 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2194 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2194 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2195 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2195
2196
2196 self.__isConfig = True
2197 self.__isConfig = True
2197
2198
2198 if self.__buffer is None:
2199 if self.__buffer is None:
2199 self.__buffer = dataOut.data_param
2200 self.__buffer = dataOut.data_param
2200 self.__firstdata = copy.copy(dataOut)
2201 self.__firstdata = copy.copy(dataOut)
2201
2202
2202 else:
2203 else:
2203 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2204 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2204
2205
2205 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2206 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2206
2207
2207 if self.__dataReady:
2208 if self.__dataReady:
2208 dataOut.utctimeInit = self.__initime
2209 dataOut.utctimeInit = self.__initime
2209
2210
2210 self.__initime += dataOut.outputInterval #to erase time offset
2211 self.__initime += dataOut.outputInterval #to erase time offset
2211
2212
2212 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2213 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2213 dataOut.flagNoData = False
2214 dataOut.flagNoData = False
2214 self.__buffer = None
2215 self.__buffer = None
2215
2216
2216 elif technique == 'Meteors1':
2217 elif technique == 'Meteors1':
2217 dataOut.flagNoData = True
2218 dataOut.flagNoData = True
2218 self.__dataReady = False
2219 self.__dataReady = False
2219
2220
2220 if 'nMins' in kwargs:
2221 if 'nMins' in kwargs:
2221 nMins = kwargs['nMins']
2222 nMins = kwargs['nMins']
2222 else: nMins = 20
2223 else: nMins = 20
2223 if 'rx_location' in kwargs:
2224 if 'rx_location' in kwargs:
2224 rx_location = kwargs['rx_location']
2225 rx_location = kwargs['rx_location']
2225 else: rx_location = [(0,1),(1,1),(1,0)]
2226 else: rx_location = [(0,1),(1,1),(1,0)]
2226 if 'azimuth' in kwargs:
2227 if 'azimuth' in kwargs:
2227 azimuth = kwargs['azimuth']
2228 azimuth = kwargs['azimuth']
2228 else: azimuth = 51.06
2229 else: azimuth = 51.06
2229 if 'dfactor' in kwargs:
2230 if 'dfactor' in kwargs:
2230 dfactor = kwargs['dfactor']
2231 dfactor = kwargs['dfactor']
2231 if 'mode' in kwargs:
2232 if 'mode' in kwargs:
2232 mode = kwargs['mode']
2233 mode = kwargs['mode']
2233 if 'theta_x' in kwargs:
2234 if 'theta_x' in kwargs:
2234 theta_x = kwargs['theta_x']
2235 theta_x = kwargs['theta_x']
2235 if 'theta_y' in kwargs:
2236 if 'theta_y' in kwargs:
2236 theta_y = kwargs['theta_y']
2237 theta_y = kwargs['theta_y']
2237 else: mode = 'SA'
2238 else: mode = 'SA'
2238
2239
2239 #Borrar luego esto
2240 #Borrar luego esto
2240 if dataOut.groupList is None:
2241 if dataOut.groupList is None:
2241 dataOut.groupList = [(0,1),(0,2),(1,2)]
2242 dataOut.groupList = [(0,1),(0,2),(1,2)]
2242 groupList = dataOut.groupList
2243 groupList = dataOut.groupList
2243 C = 3e8
2244 C = 3e8
2244 freq = 50e6
2245 freq = 50e6
2245 lamb = C/freq
2246 lamb = C/freq
2246 k = 2*numpy.pi/lamb
2247 k = 2*numpy.pi/lamb
2247
2248
2248 timeList = dataOut.abscissaList
2249 timeList = dataOut.abscissaList
2249 heightList = dataOut.heightList
2250 heightList = dataOut.heightList
2250
2251
2251 if self.__isConfig == False:
2252 if self.__isConfig == False:
2252 dataOut.outputInterval = nMins*60
2253 dataOut.outputInterval = nMins*60
2253 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2254 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2254 #Get Initial LTC time
2255 #Get Initial LTC time
2255 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2256 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2256 minuteAux = initime.minute
2257 minuteAux = initime.minute
2257 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2258 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2258 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2259 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2259
2260
2260 self.__isConfig = True
2261 self.__isConfig = True
2261
2262
2262 if self.__buffer is None:
2263 if self.__buffer is None:
2263 self.__buffer = dataOut.data_param
2264 self.__buffer = dataOut.data_param
2264 self.__firstdata = copy.copy(dataOut)
2265 self.__firstdata = copy.copy(dataOut)
2265
2266
2266 else:
2267 else:
2267 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2268 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2268
2269
2269 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2270 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2270
2271
2271 if self.__dataReady:
2272 if self.__dataReady:
2272 dataOut.utctimeInit = self.__initime
2273 dataOut.utctimeInit = self.__initime
2273 self.__initime += dataOut.outputInterval #to erase time offset
2274 self.__initime += dataOut.outputInterval #to erase time offset
2274
2275
2275 metArray = self.__buffer
2276 metArray = self.__buffer
2276 if mode == 'SA':
2277 if mode == 'SA':
2277 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2278 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2278 elif mode == 'DBS':
2279 elif mode == 'DBS':
2279 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2280 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2280 dataOut.data_output = dataOut.data_output.T
2281 dataOut.data_output = dataOut.data_output.T
2281 dataOut.flagNoData = False
2282 dataOut.flagNoData = False
2282 self.__buffer = None
2283 self.__buffer = None
2283
2284
2284 return
2285 return
2285
2286
2286 class EWDriftsEstimation(Operation):
2287 class EWDriftsEstimation(Operation):
2287
2288
2288 def __init__(self):
2289 def __init__(self):
2289 Operation.__init__(self)
2290 Operation.__init__(self)
2290
2291
2291 def __correctValues(self, heiRang, phi, velRadial, SNR):
2292 def __correctValues(self, heiRang, phi, velRadial, SNR):
2292 listPhi = phi.tolist()
2293 listPhi = phi.tolist()
2293 maxid = listPhi.index(max(listPhi))
2294 maxid = listPhi.index(max(listPhi))
2294 minid = listPhi.index(min(listPhi))
2295 minid = listPhi.index(min(listPhi))
2295
2296
2296 rango = list(range(len(phi)))
2297 rango = list(range(len(phi)))
2297 # rango = numpy.delete(rango,maxid)
2298 # rango = numpy.delete(rango,maxid)
2298
2299
2299 heiRang1 = heiRang*math.cos(phi[maxid])
2300 heiRang1 = heiRang*math.cos(phi[maxid])
2300 heiRangAux = heiRang*math.cos(phi[minid])
2301 heiRangAux = heiRang*math.cos(phi[minid])
2301 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2302 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2302 heiRang1 = numpy.delete(heiRang1,indOut)
2303 heiRang1 = numpy.delete(heiRang1,indOut)
2303
2304
2304 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2305 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2305 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2306 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2306
2307
2307 for i in rango:
2308 for i in rango:
2308 x = heiRang*math.cos(phi[i])
2309 x = heiRang*math.cos(phi[i])
2309 y1 = velRadial[i,:]
2310 y1 = velRadial[i,:]
2310 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2311 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2311
2312
2312 x1 = heiRang1
2313 x1 = heiRang1
2313 y11 = f1(x1)
2314 y11 = f1(x1)
2314
2315
2315 y2 = SNR[i,:]
2316 y2 = SNR[i,:]
2316 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2317 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2317 y21 = f2(x1)
2318 y21 = f2(x1)
2318
2319
2319 velRadial1[i,:] = y11
2320 velRadial1[i,:] = y11
2320 SNR1[i,:] = y21
2321 SNR1[i,:] = y21
2321
2322
2322 return heiRang1, velRadial1, SNR1
2323 return heiRang1, velRadial1, SNR1
2323
2324
2324 def run(self, dataOut, zenith, zenithCorrection):
2325 def run(self, dataOut, zenith, zenithCorrection):
2325 heiRang = dataOut.heightList
2326 heiRang = dataOut.heightList
2326 velRadial = dataOut.data_param[:,3,:]
2327 velRadial = dataOut.data_param[:,3,:]
2327 SNR = dataOut.data_SNR
2328 SNR = dataOut.data_SNR
2328
2329
2329 zenith = numpy.array(zenith)
2330 zenith = numpy.array(zenith)
2330 zenith -= zenithCorrection
2331 zenith -= zenithCorrection
2331 zenith *= numpy.pi/180
2332 zenith *= numpy.pi/180
2332
2333
2333 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2334 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2334
2335
2335 alp = zenith[0]
2336 alp = zenith[0]
2336 bet = zenith[1]
2337 bet = zenith[1]
2337
2338
2338 w_w = velRadial1[0,:]
2339 w_w = velRadial1[0,:]
2339 w_e = velRadial1[1,:]
2340 w_e = velRadial1[1,:]
2340
2341
2341 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2342 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2342 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2343 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2343
2344
2344 winds = numpy.vstack((u,w))
2345 winds = numpy.vstack((u,w))
2345
2346
2346 dataOut.heightList = heiRang1
2347 dataOut.heightList = heiRang1
2347 dataOut.data_output = winds
2348 dataOut.data_output = winds
2348 dataOut.data_SNR = SNR1
2349 dataOut.data_SNR = SNR1
2349
2350
2350 dataOut.utctimeInit = dataOut.utctime
2351 dataOut.utctimeInit = dataOut.utctime
2351 dataOut.outputInterval = dataOut.timeInterval
2352 dataOut.outputInterval = dataOut.timeInterval
2352 return
2353 return
2353
2354
2354 #--------------- Non Specular Meteor ----------------
2355 #--------------- Non Specular Meteor ----------------
2355
2356
2356 class NonSpecularMeteorDetection(Operation):
2357 class NonSpecularMeteorDetection(Operation):
2357
2358
2358 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2359 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2359 data_acf = dataOut.data_pre[0]
2360 data_acf = dataOut.data_pre[0]
2360 data_ccf = dataOut.data_pre[1]
2361 data_ccf = dataOut.data_pre[1]
2361 pairsList = dataOut.groupList[1]
2362 pairsList = dataOut.groupList[1]
2362
2363
2363 lamb = dataOut.C/dataOut.frequency
2364 lamb = dataOut.C/dataOut.frequency
2364 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2365 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2365 paramInterval = dataOut.paramInterval
2366 paramInterval = dataOut.paramInterval
2366
2367
2367 nChannels = data_acf.shape[0]
2368 nChannels = data_acf.shape[0]
2368 nLags = data_acf.shape[1]
2369 nLags = data_acf.shape[1]
2369 nProfiles = data_acf.shape[2]
2370 nProfiles = data_acf.shape[2]
2370 nHeights = dataOut.nHeights
2371 nHeights = dataOut.nHeights
2371 nCohInt = dataOut.nCohInt
2372 nCohInt = dataOut.nCohInt
2372 sec = numpy.round(nProfiles/dataOut.paramInterval)
2373 sec = numpy.round(nProfiles/dataOut.paramInterval)
2373 heightList = dataOut.heightList
2374 heightList = dataOut.heightList
2374 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2375 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2375 utctime = dataOut.utctime
2376 utctime = dataOut.utctime
2376
2377
2377 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2378 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2378
2379
2379 #------------------------ SNR --------------------------------------
2380 #------------------------ SNR --------------------------------------
2380 power = data_acf[:,0,:,:].real
2381 power = data_acf[:,0,:,:].real
2381 noise = numpy.zeros(nChannels)
2382 noise = numpy.zeros(nChannels)
2382 SNR = numpy.zeros(power.shape)
2383 SNR = numpy.zeros(power.shape)
2383 for i in range(nChannels):
2384 for i in range(nChannels):
2384 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2385 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2385 SNR[i] = (power[i]-noise[i])/noise[i]
2386 SNR[i] = (power[i]-noise[i])/noise[i]
2386 SNRm = numpy.nanmean(SNR, axis = 0)
2387 SNRm = numpy.nanmean(SNR, axis = 0)
2387 SNRdB = 10*numpy.log10(SNR)
2388 SNRdB = 10*numpy.log10(SNR)
2388
2389
2389 if mode == 'SA':
2390 if mode == 'SA':
2390 dataOut.groupList = dataOut.groupList[1]
2391 dataOut.groupList = dataOut.groupList[1]
2391 nPairs = data_ccf.shape[0]
2392 nPairs = data_ccf.shape[0]
2392 #---------------------- Coherence and Phase --------------------------
2393 #---------------------- Coherence and Phase --------------------------
2393 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2394 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2394 # phase1 = numpy.copy(phase)
2395 # phase1 = numpy.copy(phase)
2395 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2396 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2396
2397
2397 for p in range(nPairs):
2398 for p in range(nPairs):
2398 ch0 = pairsList[p][0]
2399 ch0 = pairsList[p][0]
2399 ch1 = pairsList[p][1]
2400 ch1 = pairsList[p][1]
2400 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2401 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2401 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2402 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2402 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2403 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2403 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2404 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2404 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2405 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2405 coh = numpy.nanmax(coh1, axis = 0)
2406 coh = numpy.nanmax(coh1, axis = 0)
2406 # struc = numpy.ones((5,1))
2407 # struc = numpy.ones((5,1))
2407 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2408 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2408 #---------------------- Radial Velocity ----------------------------
2409 #---------------------- Radial Velocity ----------------------------
2409 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2410 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2410 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2411 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2411
2412
2412 if allData:
2413 if allData:
2413 boolMetFin = ~numpy.isnan(SNRm)
2414 boolMetFin = ~numpy.isnan(SNRm)
2414 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2415 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2415 else:
2416 else:
2416 #------------------------ Meteor mask ---------------------------------
2417 #------------------------ Meteor mask ---------------------------------
2417 # #SNR mask
2418 # #SNR mask
2418 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2419 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2419 #
2420 #
2420 # #Erase small objects
2421 # #Erase small objects
2421 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2422 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2422 #
2423 #
2423 # auxEEJ = numpy.sum(boolMet1,axis=0)
2424 # auxEEJ = numpy.sum(boolMet1,axis=0)
2424 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2425 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2425 # indEEJ = numpy.where(indOver)[0]
2426 # indEEJ = numpy.where(indOver)[0]
2426 # indNEEJ = numpy.where(~indOver)[0]
2427 # indNEEJ = numpy.where(~indOver)[0]
2427 #
2428 #
2428 # boolMetFin = boolMet1
2429 # boolMetFin = boolMet1
2429 #
2430 #
2430 # if indEEJ.size > 0:
2431 # if indEEJ.size > 0:
2431 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2432 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2432 #
2433 #
2433 # boolMet2 = coh > cohThresh
2434 # boolMet2 = coh > cohThresh
2434 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2435 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2435 #
2436 #
2436 # #Final Meteor mask
2437 # #Final Meteor mask
2437 # boolMetFin = boolMet1|boolMet2
2438 # boolMetFin = boolMet1|boolMet2
2438
2439
2439 #Coherence mask
2440 #Coherence mask
2440 boolMet1 = coh > 0.75
2441 boolMet1 = coh > 0.75
2441 struc = numpy.ones((30,1))
2442 struc = numpy.ones((30,1))
2442 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2443 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2443
2444
2444 #Derivative mask
2445 #Derivative mask
2445 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2446 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2446 boolMet2 = derPhase < 0.2
2447 boolMet2 = derPhase < 0.2
2447 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2448 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2448 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2449 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2449 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2450 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2450 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2451 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2451 # #Final mask
2452 # #Final mask
2452 # boolMetFin = boolMet2
2453 # boolMetFin = boolMet2
2453 boolMetFin = boolMet1&boolMet2
2454 boolMetFin = boolMet1&boolMet2
2454 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2455 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2455 #Creating data_param
2456 #Creating data_param
2456 coordMet = numpy.where(boolMetFin)
2457 coordMet = numpy.where(boolMetFin)
2457
2458
2458 tmet = coordMet[0]
2459 tmet = coordMet[0]
2459 hmet = coordMet[1]
2460 hmet = coordMet[1]
2460
2461
2461 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2462 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2462 data_param[:,0] = utctime
2463 data_param[:,0] = utctime
2463 data_param[:,1] = tmet
2464 data_param[:,1] = tmet
2464 data_param[:,2] = hmet
2465 data_param[:,2] = hmet
2465 data_param[:,3] = SNRm[tmet,hmet]
2466 data_param[:,3] = SNRm[tmet,hmet]
2466 data_param[:,4] = velRad[tmet,hmet]
2467 data_param[:,4] = velRad[tmet,hmet]
2467 data_param[:,5] = coh[tmet,hmet]
2468 data_param[:,5] = coh[tmet,hmet]
2468 data_param[:,6:] = phase[:,tmet,hmet].T
2469 data_param[:,6:] = phase[:,tmet,hmet].T
2469
2470
2470 elif mode == 'DBS':
2471 elif mode == 'DBS':
2471 dataOut.groupList = numpy.arange(nChannels)
2472 dataOut.groupList = numpy.arange(nChannels)
2472
2473
2473 #Radial Velocities
2474 #Radial Velocities
2474 phase = numpy.angle(data_acf[:,1,:,:])
2475 phase = numpy.angle(data_acf[:,1,:,:])
2475 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2476 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2476 velRad = phase*lamb/(4*numpy.pi*tSamp)
2477 velRad = phase*lamb/(4*numpy.pi*tSamp)
2477
2478
2478 #Spectral width
2479 #Spectral width
2479 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2480 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2480 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2481 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2481 acf1 = data_acf[:,1,:,:]
2482 acf1 = data_acf[:,1,:,:]
2482 acf2 = data_acf[:,2,:,:]
2483 acf2 = data_acf[:,2,:,:]
2483
2484
2484 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2485 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2485 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2486 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2486 if allData:
2487 if allData:
2487 boolMetFin = ~numpy.isnan(SNRdB)
2488 boolMetFin = ~numpy.isnan(SNRdB)
2488 else:
2489 else:
2489 #SNR
2490 #SNR
2490 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2491 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2491 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2492 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2492
2493
2493 #Radial velocity
2494 #Radial velocity
2494 boolMet2 = numpy.abs(velRad) < 20
2495 boolMet2 = numpy.abs(velRad) < 20
2495 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2496 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2496
2497
2497 #Spectral Width
2498 #Spectral Width
2498 boolMet3 = spcWidth < 30
2499 boolMet3 = spcWidth < 30
2499 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2500 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2500 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2501 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2501 boolMetFin = boolMet1&boolMet2&boolMet3
2502 boolMetFin = boolMet1&boolMet2&boolMet3
2502
2503
2503 #Creating data_param
2504 #Creating data_param
2504 coordMet = numpy.where(boolMetFin)
2505 coordMet = numpy.where(boolMetFin)
2505
2506
2506 cmet = coordMet[0]
2507 cmet = coordMet[0]
2507 tmet = coordMet[1]
2508 tmet = coordMet[1]
2508 hmet = coordMet[2]
2509 hmet = coordMet[2]
2509
2510
2510 data_param = numpy.zeros((tmet.size, 7))
2511 data_param = numpy.zeros((tmet.size, 7))
2511 data_param[:,0] = utctime
2512 data_param[:,0] = utctime
2512 data_param[:,1] = cmet
2513 data_param[:,1] = cmet
2513 data_param[:,2] = tmet
2514 data_param[:,2] = tmet
2514 data_param[:,3] = hmet
2515 data_param[:,3] = hmet
2515 data_param[:,4] = SNR[cmet,tmet,hmet].T
2516 data_param[:,4] = SNR[cmet,tmet,hmet].T
2516 data_param[:,5] = velRad[cmet,tmet,hmet].T
2517 data_param[:,5] = velRad[cmet,tmet,hmet].T
2517 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2518 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2518
2519
2519 # self.dataOut.data_param = data_int
2520 # self.dataOut.data_param = data_int
2520 if len(data_param) == 0:
2521 if len(data_param) == 0:
2521 dataOut.flagNoData = True
2522 dataOut.flagNoData = True
2522 else:
2523 else:
2523 dataOut.data_param = data_param
2524 dataOut.data_param = data_param
2524
2525
2525 def __erase_small(self, binArray, threshX, threshY):
2526 def __erase_small(self, binArray, threshX, threshY):
2526 labarray, numfeat = ndimage.measurements.label(binArray)
2527 labarray, numfeat = ndimage.measurements.label(binArray)
2527 binArray1 = numpy.copy(binArray)
2528 binArray1 = numpy.copy(binArray)
2528
2529
2529 for i in range(1,numfeat + 1):
2530 for i in range(1,numfeat + 1):
2530 auxBin = (labarray==i)
2531 auxBin = (labarray==i)
2531 auxSize = auxBin.sum()
2532 auxSize = auxBin.sum()
2532
2533
2533 x,y = numpy.where(auxBin)
2534 x,y = numpy.where(auxBin)
2534 widthX = x.max() - x.min()
2535 widthX = x.max() - x.min()
2535 widthY = y.max() - y.min()
2536 widthY = y.max() - y.min()
2536
2537
2537 #width X: 3 seg -> 12.5*3
2538 #width X: 3 seg -> 12.5*3
2538 #width Y:
2539 #width Y:
2539
2540
2540 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2541 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2541 binArray1[auxBin] = False
2542 binArray1[auxBin] = False
2542
2543
2543 return binArray1
2544 return binArray1
2544
2545
2545 #--------------- Specular Meteor ----------------
2546 #--------------- Specular Meteor ----------------
2546
2547
2547 class SMDetection(Operation):
2548 class SMDetection(Operation):
2548 '''
2549 '''
2549 Function DetectMeteors()
2550 Function DetectMeteors()
2550 Project developed with paper:
2551 Project developed with paper:
2551 HOLDSWORTH ET AL. 2004
2552 HOLDSWORTH ET AL. 2004
2552
2553
2553 Input:
2554 Input:
2554 self.dataOut.data_pre
2555 self.dataOut.data_pre
2555
2556
2556 centerReceiverIndex: From the channels, which is the center receiver
2557 centerReceiverIndex: From the channels, which is the center receiver
2557
2558
2558 hei_ref: Height reference for the Beacon signal extraction
2559 hei_ref: Height reference for the Beacon signal extraction
2559 tauindex:
2560 tauindex:
2560 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2561 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2561
2562
2562 cohDetection: Whether to user Coherent detection or not
2563 cohDetection: Whether to user Coherent detection or not
2563 cohDet_timeStep: Coherent Detection calculation time step
2564 cohDet_timeStep: Coherent Detection calculation time step
2564 cohDet_thresh: Coherent Detection phase threshold to correct phases
2565 cohDet_thresh: Coherent Detection phase threshold to correct phases
2565
2566
2566 noise_timeStep: Noise calculation time step
2567 noise_timeStep: Noise calculation time step
2567 noise_multiple: Noise multiple to define signal threshold
2568 noise_multiple: Noise multiple to define signal threshold
2568
2569
2569 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2570 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2570 multDet_rangeLimit: Multiple Detection Removal range limit in km
2571 multDet_rangeLimit: Multiple Detection Removal range limit in km
2571
2572
2572 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2573 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2573 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2574 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2574
2575
2575 hmin: Minimum Height of the meteor to use it in the further wind estimations
2576 hmin: Minimum Height of the meteor to use it in the further wind estimations
2576 hmax: Maximum Height of the meteor to use it in the further wind estimations
2577 hmax: Maximum Height of the meteor to use it in the further wind estimations
2577 azimuth: Azimuth angle correction
2578 azimuth: Azimuth angle correction
2578
2579
2579 Affected:
2580 Affected:
2580 self.dataOut.data_param
2581 self.dataOut.data_param
2581
2582
2582 Rejection Criteria (Errors):
2583 Rejection Criteria (Errors):
2583 0: No error; analysis OK
2584 0: No error; analysis OK
2584 1: SNR < SNR threshold
2585 1: SNR < SNR threshold
2585 2: angle of arrival (AOA) ambiguously determined
2586 2: angle of arrival (AOA) ambiguously determined
2586 3: AOA estimate not feasible
2587 3: AOA estimate not feasible
2587 4: Large difference in AOAs obtained from different antenna baselines
2588 4: Large difference in AOAs obtained from different antenna baselines
2588 5: echo at start or end of time series
2589 5: echo at start or end of time series
2589 6: echo less than 5 examples long; too short for analysis
2590 6: echo less than 5 examples long; too short for analysis
2590 7: echo rise exceeds 0.3s
2591 7: echo rise exceeds 0.3s
2591 8: echo decay time less than twice rise time
2592 8: echo decay time less than twice rise time
2592 9: large power level before echo
2593 9: large power level before echo
2593 10: large power level after echo
2594 10: large power level after echo
2594 11: poor fit to amplitude for estimation of decay time
2595 11: poor fit to amplitude for estimation of decay time
2595 12: poor fit to CCF phase variation for estimation of radial drift velocity
2596 12: poor fit to CCF phase variation for estimation of radial drift velocity
2596 13: height unresolvable echo: not valid height within 70 to 110 km
2597 13: height unresolvable echo: not valid height within 70 to 110 km
2597 14: height ambiguous echo: more then one possible height within 70 to 110 km
2598 14: height ambiguous echo: more then one possible height within 70 to 110 km
2598 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2599 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2599 16: oscilatory echo, indicating event most likely not an underdense echo
2600 16: oscilatory echo, indicating event most likely not an underdense echo
2600
2601
2601 17: phase difference in meteor Reestimation
2602 17: phase difference in meteor Reestimation
2602
2603
2603 Data Storage:
2604 Data Storage:
2604 Meteors for Wind Estimation (8):
2605 Meteors for Wind Estimation (8):
2605 Utc Time | Range Height
2606 Utc Time | Range Height
2606 Azimuth Zenith errorCosDir
2607 Azimuth Zenith errorCosDir
2607 VelRad errorVelRad
2608 VelRad errorVelRad
2608 Phase0 Phase1 Phase2 Phase3
2609 Phase0 Phase1 Phase2 Phase3
2609 TypeError
2610 TypeError
2610
2611
2611 '''
2612 '''
2612
2613
2613 def run(self, dataOut, hei_ref = None, tauindex = 0,
2614 def run(self, dataOut, hei_ref = None, tauindex = 0,
2614 phaseOffsets = None,
2615 phaseOffsets = None,
2615 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2616 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2616 noise_timeStep = 4, noise_multiple = 4,
2617 noise_timeStep = 4, noise_multiple = 4,
2617 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2618 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2618 phaseThresh = 20, SNRThresh = 5,
2619 phaseThresh = 20, SNRThresh = 5,
2619 hmin = 50, hmax=150, azimuth = 0,
2620 hmin = 50, hmax=150, azimuth = 0,
2620 channelPositions = None) :
2621 channelPositions = None) :
2621
2622
2622
2623
2623 #Getting Pairslist
2624 #Getting Pairslist
2624 if channelPositions is None:
2625 if channelPositions is None:
2625 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2626 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2626 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2627 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2627 meteorOps = SMOperations()
2628 meteorOps = SMOperations()
2628 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2629 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2629 heiRang = dataOut.getHeiRange()
2630 heiRang = dataOut.getHeiRange()
2630 #Get Beacon signal - No Beacon signal anymore
2631 #Get Beacon signal - No Beacon signal anymore
2631 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2632 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2632 #
2633 #
2633 # if hei_ref != None:
2634 # if hei_ref != None:
2634 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2635 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2635 #
2636 #
2636
2637
2637
2638
2638 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2639 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2639 # see if the user put in pre defined phase shifts
2640 # see if the user put in pre defined phase shifts
2640 voltsPShift = dataOut.data_pre.copy()
2641 voltsPShift = dataOut.data_pre.copy()
2641
2642
2642 # if predefinedPhaseShifts != None:
2643 # if predefinedPhaseShifts != None:
2643 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2644 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2644 #
2645 #
2645 # # elif beaconPhaseShifts:
2646 # # elif beaconPhaseShifts:
2646 # # #get hardware phase shifts using beacon signal
2647 # # #get hardware phase shifts using beacon signal
2647 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2648 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2648 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2649 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2649 #
2650 #
2650 # else:
2651 # else:
2651 # hardwarePhaseShifts = numpy.zeros(5)
2652 # hardwarePhaseShifts = numpy.zeros(5)
2652 #
2653 #
2653 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2654 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2654 # for i in range(self.dataOut.data_pre.shape[0]):
2655 # for i in range(self.dataOut.data_pre.shape[0]):
2655 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2656 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2656
2657
2657 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2658 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2658
2659
2659 #Remove DC
2660 #Remove DC
2660 voltsDC = numpy.mean(voltsPShift,1)
2661 voltsDC = numpy.mean(voltsPShift,1)
2661 voltsDC = numpy.mean(voltsDC,1)
2662 voltsDC = numpy.mean(voltsDC,1)
2662 for i in range(voltsDC.shape[0]):
2663 for i in range(voltsDC.shape[0]):
2663 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2664 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2664
2665
2665 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2666 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2666 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2667 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2667
2668
2668 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2669 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2669 #Coherent Detection
2670 #Coherent Detection
2670 if cohDetection:
2671 if cohDetection:
2671 #use coherent detection to get the net power
2672 #use coherent detection to get the net power
2672 cohDet_thresh = cohDet_thresh*numpy.pi/180
2673 cohDet_thresh = cohDet_thresh*numpy.pi/180
2673 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2674 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2674
2675
2675 #Non-coherent detection!
2676 #Non-coherent detection!
2676 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2677 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2677 #********** END OF COH/NON-COH POWER CALCULATION**********************
2678 #********** END OF COH/NON-COH POWER CALCULATION**********************
2678
2679
2679 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2680 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2680 #Get noise
2681 #Get noise
2681 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2682 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2682 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2683 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2683 #Get signal threshold
2684 #Get signal threshold
2684 signalThresh = noise_multiple*noise
2685 signalThresh = noise_multiple*noise
2685 #Meteor echoes detection
2686 #Meteor echoes detection
2686 listMeteors = self.__findMeteors(powerNet, signalThresh)
2687 listMeteors = self.__findMeteors(powerNet, signalThresh)
2687 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2688 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2688
2689
2689 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2690 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2690 #Parameters
2691 #Parameters
2691 heiRange = dataOut.getHeiRange()
2692 heiRange = dataOut.getHeiRange()
2692 rangeInterval = heiRange[1] - heiRange[0]
2693 rangeInterval = heiRange[1] - heiRange[0]
2693 rangeLimit = multDet_rangeLimit/rangeInterval
2694 rangeLimit = multDet_rangeLimit/rangeInterval
2694 timeLimit = multDet_timeLimit/dataOut.timeInterval
2695 timeLimit = multDet_timeLimit/dataOut.timeInterval
2695 #Multiple detection removals
2696 #Multiple detection removals
2696 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2697 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2697 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2698 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2698
2699
2699 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2700 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2700 #Parameters
2701 #Parameters
2701 phaseThresh = phaseThresh*numpy.pi/180
2702 phaseThresh = phaseThresh*numpy.pi/180
2702 thresh = [phaseThresh, noise_multiple, SNRThresh]
2703 thresh = [phaseThresh, noise_multiple, SNRThresh]
2703 #Meteor reestimation (Errors N 1, 6, 12, 17)
2704 #Meteor reestimation (Errors N 1, 6, 12, 17)
2704 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2705 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2705 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2706 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2706 #Estimation of decay times (Errors N 7, 8, 11)
2707 #Estimation of decay times (Errors N 7, 8, 11)
2707 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2708 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2708 #******************* END OF METEOR REESTIMATION *******************
2709 #******************* END OF METEOR REESTIMATION *******************
2709
2710
2710 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2711 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2711 #Calculating Radial Velocity (Error N 15)
2712 #Calculating Radial Velocity (Error N 15)
2712 radialStdThresh = 10
2713 radialStdThresh = 10
2713 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2714 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2714
2715
2715 if len(listMeteors4) > 0:
2716 if len(listMeteors4) > 0:
2716 #Setting New Array
2717 #Setting New Array
2717 date = dataOut.utctime
2718 date = dataOut.utctime
2718 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2719 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2719
2720
2720 #Correcting phase offset
2721 #Correcting phase offset
2721 if phaseOffsets != None:
2722 if phaseOffsets != None:
2722 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2723 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2723 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2724 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2724
2725
2725 #Second Pairslist
2726 #Second Pairslist
2726 pairsList = []
2727 pairsList = []
2727 pairx = (0,1)
2728 pairx = (0,1)
2728 pairy = (2,3)
2729 pairy = (2,3)
2729 pairsList.append(pairx)
2730 pairsList.append(pairx)
2730 pairsList.append(pairy)
2731 pairsList.append(pairy)
2731
2732
2732 jph = numpy.array([0,0,0,0])
2733 jph = numpy.array([0,0,0,0])
2733 h = (hmin,hmax)
2734 h = (hmin,hmax)
2734 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2735 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2735
2736
2736 # #Calculate AOA (Error N 3, 4)
2737 # #Calculate AOA (Error N 3, 4)
2737 # #JONES ET AL. 1998
2738 # #JONES ET AL. 1998
2738 # error = arrayParameters[:,-1]
2739 # error = arrayParameters[:,-1]
2739 # AOAthresh = numpy.pi/8
2740 # AOAthresh = numpy.pi/8
2740 # phases = -arrayParameters[:,9:13]
2741 # phases = -arrayParameters[:,9:13]
2741 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2742 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2742 #
2743 #
2743 # #Calculate Heights (Error N 13 and 14)
2744 # #Calculate Heights (Error N 13 and 14)
2744 # error = arrayParameters[:,-1]
2745 # error = arrayParameters[:,-1]
2745 # Ranges = arrayParameters[:,2]
2746 # Ranges = arrayParameters[:,2]
2746 # zenith = arrayParameters[:,5]
2747 # zenith = arrayParameters[:,5]
2747 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2748 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2748 # error = arrayParameters[:,-1]
2749 # error = arrayParameters[:,-1]
2749 #********************* END OF PARAMETERS CALCULATION **************************
2750 #********************* END OF PARAMETERS CALCULATION **************************
2750
2751
2751 #***************************+ PASS DATA TO NEXT STEP **********************
2752 #***************************+ PASS DATA TO NEXT STEP **********************
2752 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2753 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2753 dataOut.data_param = arrayParameters
2754 dataOut.data_param = arrayParameters
2754
2755
2755 if arrayParameters is None:
2756 if arrayParameters is None:
2756 dataOut.flagNoData = True
2757 dataOut.flagNoData = True
2757 else:
2758 else:
2758 dataOut.flagNoData = True
2759 dataOut.flagNoData = True
2759
2760
2760 return
2761 return
2761
2762
2762 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2763 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2763
2764
2764 minIndex = min(newheis[0])
2765 minIndex = min(newheis[0])
2765 maxIndex = max(newheis[0])
2766 maxIndex = max(newheis[0])
2766
2767
2767 voltage = voltage0[:,:,minIndex:maxIndex+1]
2768 voltage = voltage0[:,:,minIndex:maxIndex+1]
2768 nLength = voltage.shape[1]/n
2769 nLength = voltage.shape[1]/n
2769 nMin = 0
2770 nMin = 0
2770 nMax = 0
2771 nMax = 0
2771 phaseOffset = numpy.zeros((len(pairslist),n))
2772 phaseOffset = numpy.zeros((len(pairslist),n))
2772
2773
2773 for i in range(n):
2774 for i in range(n):
2774 nMax += nLength
2775 nMax += nLength
2775 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2776 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2776 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2777 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2777 phaseOffset[:,i] = phaseCCF.transpose()
2778 phaseOffset[:,i] = phaseCCF.transpose()
2778 nMin = nMax
2779 nMin = nMax
2779 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2780 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2780
2781
2781 #Remove Outliers
2782 #Remove Outliers
2782 factor = 2
2783 factor = 2
2783 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2784 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2784 dw = numpy.std(wt,axis = 1)
2785 dw = numpy.std(wt,axis = 1)
2785 dw = dw.reshape((dw.size,1))
2786 dw = dw.reshape((dw.size,1))
2786 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2787 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2787 phaseOffset[ind] = numpy.nan
2788 phaseOffset[ind] = numpy.nan
2788 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2789 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2789
2790
2790 return phaseOffset
2791 return phaseOffset
2791
2792
2792 def __shiftPhase(self, data, phaseShift):
2793 def __shiftPhase(self, data, phaseShift):
2793 #this will shift the phase of a complex number
2794 #this will shift the phase of a complex number
2794 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2795 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2795 return dataShifted
2796 return dataShifted
2796
2797
2797 def __estimatePhaseDifference(self, array, pairslist):
2798 def __estimatePhaseDifference(self, array, pairslist):
2798 nChannel = array.shape[0]
2799 nChannel = array.shape[0]
2799 nHeights = array.shape[2]
2800 nHeights = array.shape[2]
2800 numPairs = len(pairslist)
2801 numPairs = len(pairslist)
2801 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2802 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2802 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2803 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2803
2804
2804 #Correct phases
2805 #Correct phases
2805 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2806 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2806 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2807 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2807
2808
2808 if indDer[0].shape[0] > 0:
2809 if indDer[0].shape[0] > 0:
2809 for i in range(indDer[0].shape[0]):
2810 for i in range(indDer[0].shape[0]):
2810 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2811 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2811 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2812 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2812
2813
2813 # for j in range(numSides):
2814 # for j in range(numSides):
2814 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2815 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2815 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2816 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2816 #
2817 #
2817 #Linear
2818 #Linear
2818 phaseInt = numpy.zeros((numPairs,1))
2819 phaseInt = numpy.zeros((numPairs,1))
2819 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2820 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2820 for j in range(numPairs):
2821 for j in range(numPairs):
2821 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2822 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2822 phaseInt[j] = fit[1]
2823 phaseInt[j] = fit[1]
2823 #Phase Differences
2824 #Phase Differences
2824 phaseDiff = phaseInt - phaseCCF[:,2,:]
2825 phaseDiff = phaseInt - phaseCCF[:,2,:]
2825 phaseArrival = phaseInt.reshape(phaseInt.size)
2826 phaseArrival = phaseInt.reshape(phaseInt.size)
2826
2827
2827 #Dealias
2828 #Dealias
2828 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2829 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2829 # indAlias = numpy.where(phaseArrival > numpy.pi)
2830 # indAlias = numpy.where(phaseArrival > numpy.pi)
2830 # phaseArrival[indAlias] -= 2*numpy.pi
2831 # phaseArrival[indAlias] -= 2*numpy.pi
2831 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2832 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2832 # phaseArrival[indAlias] += 2*numpy.pi
2833 # phaseArrival[indAlias] += 2*numpy.pi
2833
2834
2834 return phaseDiff, phaseArrival
2835 return phaseDiff, phaseArrival
2835
2836
2836 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2837 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2837 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2838 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2838 #find the phase shifts of each channel over 1 second intervals
2839 #find the phase shifts of each channel over 1 second intervals
2839 #only look at ranges below the beacon signal
2840 #only look at ranges below the beacon signal
2840 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2841 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2841 numBlocks = int(volts.shape[1]/numProfPerBlock)
2842 numBlocks = int(volts.shape[1]/numProfPerBlock)
2842 numHeights = volts.shape[2]
2843 numHeights = volts.shape[2]
2843 nChannel = volts.shape[0]
2844 nChannel = volts.shape[0]
2844 voltsCohDet = volts.copy()
2845 voltsCohDet = volts.copy()
2845
2846
2846 pairsarray = numpy.array(pairslist)
2847 pairsarray = numpy.array(pairslist)
2847 indSides = pairsarray[:,1]
2848 indSides = pairsarray[:,1]
2848 # indSides = numpy.array(range(nChannel))
2849 # indSides = numpy.array(range(nChannel))
2849 # indSides = numpy.delete(indSides, indCenter)
2850 # indSides = numpy.delete(indSides, indCenter)
2850 #
2851 #
2851 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2852 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2852 listBlocks = numpy.array_split(volts, numBlocks, 1)
2853 listBlocks = numpy.array_split(volts, numBlocks, 1)
2853
2854
2854 startInd = 0
2855 startInd = 0
2855 endInd = 0
2856 endInd = 0
2856
2857
2857 for i in range(numBlocks):
2858 for i in range(numBlocks):
2858 startInd = endInd
2859 startInd = endInd
2859 endInd = endInd + listBlocks[i].shape[1]
2860 endInd = endInd + listBlocks[i].shape[1]
2860
2861
2861 arrayBlock = listBlocks[i]
2862 arrayBlock = listBlocks[i]
2862 # arrayBlockCenter = listCenter[i]
2863 # arrayBlockCenter = listCenter[i]
2863
2864
2864 #Estimate the Phase Difference
2865 #Estimate the Phase Difference
2865 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2866 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2866 #Phase Difference RMS
2867 #Phase Difference RMS
2867 arrayPhaseRMS = numpy.abs(phaseDiff)
2868 arrayPhaseRMS = numpy.abs(phaseDiff)
2868 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2869 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2869 indPhase = numpy.where(phaseRMSaux==4)
2870 indPhase = numpy.where(phaseRMSaux==4)
2870 #Shifting
2871 #Shifting
2871 if indPhase[0].shape[0] > 0:
2872 if indPhase[0].shape[0] > 0:
2872 for j in range(indSides.size):
2873 for j in range(indSides.size):
2873 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2874 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2874 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2875 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2875
2876
2876 return voltsCohDet
2877 return voltsCohDet
2877
2878
2878 def __calculateCCF(self, volts, pairslist ,laglist):
2879 def __calculateCCF(self, volts, pairslist ,laglist):
2879
2880
2880 nHeights = volts.shape[2]
2881 nHeights = volts.shape[2]
2881 nPoints = volts.shape[1]
2882 nPoints = volts.shape[1]
2882 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2883 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2883
2884
2884 for i in range(len(pairslist)):
2885 for i in range(len(pairslist)):
2885 volts1 = volts[pairslist[i][0]]
2886 volts1 = volts[pairslist[i][0]]
2886 volts2 = volts[pairslist[i][1]]
2887 volts2 = volts[pairslist[i][1]]
2887
2888
2888 for t in range(len(laglist)):
2889 for t in range(len(laglist)):
2889 idxT = laglist[t]
2890 idxT = laglist[t]
2890 if idxT >= 0:
2891 if idxT >= 0:
2891 vStacked = numpy.vstack((volts2[idxT:,:],
2892 vStacked = numpy.vstack((volts2[idxT:,:],
2892 numpy.zeros((idxT, nHeights),dtype='complex')))
2893 numpy.zeros((idxT, nHeights),dtype='complex')))
2893 else:
2894 else:
2894 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2895 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2895 volts2[:(nPoints + idxT),:]))
2896 volts2[:(nPoints + idxT),:]))
2896 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2897 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2897
2898
2898 vStacked = None
2899 vStacked = None
2899 return voltsCCF
2900 return voltsCCF
2900
2901
2901 def __getNoise(self, power, timeSegment, timeInterval):
2902 def __getNoise(self, power, timeSegment, timeInterval):
2902 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2903 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2903 numBlocks = int(power.shape[0]/numProfPerBlock)
2904 numBlocks = int(power.shape[0]/numProfPerBlock)
2904 numHeights = power.shape[1]
2905 numHeights = power.shape[1]
2905
2906
2906 listPower = numpy.array_split(power, numBlocks, 0)
2907 listPower = numpy.array_split(power, numBlocks, 0)
2907 noise = numpy.zeros((power.shape[0], power.shape[1]))
2908 noise = numpy.zeros((power.shape[0], power.shape[1]))
2908 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2909 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2909
2910
2910 startInd = 0
2911 startInd = 0
2911 endInd = 0
2912 endInd = 0
2912
2913
2913 for i in range(numBlocks): #split por canal
2914 for i in range(numBlocks): #split por canal
2914 startInd = endInd
2915 startInd = endInd
2915 endInd = endInd + listPower[i].shape[0]
2916 endInd = endInd + listPower[i].shape[0]
2916
2917
2917 arrayBlock = listPower[i]
2918 arrayBlock = listPower[i]
2918 noiseAux = numpy.mean(arrayBlock, 0)
2919 noiseAux = numpy.mean(arrayBlock, 0)
2919 # noiseAux = numpy.median(noiseAux)
2920 # noiseAux = numpy.median(noiseAux)
2920 # noiseAux = numpy.mean(arrayBlock)
2921 # noiseAux = numpy.mean(arrayBlock)
2921 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2922 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2922
2923
2923 noiseAux1 = numpy.mean(arrayBlock)
2924 noiseAux1 = numpy.mean(arrayBlock)
2924 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2925 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2925
2926
2926 return noise, noise1
2927 return noise, noise1
2927
2928
2928 def __findMeteors(self, power, thresh):
2929 def __findMeteors(self, power, thresh):
2929 nProf = power.shape[0]
2930 nProf = power.shape[0]
2930 nHeights = power.shape[1]
2931 nHeights = power.shape[1]
2931 listMeteors = []
2932 listMeteors = []
2932
2933
2933 for i in range(nHeights):
2934 for i in range(nHeights):
2934 powerAux = power[:,i]
2935 powerAux = power[:,i]
2935 threshAux = thresh[:,i]
2936 threshAux = thresh[:,i]
2936
2937
2937 indUPthresh = numpy.where(powerAux > threshAux)[0]
2938 indUPthresh = numpy.where(powerAux > threshAux)[0]
2938 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2939 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2939
2940
2940 j = 0
2941 j = 0
2941
2942
2942 while (j < indUPthresh.size - 2):
2943 while (j < indUPthresh.size - 2):
2943 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2944 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2944 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2945 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2945 indDNthresh = indDNthresh[indDNAux]
2946 indDNthresh = indDNthresh[indDNAux]
2946
2947
2947 if (indDNthresh.size > 0):
2948 if (indDNthresh.size > 0):
2948 indEnd = indDNthresh[0] - 1
2949 indEnd = indDNthresh[0] - 1
2949 indInit = indUPthresh[j]
2950 indInit = indUPthresh[j]
2950
2951
2951 meteor = powerAux[indInit:indEnd + 1]
2952 meteor = powerAux[indInit:indEnd + 1]
2952 indPeak = meteor.argmax() + indInit
2953 indPeak = meteor.argmax() + indInit
2953 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
2954 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
2954
2955
2955 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
2956 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
2956 j = numpy.where(indUPthresh == indEnd)[0] + 1
2957 j = numpy.where(indUPthresh == indEnd)[0] + 1
2957 else: j+=1
2958 else: j+=1
2958 else: j+=1
2959 else: j+=1
2959
2960
2960 return listMeteors
2961 return listMeteors
2961
2962
2962 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
2963 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
2963
2964
2964 arrayMeteors = numpy.asarray(listMeteors)
2965 arrayMeteors = numpy.asarray(listMeteors)
2965 listMeteors1 = []
2966 listMeteors1 = []
2966
2967
2967 while arrayMeteors.shape[0] > 0:
2968 while arrayMeteors.shape[0] > 0:
2968 FLAs = arrayMeteors[:,4]
2969 FLAs = arrayMeteors[:,4]
2969 maxFLA = FLAs.argmax()
2970 maxFLA = FLAs.argmax()
2970 listMeteors1.append(arrayMeteors[maxFLA,:])
2971 listMeteors1.append(arrayMeteors[maxFLA,:])
2971
2972
2972 MeteorInitTime = arrayMeteors[maxFLA,1]
2973 MeteorInitTime = arrayMeteors[maxFLA,1]
2973 MeteorEndTime = arrayMeteors[maxFLA,3]
2974 MeteorEndTime = arrayMeteors[maxFLA,3]
2974 MeteorHeight = arrayMeteors[maxFLA,0]
2975 MeteorHeight = arrayMeteors[maxFLA,0]
2975
2976
2976 #Check neighborhood
2977 #Check neighborhood
2977 maxHeightIndex = MeteorHeight + rangeLimit
2978 maxHeightIndex = MeteorHeight + rangeLimit
2978 minHeightIndex = MeteorHeight - rangeLimit
2979 minHeightIndex = MeteorHeight - rangeLimit
2979 minTimeIndex = MeteorInitTime - timeLimit
2980 minTimeIndex = MeteorInitTime - timeLimit
2980 maxTimeIndex = MeteorEndTime + timeLimit
2981 maxTimeIndex = MeteorEndTime + timeLimit
2981
2982
2982 #Check Heights
2983 #Check Heights
2983 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
2984 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
2984 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
2985 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
2985 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
2986 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
2986
2987
2987 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
2988 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
2988
2989
2989 return listMeteors1
2990 return listMeteors1
2990
2991
2991 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
2992 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
2992 numHeights = volts.shape[2]
2993 numHeights = volts.shape[2]
2993 nChannel = volts.shape[0]
2994 nChannel = volts.shape[0]
2994
2995
2995 thresholdPhase = thresh[0]
2996 thresholdPhase = thresh[0]
2996 thresholdNoise = thresh[1]
2997 thresholdNoise = thresh[1]
2997 thresholdDB = float(thresh[2])
2998 thresholdDB = float(thresh[2])
2998
2999
2999 thresholdDB1 = 10**(thresholdDB/10)
3000 thresholdDB1 = 10**(thresholdDB/10)
3000 pairsarray = numpy.array(pairslist)
3001 pairsarray = numpy.array(pairslist)
3001 indSides = pairsarray[:,1]
3002 indSides = pairsarray[:,1]
3002
3003
3003 pairslist1 = list(pairslist)
3004 pairslist1 = list(pairslist)
3004 pairslist1.append((0,1))
3005 pairslist1.append((0,1))
3005 pairslist1.append((3,4))
3006 pairslist1.append((3,4))
3006
3007
3007 listMeteors1 = []
3008 listMeteors1 = []
3008 listPowerSeries = []
3009 listPowerSeries = []
3009 listVoltageSeries = []
3010 listVoltageSeries = []
3010 #volts has the war data
3011 #volts has the war data
3011
3012
3012 if frequency == 30e6:
3013 if frequency == 30e6:
3013 timeLag = 45*10**-3
3014 timeLag = 45*10**-3
3014 else:
3015 else:
3015 timeLag = 15*10**-3
3016 timeLag = 15*10**-3
3016 lag = numpy.ceil(timeLag/timeInterval)
3017 lag = numpy.ceil(timeLag/timeInterval)
3017
3018
3018 for i in range(len(listMeteors)):
3019 for i in range(len(listMeteors)):
3019
3020
3020 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3021 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3021 meteorAux = numpy.zeros(16)
3022 meteorAux = numpy.zeros(16)
3022
3023
3023 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3024 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3024 mHeight = listMeteors[i][0]
3025 mHeight = listMeteors[i][0]
3025 mStart = listMeteors[i][1]
3026 mStart = listMeteors[i][1]
3026 mPeak = listMeteors[i][2]
3027 mPeak = listMeteors[i][2]
3027 mEnd = listMeteors[i][3]
3028 mEnd = listMeteors[i][3]
3028
3029
3029 #get the volt data between the start and end times of the meteor
3030 #get the volt data between the start and end times of the meteor
3030 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3031 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3031 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3032 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3032
3033
3033 #3.6. Phase Difference estimation
3034 #3.6. Phase Difference estimation
3034 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3035 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3035
3036
3036 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3037 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3037 #meteorVolts0.- all Channels, all Profiles
3038 #meteorVolts0.- all Channels, all Profiles
3038 meteorVolts0 = volts[:,:,mHeight]
3039 meteorVolts0 = volts[:,:,mHeight]
3039 meteorThresh = noise[:,mHeight]*thresholdNoise
3040 meteorThresh = noise[:,mHeight]*thresholdNoise
3040 meteorNoise = noise[:,mHeight]
3041 meteorNoise = noise[:,mHeight]
3041 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3042 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3042 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3043 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3043
3044
3044 #Times reestimation
3045 #Times reestimation
3045 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3046 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3046 if mStart1.size > 0:
3047 if mStart1.size > 0:
3047 mStart1 = mStart1[-1] + 1
3048 mStart1 = mStart1[-1] + 1
3048
3049
3049 else:
3050 else:
3050 mStart1 = mPeak
3051 mStart1 = mPeak
3051
3052
3052 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3053 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3053 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3054 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3054 if mEndDecayTime1.size == 0:
3055 if mEndDecayTime1.size == 0:
3055 mEndDecayTime1 = powerNet0.size
3056 mEndDecayTime1 = powerNet0.size
3056 else:
3057 else:
3057 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3058 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3058 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3059 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3059
3060
3060 #meteorVolts1.- all Channels, from start to end
3061 #meteorVolts1.- all Channels, from start to end
3061 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3062 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3062 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3063 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3063 if meteorVolts2.shape[1] == 0:
3064 if meteorVolts2.shape[1] == 0:
3064 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3065 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3065 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3066 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3066 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3067 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3067 ##################### END PARAMETERS REESTIMATION #########################
3068 ##################### END PARAMETERS REESTIMATION #########################
3068
3069
3069 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3070 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3070 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3071 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3071 if meteorVolts2.shape[1] > 0:
3072 if meteorVolts2.shape[1] > 0:
3072 #Phase Difference re-estimation
3073 #Phase Difference re-estimation
3073 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3074 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3074 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3075 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3075 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3076 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3076 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3077 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3077 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3078 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3078
3079
3079 #Phase Difference RMS
3080 #Phase Difference RMS
3080 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3081 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3081 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3082 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3082 #Data from Meteor
3083 #Data from Meteor
3083 mPeak1 = powerNet1.argmax() + mStart1
3084 mPeak1 = powerNet1.argmax() + mStart1
3084 mPeakPower1 = powerNet1.max()
3085 mPeakPower1 = powerNet1.max()
3085 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3086 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3086 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3087 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3087 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3088 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3088 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3089 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3089 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3090 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3090 #Vectorize
3091 #Vectorize
3091 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3092 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3092 meteorAux[7:11] = phaseDiffint[0:4]
3093 meteorAux[7:11] = phaseDiffint[0:4]
3093
3094
3094 #Rejection Criterions
3095 #Rejection Criterions
3095 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3096 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3096 meteorAux[-1] = 17
3097 meteorAux[-1] = 17
3097 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3098 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3098 meteorAux[-1] = 1
3099 meteorAux[-1] = 1
3099
3100
3100
3101
3101 else:
3102 else:
3102 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3103 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3103 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3104 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3104 PowerSeries = 0
3105 PowerSeries = 0
3105
3106
3106 listMeteors1.append(meteorAux)
3107 listMeteors1.append(meteorAux)
3107 listPowerSeries.append(PowerSeries)
3108 listPowerSeries.append(PowerSeries)
3108 listVoltageSeries.append(meteorVolts1)
3109 listVoltageSeries.append(meteorVolts1)
3109
3110
3110 return listMeteors1, listPowerSeries, listVoltageSeries
3111 return listMeteors1, listPowerSeries, listVoltageSeries
3111
3112
3112 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3113 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3113
3114
3114 threshError = 10
3115 threshError = 10
3115 #Depending if it is 30 or 50 MHz
3116 #Depending if it is 30 or 50 MHz
3116 if frequency == 30e6:
3117 if frequency == 30e6:
3117 timeLag = 45*10**-3
3118 timeLag = 45*10**-3
3118 else:
3119 else:
3119 timeLag = 15*10**-3
3120 timeLag = 15*10**-3
3120 lag = numpy.ceil(timeLag/timeInterval)
3121 lag = numpy.ceil(timeLag/timeInterval)
3121
3122
3122 listMeteors1 = []
3123 listMeteors1 = []
3123
3124
3124 for i in range(len(listMeteors)):
3125 for i in range(len(listMeteors)):
3125 meteorPower = listPower[i]
3126 meteorPower = listPower[i]
3126 meteorAux = listMeteors[i]
3127 meteorAux = listMeteors[i]
3127
3128
3128 if meteorAux[-1] == 0:
3129 if meteorAux[-1] == 0:
3129
3130
3130 try:
3131 try:
3131 indmax = meteorPower.argmax()
3132 indmax = meteorPower.argmax()
3132 indlag = indmax + lag
3133 indlag = indmax + lag
3133
3134
3134 y = meteorPower[indlag:]
3135 y = meteorPower[indlag:]
3135 x = numpy.arange(0, y.size)*timeLag
3136 x = numpy.arange(0, y.size)*timeLag
3136
3137
3137 #first guess
3138 #first guess
3138 a = y[0]
3139 a = y[0]
3139 tau = timeLag
3140 tau = timeLag
3140 #exponential fit
3141 #exponential fit
3141 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3142 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3142 y1 = self.__exponential_function(x, *popt)
3143 y1 = self.__exponential_function(x, *popt)
3143 #error estimation
3144 #error estimation
3144 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3145 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3145
3146
3146 decayTime = popt[1]
3147 decayTime = popt[1]
3147 riseTime = indmax*timeInterval
3148 riseTime = indmax*timeInterval
3148 meteorAux[11:13] = [decayTime, error]
3149 meteorAux[11:13] = [decayTime, error]
3149
3150
3150 #Table items 7, 8 and 11
3151 #Table items 7, 8 and 11
3151 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3152 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3152 meteorAux[-1] = 7
3153 meteorAux[-1] = 7
3153 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3154 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3154 meteorAux[-1] = 8
3155 meteorAux[-1] = 8
3155 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3156 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3156 meteorAux[-1] = 11
3157 meteorAux[-1] = 11
3157
3158
3158
3159
3159 except:
3160 except:
3160 meteorAux[-1] = 11
3161 meteorAux[-1] = 11
3161
3162
3162
3163
3163 listMeteors1.append(meteorAux)
3164 listMeteors1.append(meteorAux)
3164
3165
3165 return listMeteors1
3166 return listMeteors1
3166
3167
3167 #Exponential Function
3168 #Exponential Function
3168
3169
3169 def __exponential_function(self, x, a, tau):
3170 def __exponential_function(self, x, a, tau):
3170 y = a*numpy.exp(-x/tau)
3171 y = a*numpy.exp(-x/tau)
3171 return y
3172 return y
3172
3173
3173 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3174 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3174
3175
3175 pairslist1 = list(pairslist)
3176 pairslist1 = list(pairslist)
3176 pairslist1.append((0,1))
3177 pairslist1.append((0,1))
3177 pairslist1.append((3,4))
3178 pairslist1.append((3,4))
3178 numPairs = len(pairslist1)
3179 numPairs = len(pairslist1)
3179 #Time Lag
3180 #Time Lag
3180 timeLag = 45*10**-3
3181 timeLag = 45*10**-3
3181 c = 3e8
3182 c = 3e8
3182 lag = numpy.ceil(timeLag/timeInterval)
3183 lag = numpy.ceil(timeLag/timeInterval)
3183 freq = 30e6
3184 freq = 30e6
3184
3185
3185 listMeteors1 = []
3186 listMeteors1 = []
3186
3187
3187 for i in range(len(listMeteors)):
3188 for i in range(len(listMeteors)):
3188 meteorAux = listMeteors[i]
3189 meteorAux = listMeteors[i]
3189 if meteorAux[-1] == 0:
3190 if meteorAux[-1] == 0:
3190 mStart = listMeteors[i][1]
3191 mStart = listMeteors[i][1]
3191 mPeak = listMeteors[i][2]
3192 mPeak = listMeteors[i][2]
3192 mLag = mPeak - mStart + lag
3193 mLag = mPeak - mStart + lag
3193
3194
3194 #get the volt data between the start and end times of the meteor
3195 #get the volt data between the start and end times of the meteor
3195 meteorVolts = listVolts[i]
3196 meteorVolts = listVolts[i]
3196 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3197 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3197
3198
3198 #Get CCF
3199 #Get CCF
3199 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3200 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3200
3201
3201 #Method 2
3202 #Method 2
3202 slopes = numpy.zeros(numPairs)
3203 slopes = numpy.zeros(numPairs)
3203 time = numpy.array([-2,-1,1,2])*timeInterval
3204 time = numpy.array([-2,-1,1,2])*timeInterval
3204 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3205 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3205
3206
3206 #Correct phases
3207 #Correct phases
3207 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3208 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3208 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3209 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3209
3210
3210 if indDer[0].shape[0] > 0:
3211 if indDer[0].shape[0] > 0:
3211 for i in range(indDer[0].shape[0]):
3212 for i in range(indDer[0].shape[0]):
3212 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3213 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3213 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3214 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3214
3215
3215 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3216 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3216 for j in range(numPairs):
3217 for j in range(numPairs):
3217 fit = stats.linregress(time, angAllCCF[j,:])
3218 fit = stats.linregress(time, angAllCCF[j,:])
3218 slopes[j] = fit[0]
3219 slopes[j] = fit[0]
3219
3220
3220 #Remove Outlier
3221 #Remove Outlier
3221 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3222 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3222 # slopes = numpy.delete(slopes,indOut)
3223 # slopes = numpy.delete(slopes,indOut)
3223 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3224 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3224 # slopes = numpy.delete(slopes,indOut)
3225 # slopes = numpy.delete(slopes,indOut)
3225
3226
3226 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3227 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3227 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3228 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3228 meteorAux[-2] = radialError
3229 meteorAux[-2] = radialError
3229 meteorAux[-3] = radialVelocity
3230 meteorAux[-3] = radialVelocity
3230
3231
3231 #Setting Error
3232 #Setting Error
3232 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3233 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3233 if numpy.abs(radialVelocity) > 200:
3234 if numpy.abs(radialVelocity) > 200:
3234 meteorAux[-1] = 15
3235 meteorAux[-1] = 15
3235 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3236 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3236 elif radialError > radialStdThresh:
3237 elif radialError > radialStdThresh:
3237 meteorAux[-1] = 12
3238 meteorAux[-1] = 12
3238
3239
3239 listMeteors1.append(meteorAux)
3240 listMeteors1.append(meteorAux)
3240 return listMeteors1
3241 return listMeteors1
3241
3242
3242 def __setNewArrays(self, listMeteors, date, heiRang):
3243 def __setNewArrays(self, listMeteors, date, heiRang):
3243
3244
3244 #New arrays
3245 #New arrays
3245 arrayMeteors = numpy.array(listMeteors)
3246 arrayMeteors = numpy.array(listMeteors)
3246 arrayParameters = numpy.zeros((len(listMeteors), 13))
3247 arrayParameters = numpy.zeros((len(listMeteors), 13))
3247
3248
3248 #Date inclusion
3249 #Date inclusion
3249 # date = re.findall(r'\((.*?)\)', date)
3250 # date = re.findall(r'\((.*?)\)', date)
3250 # date = date[0].split(',')
3251 # date = date[0].split(',')
3251 # date = map(int, date)
3252 # date = map(int, date)
3252 #
3253 #
3253 # if len(date)<6:
3254 # if len(date)<6:
3254 # date.append(0)
3255 # date.append(0)
3255 #
3256 #
3256 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3257 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3257 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3258 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3258 arrayDate = numpy.tile(date, (len(listMeteors)))
3259 arrayDate = numpy.tile(date, (len(listMeteors)))
3259
3260
3260 #Meteor array
3261 #Meteor array
3261 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3262 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3262 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3263 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3263
3264
3264 #Parameters Array
3265 #Parameters Array
3265 arrayParameters[:,0] = arrayDate #Date
3266 arrayParameters[:,0] = arrayDate #Date
3266 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3267 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3267 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3268 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3268 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3269 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3269 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3270 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3270
3271
3271
3272
3272 return arrayParameters
3273 return arrayParameters
3273
3274
3274 class CorrectSMPhases(Operation):
3275 class CorrectSMPhases(Operation):
3275
3276
3276 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3277 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3277
3278
3278 arrayParameters = dataOut.data_param
3279 arrayParameters = dataOut.data_param
3279 pairsList = []
3280 pairsList = []
3280 pairx = (0,1)
3281 pairx = (0,1)
3281 pairy = (2,3)
3282 pairy = (2,3)
3282 pairsList.append(pairx)
3283 pairsList.append(pairx)
3283 pairsList.append(pairy)
3284 pairsList.append(pairy)
3284 jph = numpy.zeros(4)
3285 jph = numpy.zeros(4)
3285
3286
3286 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3287 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3287 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3288 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3288 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3289 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3289
3290
3290 meteorOps = SMOperations()
3291 meteorOps = SMOperations()
3291 if channelPositions is None:
3292 if channelPositions is None:
3292 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3293 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3293 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3294 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3294
3295
3295 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3296 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3296 h = (hmin,hmax)
3297 h = (hmin,hmax)
3297
3298
3298 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3299 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3299
3300
3300 dataOut.data_param = arrayParameters
3301 dataOut.data_param = arrayParameters
3301 return
3302 return
3302
3303
3303 class SMPhaseCalibration(Operation):
3304 class SMPhaseCalibration(Operation):
3304
3305
3305 __buffer = None
3306 __buffer = None
3306
3307
3307 __initime = None
3308 __initime = None
3308
3309
3309 __dataReady = False
3310 __dataReady = False
3310
3311
3311 __isConfig = False
3312 __isConfig = False
3312
3313
3313 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3314 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3314
3315
3315 dataTime = currentTime + paramInterval
3316 dataTime = currentTime + paramInterval
3316 deltaTime = dataTime - initTime
3317 deltaTime = dataTime - initTime
3317
3318
3318 if deltaTime >= outputInterval or deltaTime < 0:
3319 if deltaTime >= outputInterval or deltaTime < 0:
3319 return True
3320 return True
3320
3321
3321 return False
3322 return False
3322
3323
3323 def __getGammas(self, pairs, d, phases):
3324 def __getGammas(self, pairs, d, phases):
3324 gammas = numpy.zeros(2)
3325 gammas = numpy.zeros(2)
3325
3326
3326 for i in range(len(pairs)):
3327 for i in range(len(pairs)):
3327
3328
3328 pairi = pairs[i]
3329 pairi = pairs[i]
3329
3330
3330 phip3 = phases[:,pairi[0]]
3331 phip3 = phases[:,pairi[0]]
3331 d3 = d[pairi[0]]
3332 d3 = d[pairi[0]]
3332 phip2 = phases[:,pairi[1]]
3333 phip2 = phases[:,pairi[1]]
3333 d2 = d[pairi[1]]
3334 d2 = d[pairi[1]]
3334 #Calculating gamma
3335 #Calculating gamma
3335 # jdcos = alp1/(k*d1)
3336 # jdcos = alp1/(k*d1)
3336 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3337 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3337 jgamma = -phip2*d3/d2 - phip3
3338 jgamma = -phip2*d3/d2 - phip3
3338 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3339 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3339 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3340 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3340 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3341 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3341
3342
3342 #Revised distribution
3343 #Revised distribution
3343 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3344 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3344
3345
3345 #Histogram
3346 #Histogram
3346 nBins = 64
3347 nBins = 64
3347 rmin = -0.5*numpy.pi
3348 rmin = -0.5*numpy.pi
3348 rmax = 0.5*numpy.pi
3349 rmax = 0.5*numpy.pi
3349 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3350 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3350
3351
3351 meteorsY = phaseHisto[0]
3352 meteorsY = phaseHisto[0]
3352 phasesX = phaseHisto[1][:-1]
3353 phasesX = phaseHisto[1][:-1]
3353 width = phasesX[1] - phasesX[0]
3354 width = phasesX[1] - phasesX[0]
3354 phasesX += width/2
3355 phasesX += width/2
3355
3356
3356 #Gaussian aproximation
3357 #Gaussian aproximation
3357 bpeak = meteorsY.argmax()
3358 bpeak = meteorsY.argmax()
3358 peak = meteorsY.max()
3359 peak = meteorsY.max()
3359 jmin = bpeak - 5
3360 jmin = bpeak - 5
3360 jmax = bpeak + 5 + 1
3361 jmax = bpeak + 5 + 1
3361
3362
3362 if jmin<0:
3363 if jmin<0:
3363 jmin = 0
3364 jmin = 0
3364 jmax = 6
3365 jmax = 6
3365 elif jmax > meteorsY.size:
3366 elif jmax > meteorsY.size:
3366 jmin = meteorsY.size - 6
3367 jmin = meteorsY.size - 6
3367 jmax = meteorsY.size
3368 jmax = meteorsY.size
3368
3369
3369 x0 = numpy.array([peak,bpeak,50])
3370 x0 = numpy.array([peak,bpeak,50])
3370 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3371 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3371
3372
3372 #Gammas
3373 #Gammas
3373 gammas[i] = coeff[0][1]
3374 gammas[i] = coeff[0][1]
3374
3375
3375 return gammas
3376 return gammas
3376
3377
3377 def __residualFunction(self, coeffs, y, t):
3378 def __residualFunction(self, coeffs, y, t):
3378
3379
3379 return y - self.__gauss_function(t, coeffs)
3380 return y - self.__gauss_function(t, coeffs)
3380
3381
3381 def __gauss_function(self, t, coeffs):
3382 def __gauss_function(self, t, coeffs):
3382
3383
3383 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3384 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3384
3385
3385 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3386 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3386 meteorOps = SMOperations()
3387 meteorOps = SMOperations()
3387 nchan = 4
3388 nchan = 4
3388 pairx = pairsList[0] #x es 0
3389 pairx = pairsList[0] #x es 0
3389 pairy = pairsList[1] #y es 1
3390 pairy = pairsList[1] #y es 1
3390 center_xangle = 0
3391 center_xangle = 0
3391 center_yangle = 0
3392 center_yangle = 0
3392 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3393 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3393 ntimes = len(range_angle)
3394 ntimes = len(range_angle)
3394
3395
3395 nstepsx = 20
3396 nstepsx = 20
3396 nstepsy = 20
3397 nstepsy = 20
3397
3398
3398 for iz in range(ntimes):
3399 for iz in range(ntimes):
3399 min_xangle = -range_angle[iz]/2 + center_xangle
3400 min_xangle = -range_angle[iz]/2 + center_xangle
3400 max_xangle = range_angle[iz]/2 + center_xangle
3401 max_xangle = range_angle[iz]/2 + center_xangle
3401 min_yangle = -range_angle[iz]/2 + center_yangle
3402 min_yangle = -range_angle[iz]/2 + center_yangle
3402 max_yangle = range_angle[iz]/2 + center_yangle
3403 max_yangle = range_angle[iz]/2 + center_yangle
3403
3404
3404 inc_x = (max_xangle-min_xangle)/nstepsx
3405 inc_x = (max_xangle-min_xangle)/nstepsx
3405 inc_y = (max_yangle-min_yangle)/nstepsy
3406 inc_y = (max_yangle-min_yangle)/nstepsy
3406
3407
3407 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3408 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3408 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3409 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3409 penalty = numpy.zeros((nstepsx,nstepsy))
3410 penalty = numpy.zeros((nstepsx,nstepsy))
3410 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3411 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3411 jph = numpy.zeros(nchan)
3412 jph = numpy.zeros(nchan)
3412
3413
3413 # Iterations looking for the offset
3414 # Iterations looking for the offset
3414 for iy in range(int(nstepsy)):
3415 for iy in range(int(nstepsy)):
3415 for ix in range(int(nstepsx)):
3416 for ix in range(int(nstepsx)):
3416 d3 = d[pairsList[1][0]]
3417 d3 = d[pairsList[1][0]]
3417 d2 = d[pairsList[1][1]]
3418 d2 = d[pairsList[1][1]]
3418 d5 = d[pairsList[0][0]]
3419 d5 = d[pairsList[0][0]]
3419 d4 = d[pairsList[0][1]]
3420 d4 = d[pairsList[0][1]]
3420
3421
3421 alp2 = alpha_y[iy] #gamma 1
3422 alp2 = alpha_y[iy] #gamma 1
3422 alp4 = alpha_x[ix] #gamma 0
3423 alp4 = alpha_x[ix] #gamma 0
3423
3424
3424 alp3 = -alp2*d3/d2 - gammas[1]
3425 alp3 = -alp2*d3/d2 - gammas[1]
3425 alp5 = -alp4*d5/d4 - gammas[0]
3426 alp5 = -alp4*d5/d4 - gammas[0]
3426 # jph[pairy[1]] = alpha_y[iy]
3427 # jph[pairy[1]] = alpha_y[iy]
3427 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3428 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3428
3429
3429 # jph[pairx[1]] = alpha_x[ix]
3430 # jph[pairx[1]] = alpha_x[ix]
3430 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3431 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3431 jph[pairsList[0][1]] = alp4
3432 jph[pairsList[0][1]] = alp4
3432 jph[pairsList[0][0]] = alp5
3433 jph[pairsList[0][0]] = alp5
3433 jph[pairsList[1][0]] = alp3
3434 jph[pairsList[1][0]] = alp3
3434 jph[pairsList[1][1]] = alp2
3435 jph[pairsList[1][1]] = alp2
3435 jph_array[:,ix,iy] = jph
3436 jph_array[:,ix,iy] = jph
3436 # d = [2.0,2.5,2.5,2.0]
3437 # d = [2.0,2.5,2.5,2.0]
3437 #falta chequear si va a leer bien los meteoros
3438 #falta chequear si va a leer bien los meteoros
3438 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3439 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3439 error = meteorsArray1[:,-1]
3440 error = meteorsArray1[:,-1]
3440 ind1 = numpy.where(error==0)[0]
3441 ind1 = numpy.where(error==0)[0]
3441 penalty[ix,iy] = ind1.size
3442 penalty[ix,iy] = ind1.size
3442
3443
3443 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3444 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3444 phOffset = jph_array[:,i,j]
3445 phOffset = jph_array[:,i,j]
3445
3446
3446 center_xangle = phOffset[pairx[1]]
3447 center_xangle = phOffset[pairx[1]]
3447 center_yangle = phOffset[pairy[1]]
3448 center_yangle = phOffset[pairy[1]]
3448
3449
3449 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3450 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3450 phOffset = phOffset*180/numpy.pi
3451 phOffset = phOffset*180/numpy.pi
3451 return phOffset
3452 return phOffset
3452
3453
3453
3454
3454 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3455 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3455
3456
3456 dataOut.flagNoData = True
3457 dataOut.flagNoData = True
3457 self.__dataReady = False
3458 self.__dataReady = False
3458 dataOut.outputInterval = nHours*3600
3459 dataOut.outputInterval = nHours*3600
3459
3460
3460 if self.__isConfig == False:
3461 if self.__isConfig == False:
3461 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3462 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3462 #Get Initial LTC time
3463 #Get Initial LTC time
3463 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3464 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3464 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3465 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3465
3466
3466 self.__isConfig = True
3467 self.__isConfig = True
3467
3468
3468 if self.__buffer is None:
3469 if self.__buffer is None:
3469 self.__buffer = dataOut.data_param.copy()
3470 self.__buffer = dataOut.data_param.copy()
3470
3471
3471 else:
3472 else:
3472 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3473 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3473
3474
3474 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3475 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3475
3476
3476 if self.__dataReady:
3477 if self.__dataReady:
3477 dataOut.utctimeInit = self.__initime
3478 dataOut.utctimeInit = self.__initime
3478 self.__initime += dataOut.outputInterval #to erase time offset
3479 self.__initime += dataOut.outputInterval #to erase time offset
3479
3480
3480 freq = dataOut.frequency
3481 freq = dataOut.frequency
3481 c = dataOut.C #m/s
3482 c = dataOut.C #m/s
3482 lamb = c/freq
3483 lamb = c/freq
3483 k = 2*numpy.pi/lamb
3484 k = 2*numpy.pi/lamb
3484 azimuth = 0
3485 azimuth = 0
3485 h = (hmin, hmax)
3486 h = (hmin, hmax)
3486 # pairs = ((0,1),(2,3)) #Estrella
3487 # pairs = ((0,1),(2,3)) #Estrella
3487 # pairs = ((1,0),(2,3)) #T
3488 # pairs = ((1,0),(2,3)) #T
3488
3489
3489 if channelPositions is None:
3490 if channelPositions is None:
3490 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3491 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3491 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3492 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3492 meteorOps = SMOperations()
3493 meteorOps = SMOperations()
3493 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3494 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3494
3495
3495 #Checking correct order of pairs
3496 #Checking correct order of pairs
3496 pairs = []
3497 pairs = []
3497 if distances[1] > distances[0]:
3498 if distances[1] > distances[0]:
3498 pairs.append((1,0))
3499 pairs.append((1,0))
3499 else:
3500 else:
3500 pairs.append((0,1))
3501 pairs.append((0,1))
3501
3502
3502 if distances[3] > distances[2]:
3503 if distances[3] > distances[2]:
3503 pairs.append((3,2))
3504 pairs.append((3,2))
3504 else:
3505 else:
3505 pairs.append((2,3))
3506 pairs.append((2,3))
3506 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3507 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3507
3508
3508 meteorsArray = self.__buffer
3509 meteorsArray = self.__buffer
3509 error = meteorsArray[:,-1]
3510 error = meteorsArray[:,-1]
3510 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3511 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3511 ind1 = numpy.where(boolError)[0]
3512 ind1 = numpy.where(boolError)[0]
3512 meteorsArray = meteorsArray[ind1,:]
3513 meteorsArray = meteorsArray[ind1,:]
3513 meteorsArray[:,-1] = 0
3514 meteorsArray[:,-1] = 0
3514 phases = meteorsArray[:,8:12]
3515 phases = meteorsArray[:,8:12]
3515
3516
3516 #Calculate Gammas
3517 #Calculate Gammas
3517 gammas = self.__getGammas(pairs, distances, phases)
3518 gammas = self.__getGammas(pairs, distances, phases)
3518 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3519 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3519 #Calculate Phases
3520 #Calculate Phases
3520 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3521 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3521 phasesOff = phasesOff.reshape((1,phasesOff.size))
3522 phasesOff = phasesOff.reshape((1,phasesOff.size))
3522 dataOut.data_output = -phasesOff
3523 dataOut.data_output = -phasesOff
3523 dataOut.flagNoData = False
3524 dataOut.flagNoData = False
3524 self.__buffer = None
3525 self.__buffer = None
3525
3526
3526
3527
3527 return
3528 return
3528
3529
3529 class SMOperations():
3530 class SMOperations():
3530
3531
3531 def __init__(self):
3532 def __init__(self):
3532
3533
3533 return
3534 return
3534
3535
3535 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3536 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3536
3537
3537 arrayParameters = arrayParameters0.copy()
3538 arrayParameters = arrayParameters0.copy()
3538 hmin = h[0]
3539 hmin = h[0]
3539 hmax = h[1]
3540 hmax = h[1]
3540
3541
3541 #Calculate AOA (Error N 3, 4)
3542 #Calculate AOA (Error N 3, 4)
3542 #JONES ET AL. 1998
3543 #JONES ET AL. 1998
3543 AOAthresh = numpy.pi/8
3544 AOAthresh = numpy.pi/8
3544 error = arrayParameters[:,-1]
3545 error = arrayParameters[:,-1]
3545 phases = -arrayParameters[:,8:12] + jph
3546 phases = -arrayParameters[:,8:12] + jph
3546 # phases = numpy.unwrap(phases)
3547 # phases = numpy.unwrap(phases)
3547 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3548 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3548
3549
3549 #Calculate Heights (Error N 13 and 14)
3550 #Calculate Heights (Error N 13 and 14)
3550 error = arrayParameters[:,-1]
3551 error = arrayParameters[:,-1]
3551 Ranges = arrayParameters[:,1]
3552 Ranges = arrayParameters[:,1]
3552 zenith = arrayParameters[:,4]
3553 zenith = arrayParameters[:,4]
3553 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3554 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3554
3555
3555 #----------------------- Get Final data ------------------------------------
3556 #----------------------- Get Final data ------------------------------------
3556 # error = arrayParameters[:,-1]
3557 # error = arrayParameters[:,-1]
3557 # ind1 = numpy.where(error==0)[0]
3558 # ind1 = numpy.where(error==0)[0]
3558 # arrayParameters = arrayParameters[ind1,:]
3559 # arrayParameters = arrayParameters[ind1,:]
3559
3560
3560 return arrayParameters
3561 return arrayParameters
3561
3562
3562 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3563 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3563
3564
3564 arrayAOA = numpy.zeros((phases.shape[0],3))
3565 arrayAOA = numpy.zeros((phases.shape[0],3))
3565 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3566 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3566
3567
3567 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3568 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3568 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3569 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3569 arrayAOA[:,2] = cosDirError
3570 arrayAOA[:,2] = cosDirError
3570
3571
3571 azimuthAngle = arrayAOA[:,0]
3572 azimuthAngle = arrayAOA[:,0]
3572 zenithAngle = arrayAOA[:,1]
3573 zenithAngle = arrayAOA[:,1]
3573
3574
3574 #Setting Error
3575 #Setting Error
3575 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3576 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3576 error[indError] = 0
3577 error[indError] = 0
3577 #Number 3: AOA not fesible
3578 #Number 3: AOA not fesible
3578 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3579 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3579 error[indInvalid] = 3
3580 error[indInvalid] = 3
3580 #Number 4: Large difference in AOAs obtained from different antenna baselines
3581 #Number 4: Large difference in AOAs obtained from different antenna baselines
3581 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3582 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3582 error[indInvalid] = 4
3583 error[indInvalid] = 4
3583 return arrayAOA, error
3584 return arrayAOA, error
3584
3585
3585 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3586 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3586
3587
3587 #Initializing some variables
3588 #Initializing some variables
3588 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3589 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3589 ang_aux = ang_aux.reshape(1,ang_aux.size)
3590 ang_aux = ang_aux.reshape(1,ang_aux.size)
3590
3591
3591 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3592 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3592 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3593 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3593
3594
3594
3595
3595 for i in range(2):
3596 for i in range(2):
3596 ph0 = arrayPhase[:,pairsList[i][0]]
3597 ph0 = arrayPhase[:,pairsList[i][0]]
3597 ph1 = arrayPhase[:,pairsList[i][1]]
3598 ph1 = arrayPhase[:,pairsList[i][1]]
3598 d0 = distances[pairsList[i][0]]
3599 d0 = distances[pairsList[i][0]]
3599 d1 = distances[pairsList[i][1]]
3600 d1 = distances[pairsList[i][1]]
3600
3601
3601 ph0_aux = ph0 + ph1
3602 ph0_aux = ph0 + ph1
3602 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3603 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3603 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3604 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3604 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3605 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3605 #First Estimation
3606 #First Estimation
3606 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3607 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3607
3608
3608 #Most-Accurate Second Estimation
3609 #Most-Accurate Second Estimation
3609 phi1_aux = ph0 - ph1
3610 phi1_aux = ph0 - ph1
3610 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3611 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3611 #Direction Cosine 1
3612 #Direction Cosine 1
3612 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3613 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3613
3614
3614 #Searching the correct Direction Cosine
3615 #Searching the correct Direction Cosine
3615 cosdir0_aux = cosdir0[:,i]
3616 cosdir0_aux = cosdir0[:,i]
3616 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3617 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3617 #Minimum Distance
3618 #Minimum Distance
3618 cosDiff = (cosdir1 - cosdir0_aux)**2
3619 cosDiff = (cosdir1 - cosdir0_aux)**2
3619 indcos = cosDiff.argmin(axis = 1)
3620 indcos = cosDiff.argmin(axis = 1)
3620 #Saving Value obtained
3621 #Saving Value obtained
3621 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3622 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3622
3623
3623 return cosdir0, cosdir
3624 return cosdir0, cosdir
3624
3625
3625 def __calculateAOA(self, cosdir, azimuth):
3626 def __calculateAOA(self, cosdir, azimuth):
3626 cosdirX = cosdir[:,0]
3627 cosdirX = cosdir[:,0]
3627 cosdirY = cosdir[:,1]
3628 cosdirY = cosdir[:,1]
3628
3629
3629 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3630 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3630 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3631 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3631 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3632 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3632
3633
3633 return angles
3634 return angles
3634
3635
3635 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3636 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3636
3637
3637 Ramb = 375 #Ramb = c/(2*PRF)
3638 Ramb = 375 #Ramb = c/(2*PRF)
3638 Re = 6371 #Earth Radius
3639 Re = 6371 #Earth Radius
3639 heights = numpy.zeros(Ranges.shape)
3640 heights = numpy.zeros(Ranges.shape)
3640
3641
3641 R_aux = numpy.array([0,1,2])*Ramb
3642 R_aux = numpy.array([0,1,2])*Ramb
3642 R_aux = R_aux.reshape(1,R_aux.size)
3643 R_aux = R_aux.reshape(1,R_aux.size)
3643
3644
3644 Ranges = Ranges.reshape(Ranges.size,1)
3645 Ranges = Ranges.reshape(Ranges.size,1)
3645
3646
3646 Ri = Ranges + R_aux
3647 Ri = Ranges + R_aux
3647 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3648 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3648
3649
3649 #Check if there is a height between 70 and 110 km
3650 #Check if there is a height between 70 and 110 km
3650 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3651 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3651 ind_h = numpy.where(h_bool == 1)[0]
3652 ind_h = numpy.where(h_bool == 1)[0]
3652
3653
3653 hCorr = hi[ind_h, :]
3654 hCorr = hi[ind_h, :]
3654 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3655 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3655
3656
3656 hCorr = hi[ind_hCorr][:len(ind_h)]
3657 hCorr = hi[ind_hCorr][:len(ind_h)]
3657 heights[ind_h] = hCorr
3658 heights[ind_h] = hCorr
3658
3659
3659 #Setting Error
3660 #Setting Error
3660 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3661 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3661 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3662 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3662 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3663 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3663 error[indError] = 0
3664 error[indError] = 0
3664 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3665 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3665 error[indInvalid2] = 14
3666 error[indInvalid2] = 14
3666 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3667 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3667 error[indInvalid1] = 13
3668 error[indInvalid1] = 13
3668
3669
3669 return heights, error
3670 return heights, error
3670
3671
3671 def getPhasePairs(self, channelPositions):
3672 def getPhasePairs(self, channelPositions):
3672 chanPos = numpy.array(channelPositions)
3673 chanPos = numpy.array(channelPositions)
3673 listOper = list(itertools.combinations(list(range(5)),2))
3674 listOper = list(itertools.combinations(list(range(5)),2))
3674
3675
3675 distances = numpy.zeros(4)
3676 distances = numpy.zeros(4)
3676 axisX = []
3677 axisX = []
3677 axisY = []
3678 axisY = []
3678 distX = numpy.zeros(3)
3679 distX = numpy.zeros(3)
3679 distY = numpy.zeros(3)
3680 distY = numpy.zeros(3)
3680 ix = 0
3681 ix = 0
3681 iy = 0
3682 iy = 0
3682
3683
3683 pairX = numpy.zeros((2,2))
3684 pairX = numpy.zeros((2,2))
3684 pairY = numpy.zeros((2,2))
3685 pairY = numpy.zeros((2,2))
3685
3686
3686 for i in range(len(listOper)):
3687 for i in range(len(listOper)):
3687 pairi = listOper[i]
3688 pairi = listOper[i]
3688
3689
3689 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3690 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3690
3691
3691 if posDif[0] == 0:
3692 if posDif[0] == 0:
3692 axisY.append(pairi)
3693 axisY.append(pairi)
3693 distY[iy] = posDif[1]
3694 distY[iy] = posDif[1]
3694 iy += 1
3695 iy += 1
3695 elif posDif[1] == 0:
3696 elif posDif[1] == 0:
3696 axisX.append(pairi)
3697 axisX.append(pairi)
3697 distX[ix] = posDif[0]
3698 distX[ix] = posDif[0]
3698 ix += 1
3699 ix += 1
3699
3700
3700 for i in range(2):
3701 for i in range(2):
3701 if i==0:
3702 if i==0:
3702 dist0 = distX
3703 dist0 = distX
3703 axis0 = axisX
3704 axis0 = axisX
3704 else:
3705 else:
3705 dist0 = distY
3706 dist0 = distY
3706 axis0 = axisY
3707 axis0 = axisY
3707
3708
3708 side = numpy.argsort(dist0)[:-1]
3709 side = numpy.argsort(dist0)[:-1]
3709 axis0 = numpy.array(axis0)[side,:]
3710 axis0 = numpy.array(axis0)[side,:]
3710 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3711 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3711 axis1 = numpy.unique(numpy.reshape(axis0,4))
3712 axis1 = numpy.unique(numpy.reshape(axis0,4))
3712 side = axis1[axis1 != chanC]
3713 side = axis1[axis1 != chanC]
3713 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3714 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3714 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3715 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3715 if diff1<0:
3716 if diff1<0:
3716 chan2 = side[0]
3717 chan2 = side[0]
3717 d2 = numpy.abs(diff1)
3718 d2 = numpy.abs(diff1)
3718 chan1 = side[1]
3719 chan1 = side[1]
3719 d1 = numpy.abs(diff2)
3720 d1 = numpy.abs(diff2)
3720 else:
3721 else:
3721 chan2 = side[1]
3722 chan2 = side[1]
3722 d2 = numpy.abs(diff2)
3723 d2 = numpy.abs(diff2)
3723 chan1 = side[0]
3724 chan1 = side[0]
3724 d1 = numpy.abs(diff1)
3725 d1 = numpy.abs(diff1)
3725
3726
3726 if i==0:
3727 if i==0:
3727 chanCX = chanC
3728 chanCX = chanC
3728 chan1X = chan1
3729 chan1X = chan1
3729 chan2X = chan2
3730 chan2X = chan2
3730 distances[0:2] = numpy.array([d1,d2])
3731 distances[0:2] = numpy.array([d1,d2])
3731 else:
3732 else:
3732 chanCY = chanC
3733 chanCY = chanC
3733 chan1Y = chan1
3734 chan1Y = chan1
3734 chan2Y = chan2
3735 chan2Y = chan2
3735 distances[2:4] = numpy.array([d1,d2])
3736 distances[2:4] = numpy.array([d1,d2])
3736 # axisXsides = numpy.reshape(axisX[ix,:],4)
3737 # axisXsides = numpy.reshape(axisX[ix,:],4)
3737 #
3738 #
3738 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3739 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3739 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3740 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3740 #
3741 #
3741 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3742 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3742 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3743 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3743 # channel25X = int(pairX[0,ind25X])
3744 # channel25X = int(pairX[0,ind25X])
3744 # channel20X = int(pairX[1,ind20X])
3745 # channel20X = int(pairX[1,ind20X])
3745 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3746 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3746 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3747 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3747 # channel25Y = int(pairY[0,ind25Y])
3748 # channel25Y = int(pairY[0,ind25Y])
3748 # channel20Y = int(pairY[1,ind20Y])
3749 # channel20Y = int(pairY[1,ind20Y])
3749
3750
3750 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3751 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3751 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3752 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3752
3753
3753 return pairslist, distances
3754 return pairslist, distances
3754 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3755 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3755 #
3756 #
3756 # arrayAOA = numpy.zeros((phases.shape[0],3))
3757 # arrayAOA = numpy.zeros((phases.shape[0],3))
3757 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3758 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3758 #
3759 #
3759 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3760 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3760 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3761 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3761 # arrayAOA[:,2] = cosDirError
3762 # arrayAOA[:,2] = cosDirError
3762 #
3763 #
3763 # azimuthAngle = arrayAOA[:,0]
3764 # azimuthAngle = arrayAOA[:,0]
3764 # zenithAngle = arrayAOA[:,1]
3765 # zenithAngle = arrayAOA[:,1]
3765 #
3766 #
3766 # #Setting Error
3767 # #Setting Error
3767 # #Number 3: AOA not fesible
3768 # #Number 3: AOA not fesible
3768 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3769 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3769 # error[indInvalid] = 3
3770 # error[indInvalid] = 3
3770 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3771 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3771 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3772 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3772 # error[indInvalid] = 4
3773 # error[indInvalid] = 4
3773 # return arrayAOA, error
3774 # return arrayAOA, error
3774 #
3775 #
3775 # def __getDirectionCosines(self, arrayPhase, pairsList):
3776 # def __getDirectionCosines(self, arrayPhase, pairsList):
3776 #
3777 #
3777 # #Initializing some variables
3778 # #Initializing some variables
3778 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3779 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3779 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3780 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3780 #
3781 #
3781 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3782 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3782 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3783 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3783 #
3784 #
3784 #
3785 #
3785 # for i in range(2):
3786 # for i in range(2):
3786 # #First Estimation
3787 # #First Estimation
3787 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3788 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3788 # #Dealias
3789 # #Dealias
3789 # indcsi = numpy.where(phi0_aux > numpy.pi)
3790 # indcsi = numpy.where(phi0_aux > numpy.pi)
3790 # phi0_aux[indcsi] -= 2*numpy.pi
3791 # phi0_aux[indcsi] -= 2*numpy.pi
3791 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3792 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3792 # phi0_aux[indcsi] += 2*numpy.pi
3793 # phi0_aux[indcsi] += 2*numpy.pi
3793 # #Direction Cosine 0
3794 # #Direction Cosine 0
3794 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3795 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3795 #
3796 #
3796 # #Most-Accurate Second Estimation
3797 # #Most-Accurate Second Estimation
3797 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3798 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3798 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3799 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3799 # #Direction Cosine 1
3800 # #Direction Cosine 1
3800 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3801 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3801 #
3802 #
3802 # #Searching the correct Direction Cosine
3803 # #Searching the correct Direction Cosine
3803 # cosdir0_aux = cosdir0[:,i]
3804 # cosdir0_aux = cosdir0[:,i]
3804 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3805 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3805 # #Minimum Distance
3806 # #Minimum Distance
3806 # cosDiff = (cosdir1 - cosdir0_aux)**2
3807 # cosDiff = (cosdir1 - cosdir0_aux)**2
3807 # indcos = cosDiff.argmin(axis = 1)
3808 # indcos = cosDiff.argmin(axis = 1)
3808 # #Saving Value obtained
3809 # #Saving Value obtained
3809 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3810 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3810 #
3811 #
3811 # return cosdir0, cosdir
3812 # return cosdir0, cosdir
3812 #
3813 #
3813 # def __calculateAOA(self, cosdir, azimuth):
3814 # def __calculateAOA(self, cosdir, azimuth):
3814 # cosdirX = cosdir[:,0]
3815 # cosdirX = cosdir[:,0]
3815 # cosdirY = cosdir[:,1]
3816 # cosdirY = cosdir[:,1]
3816 #
3817 #
3817 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3818 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3818 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3819 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3819 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3820 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3820 #
3821 #
3821 # return angles
3822 # return angles
3822 #
3823 #
3823 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3824 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3824 #
3825 #
3825 # Ramb = 375 #Ramb = c/(2*PRF)
3826 # Ramb = 375 #Ramb = c/(2*PRF)
3826 # Re = 6371 #Earth Radius
3827 # Re = 6371 #Earth Radius
3827 # heights = numpy.zeros(Ranges.shape)
3828 # heights = numpy.zeros(Ranges.shape)
3828 #
3829 #
3829 # R_aux = numpy.array([0,1,2])*Ramb
3830 # R_aux = numpy.array([0,1,2])*Ramb
3830 # R_aux = R_aux.reshape(1,R_aux.size)
3831 # R_aux = R_aux.reshape(1,R_aux.size)
3831 #
3832 #
3832 # Ranges = Ranges.reshape(Ranges.size,1)
3833 # Ranges = Ranges.reshape(Ranges.size,1)
3833 #
3834 #
3834 # Ri = Ranges + R_aux
3835 # Ri = Ranges + R_aux
3835 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3836 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3836 #
3837 #
3837 # #Check if there is a height between 70 and 110 km
3838 # #Check if there is a height between 70 and 110 km
3838 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3839 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3839 # ind_h = numpy.where(h_bool == 1)[0]
3840 # ind_h = numpy.where(h_bool == 1)[0]
3840 #
3841 #
3841 # hCorr = hi[ind_h, :]
3842 # hCorr = hi[ind_h, :]
3842 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3843 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3843 #
3844 #
3844 # hCorr = hi[ind_hCorr]
3845 # hCorr = hi[ind_hCorr]
3845 # heights[ind_h] = hCorr
3846 # heights[ind_h] = hCorr
3846 #
3847 #
3847 # #Setting Error
3848 # #Setting Error
3848 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3849 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3849 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3850 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3850 #
3851 #
3851 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3852 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3852 # error[indInvalid2] = 14
3853 # error[indInvalid2] = 14
3853 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3854 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3854 # error[indInvalid1] = 13
3855 # error[indInvalid1] = 13
3855 #
3856 #
3856 # return heights, error
3857 # return heights, error
3857 No newline at end of file
1 NO CONTENT: modified file
NO CONTENT: modified file
@@ -1,1328 +1,1327
1 import sys
1 import sys
2 import numpy
2 import numpy
3 from scipy import interpolate
3 from scipy import interpolate
4 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
4 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
5 from schainpy.model.data.jrodata import Voltage
5 from schainpy.model.data.jrodata import Voltage
6 from schainpy.utils import log
6 from schainpy.utils import log
7 from time import time
7 from time import time
8
8
9
9
10 @MPDecorator
10 @MPDecorator
11 class VoltageProc(ProcessingUnit):
11 class VoltageProc(ProcessingUnit):
12
12
13 def __init__(self):
13 def __init__(self):
14
14
15 ProcessingUnit.__init__(self)
15 ProcessingUnit.__init__(self)
16
16
17 self.dataOut = Voltage()
17 self.dataOut = Voltage()
18 self.flip = 1
18 self.flip = 1
19 self.setupReq = False
19 self.setupReq = False
20
20
21 def run(self):
21 def run(self):
22
22
23 if self.dataIn.type == 'AMISR':
23 if self.dataIn.type == 'AMISR':
24 self.__updateObjFromAmisrInput()
24 self.__updateObjFromAmisrInput()
25
25
26 if self.dataIn.type == 'Voltage':
26 if self.dataIn.type == 'Voltage':
27 self.dataOut.copy(self.dataIn)
27 self.dataOut.copy(self.dataIn)
28
28
29 # self.dataOut.copy(self.dataIn)
29 # self.dataOut.copy(self.dataIn)
30
30
31 def __updateObjFromAmisrInput(self):
31 def __updateObjFromAmisrInput(self):
32
32
33 self.dataOut.timeZone = self.dataIn.timeZone
33 self.dataOut.timeZone = self.dataIn.timeZone
34 self.dataOut.dstFlag = self.dataIn.dstFlag
34 self.dataOut.dstFlag = self.dataIn.dstFlag
35 self.dataOut.errorCount = self.dataIn.errorCount
35 self.dataOut.errorCount = self.dataIn.errorCount
36 self.dataOut.useLocalTime = self.dataIn.useLocalTime
36 self.dataOut.useLocalTime = self.dataIn.useLocalTime
37
37
38 self.dataOut.flagNoData = self.dataIn.flagNoData
38 self.dataOut.flagNoData = self.dataIn.flagNoData
39 self.dataOut.data = self.dataIn.data
39 self.dataOut.data = self.dataIn.data
40 self.dataOut.utctime = self.dataIn.utctime
40 self.dataOut.utctime = self.dataIn.utctime
41 self.dataOut.channelList = self.dataIn.channelList
41 self.dataOut.channelList = self.dataIn.channelList
42 #self.dataOut.timeInterval = self.dataIn.timeInterval
42 #self.dataOut.timeInterval = self.dataIn.timeInterval
43 self.dataOut.heightList = self.dataIn.heightList
43 self.dataOut.heightList = self.dataIn.heightList
44 self.dataOut.nProfiles = self.dataIn.nProfiles
44 self.dataOut.nProfiles = self.dataIn.nProfiles
45
45
46 self.dataOut.nCohInt = self.dataIn.nCohInt
46 self.dataOut.nCohInt = self.dataIn.nCohInt
47 self.dataOut.ippSeconds = self.dataIn.ippSeconds
47 self.dataOut.ippSeconds = self.dataIn.ippSeconds
48 self.dataOut.frequency = self.dataIn.frequency
48 self.dataOut.frequency = self.dataIn.frequency
49
49
50 self.dataOut.azimuth = self.dataIn.azimuth
50 self.dataOut.azimuth = self.dataIn.azimuth
51 self.dataOut.zenith = self.dataIn.zenith
51 self.dataOut.zenith = self.dataIn.zenith
52
52
53 self.dataOut.beam.codeList = self.dataIn.beam.codeList
53 self.dataOut.beam.codeList = self.dataIn.beam.codeList
54 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
54 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
55 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
55 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
56 #
56 #
57 # pass#
57 # pass#
58 #
58 #
59 # def init(self):
59 # def init(self):
60 #
60 #
61 #
61 #
62 # if self.dataIn.type == 'AMISR':
62 # if self.dataIn.type == 'AMISR':
63 # self.__updateObjFromAmisrInput()
63 # self.__updateObjFromAmisrInput()
64 #
64 #
65 # if self.dataIn.type == 'Voltage':
65 # if self.dataIn.type == 'Voltage':
66 # self.dataOut.copy(self.dataIn)
66 # self.dataOut.copy(self.dataIn)
67 # # No necesita copiar en cada init() los atributos de dataIn
67 # # No necesita copiar en cada init() los atributos de dataIn
68 # # la copia deberia hacerse por cada nuevo bloque de datos
68 # # la copia deberia hacerse por cada nuevo bloque de datos
69
69
70 def selectChannels(self, channelList):
70 def selectChannels(self, channelList):
71
71
72 channelIndexList = []
72 channelIndexList = []
73
73
74 for channel in channelList:
74 for channel in channelList:
75 if channel not in self.dataOut.channelList:
75 if channel not in self.dataOut.channelList:
76 raise ValueError("Channel %d is not in %s" %(channel, str(self.dataOut.channelList)))
76 raise ValueError("Channel %d is not in %s" %(channel, str(self.dataOut.channelList)))
77
77
78 index = self.dataOut.channelList.index(channel)
78 index = self.dataOut.channelList.index(channel)
79 channelIndexList.append(index)
79 channelIndexList.append(index)
80
80
81 self.selectChannelsByIndex(channelIndexList)
81 self.selectChannelsByIndex(channelIndexList)
82
82
83 def selectChannelsByIndex(self, channelIndexList):
83 def selectChannelsByIndex(self, channelIndexList):
84 """
84 """
85 Selecciona un bloque de datos en base a canales segun el channelIndexList
85 Selecciona un bloque de datos en base a canales segun el channelIndexList
86
86
87 Input:
87 Input:
88 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
88 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
89
89
90 Affected:
90 Affected:
91 self.dataOut.data
91 self.dataOut.data
92 self.dataOut.channelIndexList
92 self.dataOut.channelIndexList
93 self.dataOut.nChannels
93 self.dataOut.nChannels
94 self.dataOut.m_ProcessingHeader.totalSpectra
94 self.dataOut.m_ProcessingHeader.totalSpectra
95 self.dataOut.systemHeaderObj.numChannels
95 self.dataOut.systemHeaderObj.numChannels
96 self.dataOut.m_ProcessingHeader.blockSize
96 self.dataOut.m_ProcessingHeader.blockSize
97
97
98 Return:
98 Return:
99 None
99 None
100 """
100 """
101
101
102 for channelIndex in channelIndexList:
102 for channelIndex in channelIndexList:
103 if channelIndex not in self.dataOut.channelIndexList:
103 if channelIndex not in self.dataOut.channelIndexList:
104 print(channelIndexList)
104 print(channelIndexList)
105 raise ValueError("The value %d in channelIndexList is not valid" %channelIndex)
105 raise ValueError("The value %d in channelIndexList is not valid" %channelIndex)
106
106
107 if self.dataOut.flagDataAsBlock:
107 if self.dataOut.flagDataAsBlock:
108 """
108 """
109 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
109 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
110 """
110 """
111 data = self.dataOut.data[channelIndexList,:,:]
111 data = self.dataOut.data[channelIndexList,:,:]
112 else:
112 else:
113 data = self.dataOut.data[channelIndexList,:]
113 data = self.dataOut.data[channelIndexList,:]
114
114
115 self.dataOut.data = data
115 self.dataOut.data = data
116 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
116 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
117 self.dataOut.channelList = range(len(channelIndexList))
117 self.dataOut.channelList = range(len(channelIndexList))
118
118
119 return 1
119 return 1
120
120
121 def selectHeights(self, minHei=None, maxHei=None):
121 def selectHeights(self, minHei=None, maxHei=None):
122 """
122 """
123 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
123 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
124 minHei <= height <= maxHei
124 minHei <= height <= maxHei
125
125
126 Input:
126 Input:
127 minHei : valor minimo de altura a considerar
127 minHei : valor minimo de altura a considerar
128 maxHei : valor maximo de altura a considerar
128 maxHei : valor maximo de altura a considerar
129
129
130 Affected:
130 Affected:
131 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
131 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
132
132
133 Return:
133 Return:
134 1 si el metodo se ejecuto con exito caso contrario devuelve 0
134 1 si el metodo se ejecuto con exito caso contrario devuelve 0
135 """
135 """
136
136
137 if minHei == None:
137 if minHei == None:
138 minHei = self.dataOut.heightList[0]
138 minHei = self.dataOut.heightList[0]
139
139
140 if maxHei == None:
140 if maxHei == None:
141 maxHei = self.dataOut.heightList[-1]
141 maxHei = self.dataOut.heightList[-1]
142
142
143 if (minHei < self.dataOut.heightList[0]):
143 if (minHei < self.dataOut.heightList[0]):
144 minHei = self.dataOut.heightList[0]
144 minHei = self.dataOut.heightList[0]
145
145
146 if (maxHei > self.dataOut.heightList[-1]):
146 if (maxHei > self.dataOut.heightList[-1]):
147 maxHei = self.dataOut.heightList[-1]
147 maxHei = self.dataOut.heightList[-1]
148
148
149 minIndex = 0
149 minIndex = 0
150 maxIndex = 0
150 maxIndex = 0
151 heights = self.dataOut.heightList
151 heights = self.dataOut.heightList
152
152
153 inda = numpy.where(heights >= minHei)
153 inda = numpy.where(heights >= minHei)
154 indb = numpy.where(heights <= maxHei)
154 indb = numpy.where(heights <= maxHei)
155
155
156 try:
156 try:
157 minIndex = inda[0][0]
157 minIndex = inda[0][0]
158 except:
158 except:
159 minIndex = 0
159 minIndex = 0
160
160
161 try:
161 try:
162 maxIndex = indb[0][-1]
162 maxIndex = indb[0][-1]
163 except:
163 except:
164 maxIndex = len(heights)
164 maxIndex = len(heights)
165
165
166 self.selectHeightsByIndex(minIndex, maxIndex)
166 self.selectHeightsByIndex(minIndex, maxIndex)
167
167
168 return 1
168 return 1
169
169
170
170
171 def selectHeightsByIndex(self, minIndex, maxIndex):
171 def selectHeightsByIndex(self, minIndex, maxIndex):
172 """
172 """
173 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
173 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
174 minIndex <= index <= maxIndex
174 minIndex <= index <= maxIndex
175
175
176 Input:
176 Input:
177 minIndex : valor de indice minimo de altura a considerar
177 minIndex : valor de indice minimo de altura a considerar
178 maxIndex : valor de indice maximo de altura a considerar
178 maxIndex : valor de indice maximo de altura a considerar
179
179
180 Affected:
180 Affected:
181 self.dataOut.data
181 self.dataOut.data
182 self.dataOut.heightList
182 self.dataOut.heightList
183
183
184 Return:
184 Return:
185 1 si el metodo se ejecuto con exito caso contrario devuelve 0
185 1 si el metodo se ejecuto con exito caso contrario devuelve 0
186 """
186 """
187
187
188 if (minIndex < 0) or (minIndex > maxIndex):
188 if (minIndex < 0) or (minIndex > maxIndex):
189 raise ValueError("Height index range (%d,%d) is not valid" % (minIndex, maxIndex))
189 raise ValueError("Height index range (%d,%d) is not valid" % (minIndex, maxIndex))
190
190
191 if (maxIndex >= self.dataOut.nHeights):
191 if (maxIndex >= self.dataOut.nHeights):
192 maxIndex = self.dataOut.nHeights
192 maxIndex = self.dataOut.nHeights
193
193
194 #voltage
194 #voltage
195 if self.dataOut.flagDataAsBlock:
195 if self.dataOut.flagDataAsBlock:
196 """
196 """
197 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
197 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
198 """
198 """
199 data = self.dataOut.data[:,:, minIndex:maxIndex]
199 data = self.dataOut.data[:,:, minIndex:maxIndex]
200 else:
200 else:
201 data = self.dataOut.data[:, minIndex:maxIndex]
201 data = self.dataOut.data[:, minIndex:maxIndex]
202
202
203 # firstHeight = self.dataOut.heightList[minIndex]
203 # firstHeight = self.dataOut.heightList[minIndex]
204
204
205 self.dataOut.data = data
205 self.dataOut.data = data
206 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
206 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
207
207
208 if self.dataOut.nHeights <= 1:
208 if self.dataOut.nHeights <= 1:
209 raise ValueError("selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights))
209 raise ValueError("selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights))
210
210
211 return 1
211 return 1
212
212
213
213
214 def filterByHeights(self, window):
214 def filterByHeights(self, window):
215
215
216 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
216 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
217
217
218 if window == None:
218 if window == None:
219 window = (self.dataOut.radarControllerHeaderObj.txA/self.dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
219 window = (self.dataOut.radarControllerHeaderObj.txA/self.dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
220
220
221 newdelta = deltaHeight * window
221 newdelta = deltaHeight * window
222 r = self.dataOut.nHeights % window
222 r = self.dataOut.nHeights % window
223 newheights = (self.dataOut.nHeights-r)/window
223 newheights = (self.dataOut.nHeights-r)/window
224
224
225 if newheights <= 1:
225 if newheights <= 1:
226 raise ValueError("filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(self.dataOut.nHeights, window))
226 raise ValueError("filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(self.dataOut.nHeights, window))
227
227
228 if self.dataOut.flagDataAsBlock:
228 if self.dataOut.flagDataAsBlock:
229 """
229 """
230 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
230 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
231 """
231 """
232 buffer = self.dataOut.data[:, :, 0:int(self.dataOut.nHeights-r)]
232 buffer = self.dataOut.data[:, :, 0:int(self.dataOut.nHeights-r)]
233 buffer = buffer.reshape(self.dataOut.nChannels, self.dataOut.nProfiles, int(self.dataOut.nHeights/window), window)
233 buffer = buffer.reshape(self.dataOut.nChannels, self.dataOut.nProfiles, int(self.dataOut.nHeights/window), window)
234 buffer = numpy.sum(buffer,3)
234 buffer = numpy.sum(buffer,3)
235
235
236 else:
236 else:
237 buffer = self.dataOut.data[:,0:int(self.dataOut.nHeights-r)]
237 buffer = self.dataOut.data[:,0:int(self.dataOut.nHeights-r)]
238 buffer = buffer.reshape(self.dataOut.nChannels,int(self.dataOut.nHeights/window),int(window))
238 buffer = buffer.reshape(self.dataOut.nChannels,int(self.dataOut.nHeights/window),int(window))
239 buffer = numpy.sum(buffer,2)
239 buffer = numpy.sum(buffer,2)
240
240
241 self.dataOut.data = buffer
241 self.dataOut.data = buffer
242 self.dataOut.heightList = self.dataOut.heightList[0] + numpy.arange( newheights )*newdelta
242 self.dataOut.heightList = self.dataOut.heightList[0] + numpy.arange( newheights )*newdelta
243 self.dataOut.windowOfFilter = window
243 self.dataOut.windowOfFilter = window
244
244
245 def setH0(self, h0, deltaHeight = None):
245 def setH0(self, h0, deltaHeight = None):
246
246
247 if not deltaHeight:
247 if not deltaHeight:
248 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
248 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
249
249
250 nHeights = self.dataOut.nHeights
250 nHeights = self.dataOut.nHeights
251
251
252 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
252 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
253
253
254 self.dataOut.heightList = newHeiRange
254 self.dataOut.heightList = newHeiRange
255
255
256 def deFlip(self, channelList = []):
256 def deFlip(self, channelList = []):
257
257
258 data = self.dataOut.data.copy()
258 data = self.dataOut.data.copy()
259
259
260 if self.dataOut.flagDataAsBlock:
260 if self.dataOut.flagDataAsBlock:
261 flip = self.flip
261 flip = self.flip
262 profileList = list(range(self.dataOut.nProfiles))
262 profileList = list(range(self.dataOut.nProfiles))
263
263
264 if not channelList:
264 if not channelList:
265 for thisProfile in profileList:
265 for thisProfile in profileList:
266 data[:,thisProfile,:] = data[:,thisProfile,:]*flip
266 data[:,thisProfile,:] = data[:,thisProfile,:]*flip
267 flip *= -1.0
267 flip *= -1.0
268 else:
268 else:
269 for thisChannel in channelList:
269 for thisChannel in channelList:
270 if thisChannel not in self.dataOut.channelList:
270 if thisChannel not in self.dataOut.channelList:
271 continue
271 continue
272
272
273 for thisProfile in profileList:
273 for thisProfile in profileList:
274 data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip
274 data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip
275 flip *= -1.0
275 flip *= -1.0
276
276
277 self.flip = flip
277 self.flip = flip
278
278
279 else:
279 else:
280 if not channelList:
280 if not channelList:
281 data[:,:] = data[:,:]*self.flip
281 data[:,:] = data[:,:]*self.flip
282 else:
282 else:
283 for thisChannel in channelList:
283 for thisChannel in channelList:
284 if thisChannel not in self.dataOut.channelList:
284 if thisChannel not in self.dataOut.channelList:
285 continue
285 continue
286
286
287 data[thisChannel,:] = data[thisChannel,:]*self.flip
287 data[thisChannel,:] = data[thisChannel,:]*self.flip
288
288
289 self.flip *= -1.
289 self.flip *= -1.
290
290
291 self.dataOut.data = data
291 self.dataOut.data = data
292
292
293 def setRadarFrequency(self, frequency=None):
293 def setRadarFrequency(self, frequency=None):
294
294
295 if frequency != None:
295 if frequency != None:
296 self.dataOut.frequency = frequency
296 self.dataOut.frequency = frequency
297
297
298 return 1
298 return 1
299
299
300 def interpolateHeights(self, topLim, botLim):
300 def interpolateHeights(self, topLim, botLim):
301 #69 al 72 para julia
301 #69 al 72 para julia
302 #82-84 para meteoros
302 #82-84 para meteoros
303 if len(numpy.shape(self.dataOut.data))==2:
303 if len(numpy.shape(self.dataOut.data))==2:
304 sampInterp = (self.dataOut.data[:,botLim-1] + self.dataOut.data[:,topLim+1])/2
304 sampInterp = (self.dataOut.data[:,botLim-1] + self.dataOut.data[:,topLim+1])/2
305 sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1)))
305 sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1)))
306 #self.dataOut.data[:,botLim:limSup+1] = sampInterp
306 #self.dataOut.data[:,botLim:limSup+1] = sampInterp
307 self.dataOut.data[:,botLim:topLim+1] = sampInterp
307 self.dataOut.data[:,botLim:topLim+1] = sampInterp
308 else:
308 else:
309 nHeights = self.dataOut.data.shape[2]
309 nHeights = self.dataOut.data.shape[2]
310 x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights)))
310 x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights)))
311 y = self.dataOut.data[:,:,list(range(botLim))+list(range(topLim+1,nHeights))]
311 y = self.dataOut.data[:,:,list(range(botLim))+list(range(topLim+1,nHeights))]
312 f = interpolate.interp1d(x, y, axis = 2)
312 f = interpolate.interp1d(x, y, axis = 2)
313 xnew = numpy.arange(botLim,topLim+1)
313 xnew = numpy.arange(botLim,topLim+1)
314 ynew = f(xnew)
314 ynew = f(xnew)
315
315
316 self.dataOut.data[:,:,botLim:topLim+1] = ynew
316 self.dataOut.data[:,:,botLim:topLim+1] = ynew
317
317
318 # import collections
318 # import collections
319
319
320 class CohInt(Operation):
320 class CohInt(Operation):
321
321
322 isConfig = False
322 isConfig = False
323 __profIndex = 0
323 __profIndex = 0
324 __byTime = False
324 __byTime = False
325 __initime = None
325 __initime = None
326 __lastdatatime = None
326 __lastdatatime = None
327 __integrationtime = None
327 __integrationtime = None
328 __buffer = None
328 __buffer = None
329 __bufferStride = []
329 __bufferStride = []
330 __dataReady = False
330 __dataReady = False
331 __profIndexStride = 0
331 __profIndexStride = 0
332 __dataToPutStride = False
332 __dataToPutStride = False
333 n = None
333 n = None
334
334
335 def __init__(self, **kwargs):
335 def __init__(self, **kwargs):
336
336
337 Operation.__init__(self, **kwargs)
337 Operation.__init__(self, **kwargs)
338
338
339 # self.isConfig = False
339 # self.isConfig = False
340
340
341 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
341 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
342 """
342 """
343 Set the parameters of the integration class.
343 Set the parameters of the integration class.
344
344
345 Inputs:
345 Inputs:
346
346
347 n : Number of coherent integrations
347 n : Number of coherent integrations
348 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
348 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
349 overlapping :
349 overlapping :
350 """
350 """
351
351
352 self.__initime = None
352 self.__initime = None
353 self.__lastdatatime = 0
353 self.__lastdatatime = 0
354 self.__buffer = None
354 self.__buffer = None
355 self.__dataReady = False
355 self.__dataReady = False
356 self.byblock = byblock
356 self.byblock = byblock
357 self.stride = stride
357 self.stride = stride
358
358
359 if n == None and timeInterval == None:
359 if n == None and timeInterval == None:
360 raise ValueError("n or timeInterval should be specified ...")
360 raise ValueError("n or timeInterval should be specified ...")
361
361
362 if n != None:
362 if n != None:
363 self.n = n
363 self.n = n
364 self.__byTime = False
364 self.__byTime = False
365 else:
365 else:
366 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
366 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
367 self.n = 9999
367 self.n = 9999
368 self.__byTime = True
368 self.__byTime = True
369
369
370 if overlapping:
370 if overlapping:
371 self.__withOverlapping = True
371 self.__withOverlapping = True
372 self.__buffer = None
372 self.__buffer = None
373 else:
373 else:
374 self.__withOverlapping = False
374 self.__withOverlapping = False
375 self.__buffer = 0
375 self.__buffer = 0
376
376
377 self.__profIndex = 0
377 self.__profIndex = 0
378
378
379 def putData(self, data):
379 def putData(self, data):
380
380
381 """
381 """
382 Add a profile to the __buffer and increase in one the __profileIndex
382 Add a profile to the __buffer and increase in one the __profileIndex
383
383
384 """
384 """
385
385
386 if not self.__withOverlapping:
386 if not self.__withOverlapping:
387 self.__buffer += data.copy()
387 self.__buffer += data.copy()
388 self.__profIndex += 1
388 self.__profIndex += 1
389 return
389 return
390
390
391 #Overlapping data
391 #Overlapping data
392 nChannels, nHeis = data.shape
392 nChannels, nHeis = data.shape
393 data = numpy.reshape(data, (1, nChannels, nHeis))
393 data = numpy.reshape(data, (1, nChannels, nHeis))
394
394
395 #If the buffer is empty then it takes the data value
395 #If the buffer is empty then it takes the data value
396 if self.__buffer is None:
396 if self.__buffer is None:
397 self.__buffer = data
397 self.__buffer = data
398 self.__profIndex += 1
398 self.__profIndex += 1
399 return
399 return
400
400
401 #If the buffer length is lower than n then stakcing the data value
401 #If the buffer length is lower than n then stakcing the data value
402 if self.__profIndex < self.n:
402 if self.__profIndex < self.n:
403 self.__buffer = numpy.vstack((self.__buffer, data))
403 self.__buffer = numpy.vstack((self.__buffer, data))
404 self.__profIndex += 1
404 self.__profIndex += 1
405 return
405 return
406
406
407 #If the buffer length is equal to n then replacing the last buffer value with the data value
407 #If the buffer length is equal to n then replacing the last buffer value with the data value
408 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
408 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
409 self.__buffer[self.n-1] = data
409 self.__buffer[self.n-1] = data
410 self.__profIndex = self.n
410 self.__profIndex = self.n
411 return
411 return
412
412
413
413
414 def pushData(self):
414 def pushData(self):
415 """
415 """
416 Return the sum of the last profiles and the profiles used in the sum.
416 Return the sum of the last profiles and the profiles used in the sum.
417
417
418 Affected:
418 Affected:
419
419
420 self.__profileIndex
420 self.__profileIndex
421
421
422 """
422 """
423
423
424 if not self.__withOverlapping:
424 if not self.__withOverlapping:
425 data = self.__buffer
425 data = self.__buffer
426 n = self.__profIndex
426 n = self.__profIndex
427
427
428 self.__buffer = 0
428 self.__buffer = 0
429 self.__profIndex = 0
429 self.__profIndex = 0
430
430
431 return data, n
431 return data, n
432
432
433 #Integration with Overlapping
433 #Integration with Overlapping
434 data = numpy.sum(self.__buffer, axis=0)
434 data = numpy.sum(self.__buffer, axis=0)
435 # print data
435 # print data
436 # raise
436 # raise
437 n = self.__profIndex
437 n = self.__profIndex
438
438
439 return data, n
439 return data, n
440
440
441 def byProfiles(self, data):
441 def byProfiles(self, data):
442
442
443 self.__dataReady = False
443 self.__dataReady = False
444 avgdata = None
444 avgdata = None
445 # n = None
445 # n = None
446 # print data
446 # print data
447 # raise
447 # raise
448 self.putData(data)
448 self.putData(data)
449
449
450 if self.__profIndex == self.n:
450 if self.__profIndex == self.n:
451 avgdata, n = self.pushData()
451 avgdata, n = self.pushData()
452 self.__dataReady = True
452 self.__dataReady = True
453
453
454 return avgdata
454 return avgdata
455
455
456 def byTime(self, data, datatime):
456 def byTime(self, data, datatime):
457
457
458 self.__dataReady = False
458 self.__dataReady = False
459 avgdata = None
459 avgdata = None
460 n = None
460 n = None
461
461
462 self.putData(data)
462 self.putData(data)
463
463
464 if (datatime - self.__initime) >= self.__integrationtime:
464 if (datatime - self.__initime) >= self.__integrationtime:
465 avgdata, n = self.pushData()
465 avgdata, n = self.pushData()
466 self.n = n
466 self.n = n
467 self.__dataReady = True
467 self.__dataReady = True
468
468
469 return avgdata
469 return avgdata
470
470
471 def integrateByStride(self, data, datatime):
471 def integrateByStride(self, data, datatime):
472 # print data
472 # print data
473 if self.__profIndex == 0:
473 if self.__profIndex == 0:
474 self.__buffer = [[data.copy(), datatime]]
474 self.__buffer = [[data.copy(), datatime]]
475 else:
475 else:
476 self.__buffer.append([data.copy(),datatime])
476 self.__buffer.append([data.copy(),datatime])
477 self.__profIndex += 1
477 self.__profIndex += 1
478 self.__dataReady = False
478 self.__dataReady = False
479
479
480 if self.__profIndex == self.n * self.stride :
480 if self.__profIndex == self.n * self.stride :
481 self.__dataToPutStride = True
481 self.__dataToPutStride = True
482 self.__profIndexStride = 0
482 self.__profIndexStride = 0
483 self.__profIndex = 0
483 self.__profIndex = 0
484 self.__bufferStride = []
484 self.__bufferStride = []
485 for i in range(self.stride):
485 for i in range(self.stride):
486 current = self.__buffer[i::self.stride]
486 current = self.__buffer[i::self.stride]
487 data = numpy.sum([t[0] for t in current], axis=0)
487 data = numpy.sum([t[0] for t in current], axis=0)
488 avgdatatime = numpy.average([t[1] for t in current])
488 avgdatatime = numpy.average([t[1] for t in current])
489 # print data
489 # print data
490 self.__bufferStride.append((data, avgdatatime))
490 self.__bufferStride.append((data, avgdatatime))
491
491
492 if self.__dataToPutStride:
492 if self.__dataToPutStride:
493 self.__dataReady = True
493 self.__dataReady = True
494 self.__profIndexStride += 1
494 self.__profIndexStride += 1
495 if self.__profIndexStride == self.stride:
495 if self.__profIndexStride == self.stride:
496 self.__dataToPutStride = False
496 self.__dataToPutStride = False
497 # print self.__bufferStride[self.__profIndexStride - 1]
497 # print self.__bufferStride[self.__profIndexStride - 1]
498 # raise
498 # raise
499 return self.__bufferStride[self.__profIndexStride - 1]
499 return self.__bufferStride[self.__profIndexStride - 1]
500
500
501
501
502 return None, None
502 return None, None
503
503
504 def integrate(self, data, datatime=None):
504 def integrate(self, data, datatime=None):
505
505
506 if self.__initime == None:
506 if self.__initime == None:
507 self.__initime = datatime
507 self.__initime = datatime
508
508
509 if self.__byTime:
509 if self.__byTime:
510 avgdata = self.byTime(data, datatime)
510 avgdata = self.byTime(data, datatime)
511 else:
511 else:
512 avgdata = self.byProfiles(data)
512 avgdata = self.byProfiles(data)
513
513
514
514
515 self.__lastdatatime = datatime
515 self.__lastdatatime = datatime
516
516
517 if avgdata is None:
517 if avgdata is None:
518 return None, None
518 return None, None
519
519
520 avgdatatime = self.__initime
520 avgdatatime = self.__initime
521
521
522 deltatime = datatime - self.__lastdatatime
522 deltatime = datatime - self.__lastdatatime
523
523
524 if not self.__withOverlapping:
524 if not self.__withOverlapping:
525 self.__initime = datatime
525 self.__initime = datatime
526 else:
526 else:
527 self.__initime += deltatime
527 self.__initime += deltatime
528
528
529 return avgdata, avgdatatime
529 return avgdata, avgdatatime
530
530
531 def integrateByBlock(self, dataOut):
531 def integrateByBlock(self, dataOut):
532
532
533 times = int(dataOut.data.shape[1]/self.n)
533 times = int(dataOut.data.shape[1]/self.n)
534 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
534 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
535
535
536 id_min = 0
536 id_min = 0
537 id_max = self.n
537 id_max = self.n
538
538
539 for i in range(times):
539 for i in range(times):
540 junk = dataOut.data[:,id_min:id_max,:]
540 junk = dataOut.data[:,id_min:id_max,:]
541 avgdata[:,i,:] = junk.sum(axis=1)
541 avgdata[:,i,:] = junk.sum(axis=1)
542 id_min += self.n
542 id_min += self.n
543 id_max += self.n
543 id_max += self.n
544
544
545 timeInterval = dataOut.ippSeconds*self.n
545 timeInterval = dataOut.ippSeconds*self.n
546 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
546 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
547 self.__dataReady = True
547 self.__dataReady = True
548 return avgdata, avgdatatime
548 return avgdata, avgdatatime
549
549
550 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
550 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
551
551
552 if not self.isConfig:
552 if not self.isConfig:
553 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
553 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
554 self.isConfig = True
554 self.isConfig = True
555
555
556 if dataOut.flagDataAsBlock:
556 if dataOut.flagDataAsBlock:
557 """
557 """
558 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
558 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
559 """
559 """
560 avgdata, avgdatatime = self.integrateByBlock(dataOut)
560 avgdata, avgdatatime = self.integrateByBlock(dataOut)
561 dataOut.nProfiles /= self.n
561 dataOut.nProfiles /= self.n
562 else:
562 else:
563 if stride is None:
563 if stride is None:
564 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
564 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
565 else:
565 else:
566 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
566 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
567
567
568
568
569 # dataOut.timeInterval *= n
569 # dataOut.timeInterval *= n
570 dataOut.flagNoData = True
570 dataOut.flagNoData = True
571
571
572 if self.__dataReady:
572 if self.__dataReady:
573 dataOut.data = avgdata
573 dataOut.data = avgdata
574 dataOut.nCohInt *= self.n
574 dataOut.nCohInt *= self.n
575 dataOut.utctime = avgdatatime
575 dataOut.utctime = avgdatatime
576 # print avgdata, avgdatatime
576 # print avgdata, avgdatatime
577 # raise
577 # raise
578 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
578 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
579 dataOut.flagNoData = False
579 dataOut.flagNoData = False
580 return dataOut
580 return dataOut
581
581
582 class Decoder(Operation):
582 class Decoder(Operation):
583
583
584 isConfig = False
584 isConfig = False
585 __profIndex = 0
585 __profIndex = 0
586
586
587 code = None
587 code = None
588
588
589 nCode = None
589 nCode = None
590 nBaud = None
590 nBaud = None
591
591
592 def __init__(self, **kwargs):
592 def __init__(self, **kwargs):
593
593
594 Operation.__init__(self, **kwargs)
594 Operation.__init__(self, **kwargs)
595
595
596 self.times = None
596 self.times = None
597 self.osamp = None
597 self.osamp = None
598 # self.__setValues = False
598 # self.__setValues = False
599 self.isConfig = False
599 self.isConfig = False
600 self.setupReq = False
600 self.setupReq = False
601 def setup(self, code, osamp, dataOut):
601 def setup(self, code, osamp, dataOut):
602
602
603 self.__profIndex = 0
603 self.__profIndex = 0
604
604
605 self.code = code
605 self.code = code
606
606
607 self.nCode = len(code)
607 self.nCode = len(code)
608 self.nBaud = len(code[0])
608 self.nBaud = len(code[0])
609
610 if (osamp != None) and (osamp >1):
609 if (osamp != None) and (osamp >1):
611 self.osamp = osamp
610 self.osamp = osamp
612 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
611 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
613 self.nBaud = self.nBaud*self.osamp
612 self.nBaud = self.nBaud*self.osamp
614
613
615 self.__nChannels = dataOut.nChannels
614 self.__nChannels = dataOut.nChannels
616 self.__nProfiles = dataOut.nProfiles
615 self.__nProfiles = dataOut.nProfiles
617 self.__nHeis = dataOut.nHeights
616 self.__nHeis = dataOut.nHeights
618
617
619 if self.__nHeis < self.nBaud:
618 if self.__nHeis < self.nBaud:
620 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
619 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
621
620
622 #Frequency
621 #Frequency
623 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
622 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
624
623
625 __codeBuffer[:,0:self.nBaud] = self.code
624 __codeBuffer[:,0:self.nBaud] = self.code
626
625
627 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
626 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
628
627
629 if dataOut.flagDataAsBlock:
628 if dataOut.flagDataAsBlock:
630
629
631 self.ndatadec = self.__nHeis #- self.nBaud + 1
630 self.ndatadec = self.__nHeis #- self.nBaud + 1
632
631
633 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
632 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
634
633
635 else:
634 else:
636
635
637 #Time
636 #Time
638 self.ndatadec = self.__nHeis #- self.nBaud + 1
637 self.ndatadec = self.__nHeis #- self.nBaud + 1
639
638
640 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
639 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
641
640
642 def __convolutionInFreq(self, data):
641 def __convolutionInFreq(self, data):
643
642
644 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
643 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
645
644
646 fft_data = numpy.fft.fft(data, axis=1)
645 fft_data = numpy.fft.fft(data, axis=1)
647
646
648 conv = fft_data*fft_code
647 conv = fft_data*fft_code
649
648
650 data = numpy.fft.ifft(conv,axis=1)
649 data = numpy.fft.ifft(conv,axis=1)
651
650
652 return data
651 return data
653
652
654 def __convolutionInFreqOpt(self, data):
653 def __convolutionInFreqOpt(self, data):
655
654
656 raise NotImplementedError
655 raise NotImplementedError
657
656
658 def __convolutionInTime(self, data):
657 def __convolutionInTime(self, data):
659
658
660 code = self.code[self.__profIndex]
659 code = self.code[self.__profIndex]
661 for i in range(self.__nChannels):
660 for i in range(self.__nChannels):
662 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
661 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
663
662
664 return self.datadecTime
663 return self.datadecTime
665
664
666 def __convolutionByBlockInTime(self, data):
665 def __convolutionByBlockInTime(self, data):
667
666
668 repetitions = int(self.__nProfiles / self.nCode)
667 repetitions = int(self.__nProfiles / self.nCode)
669 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
668 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
670 junk = junk.flatten()
669 junk = junk.flatten()
671 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
670 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
672 profilesList = range(self.__nProfiles)
671 profilesList = range(self.__nProfiles)
673
672
674 for i in range(self.__nChannels):
673 for i in range(self.__nChannels):
675 for j in profilesList:
674 for j in profilesList:
676 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
675 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
677 return self.datadecTime
676 return self.datadecTime
678
677
679 def __convolutionByBlockInFreq(self, data):
678 def __convolutionByBlockInFreq(self, data):
680
679
681 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
680 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
682
681
683
682
684 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
683 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
685
684
686 fft_data = numpy.fft.fft(data, axis=2)
685 fft_data = numpy.fft.fft(data, axis=2)
687
686
688 conv = fft_data*fft_code
687 conv = fft_data*fft_code
689
688
690 data = numpy.fft.ifft(conv,axis=2)
689 data = numpy.fft.ifft(conv,axis=2)
691
690
692 return data
691 return data
693
692
694
693
695 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
694 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
696
695
697 if dataOut.flagDecodeData:
696 if dataOut.flagDecodeData:
698 print("This data is already decoded, recoding again ...")
697 print("This data is already decoded, recoding again ...")
699
698
700 if not self.isConfig:
699 if not self.isConfig:
701
700
702 if code is None:
701 if code is None:
703 if dataOut.code is None:
702 if dataOut.code is None:
704 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
703 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
705
704
706 code = dataOut.code
705 code = dataOut.code
707 else:
706 else:
708 code = numpy.array(code).reshape(nCode,nBaud)
707 code = numpy.array(code).reshape(nCode,nBaud)
709 self.setup(code, osamp, dataOut)
708 self.setup(code, osamp, dataOut)
710
709
711 self.isConfig = True
710 self.isConfig = True
712
711
713 if mode == 3:
712 if mode == 3:
714 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
713 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
715
714
716 if times != None:
715 if times != None:
717 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
716 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
718
717
719 if self.code is None:
718 if self.code is None:
720 print("Fail decoding: Code is not defined.")
719 print("Fail decoding: Code is not defined.")
721 return
720 return
722
721
723 self.__nProfiles = dataOut.nProfiles
722 self.__nProfiles = dataOut.nProfiles
724 datadec = None
723 datadec = None
725
724
726 if mode == 3:
725 if mode == 3:
727 mode = 0
726 mode = 0
728
727
729 if dataOut.flagDataAsBlock:
728 if dataOut.flagDataAsBlock:
730 """
729 """
731 Decoding when data have been read as block,
730 Decoding when data have been read as block,
732 """
731 """
733
732
734 if mode == 0:
733 if mode == 0:
735 datadec = self.__convolutionByBlockInTime(dataOut.data)
734 datadec = self.__convolutionByBlockInTime(dataOut.data)
736 if mode == 1:
735 if mode == 1:
737 datadec = self.__convolutionByBlockInFreq(dataOut.data)
736 datadec = self.__convolutionByBlockInFreq(dataOut.data)
738 else:
737 else:
739 """
738 """
740 Decoding when data have been read profile by profile
739 Decoding when data have been read profile by profile
741 """
740 """
742 if mode == 0:
741 if mode == 0:
743 datadec = self.__convolutionInTime(dataOut.data)
742 datadec = self.__convolutionInTime(dataOut.data)
744
743
745 if mode == 1:
744 if mode == 1:
746 datadec = self.__convolutionInFreq(dataOut.data)
745 datadec = self.__convolutionInFreq(dataOut.data)
747
746
748 if mode == 2:
747 if mode == 2:
749 datadec = self.__convolutionInFreqOpt(dataOut.data)
748 datadec = self.__convolutionInFreqOpt(dataOut.data)
750
749
751 if datadec is None:
750 if datadec is None:
752 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
751 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
753
752
754 dataOut.code = self.code
753 dataOut.code = self.code
755 dataOut.nCode = self.nCode
754 dataOut.nCode = self.nCode
756 dataOut.nBaud = self.nBaud
755 dataOut.nBaud = self.nBaud
757
756
758 dataOut.data = datadec
757 dataOut.data = datadec
759
758
760 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
759 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
761
760
762 dataOut.flagDecodeData = True #asumo q la data esta decodificada
761 dataOut.flagDecodeData = True #asumo q la data esta decodificada
763
762
764 if self.__profIndex == self.nCode-1:
763 if self.__profIndex == self.nCode-1:
765 self.__profIndex = 0
764 self.__profIndex = 0
766 return dataOut
765 return dataOut
767
766
768 self.__profIndex += 1
767 self.__profIndex += 1
769
768
770 return dataOut
769 return dataOut
771 # dataOut.flagDeflipData = True #asumo q la data no esta sin flip
770 # dataOut.flagDeflipData = True #asumo q la data no esta sin flip
772
771
773
772
774 class ProfileConcat(Operation):
773 class ProfileConcat(Operation):
775
774
776 isConfig = False
775 isConfig = False
777 buffer = None
776 buffer = None
778
777
779 def __init__(self, **kwargs):
778 def __init__(self, **kwargs):
780
779
781 Operation.__init__(self, **kwargs)
780 Operation.__init__(self, **kwargs)
782 self.profileIndex = 0
781 self.profileIndex = 0
783
782
784 def reset(self):
783 def reset(self):
785 self.buffer = numpy.zeros_like(self.buffer)
784 self.buffer = numpy.zeros_like(self.buffer)
786 self.start_index = 0
785 self.start_index = 0
787 self.times = 1
786 self.times = 1
788
787
789 def setup(self, data, m, n=1):
788 def setup(self, data, m, n=1):
790 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
789 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
791 self.nHeights = data.shape[1]#.nHeights
790 self.nHeights = data.shape[1]#.nHeights
792 self.start_index = 0
791 self.start_index = 0
793 self.times = 1
792 self.times = 1
794
793
795 def concat(self, data):
794 def concat(self, data):
796
795
797 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
796 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
798 self.start_index = self.start_index + self.nHeights
797 self.start_index = self.start_index + self.nHeights
799
798
800 def run(self, dataOut, m):
799 def run(self, dataOut, m):
801 dataOut.flagNoData = True
800 dataOut.flagNoData = True
802
801
803 if not self.isConfig:
802 if not self.isConfig:
804 self.setup(dataOut.data, m, 1)
803 self.setup(dataOut.data, m, 1)
805 self.isConfig = True
804 self.isConfig = True
806
805
807 if dataOut.flagDataAsBlock:
806 if dataOut.flagDataAsBlock:
808 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
807 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
809
808
810 else:
809 else:
811 self.concat(dataOut.data)
810 self.concat(dataOut.data)
812 self.times += 1
811 self.times += 1
813 if self.times > m:
812 if self.times > m:
814 dataOut.data = self.buffer
813 dataOut.data = self.buffer
815 self.reset()
814 self.reset()
816 dataOut.flagNoData = False
815 dataOut.flagNoData = False
817 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
816 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
818 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
817 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
819 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
818 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
820 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
819 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
821 dataOut.ippSeconds *= m
820 dataOut.ippSeconds *= m
822 return dataOut
821 return dataOut
823
822
824 class ProfileSelector(Operation):
823 class ProfileSelector(Operation):
825
824
826 profileIndex = None
825 profileIndex = None
827 # Tamanho total de los perfiles
826 # Tamanho total de los perfiles
828 nProfiles = None
827 nProfiles = None
829
828
830 def __init__(self, **kwargs):
829 def __init__(self, **kwargs):
831
830
832 Operation.__init__(self, **kwargs)
831 Operation.__init__(self, **kwargs)
833 self.profileIndex = 0
832 self.profileIndex = 0
834
833
835 def incProfileIndex(self):
834 def incProfileIndex(self):
836
835
837 self.profileIndex += 1
836 self.profileIndex += 1
838
837
839 if self.profileIndex >= self.nProfiles:
838 if self.profileIndex >= self.nProfiles:
840 self.profileIndex = 0
839 self.profileIndex = 0
841
840
842 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
841 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
843
842
844 if profileIndex < minIndex:
843 if profileIndex < minIndex:
845 return False
844 return False
846
845
847 if profileIndex > maxIndex:
846 if profileIndex > maxIndex:
848 return False
847 return False
849
848
850 return True
849 return True
851
850
852 def isThisProfileInList(self, profileIndex, profileList):
851 def isThisProfileInList(self, profileIndex, profileList):
853
852
854 if profileIndex not in profileList:
853 if profileIndex not in profileList:
855 return False
854 return False
856
855
857 return True
856 return True
858
857
859 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
858 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
860
859
861 """
860 """
862 ProfileSelector:
861 ProfileSelector:
863
862
864 Inputs:
863 Inputs:
865 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
864 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
866
865
867 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
866 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
868
867
869 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
868 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
870
869
871 """
870 """
872
871
873 if rangeList is not None:
872 if rangeList is not None:
874 if type(rangeList[0]) not in (tuple, list):
873 if type(rangeList[0]) not in (tuple, list):
875 rangeList = [rangeList]
874 rangeList = [rangeList]
876
875
877 dataOut.flagNoData = True
876 dataOut.flagNoData = True
878
877
879 if dataOut.flagDataAsBlock:
878 if dataOut.flagDataAsBlock:
880 """
879 """
881 data dimension = [nChannels, nProfiles, nHeis]
880 data dimension = [nChannels, nProfiles, nHeis]
882 """
881 """
883 if profileList != None:
882 if profileList != None:
884 dataOut.data = dataOut.data[:,profileList,:]
883 dataOut.data = dataOut.data[:,profileList,:]
885
884
886 if profileRangeList != None:
885 if profileRangeList != None:
887 minIndex = profileRangeList[0]
886 minIndex = profileRangeList[0]
888 maxIndex = profileRangeList[1]
887 maxIndex = profileRangeList[1]
889 profileList = list(range(minIndex, maxIndex+1))
888 profileList = list(range(minIndex, maxIndex+1))
890
889
891 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
890 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
892
891
893 if rangeList != None:
892 if rangeList != None:
894
893
895 profileList = []
894 profileList = []
896
895
897 for thisRange in rangeList:
896 for thisRange in rangeList:
898 minIndex = thisRange[0]
897 minIndex = thisRange[0]
899 maxIndex = thisRange[1]
898 maxIndex = thisRange[1]
900
899
901 profileList.extend(list(range(minIndex, maxIndex+1)))
900 profileList.extend(list(range(minIndex, maxIndex+1)))
902
901
903 dataOut.data = dataOut.data[:,profileList,:]
902 dataOut.data = dataOut.data[:,profileList,:]
904
903
905 dataOut.nProfiles = len(profileList)
904 dataOut.nProfiles = len(profileList)
906 dataOut.profileIndex = dataOut.nProfiles - 1
905 dataOut.profileIndex = dataOut.nProfiles - 1
907 dataOut.flagNoData = False
906 dataOut.flagNoData = False
908
907
909 return dataOut
908 return dataOut
910
909
911 """
910 """
912 data dimension = [nChannels, nHeis]
911 data dimension = [nChannels, nHeis]
913 """
912 """
914
913
915 if profileList != None:
914 if profileList != None:
916
915
917 if self.isThisProfileInList(dataOut.profileIndex, profileList):
916 if self.isThisProfileInList(dataOut.profileIndex, profileList):
918
917
919 self.nProfiles = len(profileList)
918 self.nProfiles = len(profileList)
920 dataOut.nProfiles = self.nProfiles
919 dataOut.nProfiles = self.nProfiles
921 dataOut.profileIndex = self.profileIndex
920 dataOut.profileIndex = self.profileIndex
922 dataOut.flagNoData = False
921 dataOut.flagNoData = False
923
922
924 self.incProfileIndex()
923 self.incProfileIndex()
925 return dataOut
924 return dataOut
926
925
927 if profileRangeList != None:
926 if profileRangeList != None:
928
927
929 minIndex = profileRangeList[0]
928 minIndex = profileRangeList[0]
930 maxIndex = profileRangeList[1]
929 maxIndex = profileRangeList[1]
931
930
932 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
931 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
933
932
934 self.nProfiles = maxIndex - minIndex + 1
933 self.nProfiles = maxIndex - minIndex + 1
935 dataOut.nProfiles = self.nProfiles
934 dataOut.nProfiles = self.nProfiles
936 dataOut.profileIndex = self.profileIndex
935 dataOut.profileIndex = self.profileIndex
937 dataOut.flagNoData = False
936 dataOut.flagNoData = False
938
937
939 self.incProfileIndex()
938 self.incProfileIndex()
940 return dataOut
939 return dataOut
941
940
942 if rangeList != None:
941 if rangeList != None:
943
942
944 nProfiles = 0
943 nProfiles = 0
945
944
946 for thisRange in rangeList:
945 for thisRange in rangeList:
947 minIndex = thisRange[0]
946 minIndex = thisRange[0]
948 maxIndex = thisRange[1]
947 maxIndex = thisRange[1]
949
948
950 nProfiles += maxIndex - minIndex + 1
949 nProfiles += maxIndex - minIndex + 1
951
950
952 for thisRange in rangeList:
951 for thisRange in rangeList:
953
952
954 minIndex = thisRange[0]
953 minIndex = thisRange[0]
955 maxIndex = thisRange[1]
954 maxIndex = thisRange[1]
956
955
957 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
956 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
958
957
959 self.nProfiles = nProfiles
958 self.nProfiles = nProfiles
960 dataOut.nProfiles = self.nProfiles
959 dataOut.nProfiles = self.nProfiles
961 dataOut.profileIndex = self.profileIndex
960 dataOut.profileIndex = self.profileIndex
962 dataOut.flagNoData = False
961 dataOut.flagNoData = False
963
962
964 self.incProfileIndex()
963 self.incProfileIndex()
965
964
966 break
965 break
967
966
968 return dataOut
967 return dataOut
969
968
970
969
971 if beam != None: #beam is only for AMISR data
970 if beam != None: #beam is only for AMISR data
972 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
971 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
973 dataOut.flagNoData = False
972 dataOut.flagNoData = False
974 dataOut.profileIndex = self.profileIndex
973 dataOut.profileIndex = self.profileIndex
975
974
976 self.incProfileIndex()
975 self.incProfileIndex()
977
976
978 return dataOut
977 return dataOut
979
978
980 raise ValueError("ProfileSelector needs profileList, profileRangeList or rangeList parameter")
979 raise ValueError("ProfileSelector needs profileList, profileRangeList or rangeList parameter")
981
980
982 #return False
981 #return False
983 return dataOut
982 return dataOut
984
983
985 class Reshaper(Operation):
984 class Reshaper(Operation):
986
985
987 def __init__(self, **kwargs):
986 def __init__(self, **kwargs):
988
987
989 Operation.__init__(self, **kwargs)
988 Operation.__init__(self, **kwargs)
990
989
991 self.__buffer = None
990 self.__buffer = None
992 self.__nitems = 0
991 self.__nitems = 0
993
992
994 def __appendProfile(self, dataOut, nTxs):
993 def __appendProfile(self, dataOut, nTxs):
995
994
996 if self.__buffer is None:
995 if self.__buffer is None:
997 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
996 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
998 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
997 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
999
998
1000 ini = dataOut.nHeights * self.__nitems
999 ini = dataOut.nHeights * self.__nitems
1001 end = ini + dataOut.nHeights
1000 end = ini + dataOut.nHeights
1002
1001
1003 self.__buffer[:, ini:end] = dataOut.data
1002 self.__buffer[:, ini:end] = dataOut.data
1004
1003
1005 self.__nitems += 1
1004 self.__nitems += 1
1006
1005
1007 return int(self.__nitems*nTxs)
1006 return int(self.__nitems*nTxs)
1008
1007
1009 def __getBuffer(self):
1008 def __getBuffer(self):
1010
1009
1011 if self.__nitems == int(1./self.__nTxs):
1010 if self.__nitems == int(1./self.__nTxs):
1012
1011
1013 self.__nitems = 0
1012 self.__nitems = 0
1014
1013
1015 return self.__buffer.copy()
1014 return self.__buffer.copy()
1016
1015
1017 return None
1016 return None
1018
1017
1019 def __checkInputs(self, dataOut, shape, nTxs):
1018 def __checkInputs(self, dataOut, shape, nTxs):
1020
1019
1021 if shape is None and nTxs is None:
1020 if shape is None and nTxs is None:
1022 raise ValueError("Reshaper: shape of factor should be defined")
1021 raise ValueError("Reshaper: shape of factor should be defined")
1023
1022
1024 if nTxs:
1023 if nTxs:
1025 if nTxs < 0:
1024 if nTxs < 0:
1026 raise ValueError("nTxs should be greater than 0")
1025 raise ValueError("nTxs should be greater than 0")
1027
1026
1028 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
1027 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
1029 raise ValueError("nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)))
1028 raise ValueError("nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)))
1030
1029
1031 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
1030 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
1032
1031
1033 return shape, nTxs
1032 return shape, nTxs
1034
1033
1035 if len(shape) != 2 and len(shape) != 3:
1034 if len(shape) != 2 and len(shape) != 3:
1036 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))
1035 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))
1037
1036
1038 if len(shape) == 2:
1037 if len(shape) == 2:
1039 shape_tuple = [dataOut.nChannels]
1038 shape_tuple = [dataOut.nChannels]
1040 shape_tuple.extend(shape)
1039 shape_tuple.extend(shape)
1041 else:
1040 else:
1042 shape_tuple = list(shape)
1041 shape_tuple = list(shape)
1043
1042
1044 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
1043 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
1045
1044
1046 return shape_tuple, nTxs
1045 return shape_tuple, nTxs
1047
1046
1048 def run(self, dataOut, shape=None, nTxs=None):
1047 def run(self, dataOut, shape=None, nTxs=None):
1049
1048
1050 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
1049 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
1051
1050
1052 dataOut.flagNoData = True
1051 dataOut.flagNoData = True
1053 profileIndex = None
1052 profileIndex = None
1054
1053
1055 if dataOut.flagDataAsBlock:
1054 if dataOut.flagDataAsBlock:
1056
1055
1057 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
1056 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
1058 dataOut.flagNoData = False
1057 dataOut.flagNoData = False
1059
1058
1060 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
1059 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
1061
1060
1062 else:
1061 else:
1063
1062
1064 if self.__nTxs < 1:
1063 if self.__nTxs < 1:
1065
1064
1066 self.__appendProfile(dataOut, self.__nTxs)
1065 self.__appendProfile(dataOut, self.__nTxs)
1067 new_data = self.__getBuffer()
1066 new_data = self.__getBuffer()
1068
1067
1069 if new_data is not None:
1068 if new_data is not None:
1070 dataOut.data = new_data
1069 dataOut.data = new_data
1071 dataOut.flagNoData = False
1070 dataOut.flagNoData = False
1072
1071
1073 profileIndex = dataOut.profileIndex*nTxs
1072 profileIndex = dataOut.profileIndex*nTxs
1074
1073
1075 else:
1074 else:
1076 raise ValueError("nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)")
1075 raise ValueError("nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)")
1077
1076
1078 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1077 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1079
1078
1080 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
1079 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
1081
1080
1082 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
1081 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
1083
1082
1084 dataOut.profileIndex = profileIndex
1083 dataOut.profileIndex = profileIndex
1085
1084
1086 dataOut.ippSeconds /= self.__nTxs
1085 dataOut.ippSeconds /= self.__nTxs
1087
1086
1088 return dataOut
1087 return dataOut
1089
1088
1090 class SplitProfiles(Operation):
1089 class SplitProfiles(Operation):
1091
1090
1092 def __init__(self, **kwargs):
1091 def __init__(self, **kwargs):
1093
1092
1094 Operation.__init__(self, **kwargs)
1093 Operation.__init__(self, **kwargs)
1095
1094
1096 def run(self, dataOut, n):
1095 def run(self, dataOut, n):
1097
1096
1098 dataOut.flagNoData = True
1097 dataOut.flagNoData = True
1099 profileIndex = None
1098 profileIndex = None
1100
1099
1101 if dataOut.flagDataAsBlock:
1100 if dataOut.flagDataAsBlock:
1102
1101
1103 #nchannels, nprofiles, nsamples
1102 #nchannels, nprofiles, nsamples
1104 shape = dataOut.data.shape
1103 shape = dataOut.data.shape
1105
1104
1106 if shape[2] % n != 0:
1105 if shape[2] % n != 0:
1107 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
1106 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
1108
1107
1109 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
1108 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
1110
1109
1111 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1110 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1112 dataOut.flagNoData = False
1111 dataOut.flagNoData = False
1113
1112
1114 profileIndex = int(dataOut.nProfiles/n) - 1
1113 profileIndex = int(dataOut.nProfiles/n) - 1
1115
1114
1116 else:
1115 else:
1117
1116
1118 raise ValueError("Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)")
1117 raise ValueError("Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)")
1119
1118
1120 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1119 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1121
1120
1122 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
1121 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
1123
1122
1124 dataOut.nProfiles = int(dataOut.nProfiles*n)
1123 dataOut.nProfiles = int(dataOut.nProfiles*n)
1125
1124
1126 dataOut.profileIndex = profileIndex
1125 dataOut.profileIndex = profileIndex
1127
1126
1128 dataOut.ippSeconds /= n
1127 dataOut.ippSeconds /= n
1129
1128
1130 return dataOut
1129 return dataOut
1131
1130
1132 class CombineProfiles(Operation):
1131 class CombineProfiles(Operation):
1133 def __init__(self, **kwargs):
1132 def __init__(self, **kwargs):
1134
1133
1135 Operation.__init__(self, **kwargs)
1134 Operation.__init__(self, **kwargs)
1136
1135
1137 self.__remData = None
1136 self.__remData = None
1138 self.__profileIndex = 0
1137 self.__profileIndex = 0
1139
1138
1140 def run(self, dataOut, n):
1139 def run(self, dataOut, n):
1141
1140
1142 dataOut.flagNoData = True
1141 dataOut.flagNoData = True
1143 profileIndex = None
1142 profileIndex = None
1144
1143
1145 if dataOut.flagDataAsBlock:
1144 if dataOut.flagDataAsBlock:
1146
1145
1147 #nchannels, nprofiles, nsamples
1146 #nchannels, nprofiles, nsamples
1148 shape = dataOut.data.shape
1147 shape = dataOut.data.shape
1149 new_shape = shape[0], shape[1]/n, shape[2]*n
1148 new_shape = shape[0], shape[1]/n, shape[2]*n
1150
1149
1151 if shape[1] % n != 0:
1150 if shape[1] % n != 0:
1152 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]))
1151 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]))
1153
1152
1154 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1153 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1155 dataOut.flagNoData = False
1154 dataOut.flagNoData = False
1156
1155
1157 profileIndex = int(dataOut.nProfiles*n) - 1
1156 profileIndex = int(dataOut.nProfiles*n) - 1
1158
1157
1159 else:
1158 else:
1160
1159
1161 #nchannels, nsamples
1160 #nchannels, nsamples
1162 if self.__remData is None:
1161 if self.__remData is None:
1163 newData = dataOut.data
1162 newData = dataOut.data
1164 else:
1163 else:
1165 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
1164 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
1166
1165
1167 self.__profileIndex += 1
1166 self.__profileIndex += 1
1168
1167
1169 if self.__profileIndex < n:
1168 if self.__profileIndex < n:
1170 self.__remData = newData
1169 self.__remData = newData
1171 #continue
1170 #continue
1172 return
1171 return
1173
1172
1174 self.__profileIndex = 0
1173 self.__profileIndex = 0
1175 self.__remData = None
1174 self.__remData = None
1176
1175
1177 dataOut.data = newData
1176 dataOut.data = newData
1178 dataOut.flagNoData = False
1177 dataOut.flagNoData = False
1179
1178
1180 profileIndex = dataOut.profileIndex/n
1179 profileIndex = dataOut.profileIndex/n
1181
1180
1182
1181
1183 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1182 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1184
1183
1185 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
1184 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
1186
1185
1187 dataOut.nProfiles = int(dataOut.nProfiles/n)
1186 dataOut.nProfiles = int(dataOut.nProfiles/n)
1188
1187
1189 dataOut.profileIndex = profileIndex
1188 dataOut.profileIndex = profileIndex
1190
1189
1191 dataOut.ippSeconds *= n
1190 dataOut.ippSeconds *= n
1192
1191
1193 return dataOut
1192 return dataOut
1194 # import collections
1193 # import collections
1195 # from scipy.stats import mode
1194 # from scipy.stats import mode
1196 #
1195 #
1197 # class Synchronize(Operation):
1196 # class Synchronize(Operation):
1198 #
1197 #
1199 # isConfig = False
1198 # isConfig = False
1200 # __profIndex = 0
1199 # __profIndex = 0
1201 #
1200 #
1202 # def __init__(self, **kwargs):
1201 # def __init__(self, **kwargs):
1203 #
1202 #
1204 # Operation.__init__(self, **kwargs)
1203 # Operation.__init__(self, **kwargs)
1205 # # self.isConfig = False
1204 # # self.isConfig = False
1206 # self.__powBuffer = None
1205 # self.__powBuffer = None
1207 # self.__startIndex = 0
1206 # self.__startIndex = 0
1208 # self.__pulseFound = False
1207 # self.__pulseFound = False
1209 #
1208 #
1210 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1209 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1211 #
1210 #
1212 # #Read data
1211 # #Read data
1213 #
1212 #
1214 # powerdB = dataOut.getPower(channel = channel)
1213 # powerdB = dataOut.getPower(channel = channel)
1215 # noisedB = dataOut.getNoise(channel = channel)[0]
1214 # noisedB = dataOut.getNoise(channel = channel)[0]
1216 #
1215 #
1217 # self.__powBuffer.extend(powerdB.flatten())
1216 # self.__powBuffer.extend(powerdB.flatten())
1218 #
1217 #
1219 # dataArray = numpy.array(self.__powBuffer)
1218 # dataArray = numpy.array(self.__powBuffer)
1220 #
1219 #
1221 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1220 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1222 #
1221 #
1223 # maxValue = numpy.nanmax(filteredPower)
1222 # maxValue = numpy.nanmax(filteredPower)
1224 #
1223 #
1225 # if maxValue < noisedB + 10:
1224 # if maxValue < noisedB + 10:
1226 # #No se encuentra ningun pulso de transmision
1225 # #No se encuentra ningun pulso de transmision
1227 # return None
1226 # return None
1228 #
1227 #
1229 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1228 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1230 #
1229 #
1231 # if len(maxValuesIndex) < 2:
1230 # if len(maxValuesIndex) < 2:
1232 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1231 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1233 # return None
1232 # return None
1234 #
1233 #
1235 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1234 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1236 #
1235 #
1237 # #Seleccionar solo valores con un espaciamiento de nSamples
1236 # #Seleccionar solo valores con un espaciamiento de nSamples
1238 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1237 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1239 #
1238 #
1240 # if len(pulseIndex) < 2:
1239 # if len(pulseIndex) < 2:
1241 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1240 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1242 # return None
1241 # return None
1243 #
1242 #
1244 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1243 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1245 #
1244 #
1246 # #remover senales que se distancien menos de 10 unidades o muestras
1245 # #remover senales que se distancien menos de 10 unidades o muestras
1247 # #(No deberian existir IPP menor a 10 unidades)
1246 # #(No deberian existir IPP menor a 10 unidades)
1248 #
1247 #
1249 # realIndex = numpy.where(spacing > 10 )[0]
1248 # realIndex = numpy.where(spacing > 10 )[0]
1250 #
1249 #
1251 # if len(realIndex) < 2:
1250 # if len(realIndex) < 2:
1252 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1251 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1253 # return None
1252 # return None
1254 #
1253 #
1255 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1254 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1256 # realPulseIndex = pulseIndex[realIndex]
1255 # realPulseIndex = pulseIndex[realIndex]
1257 #
1256 #
1258 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1257 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1259 #
1258 #
1260 # print "IPP = %d samples" %period
1259 # print "IPP = %d samples" %period
1261 #
1260 #
1262 # self.__newNSamples = dataOut.nHeights #int(period)
1261 # self.__newNSamples = dataOut.nHeights #int(period)
1263 # self.__startIndex = int(realPulseIndex[0])
1262 # self.__startIndex = int(realPulseIndex[0])
1264 #
1263 #
1265 # return 1
1264 # return 1
1266 #
1265 #
1267 #
1266 #
1268 # def setup(self, nSamples, nChannels, buffer_size = 4):
1267 # def setup(self, nSamples, nChannels, buffer_size = 4):
1269 #
1268 #
1270 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1269 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1271 # maxlen = buffer_size*nSamples)
1270 # maxlen = buffer_size*nSamples)
1272 #
1271 #
1273 # bufferList = []
1272 # bufferList = []
1274 #
1273 #
1275 # for i in range(nChannels):
1274 # for i in range(nChannels):
1276 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1275 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1277 # maxlen = buffer_size*nSamples)
1276 # maxlen = buffer_size*nSamples)
1278 #
1277 #
1279 # bufferList.append(bufferByChannel)
1278 # bufferList.append(bufferByChannel)
1280 #
1279 #
1281 # self.__nSamples = nSamples
1280 # self.__nSamples = nSamples
1282 # self.__nChannels = nChannels
1281 # self.__nChannels = nChannels
1283 # self.__bufferList = bufferList
1282 # self.__bufferList = bufferList
1284 #
1283 #
1285 # def run(self, dataOut, channel = 0):
1284 # def run(self, dataOut, channel = 0):
1286 #
1285 #
1287 # if not self.isConfig:
1286 # if not self.isConfig:
1288 # nSamples = dataOut.nHeights
1287 # nSamples = dataOut.nHeights
1289 # nChannels = dataOut.nChannels
1288 # nChannels = dataOut.nChannels
1290 # self.setup(nSamples, nChannels)
1289 # self.setup(nSamples, nChannels)
1291 # self.isConfig = True
1290 # self.isConfig = True
1292 #
1291 #
1293 # #Append new data to internal buffer
1292 # #Append new data to internal buffer
1294 # for thisChannel in range(self.__nChannels):
1293 # for thisChannel in range(self.__nChannels):
1295 # bufferByChannel = self.__bufferList[thisChannel]
1294 # bufferByChannel = self.__bufferList[thisChannel]
1296 # bufferByChannel.extend(dataOut.data[thisChannel])
1295 # bufferByChannel.extend(dataOut.data[thisChannel])
1297 #
1296 #
1298 # if self.__pulseFound:
1297 # if self.__pulseFound:
1299 # self.__startIndex -= self.__nSamples
1298 # self.__startIndex -= self.__nSamples
1300 #
1299 #
1301 # #Finding Tx Pulse
1300 # #Finding Tx Pulse
1302 # if not self.__pulseFound:
1301 # if not self.__pulseFound:
1303 # indexFound = self.__findTxPulse(dataOut, channel)
1302 # indexFound = self.__findTxPulse(dataOut, channel)
1304 #
1303 #
1305 # if indexFound == None:
1304 # if indexFound == None:
1306 # dataOut.flagNoData = True
1305 # dataOut.flagNoData = True
1307 # return
1306 # return
1308 #
1307 #
1309 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1308 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1310 # self.__pulseFound = True
1309 # self.__pulseFound = True
1311 # self.__startIndex = indexFound
1310 # self.__startIndex = indexFound
1312 #
1311 #
1313 # #If pulse was found ...
1312 # #If pulse was found ...
1314 # for thisChannel in range(self.__nChannels):
1313 # for thisChannel in range(self.__nChannels):
1315 # bufferByChannel = self.__bufferList[thisChannel]
1314 # bufferByChannel = self.__bufferList[thisChannel]
1316 # #print self.__startIndex
1315 # #print self.__startIndex
1317 # x = numpy.array(bufferByChannel)
1316 # x = numpy.array(bufferByChannel)
1318 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1317 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1319 #
1318 #
1320 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1319 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1321 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1320 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1322 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1321 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1323 #
1322 #
1324 # dataOut.data = self.__arrayBuffer
1323 # dataOut.data = self.__arrayBuffer
1325 #
1324 #
1326 # self.__startIndex += self.__newNSamples
1325 # self.__startIndex += self.__newNSamples
1327 #
1326 #
1328 # return
1327 # return
1 NO CONTENT: modified file
NO CONTENT: modified file
1 NO CONTENT: modified file
NO CONTENT: modified file
General Comments 0
You need to be logged in to leave comments. Login now