##// END OF EJS Templates
First Spectral Fitting and EW Drifts operative module inside Signal Chain TRUNK
Julio Valdez -
r513:19f921674eb5
parent child
Show More
@@ -0,0 +1,135
1 # DIAS 19 Y 20 FEB 2014
2 # Comprobacion de Resultados DBS con SA
3
4 import os, sys
5
6 path = os.path.split(os.getcwd())[0]
7 sys.path.append(path)
8
9 from controller import *
10
11 desc = "DBS Experiment Test"
12 filename = "DBStest.xml"
13
14 controllerObj = Project()
15
16 controllerObj.setup(id = '191', name='test01', description=desc)
17
18 #Experimentos
19
20 path = '/host/Jicamarca/EW_Drifts/d2012248'
21 pathFigure = '/home/propietario/workspace/Graficos/drifts'
22
23
24 path = "/home/soporte/Data/drifts"
25 pathFigure = '/home/soporte/workspace/Graficos/drifts/prueba'
26
27 xmin = 11.75
28 xmax = 14.75
29 #------------------------------------------------------------------------------------------------
30 readUnitConfObj = controllerObj.addReadUnit(datatype='VoltageReader',
31 path=path,
32 startDate='2012/01/01',
33 endDate='2012/12/31',
34 startTime='00:00:00',
35 endTime='23:59:59',
36 online=0,
37 walk=1)
38
39 opObj11 = readUnitConfObj.addOperation(name='printNumberOfBlock')
40
41 #--------------------------------------------------------------------------------------------------
42
43 procUnitConfObj0 = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
44
45 opObj11 = procUnitConfObj0.addOperation(name='ProfileSelector', optype='other')
46 opObj11.addParameter(name='profileRangeList', value='0,127', format='intlist')
47
48 opObj11 = procUnitConfObj0.addOperation(name='filterByHeights')
49 opObj11.addParameter(name='window', value='3', format='int')
50
51 opObj11 = procUnitConfObj0.addOperation(name='Decoder', optype='other')
52 # opObj11.addParameter(name='code', value='1,-1', format='floatlist')
53 # opObj11.addParameter(name='nCode', value='2', format='int')
54 # opObj11.addParameter(name='nBaud', value='1', format='int')
55
56 procUnitConfObj1 = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObj0.getId())
57 procUnitConfObj1.addParameter(name='nFFTPoints', value='128', format='int')
58 procUnitConfObj1.addParameter(name='nProfiles', value='128', format='int')
59 procUnitConfObj1.addParameter(name='pairsList', value='(0,1),(2,3)', format='pairsList')#,(2,3)
60
61 opObj11 = procUnitConfObj1.addOperation(name='selectHeights')
62 # # opObj11.addParameter(name='minHei', value='320.0', format='float')
63 # # opObj11.addParameter(name='maxHei', value='350.0', format='float')
64 opObj11.addParameter(name='minHei', value='200.0', format='float')
65 opObj11.addParameter(name='maxHei', value='600.0', format='float')
66
67 opObj11 = procUnitConfObj1.addOperation(name='selectChannels')
68 opObj11.addParameter(name='channelList', value='0,1,2,3', format='intlist')
69
70 opObj11 = procUnitConfObj1.addOperation(name='IncohInt', optype='other')
71 opObj11.addParameter(name='timeInterval', value='300.0', format='float')
72
73 opObj13 = procUnitConfObj1.addOperation(name='removeDC')
74
75 # opObj14 = procUnitConfObj1.addOperation(name='SpectraPlot', optype='other')
76 # opObj14.addParameter(name='id', value='1', format='int')
77 # # opObj14.addParameter(name='wintitle', value='Con interf', format='str')
78 # opObj14.addParameter(name='save', value='1', format='bool')
79 # opObj14.addParameter(name='figpath', value=pathFigure, format='str')
80 # # opObj14.addParameter(name='zmin', value='5', format='int')
81 # opObj14.addParameter(name='zmax', value='30', format='int')
82 #
83 # opObj12 = procUnitConfObj1.addOperation(name='RTIPlot', optype='other')
84 # opObj12.addParameter(name='id', value='2', format='int')
85 # opObj12.addParameter(name='wintitle', value='RTI Plot', format='str')
86 # opObj12.addParameter(name='save', value='1', format='bool')
87 # opObj12.addParameter(name='figpath', value = pathFigure, format='str')
88 # opObj12.addParameter(name='xmin', value=xmin, format='float')
89 # opObj12.addParameter(name='xmax', value=xmax, format='float')
90 # # opObj12.addParameter(name='zmin', value='5', format='int')
91 # opObj12.addParameter(name='zmax', value='30', format='int')
92
93 #--------------------------------------------------------------------------------------------------
94
95 procUnitConfObj2 = controllerObj.addProcUnit(datatype='ParametersProc', inputId=procUnitConfObj1.getId())
96 opObj20 = procUnitConfObj2.addOperation(name='SpectralFitting')
97 opObj20.addParameter(name='path', value='/home/soporte/workspace/RemoteSystemsTempFiles', format='str')
98 opObj20.addParameter(name='file', value='modelSpectralFitting', format='str')
99 opObj20.addParameter(name='groupList', value='(0,1),(2,3)',format='multiList')
100
101 opObj11 = procUnitConfObj2.addOperation(name='SpectralFittingPlot', optype='other')
102 opObj11.addParameter(name='id', value='3', format='int')
103 opObj11.addParameter(name='wintitle', value='DopplerPlot', format='str')
104 opObj11.addParameter(name='cutHeight', value='350', format='int')
105 opObj11.addParameter(name='fit', value='1', format='int')#1--True/include fit
106 opObj11.addParameter(name='save', value='1', format='bool')
107 opObj11.addParameter(name='figpath', value = pathFigure, format='str')
108
109 opObj11 = procUnitConfObj2.addOperation(name='EWDriftsEstimation', optype='other')
110 opObj11.addParameter(name='zenith', value='-3.80208,3.10658', format='floatlist')
111 opObj11.addParameter(name='zenithCorrection', value='0.183201', format='float')
112
113 opObj23 = procUnitConfObj2.addOperation(name='EWDriftsPlot', optype='other')
114 opObj23.addParameter(name='id', value='4', format='int')
115 opObj23.addParameter(name='wintitle', value='EW Drifts', format='str')
116 opObj23.addParameter(name='save', value='1', format='bool')
117 opObj23.addParameter(name='figpath', value = pathFigure, format='str')
118 opObj23.addParameter(name='zminZonal', value='-150', format='int')
119 opObj23.addParameter(name='zmaxZonal', value='150', format='int')
120 opObj23.addParameter(name='zminVertical', value='-30', format='float')
121 opObj23.addParameter(name='zmaxVertical', value='30', format='float')
122 opObj23.addParameter(name='SNR_1', value='1', format='bool')
123 opObj23.addParameter(name='SNRmax', value='5', format='int')
124 # opObj23.addParameter(name='SNRthresh', value='-50', format='float')
125 opObj23.addParameter(name='xmin', value=xmin, format='float')
126 opObj23.addParameter(name='xmax', value=xmax, format='float')
127 #--------------------------------------------------------------------------------------------------
128 print "Escribiendo el archivo XML"
129 controllerObj.writeXml(filename)
130 print "Leyendo el archivo XML"
131 controllerObj.readXml(filename)
132
133 controllerObj.createObjects()
134 controllerObj.connectObjects()
135 controllerObj.run() No newline at end of file
@@ -1,967 +1,983
1 1 '''
2 2
3 3 $Author: murco $
4 4 $Id: JROData.py 173 2012-11-20 15:06:21Z murco $
5 5 '''
6 6
7 7 import copy
8 8 import numpy
9 9 import datetime
10 10
11 11 from jroheaderIO import SystemHeader, RadarControllerHeader
12 12
13 13 def getNumpyDtype(dataTypeCode):
14 14
15 15 if dataTypeCode == 0:
16 16 numpyDtype = numpy.dtype([('real','<i1'),('imag','<i1')])
17 17 elif dataTypeCode == 1:
18 18 numpyDtype = numpy.dtype([('real','<i2'),('imag','<i2')])
19 19 elif dataTypeCode == 2:
20 20 numpyDtype = numpy.dtype([('real','<i4'),('imag','<i4')])
21 21 elif dataTypeCode == 3:
22 22 numpyDtype = numpy.dtype([('real','<i8'),('imag','<i8')])
23 23 elif dataTypeCode == 4:
24 24 numpyDtype = numpy.dtype([('real','<f4'),('imag','<f4')])
25 25 elif dataTypeCode == 5:
26 26 numpyDtype = numpy.dtype([('real','<f8'),('imag','<f8')])
27 27 else:
28 28 raise ValueError, 'dataTypeCode was not defined'
29 29
30 30 return numpyDtype
31 31
32 32 def getDataTypeCode(numpyDtype):
33 33
34 34 if numpyDtype == numpy.dtype([('real','<i1'),('imag','<i1')]):
35 35 datatype = 0
36 36 elif numpyDtype == numpy.dtype([('real','<i2'),('imag','<i2')]):
37 37 datatype = 1
38 38 elif numpyDtype == numpy.dtype([('real','<i4'),('imag','<i4')]):
39 39 datatype = 2
40 40 elif numpyDtype == numpy.dtype([('real','<i8'),('imag','<i8')]):
41 41 datatype = 3
42 42 elif numpyDtype == numpy.dtype([('real','<f4'),('imag','<f4')]):
43 43 datatype = 4
44 44 elif numpyDtype == numpy.dtype([('real','<f8'),('imag','<f8')]):
45 45 datatype = 5
46 46 else:
47 47 datatype = None
48 48
49 49 return datatype
50 50
51 51 def hildebrand_sekhon(data, navg):
52 52
53 53 data = data.copy()
54 54
55 55 sortdata = numpy.sort(data,axis=None)
56 56 lenOfData = len(sortdata)
57 57 nums_min = lenOfData/10
58 58
59 59 if (lenOfData/10) > 2:
60 60 nums_min = lenOfData/10
61 61 else:
62 62 nums_min = 2
63 63
64 64 sump = 0.
65 65
66 66 sumq = 0.
67 67
68 68 j = 0
69 69
70 70 cont = 1
71 71
72 72 while((cont==1)and(j<lenOfData)):
73 73
74 74 sump += sortdata[j]
75 75
76 76 sumq += sortdata[j]**2
77 77
78 78 j += 1
79 79
80 80 if j > nums_min:
81 81 rtest = float(j)/(j-1) + 1.0/navg
82 82 if ((sumq*j) > (rtest*sump**2)):
83 83 j = j - 1
84 84 sump = sump - sortdata[j]
85 85 sumq = sumq - sortdata[j]**2
86 86 cont = 0
87 87
88 88 lnoise = sump /j
89 89 stdv = numpy.sqrt((sumq - lnoise**2)/(j - 1))
90 90 return lnoise
91 91
92 92 class Beam:
93 93 def __init__(self):
94 94 self.codeList = []
95 95 self.azimuthList = []
96 96 self.zenithList = []
97 97
98 98 class GenericData(object):
99 99
100 100 flagNoData = True
101 101
102 102 def __init__(self):
103 103
104 104 raise ValueError, "This class has not been implemented"
105 105
106 106 def copy(self, inputObj=None):
107 107
108 108 if inputObj == None:
109 109 return copy.deepcopy(self)
110 110
111 111 for key in inputObj.__dict__.keys():
112 112 self.__dict__[key] = inputObj.__dict__[key]
113 113
114 114 def deepcopy(self):
115 115
116 116 return copy.deepcopy(self)
117 117
118 118 def isEmpty(self):
119 119
120 120 return self.flagNoData
121 121
122 122 class JROData(GenericData):
123 123
124 124 # m_BasicHeader = BasicHeader()
125 125 # m_ProcessingHeader = ProcessingHeader()
126 126
127 127 systemHeaderObj = SystemHeader()
128 128
129 129 radarControllerHeaderObj = RadarControllerHeader()
130 130
131 131 # data = None
132 132
133 133 type = None
134 134
135 135 datatype = None #dtype but in string
136 136
137 137 # dtype = None
138 138
139 139 # nChannels = None
140 140
141 141 # nHeights = None
142 142
143 143 nProfiles = None
144 144
145 145 heightList = None
146 146
147 147 channelList = None
148 148
149 149 flagTimeBlock = False
150 150
151 151 useLocalTime = False
152 152
153 153 utctime = None
154 154
155 155 timeZone = None
156 156
157 157 dstFlag = None
158 158
159 159 errorCount = None
160 160
161 161 blocksize = None
162 162
163 163 nCode = None
164 164
165 165 nBaud = None
166 166
167 167 code = None
168 168
169 169 flagDecodeData = False #asumo q la data no esta decodificada
170 170
171 171 flagDeflipData = False #asumo q la data no esta sin flip
172 172
173 173 flagShiftFFT = False
174 174
175 175 # ippSeconds = None
176 176
177 177 timeInterval = None
178 178
179 179 nCohInt = None
180 180
181 181 noise = None
182 182
183 183 windowOfFilter = 1
184 184
185 185 #Speed of ligth
186 186 C = 3e8
187 187
188 188 frequency = 49.92e6
189 189
190 190 realtime = False
191 191
192 192 beacon_heiIndexList = None
193 193
194 194 last_block = None
195 195
196 196 blocknow = None
197 197
198 198 azimuth = None
199 199
200 200 zenith = None
201 201
202 202 beam = Beam()
203 203
204 204 def __init__(self):
205 205
206 206 raise ValueError, "This class has not been implemented"
207 207
208 208 def getNoise(self):
209 209
210 210 raise ValueError, "Not implemented"
211 211
212 212 def getNChannels(self):
213 213
214 214 return len(self.channelList)
215 215
216 216 def getChannelIndexList(self):
217 217
218 218 return range(self.nChannels)
219 219
220 220 def getNHeights(self):
221 221
222 222 return len(self.heightList)
223 223
224 224 def getHeiRange(self, extrapoints=0):
225 225
226 226 heis = self.heightList
227 227 # deltah = self.heightList[1] - self.heightList[0]
228 228 #
229 229 # heis.append(self.heightList[-1])
230 230
231 231 return heis
232 232
233 233 def getltctime(self):
234 234
235 235 if self.useLocalTime:
236 236 return self.utctime - self.timeZone*60
237 237
238 238 return self.utctime
239 239
240 240 def getDatatime(self):
241 241
242 242 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
243 243 return datatimeValue
244 244
245 245 def getTimeRange(self):
246 246
247 247 datatime = []
248 248
249 249 datatime.append(self.ltctime)
250 250 datatime.append(self.ltctime + self.timeInterval)
251 251
252 252 datatime = numpy.array(datatime)
253 253
254 254 return datatime
255 255
256 256 def getFmax(self):
257 257
258 258 PRF = 1./(self.ippSeconds * self.nCohInt)
259 259
260 260 fmax = PRF/2.
261 261
262 262 return fmax
263 263
264 264 def getVmax(self):
265 265
266 266 _lambda = self.C/self.frequency
267 267
268 268 vmax = self.getFmax() * _lambda
269 269
270 270 return vmax
271 271
272 272 def get_ippSeconds(self):
273 273 '''
274 274 '''
275 275 return self.radarControllerHeaderObj.ippSeconds
276 276
277 277 def set_ippSeconds(self, ippSeconds):
278 278 '''
279 279 '''
280 280
281 281 self.radarControllerHeaderObj.ippSeconds = ippSeconds
282 282
283 283 return
284 284
285 285 def get_dtype(self):
286 286 '''
287 287 '''
288 288 return getNumpyDtype(self.datatype)
289 289
290 290 def set_dtype(self, numpyDtype):
291 291 '''
292 292 '''
293 293
294 294 self.datatype = getDataTypeCode(numpyDtype)
295 295
296 296 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
297 297 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
298 298 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
299 299 #noise = property(getNoise, "I'm the 'nHeights' property.")
300 300 datatime = property(getDatatime, "I'm the 'datatime' property")
301 301 ltctime = property(getltctime, "I'm the 'ltctime' property")
302 302 ippSeconds = property(get_ippSeconds, set_ippSeconds)
303 303 dtype = property(get_dtype, set_dtype)
304 304
305 305 class Voltage(JROData):
306 306
307 307 #data es un numpy array de 2 dmensiones (canales, alturas)
308 308 data = None
309 309
310 310 def __init__(self):
311 311 '''
312 312 Constructor
313 313 '''
314 314
315 315 self.radarControllerHeaderObj = RadarControllerHeader()
316 316
317 317 self.systemHeaderObj = SystemHeader()
318 318
319 319 self.type = "Voltage"
320 320
321 321 self.data = None
322 322
323 323 # self.dtype = None
324 324
325 325 # self.nChannels = 0
326 326
327 327 # self.nHeights = 0
328 328
329 329 self.nProfiles = None
330 330
331 331 self.heightList = None
332 332
333 333 self.channelList = None
334 334
335 335 # self.channelIndexList = None
336 336
337 337 self.flagNoData = True
338 338
339 339 self.flagTimeBlock = False
340 340
341 341 self.utctime = None
342 342
343 343 self.timeZone = None
344 344
345 345 self.dstFlag = None
346 346
347 347 self.errorCount = None
348 348
349 349 self.nCohInt = None
350 350
351 351 self.blocksize = None
352 352
353 353 self.flagDecodeData = False #asumo q la data no esta decodificada
354 354
355 355 self.flagDeflipData = False #asumo q la data no esta sin flip
356 356
357 357 self.flagShiftFFT = False
358 358
359 359
360 360 def getNoisebyHildebrand(self):
361 361 """
362 362 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
363 363
364 364 Return:
365 365 noiselevel
366 366 """
367 367
368 368 for channel in range(self.nChannels):
369 369 daux = self.data_spc[channel,:,:]
370 370 self.noise[channel] = hildebrand_sekhon(daux, self.nCohInt)
371 371
372 372 return self.noise
373 373
374 374 def getNoise(self, type = 1):
375 375
376 376 self.noise = numpy.zeros(self.nChannels)
377 377
378 378 if type == 1:
379 379 noise = self.getNoisebyHildebrand()
380 380
381 381 return 10*numpy.log10(noise)
382 382
383 383 noise = property(getNoise, "I'm the 'nHeights' property.")
384 384
385 385 class Spectra(JROData):
386 386
387 387 #data es un numpy array de 2 dmensiones (canales, perfiles, alturas)
388 388 data_spc = None
389 389
390 390 #data es un numpy array de 2 dmensiones (canales, pares, alturas)
391 391 data_cspc = None
392 392
393 393 #data es un numpy array de 2 dmensiones (canales, alturas)
394 394 data_dc = None
395 395
396 396 nFFTPoints = None
397 397
398 398 # nPairs = None
399 399
400 400 pairsList = None
401 401
402 402 nIncohInt = None
403 403
404 404 wavelength = None #Necesario para cacular el rango de velocidad desde la frecuencia
405 405
406 406 nCohInt = None #se requiere para determinar el valor de timeInterval
407 407
408 408 ippFactor = None
409 409
410 410 def __init__(self):
411 411 '''
412 412 Constructor
413 413 '''
414 414
415 415 self.radarControllerHeaderObj = RadarControllerHeader()
416 416
417 417 self.systemHeaderObj = SystemHeader()
418 418
419 419 self.type = "Spectra"
420 420
421 421 # self.data = None
422 422
423 423 # self.dtype = None
424 424
425 425 # self.nChannels = 0
426 426
427 427 # self.nHeights = 0
428 428
429 429 self.nProfiles = None
430 430
431 431 self.heightList = None
432 432
433 433 self.channelList = None
434 434
435 435 # self.channelIndexList = None
436 436
437 437 self.pairsList = None
438 438
439 439 self.flagNoData = True
440 440
441 441 self.flagTimeBlock = False
442 442
443 443 self.utctime = None
444 444
445 445 self.nCohInt = None
446 446
447 447 self.nIncohInt = None
448 448
449 449 self.blocksize = None
450 450
451 451 self.nFFTPoints = None
452 452
453 453 self.wavelength = None
454 454
455 455 self.flagDecodeData = False #asumo q la data no esta decodificada
456 456
457 457 self.flagDeflipData = False #asumo q la data no esta sin flip
458 458
459 459 self.flagShiftFFT = False
460 460
461 461 self.ippFactor = 1
462 462
463 463 #self.noise = None
464 464
465 465 self.beacon_heiIndexList = []
466 466
467 467 self.noise_estimation = None
468 468
469 469
470 470 def getNoisebyHildebrand(self):
471 471 """
472 472 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
473 473
474 474 Return:
475 475 noiselevel
476 476 """
477 477
478 478 noise = numpy.zeros(self.nChannels)
479 479 for channel in range(self.nChannels):
480 480 daux = self.data_spc[channel,:,:]
481 481 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
482 482
483 483 return noise
484 484
485 485 def getNoise(self):
486 486 if self.noise_estimation != None:
487 487 return self.noise_estimation #this was estimated by getNoise Operation defined in jroproc_spectra.py
488 488 else:
489 489 noise = self.getNoisebyHildebrand()
490 490 return noise
491 491
492 492
493 493 def getFreqRange(self, extrapoints=0):
494 494
495 495 deltafreq = self.getFmax() / (self.nFFTPoints*self.ippFactor)
496 496 freqrange = deltafreq*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltafreq/2
497 497
498 498 return freqrange
499 499
500 500 def getVelRange(self, extrapoints=0):
501 501
502 502 deltav = self.getVmax() / (self.nFFTPoints*self.ippFactor)
503 503 velrange = deltav*(numpy.arange(self.nFFTPoints+extrapoints)-self.nFFTPoints/2.) - deltav/2
504 504
505 505 return velrange
506 506
507 507 def getNPairs(self):
508 508
509 509 return len(self.pairsList)
510 510
511 511 def getPairsIndexList(self):
512 512
513 513 return range(self.nPairs)
514 514
515 515 def getNormFactor(self):
516 516 pwcode = 1
517 517 if self.flagDecodeData:
518 518 pwcode = numpy.sum(self.code[0]**2)
519 519 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
520 520 normFactor = self.nProfiles*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
521 521
522 522 return normFactor
523 523
524 524 def getFlagCspc(self):
525 525
526 526 if self.data_cspc == None:
527 527 return True
528 528
529 529 return False
530 530
531 531 def getFlagDc(self):
532 532
533 533 if self.data_dc == None:
534 534 return True
535 535
536 536 return False
537 537
538 538 nPairs = property(getNPairs, "I'm the 'nPairs' property.")
539 539 pairsIndexList = property(getPairsIndexList, "I'm the 'pairsIndexList' property.")
540 540 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
541 541 flag_cspc = property(getFlagCspc)
542 542 flag_dc = property(getFlagDc)
543 543 noise = property(getNoise, "I'm the 'nHeights' property.")
544 544
545 545 class SpectraHeis(Spectra):
546 546
547 547 data_spc = None
548 548
549 549 data_cspc = None
550 550
551 551 data_dc = None
552 552
553 553 nFFTPoints = None
554 554
555 555 # nPairs = None
556 556
557 557 pairsList = None
558 558
559 559 nIncohInt = None
560 560
561 561 def __init__(self):
562 562
563 563 self.radarControllerHeaderObj = RadarControllerHeader()
564 564
565 565 self.systemHeaderObj = SystemHeader()
566 566
567 567 self.type = "SpectraHeis"
568 568
569 569 # self.dtype = None
570 570
571 571 # self.nChannels = 0
572 572
573 573 # self.nHeights = 0
574 574
575 575 self.nProfiles = None
576 576
577 577 self.heightList = None
578 578
579 579 self.channelList = None
580 580
581 581 # self.channelIndexList = None
582 582
583 583 self.flagNoData = True
584 584
585 585 self.flagTimeBlock = False
586 586
587 587 # self.nPairs = 0
588 588
589 589 self.utctime = None
590 590
591 591 self.blocksize = None
592 592
593 593 def getNormFactor(self):
594 594 pwcode = 1
595 595 if self.flagDecodeData:
596 596 pwcode = numpy.sum(self.code[0]**2)
597 597
598 598 normFactor = self.nIncohInt*self.nCohInt*pwcode
599 599
600 600 return normFactor
601 601
602 602 normFactor = property(getNormFactor, "I'm the 'getNormFactor' property.")
603 603
604 604 class Fits:
605 605
606 606 heightList = None
607 607
608 608 channelList = None
609 609
610 610 flagNoData = True
611 611
612 612 flagTimeBlock = False
613 613
614 614 useLocalTime = False
615 615
616 616 utctime = None
617 617
618 618 timeZone = None
619 619
620 620 # ippSeconds = None
621 621
622 622 timeInterval = None
623 623
624 624 nCohInt = None
625 625
626 626 nIncohInt = None
627 627
628 628 noise = None
629 629
630 630 windowOfFilter = 1
631 631
632 632 #Speed of ligth
633 633 C = 3e8
634 634
635 635 frequency = 49.92e6
636 636
637 637 realtime = False
638 638
639 639
640 640 def __init__(self):
641 641
642 642 self.type = "Fits"
643 643
644 644 self.nProfiles = None
645 645
646 646 self.heightList = None
647 647
648 648 self.channelList = None
649 649
650 650 # self.channelIndexList = None
651 651
652 652 self.flagNoData = True
653 653
654 654 self.utctime = None
655 655
656 656 self.nCohInt = None
657 657
658 658 self.nIncohInt = None
659 659
660 660 self.useLocalTime = True
661 661
662 662 # self.utctime = None
663 663 # self.timeZone = None
664 664 # self.ltctime = None
665 665 # self.timeInterval = None
666 666 # self.header = None
667 667 # self.data_header = None
668 668 # self.data = None
669 669 # self.datatime = None
670 670 # self.flagNoData = False
671 671 # self.expName = ''
672 672 # self.nChannels = None
673 673 # self.nSamples = None
674 674 # self.dataBlocksPerFile = None
675 675 # self.comments = ''
676 676 #
677 677
678 678
679 679 def getltctime(self):
680 680
681 681 if self.useLocalTime:
682 682 return self.utctime - self.timeZone*60
683 683
684 684 return self.utctime
685 685
686 686 def getDatatime(self):
687 687
688 688 datatime = datetime.datetime.utcfromtimestamp(self.ltctime)
689 689 return datatime
690 690
691 691 def getTimeRange(self):
692 692
693 693 datatime = []
694 694
695 695 datatime.append(self.ltctime)
696 696 datatime.append(self.ltctime + self.timeInterval)
697 697
698 698 datatime = numpy.array(datatime)
699 699
700 700 return datatime
701 701
702 702 def getHeiRange(self):
703 703
704 704 heis = self.heightList
705 705
706 706 return heis
707 707
708 708 def isEmpty(self):
709 709
710 710 return self.flagNoData
711 711
712 712 def getNHeights(self):
713 713
714 714 return len(self.heightList)
715 715
716 716 def getNChannels(self):
717 717
718 718 return len(self.channelList)
719 719
720 720 def getChannelIndexList(self):
721 721
722 722 return range(self.nChannels)
723 723
724 724 def getNoise(self, type = 1):
725 725
726 726 self.noise = numpy.zeros(self.nChannels)
727 727
728 728 if type == 1:
729 729 noise = self.getNoisebyHildebrand()
730 730
731 731 if type == 2:
732 732 noise = self.getNoisebySort()
733 733
734 734 if type == 3:
735 735 noise = self.getNoisebyWindow()
736 736
737 737 return noise
738 738
739 739 datatime = property(getDatatime, "I'm the 'datatime' property")
740 740 nHeights = property(getNHeights, "I'm the 'nHeights' property.")
741 741 nChannels = property(getNChannels, "I'm the 'nChannel' property.")
742 742 channelIndexList = property(getChannelIndexList, "I'm the 'channelIndexList' property.")
743 743 noise = property(getNoise, "I'm the 'nHeights' property.")
744 744 datatime = property(getDatatime, "I'm the 'datatime' property")
745 745 ltctime = property(getltctime, "I'm the 'ltctime' property")
746 746
747 747 class Correlation(JROData):
748 748
749 749 noise = None
750 750
751 751 SNR = None
752 752
753 753 pairsAutoCorr = None #Pairs of Autocorrelation
754 754
755 755 #--------------------------------------------------
756 756
757 757 data_corr = None
758 758
759 759 data_volt = None
760 760
761 761 lagT = None # each element value is a profileIndex
762 762
763 763 lagR = None # each element value is in km
764 764
765 765 pairsList = None
766 766
767 767 calculateVelocity = None
768 768
769 769 nPoints = None
770 770
771 771 nAvg = None
772 772
773 773 bufferSize = None
774 774
775 775 def __init__(self):
776 776 '''
777 777 Constructor
778 778 '''
779 779 self.radarControllerHeaderObj = RadarControllerHeader()
780 780
781 781 self.systemHeaderObj = SystemHeader()
782 782
783 783 self.type = "Correlation"
784 784
785 785 self.data = None
786 786
787 787 self.dtype = None
788 788
789 789 self.nProfiles = None
790 790
791 791 self.heightList = None
792 792
793 793 self.channelList = None
794 794
795 795 self.flagNoData = True
796 796
797 797 self.flagTimeBlock = False
798 798
799 799 self.utctime = None
800 800
801 801 self.timeZone = None
802 802
803 803 self.dstFlag = None
804 804
805 805 self.errorCount = None
806 806
807 807 self.blocksize = None
808 808
809 809 self.flagDecodeData = False #asumo q la data no esta decodificada
810 810
811 811 self.flagDeflipData = False #asumo q la data no esta sin flip
812 812
813 813 self.pairsList = None
814 814
815 815 self.nPoints = None
816 816
817 817 def getLagTRange(self, extrapoints=0):
818 818
819 819 lagTRange = self.lagT
820 820 diff = lagTRange[1] - lagTRange[0]
821 821 extra = numpy.arange(1,extrapoints + 1)*diff + lagTRange[-1]
822 822 lagTRange = numpy.hstack((lagTRange, extra))
823 823
824 824 return lagTRange
825 825
826 826 def getLagRRange(self, extrapoints=0):
827 827
828 828 return self.lagR
829 829
830 830 def getPairsList(self):
831 831
832 832 return self.pairsList
833 833
834 834 def getCalculateVelocity(self):
835 835
836 836 return self.calculateVelocity
837 837
838 838 def getNPoints(self):
839 839
840 840 return self.nPoints
841 841
842 842 def getNAvg(self):
843 843
844 844 return self.nAvg
845 845
846 846 def getBufferSize(self):
847 847
848 848 return self.bufferSize
849 849
850 850 def getPairsAutoCorr(self):
851 851 pairsList = self.pairsList
852 852 pairsAutoCorr = numpy.zeros(self.nChannels, dtype = 'int')*numpy.nan
853 853
854 854 for l in range(len(pairsList)):
855 855 firstChannel = pairsList[l][0]
856 856 secondChannel = pairsList[l][1]
857 857
858 858 #Obteniendo pares de Autocorrelacion
859 859 if firstChannel == secondChannel:
860 860 pairsAutoCorr[firstChannel] = int(l)
861 861
862 862 pairsAutoCorr = pairsAutoCorr.astype(int)
863 863
864 864 return pairsAutoCorr
865 865
866 866 def getNoise(self, mode = 2):
867 867
868 868 indR = numpy.where(self.lagR == 0)[0][0]
869 869 indT = numpy.where(self.lagT == 0)[0][0]
870 870
871 871 jspectra0 = self.data_corr[:,:,indR,:]
872 872 jspectra = copy.copy(jspectra0)
873 873
874 874 num_chan = jspectra.shape[0]
875 875 num_hei = jspectra.shape[2]
876 876
877 877 freq_dc = jspectra.shape[1]/2
878 878 ind_vel = numpy.array([-2,-1,1,2]) + freq_dc
879 879
880 880 if ind_vel[0]<0:
881 881 ind_vel[range(0,1)] = ind_vel[range(0,1)] + self.num_prof
882 882
883 883 if mode == 1:
884 884 jspectra[:,freq_dc,:] = (jspectra[:,ind_vel[1],:] + jspectra[:,ind_vel[2],:])/2 #CORRECCION
885 885
886 886 if mode == 2:
887 887
888 888 vel = numpy.array([-2,-1,1,2])
889 889 xx = numpy.zeros([4,4])
890 890
891 891 for fil in range(4):
892 892 xx[fil,:] = vel[fil]**numpy.asarray(range(4))
893 893
894 894 xx_inv = numpy.linalg.inv(xx)
895 895 xx_aux = xx_inv[0,:]
896 896
897 897 for ich in range(num_chan):
898 898 yy = jspectra[ich,ind_vel,:]
899 899 jspectra[ich,freq_dc,:] = numpy.dot(xx_aux,yy)
900 900
901 901 junkid = jspectra[ich,freq_dc,:]<=0
902 902 cjunkid = sum(junkid)
903 903
904 904 if cjunkid.any():
905 905 jspectra[ich,freq_dc,junkid.nonzero()] = (jspectra[ich,ind_vel[1],junkid] + jspectra[ich,ind_vel[2],junkid])/2
906 906
907 907 noise = jspectra0[:,freq_dc,:] - jspectra[:,freq_dc,:]
908 908
909 909 return noise
910 910
911 911 # pairsList = property(getPairsList, "I'm the 'pairsList' property.")
912 912 # nPoints = property(getNPoints, "I'm the 'nPoints' property.")
913 913 calculateVelocity = property(getCalculateVelocity, "I'm the 'calculateVelocity' property.")
914 914 nAvg = property(getNAvg, "I'm the 'nAvg' property.")
915 915 bufferSize = property(getBufferSize, "I'm the 'bufferSize' property.")
916 916
917 917
918 918 class Parameters(JROData):
919 919
920 #Information from previous data
921
920 922 inputUnit = None #Type of data to be processed
921 923
922 924 operation = None #Type of operation to parametrize
923 925
926 normFactor = None #Normalization Factor
927
928 groupList = None #List of Pairs, Groups, etc
929
930 #Parameters
931
924 932 data_param = None #Parameters obtained
925 933
926 934 data_pre = None #Data Pre Parametrization
927 935
928 936 heightRange = None #Heights
929 937
930 938 abscissaRange = None #Abscissa, can be velocities, lags or time
931 939
932 940 noise = None #Noise Potency
933 941
934 942 SNR = None #Signal to Noise Ratio
935 943
936 pairsList = None #List of Pairs for Cross correlations or Cross spectrum
937
938 944 initUtcTime = None #Initial UTC time
939 945
940 946 paramInterval = None #Time interval to calculate Parameters in seconds
941 947
942 windsInterval = None #Time interval to calculate Winds in seconds
948 #Fitting
949
950 constants = None
951
952 error = None
953
954 library = None
955
956 #Output signal
957
958 outputInterval = None #Time interval to calculate output signal in seconds
959
960 data_output = None #Out signal
943 961
944 normFactor = None #Normalization Factor
945 962
946 winds = None #Wind estimations
947 963
948 964 def __init__(self):
949 965 '''
950 966 Constructor
951 967 '''
952 968 self.radarControllerHeaderObj = RadarControllerHeader()
953 969
954 970 self.systemHeaderObj = SystemHeader()
955 971
956 972 self.type = "Parameters"
957 973
958 974 def getTimeRange1(self):
959 975
960 976 datatime = []
961 977
962 978 datatime.append(self.initUtcTime)
963 datatime.append(self.initUtcTime + self.windsInterval - 1)
979 datatime.append(self.initUtcTime + self.outputInterval - 1)
964 980
965 981 datatime = numpy.array(datatime)
966 982
967 983 return datatime
@@ -1,774 +1,1178
1 1 import os
2 2 import datetime
3 3 import numpy
4 4
5 5 from figure import Figure, isRealtime
6 6
7 7 class MomentsPlot(Figure):
8 8
9 9 isConfig = None
10 10 __nsubplots = None
11 11
12 12 WIDTHPROF = None
13 13 HEIGHTPROF = None
14 14 PREFIX = 'prm'
15 15
16 16 def __init__(self):
17 17
18 18 self.isConfig = False
19 19 self.__nsubplots = 1
20 20
21 21 self.WIDTH = 280
22 22 self.HEIGHT = 250
23 23 self.WIDTHPROF = 120
24 24 self.HEIGHTPROF = 0
25 25 self.counter_imagwr = 0
26 26
27 27 self.PLOT_CODE = 1
28 28 self.FTP_WEI = None
29 29 self.EXP_CODE = None
30 30 self.SUB_EXP_CODE = None
31 31 self.PLOT_POS = None
32 32
33 33 def getSubplots(self):
34 34
35 35 ncol = int(numpy.sqrt(self.nplots)+0.9)
36 36 nrow = int(self.nplots*1./ncol + 0.9)
37 37
38 38 return nrow, ncol
39 39
40 40 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
41 41
42 42 self.__showprofile = showprofile
43 43 self.nplots = nplots
44 44
45 45 ncolspan = 1
46 46 colspan = 1
47 47 if showprofile:
48 48 ncolspan = 3
49 49 colspan = 2
50 50 self.__nsubplots = 2
51 51
52 52 self.createFigure(id = id,
53 53 wintitle = wintitle,
54 54 widthplot = self.WIDTH + self.WIDTHPROF,
55 55 heightplot = self.HEIGHT + self.HEIGHTPROF,
56 56 show=show)
57 57
58 58 nrow, ncol = self.getSubplots()
59 59
60 60 counter = 0
61 61 for y in range(nrow):
62 62 for x in range(ncol):
63 63
64 64 if counter >= self.nplots:
65 65 break
66 66
67 67 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
68 68
69 69 if showprofile:
70 70 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
71 71
72 72 counter += 1
73 73
74 74 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=True,
75 75 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
76 76 save=False, figpath='', figfile=None, show=True, ftp=False, wr_period=1,
77 77 server=None, folder=None, username=None, password=None,
78 78 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
79 79
80 80 """
81 81
82 82 Input:
83 83 dataOut :
84 84 id :
85 85 wintitle :
86 86 channelList :
87 87 showProfile :
88 88 xmin : None,
89 89 xmax : None,
90 90 ymin : None,
91 91 ymax : None,
92 92 zmin : None,
93 93 zmax : None
94 94 """
95 95
96 96 if dataOut.flagNoData:
97 97 return None
98 98
99 99 if realtime:
100 100 if not(isRealtime(utcdatatime = dataOut.utctime)):
101 101 print 'Skipping this plot function'
102 102 return
103 103
104 104 if channelList == None:
105 105 channelIndexList = dataOut.channelIndexList
106 106 else:
107 107 channelIndexList = []
108 108 for channel in channelList:
109 109 if channel not in dataOut.channelList:
110 110 raise ValueError, "Channel %d is not in dataOut.channelList"
111 111 channelIndexList.append(dataOut.channelList.index(channel))
112 112
113 113 factor = dataOut.normFactor
114 114 x = dataOut.abscissaRange
115 115 y = dataOut.heightRange
116 116
117 117 z = dataOut.data_pre[channelIndexList,:,:]/factor
118 118 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
119 119 avg = numpy.average(z, axis=1)
120 120 noise = dataOut.noise/factor
121 121
122 122 zdB = 10*numpy.log10(z)
123 123 avgdB = 10*numpy.log10(avg)
124 124 noisedB = 10*numpy.log10(noise)
125 125
126 126 #thisDatetime = dataOut.datatime
127 127 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[1])
128 128 title = wintitle + " Parameters"
129 129 xlabel = "Velocity (m/s)"
130 130 ylabel = "Range (Km)"
131 131
132 132 if not self.isConfig:
133 133
134 134 nplots = len(channelIndexList)
135 135
136 136 self.setup(id=id,
137 137 nplots=nplots,
138 138 wintitle=wintitle,
139 139 showprofile=showprofile,
140 140 show=show)
141 141
142 142 if xmin == None: xmin = numpy.nanmin(x)
143 143 if xmax == None: xmax = numpy.nanmax(x)
144 144 if ymin == None: ymin = numpy.nanmin(y)
145 145 if ymax == None: ymax = numpy.nanmax(y)
146 146 if zmin == None: zmin = numpy.nanmin(avgdB)*0.9
147 147 if zmax == None: zmax = numpy.nanmax(avgdB)*0.9
148 148
149 149 self.FTP_WEI = ftp_wei
150 150 self.EXP_CODE = exp_code
151 151 self.SUB_EXP_CODE = sub_exp_code
152 152 self.PLOT_POS = plot_pos
153 153
154 154 self.isConfig = True
155 155
156 156 self.setWinTitle(title)
157 157
158 158 for i in range(self.nplots):
159 159 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
160 160 title = "Channel %d: %4.2fdB: %s" %(dataOut.channelList[i]+1, noisedB[i], str_datetime)
161 161 axes = self.axesList[i*self.__nsubplots]
162 162 axes.pcolor(x, y, zdB[i,:,:],
163 163 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
164 164 xlabel=xlabel, ylabel=ylabel, title=title,
165 165 ticksize=9, cblabel='')
166 166 #Mean Line
167 167 mean = dataOut.data_param[i, 1, :]
168 168 axes.addpline(mean, y, idline=0, color="black", linestyle="solid", lw=1)
169 169
170 170 if self.__showprofile:
171 171 axes = self.axesList[i*self.__nsubplots +1]
172 172 axes.pline(avgdB[i], y,
173 173 xmin=zmin, xmax=zmax, ymin=ymin, ymax=ymax,
174 174 xlabel='dB', ylabel='', title='',
175 175 ytick_visible=False,
176 176 grid='x')
177 177
178 178 noiseline = numpy.repeat(noisedB[i], len(y))
179 179 axes.addpline(noiseline, y, idline=1, color="black", linestyle="dashed", lw=2)
180 180
181 181 self.draw()
182 182
183 183 if figfile == None:
184 184 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
185 185 figfile = self.getFilename(name = str_datetime)
186 186
187 187 if figpath != '':
188 188 self.counter_imagwr += 1
189 189 if (self.counter_imagwr>=wr_period):
190 190 # store png plot to local folder
191 191 self.saveFigure(figpath, figfile)
192 192 # store png plot to FTP server according to RT-Web format
193 193 name = self.getNameToFtp(thisDatetime, self.FTP_WEI, self.EXP_CODE, self.SUB_EXP_CODE, self.PLOT_CODE, self.PLOT_POS)
194 194 ftp_filename = os.path.join(figpath, name)
195 195 self.saveFigure(figpath, ftp_filename)
196 196 self.counter_imagwr = 0
197 197
198 198 class SkyMapPlot(Figure):
199 199
200 200 __isConfig = None
201 201 __nsubplots = None
202 202
203 203 WIDTHPROF = None
204 204 HEIGHTPROF = None
205 205 PREFIX = 'prm'
206 206
207 207 def __init__(self):
208 208
209 209 self.__isConfig = False
210 210 self.__nsubplots = 1
211 211
212 212 # self.WIDTH = 280
213 213 # self.HEIGHT = 250
214 214 self.WIDTH = 600
215 215 self.HEIGHT = 600
216 216 self.WIDTHPROF = 120
217 217 self.HEIGHTPROF = 0
218 218 self.counter_imagwr = 0
219 219
220 220 self.PLOT_CODE = 1
221 221 self.FTP_WEI = None
222 222 self.EXP_CODE = None
223 223 self.SUB_EXP_CODE = None
224 224 self.PLOT_POS = None
225 225
226 226 def getSubplots(self):
227 227
228 228 ncol = int(numpy.sqrt(self.nplots)+0.9)
229 229 nrow = int(self.nplots*1./ncol + 0.9)
230 230
231 231 return nrow, ncol
232 232
233 233 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
234 234
235 235 self.__showprofile = showprofile
236 236 self.nplots = nplots
237 237
238 238 ncolspan = 1
239 239 colspan = 1
240 240
241 241 self.createFigure(id = id,
242 242 wintitle = wintitle,
243 243 widthplot = self.WIDTH, #+ self.WIDTHPROF,
244 244 heightplot = self.HEIGHT,# + self.HEIGHTPROF,
245 245 show=show)
246 246
247 247 nrow, ncol = 1,1
248 248 counter = 0
249 249 x = 0
250 250 y = 0
251 251 self.addAxes(1, 1, 0, 0, 1, 1, True)
252 252
253 253 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
254 254 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
255 255 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
256 256 server=None, folder=None, username=None, password=None,
257 257 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0, realtime=False):
258 258
259 259 """
260 260
261 261 Input:
262 262 dataOut :
263 263 id :
264 264 wintitle :
265 265 channelList :
266 266 showProfile :
267 267 xmin : None,
268 268 xmax : None,
269 269 ymin : None,
270 270 ymax : None,
271 271 zmin : None,
272 272 zmax : None
273 273 """
274 274
275 275 arrayParameters = dataOut.data_param
276 276 error = arrayParameters[:,-1]
277 277 indValid = numpy.where(error == 0)[0]
278 278 finalMeteor = arrayParameters[indValid,:]
279 279 finalAzimuth = finalMeteor[:,4]
280 280 finalZenith = finalMeteor[:,5]
281 281
282 282 x = finalAzimuth*numpy.pi/180
283 283 y = finalZenith
284 284
285 285
286 286 #thisDatetime = dataOut.datatime
287 287 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[1])
288 288 title = wintitle + " Parameters"
289 289 xlabel = "Zonal Zenith Angle (deg) "
290 290 ylabel = "Meridional Zenith Angle (deg)"
291 291
292 292 if not self.__isConfig:
293 293
294 294 nplots = 1
295 295
296 296 self.setup(id=id,
297 297 nplots=nplots,
298 298 wintitle=wintitle,
299 299 showprofile=showprofile,
300 300 show=show)
301 301
302 302 self.FTP_WEI = ftp_wei
303 303 self.EXP_CODE = exp_code
304 304 self.SUB_EXP_CODE = sub_exp_code
305 305 self.PLOT_POS = plot_pos
306 306 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
307 307 self.firstdate = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
308 308 self.__isConfig = True
309 309
310 310 self.setWinTitle(title)
311 311
312 312 i = 0
313 313 str_datetime = '%s %s'%(thisDatetime.strftime("%Y/%m/%d"),thisDatetime.strftime("%H:%M:%S"))
314 314
315 315 axes = self.axesList[i*self.__nsubplots]
316 316 nevents = axes.x_buffer.shape[0] + x.shape[0]
317 317 title = "Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n" %(self.firstdate,str_datetime,nevents)
318 318 axes.polar(x, y,
319 319 title=title, xlabel=xlabel, ylabel=ylabel,
320 320 ticksize=9, cblabel='')
321 321
322 322 self.draw()
323 323
324 324 if save:
325 325
326 326 self.counter_imagwr += 1
327 327 if (self.counter_imagwr==wr_period):
328 328
329 329 if figfile == None:
330 330 figfile = self.getFilename(name = self.name)
331 331 self.saveFigure(figpath, figfile)
332 332
333 333 if ftp:
334 334 #provisionalmente envia archivos en el formato de la web en tiempo real
335 335 name = self.getNameToFtp(thisDatetime, self.FTP_WEI, self.EXP_CODE, self.SUB_EXP_CODE, self.PLOT_CODE, self.PLOT_POS)
336 336 path = '%s%03d' %(self.PREFIX, self.id)
337 337 ftp_file = os.path.join(path,'ftp','%s.png'%name)
338 338 self.saveFigure(figpath, ftp_file)
339 339 ftp_filename = os.path.join(figpath,ftp_file)
340 340
341 341
342 342 try:
343 343 self.sendByFTP(ftp_filename, server, folder, username, password)
344 344 except:
345 345 self.counter_imagwr = 0
346 346 raise ValueError, 'Error FTP'
347 347
348 348 self.counter_imagwr = 0
349 349
350 350
351 351 class WindProfilerPlot(Figure):
352 352
353 353 __isConfig = None
354 354 __nsubplots = None
355 355
356 356 WIDTHPROF = None
357 357 HEIGHTPROF = None
358 358 PREFIX = 'wind'
359 359
360 360 def __init__(self):
361 361
362 362 self.timerange = 2*60*60
363 363 self.__isConfig = False
364 364 self.__nsubplots = 1
365 365
366 366 self.WIDTH = 800
367 367 self.HEIGHT = 150
368 368 self.WIDTHPROF = 120
369 369 self.HEIGHTPROF = 0
370 370 self.counter_imagwr = 0
371 371
372 372 self.PLOT_CODE = 0
373 373 self.FTP_WEI = None
374 374 self.EXP_CODE = None
375 375 self.SUB_EXP_CODE = None
376 376 self.PLOT_POS = None
377 377 self.tmin = None
378 378 self.tmax = None
379 379
380 380 self.xmin = None
381 381 self.xmax = None
382 382
383 383 self.figfile = None
384 384
385 385 def getSubplots(self):
386 386
387 387 ncol = 1
388 388 nrow = self.nplots
389 389
390 390 return nrow, ncol
391 391
392 392 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
393 393
394 394 self.__showprofile = showprofile
395 395 self.nplots = nplots
396 396
397 397 ncolspan = 1
398 398 colspan = 1
399 399
400 400 self.createFigure(id = id,
401 401 wintitle = wintitle,
402 402 widthplot = self.WIDTH + self.WIDTHPROF,
403 403 heightplot = self.HEIGHT + self.HEIGHTPROF,
404 404 show=show)
405 405
406 406 nrow, ncol = self.getSubplots()
407 407
408 408 counter = 0
409 409 for y in range(nrow):
410 410 if counter >= self.nplots:
411 411 break
412 412
413 413 self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1)
414 414 counter += 1
415 415
416 416 def run(self, dataOut, id, wintitle="", channelList=None,
417 417 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
418 418 zmax_ver = None, zmin_ver = None, SNRmin = None, SNRmax = None,
419 419 timerange=None, SNRthresh = None,
420 420 save=False, figpath='', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
421 421 server=None, folder=None, username=None, password=None,
422 422 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
423 423 """
424 424
425 425 Input:
426 426 dataOut :
427 427 id :
428 428 wintitle :
429 429 channelList :
430 430 showProfile :
431 431 xmin : None,
432 432 xmax : None,
433 433 ymin : None,
434 434 ymax : None,
435 435 zmin : None,
436 436 zmax : None
437 437 """
438 438
439 439 if channelList == None:
440 440 channelIndexList = dataOut.channelIndexList
441 441 else:
442 442 channelIndexList = []
443 443 for channel in channelList:
444 444 if channel not in dataOut.channelList:
445 445 raise ValueError, "Channel %d is not in dataOut.channelList"
446 446 channelIndexList.append(dataOut.channelList.index(channel))
447 447
448 448 if timerange != None:
449 449 self.timerange = timerange
450 450
451 451 tmin = None
452 452 tmax = None
453 453
454 454 x = dataOut.getTimeRange1()
455 455 # y = dataOut.heightRange
456 456 y = dataOut.heightRange
457 457
458 z = dataOut.winds.copy()
458 z = dataOut.data_output.copy()
459 459 nplots = z.shape[0] #Number of wind dimensions estimated
460 460 nplotsw = nplots
461 461
462 462 #If there is a SNR function defined
463 463 if dataOut.SNR != None:
464 464 nplots += 1
465 465 SNR = dataOut.SNR
466 466 SNRavg = numpy.average(SNR, axis=0)
467 467
468 468 SNRdB = 10*numpy.log10(SNR)
469 469 SNRavgdB = 10*numpy.log10(SNRavg)
470 470
471 471 if SNRthresh == None: SNRthresh = -5.0
472 472 ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0]
473 473
474 474 for i in range(nplotsw):
475 475 z[i,ind] = numpy.nan
476 476
477 477
478 478 showprofile = False
479 479 # thisDatetime = dataOut.datatime
480 480 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[1])
481 481 title = wintitle + "Wind"
482 482 xlabel = ""
483 483 ylabel = "Range (Km)"
484 484
485 485 if not self.__isConfig:
486 486
487 487 self.setup(id=id,
488 488 nplots=nplots,
489 489 wintitle=wintitle,
490 490 showprofile=showprofile,
491 491 show=show)
492 492
493 493 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
494 494
495 495 if ymin == None: ymin = numpy.nanmin(y)
496 496 if ymax == None: ymax = numpy.nanmax(y)
497 497
498 498 if zmax == None: zmax = numpy.nanmax(abs(z[range(2),:]))
499 499 #if numpy.isnan(zmax): zmax = 50
500 500 if zmin == None: zmin = -zmax
501 501
502 502 if nplotsw == 3:
503 503 if zmax_ver == None: zmax_ver = numpy.nanmax(abs(z[2,:]))
504 504 if zmin_ver == None: zmin_ver = -zmax_ver
505 505
506 506 if dataOut.SNR != None:
507 507 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
508 508 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
509 509
510 510 self.FTP_WEI = ftp_wei
511 511 self.EXP_CODE = exp_code
512 512 self.SUB_EXP_CODE = sub_exp_code
513 513 self.PLOT_POS = plot_pos
514 514
515 515 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
516 516 self.__isConfig = True
517 517
518 518
519 519 self.setWinTitle(title)
520 520
521 521 if ((self.xmax - x[1]) < (x[1]-x[0])):
522 522 x[1] = self.xmax
523 523
524 524 strWind = ['Zonal', 'Meridional', 'Vertical']
525 525 strCb = ['Velocity (m/s)','Velocity (m/s)','Velocity (cm/s)']
526 526 zmaxVector = [zmax, zmax, zmax_ver]
527 527 zminVector = [zmin, zmin, zmin_ver]
528 528 windFactor = [1,1,100]
529 529
530 530 for i in range(nplotsw):
531 531
532 532 title = "%s Wind: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
533 533 axes = self.axesList[i*self.__nsubplots]
534 534
535 535 z1 = z[i,:].reshape((1,-1))*windFactor[i]
536 536
537 537 axes.pcolorbuffer(x, y, z1,
538 538 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i],
539 539 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
540 540 ticksize=9, cblabel=strCb[i], cbsize="1%", colormap="RdBu_r" )
541 541
542 542 if dataOut.SNR != None:
543 543 i += 1
544 544 title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
545 545 axes = self.axesList[i*self.__nsubplots]
546 546
547 547 SNRavgdB = SNRavgdB.reshape((1,-1))
548 548
549 549 axes.pcolorbuffer(x, y, SNRavgdB,
550 550 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
551 551 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
552 552 ticksize=9, cblabel='', cbsize="1%", colormap="jet")
553 553
554 554 self.draw()
555 555
556 556 if self.figfile == None:
557 557 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
558 558 self.figfile = self.getFilename(name = str_datetime)
559 559
560 560 if figpath != '':
561 561
562 562 self.counter_imagwr += 1
563 563 if (self.counter_imagwr>=wr_period):
564 564 # store png plot to local folder
565 565 self.saveFigure(figpath, self.figfile)
566 566 # store png plot to FTP server according to RT-Web format
567 567 name = self.getNameToFtp(thisDatetime, self.FTP_WEI, self.EXP_CODE, self.SUB_EXP_CODE, self.PLOT_CODE, self.PLOT_POS)
568 568 ftp_filename = os.path.join(figpath, name)
569 569 self.saveFigure(figpath, ftp_filename)
570 570
571 571 self.counter_imagwr = 0
572 572
573 573 if x[1] >= self.axesList[0].xmax:
574 574 self.counter_imagwr = wr_period
575 575 self.__isConfig = False
576 576 self.figfile = None
577 577
578 578
579 579 class ParametersPlot(Figure):
580 580
581 581 __isConfig = None
582 582 __nsubplots = None
583 583
584 584 WIDTHPROF = None
585 585 HEIGHTPROF = None
586 586 PREFIX = 'prm'
587 587
588 588 def __init__(self):
589 589
590 590 self.timerange = 2*60*60
591 591 self.__isConfig = False
592 592 self.__nsubplots = 1
593 593
594 594 self.WIDTH = 800
595 595 self.HEIGHT = 150
596 596 self.WIDTHPROF = 120
597 597 self.HEIGHTPROF = 0
598 598 self.counter_imagwr = 0
599 599
600 600 self.PLOT_CODE = 0
601 601 self.FTP_WEI = None
602 602 self.EXP_CODE = None
603 603 self.SUB_EXP_CODE = None
604 604 self.PLOT_POS = None
605 605 self.tmin = None
606 606 self.tmax = None
607 607
608 608 self.xmin = None
609 609 self.xmax = None
610 610
611 611 self.figfile = None
612 612
613 613 def getSubplots(self):
614 614
615 615 ncol = 1
616 616 nrow = self.nplots
617 617
618 618 return nrow, ncol
619 619
620 620 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
621 621
622 622 self.__showprofile = showprofile
623 623 self.nplots = nplots
624 624
625 625 ncolspan = 1
626 626 colspan = 1
627 627
628 628 self.createFigure(id = id,
629 629 wintitle = wintitle,
630 630 widthplot = self.WIDTH + self.WIDTHPROF,
631 631 heightplot = self.HEIGHT + self.HEIGHTPROF,
632 632 show=show)
633 633
634 634 nrow, ncol = self.getSubplots()
635 635
636 636 counter = 0
637 637 for y in range(nrow):
638 638 for x in range(ncol):
639 639
640 640 if counter >= self.nplots:
641 641 break
642 642
643 643 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
644 644
645 645 if showprofile:
646 646 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
647 647
648 648 counter += 1
649 649
650 650 def run(self, dataOut, id, wintitle="", channelList=None, showprofile=False,
651 651 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,timerange=None,
652 652 SNRmin = None, SNRmax = None, SNRthresh = None, paramIndex = None, onlyPositive = False,
653 653 zlabel = "", parameterName = "",
654 654 save=False, figpath='', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
655 655 server=None, folder=None, username=None, password=None,
656 656 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
657 657
658 658 """
659 659
660 660 Input:
661 661 dataOut :
662 662 id :
663 663 wintitle :
664 664 channelList :
665 665 showProfile :
666 666 xmin : None,
667 667 xmax : None,
668 668 ymin : None,
669 669 ymax : None,
670 670 zmin : None,
671 671 zmax : None
672 672 """
673 673
674 674 if channelList == None:
675 675 channelIndexList = dataOut.channelIndexList
676 676 else:
677 677 channelIndexList = []
678 678 for channel in channelList:
679 679 if channel not in dataOut.channelList:
680 680 raise ValueError, "Channel %d is not in dataOut.channelList"
681 681 channelIndexList.append(dataOut.channelList.index(channel))
682 682
683 683 if timerange != None:
684 684 self.timerange = timerange
685 685
686 686 #tmin = None
687 687 #tmax = None
688 688 if paramIndex == None:
689 689 paramIndex = 1
690 690 x = dataOut.getTimeRange1()
691 691 y = dataOut.heightRange
692 692 z = dataOut.data_param[channelIndexList,paramIndex,:].copy()
693 693
694 694 zRange = dataOut.abscissaRange
695 695 nplots = z.shape[0] #Number of wind dimensions estimated
696 696 # thisDatetime = dataOut.datatime
697 697 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[1])
698 698 title = wintitle + " Parameters Plot" #: %s" %(thisDatetime.strftime("%d-%b-%Y"))
699 699 xlabel = ""
700 700 ylabel = "Range (Km)"
701 701
702 702 if onlyPositive:
703 703 colormap = "jet"
704 704 zmin = 0
705 705 else: colormap = "RdBu_r"
706 706
707 707 if not self.__isConfig:
708 708
709 709 self.setup(id=id,
710 710 nplots=nplots,
711 711 wintitle=wintitle,
712 712 showprofile=showprofile,
713 713 show=show)
714 714
715 715 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
716 716
717 717 if ymin == None: ymin = numpy.nanmin(y)
718 718 if ymax == None: ymax = numpy.nanmax(y)
719 719 if zmin == None: zmin = numpy.nanmin(zRange)
720 720 if zmax == None: zmax = numpy.nanmax(zRange)
721 721
722 722 if dataOut.SNR != None:
723 723 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
724 724 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
725 725
726 726 self.FTP_WEI = ftp_wei
727 727 self.EXP_CODE = exp_code
728 728 self.SUB_EXP_CODE = sub_exp_code
729 729 self.PLOT_POS = plot_pos
730 730
731 731 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
732 732 self.__isConfig = True
733 733 self.figfile = figfile
734 734
735 735 self.setWinTitle(title)
736 736
737 737 if ((self.xmax - x[1]) < (x[1]-x[0])):
738 738 x[1] = self.xmax
739 739
740 740 for i in range(nplots):
741 741 title = "%s Channel %d: %s" %(parameterName, dataOut.channelList[i]+1, thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
742 742
743 743 if ((dataOut.azimuth!=None) and (dataOut.zenith!=None)):
744 744 title = title + '_' + 'azimuth,zenith=%2.2f,%2.2f'%(dataOut.azimuth, dataOut.zenith)
745 745 axes = self.axesList[i*self.__nsubplots]
746 746 z1 = z[i,:].reshape((1,-1))
747 747 axes.pcolorbuffer(x, y, z1,
748 748 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zmin, zmax=zmax,
749 749 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,colormap=colormap,
750 750 ticksize=9, cblabel=zlabel, cbsize="1%")
751 751
752 752 self.draw()
753 753
754 754 if self.figfile == None:
755 755 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
756 756 self.figfile = self.getFilename(name = str_datetime)
757 757
758 758 if figpath != '':
759 759
760 760 self.counter_imagwr += 1
761 761 if (self.counter_imagwr>=wr_period):
762 762 # store png plot to local folder
763 763 self.saveFigure(figpath, self.figfile)
764 764 # store png plot to FTP server according to RT-Web format
765 765 name = self.getNameToFtp(thisDatetime, self.FTP_WEI, self.EXP_CODE, self.SUB_EXP_CODE, self.PLOT_CODE, self.PLOT_POS)
766 766 ftp_filename = os.path.join(figpath, name)
767 767 self.saveFigure(figpath, ftp_filename)
768 768
769 769 self.counter_imagwr = 0
770 770
771 771 if x[1] >= self.axesList[0].xmax:
772 772 self.counter_imagwr = wr_period
773 773 self.__isConfig = False
774 self.figfile = None
775
776
777 class SpectralFittingPlot(Figure):
778
779 __isConfig = None
780 __nsubplots = None
781
782 WIDTHPROF = None
783 HEIGHTPROF = None
784 PREFIX = 'prm'
785
786
787 N = None
788 ippSeconds = None
789
790 def __init__(self):
791 self.__isConfig = False
792 self.__nsubplots = 1
793
794 self.WIDTH = 450
795 self.HEIGHT = 250
796 self.WIDTHPROF = 0
797 self.HEIGHTPROF = 0
798
799 def getSubplots(self):
800
801 ncol = int(numpy.sqrt(self.nplots)+0.9)
802 nrow = int(self.nplots*1./ncol + 0.9)
803
804 return nrow, ncol
805
806 def setup(self, id, nplots, wintitle, showprofile=False, show=True):
807
808 showprofile = False
809 self.__showprofile = showprofile
810 self.nplots = nplots
811
812 ncolspan = 5
813 colspan = 4
814 if showprofile:
815 ncolspan = 5
816 colspan = 4
817 self.__nsubplots = 2
818
819 self.createFigure(id = id,
820 wintitle = wintitle,
821 widthplot = self.WIDTH + self.WIDTHPROF,
822 heightplot = self.HEIGHT + self.HEIGHTPROF,
823 show=show)
824
825 nrow, ncol = self.getSubplots()
826
827 counter = 0
828 for y in range(nrow):
829 for x in range(ncol):
830
831 if counter >= self.nplots:
832 break
833
834 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan, colspan, 1)
835
836 if showprofile:
837 self.addAxes(nrow, ncol*ncolspan, y, x*ncolspan+colspan, 1, 1)
838
839 counter += 1
840
841 def run(self, dataOut, id, cutHeight=None, fit=False, wintitle="", channelList=None, showprofile=True,
842 xmin=None, xmax=None, ymin=None, ymax=None,
843 save=False, figpath='./', figfile=None, show=True):
844
845 """
846
847 Input:
848 dataOut :
849 id :
850 wintitle :
851 channelList :
852 showProfile :
853 xmin : None,
854 xmax : None,
855 zmin : None,
856 zmax : None
857 """
858
859 if cutHeight==None:
860 h=270
861 heightindex = numpy.abs(cutHeight - dataOut.heightList).argmin()
862 cutHeight = dataOut.heightList[heightindex]
863
864 factor = dataOut.normFactor
865 x = dataOut.abscissaRange[:-1]
866 #y = dataOut.getHeiRange()
867
868 z = dataOut.data_pre[:,:,heightindex]/factor
869 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
870 avg = numpy.average(z, axis=1)
871 listChannels = z.shape[0]
872
873 #Reconstruct Function
874 if fit==True:
875 groupArray = dataOut.groupList
876 listChannels = groupArray.reshape((groupArray.size))
877 listChannels.sort()
878 spcFitLine = numpy.zeros(z.shape)
879 constants = dataOut.constants
880
881 nGroups = groupArray.shape[0]
882 nChannels = groupArray.shape[1]
883 nProfiles = z.shape[1]
884
885 for f in range(nGroups):
886 groupChann = groupArray[f,:]
887 p = dataOut.data_param[f,:,heightindex]
888 # p = numpy.array([ 89.343967,0.14036615,0.17086219,18.89835291,1.58388365,1.55099167])
889 fitLineAux = dataOut.library.modelFunction(p, constants)*nProfiles
890 fitLineAux = fitLineAux.reshape((nChannels,nProfiles))
891 spcFitLine[groupChann,:] = fitLineAux
892 # spcFitLine = spcFitLine/factor
893
894 z = z[listChannels,:]
895 spcFitLine = spcFitLine[listChannels,:]
896 spcFitLinedB = 10*numpy.log10(spcFitLine)
897
898 zdB = 10*numpy.log10(z)
899 #thisDatetime = dataOut.datatime
900 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[1])
901 title = wintitle + " Doppler Spectra: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
902 xlabel = "Velocity (m/s)"
903 ylabel = "Spectrum"
904
905 if not self.__isConfig:
906
907 nplots = listChannels.size
908
909 self.setup(id=id,
910 nplots=nplots,
911 wintitle=wintitle,
912 showprofile=showprofile,
913 show=show)
914
915 if xmin == None: xmin = numpy.nanmin(x)
916 if xmax == None: xmax = numpy.nanmax(x)
917 if ymin == None: ymin = numpy.nanmin(zdB)
918 if ymax == None: ymax = numpy.nanmax(zdB)+2
919
920 self.__isConfig = True
921
922 self.setWinTitle(title)
923 for i in range(self.nplots):
924 # title = "Channel %d: %4.2fdB" %(dataOut.channelList[i]+1, noisedB[i])
925 title = "Height %4.1f km\nChannel %d:" %(cutHeight, listChannels[i]+1)
926 axes = self.axesList[i*self.__nsubplots]
927 if fit == False:
928 axes.pline(x, zdB[i,:],
929 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
930 xlabel=xlabel, ylabel=ylabel, title=title
931 )
932 if fit == True:
933 fitline=spcFitLinedB[i,:]
934 y=numpy.vstack([zdB[i,:],fitline] )
935 legendlabels=['Data','Fitting']
936 axes.pmultilineyaxis(x, y,
937 xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax,
938 xlabel=xlabel, ylabel=ylabel, title=title,
939 legendlabels=legendlabels, marker=None,
940 linestyle='solid', grid='both')
941
942 self.draw()
943
944 if save:
945 date = thisDatetime.strftime("%Y%m%d_%H%M%S")
946 if figfile == None:
947 figfile = self.getFilename(name = date)
948
949 self.saveFigure(figpath, figfile)
950
951
952 class EWDriftsPlot(Figure):
953
954 __isConfig = None
955 __nsubplots = None
956
957 WIDTHPROF = None
958 HEIGHTPROF = None
959 PREFIX = 'drift'
960
961 def __init__(self):
962
963 self.timerange = 2*60*60
964 self.isConfig = False
965 self.__nsubplots = 1
966
967 self.WIDTH = 800
968 self.HEIGHT = 150
969 self.WIDTHPROF = 120
970 self.HEIGHTPROF = 0
971 self.counter_imagwr = 0
972
973 self.PLOT_CODE = 0
974 self.FTP_WEI = None
975 self.EXP_CODE = None
976 self.SUB_EXP_CODE = None
977 self.PLOT_POS = None
978 self.tmin = None
979 self.tmax = None
980
981 self.xmin = None
982 self.xmax = None
983
984 self.figfile = None
985
986 def getSubplots(self):
987
988 ncol = 1
989 nrow = self.nplots
990
991 return nrow, ncol
992
993 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
994
995 self.__showprofile = showprofile
996 self.nplots = nplots
997
998 ncolspan = 1
999 colspan = 1
1000
1001 self.createFigure(id = id,
1002 wintitle = wintitle,
1003 widthplot = self.WIDTH + self.WIDTHPROF,
1004 heightplot = self.HEIGHT + self.HEIGHTPROF,
1005 show=show)
1006
1007 nrow, ncol = self.getSubplots()
1008
1009 counter = 0
1010 for y in range(nrow):
1011 if counter >= self.nplots:
1012 break
1013
1014 self.addAxes(nrow, ncol*ncolspan, y, 0, colspan, 1)
1015 counter += 1
1016
1017 def run(self, dataOut, id, wintitle="", channelList=None,
1018 xmin=None, xmax=None, ymin=None, ymax=None, zmin=None, zmax=None,
1019 zmaxVertical = None, zminVertical = None, zmaxZonal = None, zminZonal = None,
1020 timerange=None, SNRthresh = -numpy.inf, SNRmin = None, SNRmax = None, SNR_1 = False,
1021 save=False, figpath='', lastone=0,figfile=None, ftp=False, wr_period=1, show=True,
1022 server=None, folder=None, username=None, password=None,
1023 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1024 """
1025
1026 Input:
1027 dataOut :
1028 id :
1029 wintitle :
1030 channelList :
1031 showProfile :
1032 xmin : None,
1033 xmax : None,
1034 ymin : None,
1035 ymax : None,
1036 zmin : None,
1037 zmax : None
1038 """
1039
1040 if channelList == None:
1041 channelIndexList = dataOut.channelIndexList
1042 else:
1043 channelIndexList = []
1044 for channel in channelList:
1045 if channel not in dataOut.channelList:
1046 raise ValueError, "Channel %d is not in dataOut.channelList"
1047 channelIndexList.append(dataOut.channelList.index(channel))
1048
1049 if timerange != None:
1050 self.timerange = timerange
1051
1052 tmin = None
1053 tmax = None
1054
1055 x = dataOut.getTimeRange1()
1056 # y = dataOut.heightRange
1057 y = dataOut.heightList
1058
1059 z = dataOut.data_output
1060 nplots = z.shape[0] #Number of wind dimensions estimated
1061 nplotsw = nplots
1062
1063 #If there is a SNR function defined
1064 if dataOut.SNR != None:
1065 nplots += 1
1066 SNR = dataOut.SNR
1067
1068 if SNR_1:
1069 SNR += 1
1070
1071 SNRavg = numpy.average(SNR, axis=0)
1072
1073 SNRdB = 10*numpy.log10(SNR)
1074 SNRavgdB = 10*numpy.log10(SNRavg)
1075
1076 ind = numpy.where(SNRavg < 10**(SNRthresh/10))[0]
1077
1078 for i in range(nplotsw):
1079 z[i,ind] = numpy.nan
1080
1081
1082 showprofile = False
1083 # thisDatetime = dataOut.datatime
1084 thisDatetime = datetime.datetime.utcfromtimestamp(dataOut.getTimeRange()[1])
1085 title = wintitle + " EW Drifts"
1086 xlabel = ""
1087 ylabel = "Height (Km)"
1088
1089 if not self.__isConfig:
1090
1091 self.setup(id=id,
1092 nplots=nplots,
1093 wintitle=wintitle,
1094 showprofile=showprofile,
1095 show=show)
1096
1097 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1098
1099 if ymin == None: ymin = numpy.nanmin(y)
1100 if ymax == None: ymax = numpy.nanmax(y)
1101
1102 if zmaxZonal == None: zmaxZonal = numpy.nanmax(abs(z[0,:]))
1103 if zminZonal == None: zminZonal = -zmaxZonal
1104 if zmaxVertical == None: zmaxVertical = numpy.nanmax(abs(z[1,:]))
1105 if zminVertical == None: zminVertical = -zmaxVertical
1106
1107 if dataOut.SNR != None:
1108 if SNRmin == None: SNRmin = numpy.nanmin(SNRavgdB)
1109 if SNRmax == None: SNRmax = numpy.nanmax(SNRavgdB)
1110
1111 self.FTP_WEI = ftp_wei
1112 self.EXP_CODE = exp_code
1113 self.SUB_EXP_CODE = sub_exp_code
1114 self.PLOT_POS = plot_pos
1115
1116 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1117 self.__isConfig = True
1118
1119
1120 self.setWinTitle(title)
1121
1122 if ((self.xmax - x[1]) < (x[1]-x[0])):
1123 x[1] = self.xmax
1124
1125 strWind = ['Zonal','Vertical']
1126 strCb = 'Velocity (m/s)'
1127 zmaxVector = [zmaxZonal, zmaxVertical]
1128 zminVector = [zminZonal, zminVertical]
1129
1130 for i in range(nplotsw):
1131
1132 title = "%s Drifts: %s" %(strWind[i], thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1133 axes = self.axesList[i*self.__nsubplots]
1134
1135 z1 = z[i,:].reshape((1,-1))
1136
1137 axes.pcolorbuffer(x, y, z1,
1138 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=zminVector[i], zmax=zmaxVector[i],
1139 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1140 ticksize=9, cblabel=strCb, cbsize="1%", colormap="RdBu_r")
1141
1142 if dataOut.SNR != None:
1143 i += 1
1144 if SNR_1:
1145 title = "Signal Noise Ratio + 1 (SNR+1): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1146 else:
1147 title = "Signal Noise Ratio (SNR): %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1148 axes = self.axesList[i*self.__nsubplots]
1149 SNRavgdB = SNRavgdB.reshape((1,-1))
1150
1151 axes.pcolorbuffer(x, y, SNRavgdB,
1152 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax, zmin=SNRmin, zmax=SNRmax,
1153 xlabel=xlabel, ylabel=ylabel, title=title, rti=True, XAxisAsTime=True,
1154 ticksize=9, cblabel='', cbsize="1%", colormap="jet")
1155
1156 self.draw()
1157
1158 if self.figfile == None:
1159 str_datetime = thisDatetime.strftime("%Y%m%d_%H%M%S")
1160 self.figfile = self.getFilename(name = str_datetime)
1161
1162 if figpath != '':
1163
1164 self.counter_imagwr += 1
1165 if (self.counter_imagwr>=wr_period):
1166 # store png plot to local folder
1167 self.saveFigure(figpath, self.figfile)
1168 # store png plot to FTP server according to RT-Web format
1169 name = self.getNameToFtp(thisDatetime, self.FTP_WEI, self.EXP_CODE, self.SUB_EXP_CODE, self.PLOT_CODE, self.PLOT_POS)
1170 ftp_filename = os.path.join(figpath, name)
1171 self.saveFigure(figpath, ftp_filename)
1172
1173 self.counter_imagwr = 0
1174
1175 if x[1] >= self.axesList[0].xmax:
1176 self.counter_imagwr = wr_period
1177 self.__isConfig = False
774 1178 self.figfile = None No newline at end of file
@@ -1,427 +1,427
1 1 import numpy
2 2 import datetime
3 3 import sys
4 4 import matplotlib
5 5
6 6 if 'linux' in sys.platform:
7 7 matplotlib.use("TKAgg")
8 8
9 9 if 'darwin' in sys.platform:
10 10 matplotlib.use("TKAgg")
11 11
12 12 import matplotlib.pyplot
13 13
14 14 from mpl_toolkits.axes_grid1 import make_axes_locatable
15 15 from matplotlib.ticker import *
16 16
17 17 ###########################################
18 18 #Actualizacion de las funciones del driver
19 19 ###########################################
20 20
21 21 def createFigure(id, wintitle, width, height, facecolor="w", show=True):
22 22
23 23 matplotlib.pyplot.ioff()
24 24 fig = matplotlib.pyplot.figure(num=id, facecolor=facecolor)
25 25 fig.canvas.manager.set_window_title(wintitle)
26 26 fig.canvas.manager.resize(width, height)
27 27 matplotlib.pyplot.ion()
28 28 if show:
29 29 matplotlib.pyplot.show()
30 30
31 31 return fig
32 32
33 33 def closeFigure(show=True):
34 34
35 35 matplotlib.pyplot.ioff()
36 36 if show:
37 37 matplotlib.pyplot.show()
38 38
39 39 return
40 40
41 41 def saveFigure(fig, filename):
42 42
43 43 matplotlib.pyplot.ioff()
44 44 fig.savefig(filename)
45 45 matplotlib.pyplot.ion()
46 46
47 47 def setWinTitle(fig, title):
48 48
49 49 fig.canvas.manager.set_window_title(title)
50 50
51 51 def setTitle(fig, title):
52 52
53 53 fig.suptitle(title)
54 54
55 55 def createAxes(fig, nrow, ncol, xpos, ypos, colspan, rowspan, polar=False):
56 56
57 57 matplotlib.pyplot.ioff()
58 58 matplotlib.pyplot.figure(fig.number)
59 59 axes = matplotlib.pyplot.subplot2grid((nrow, ncol),
60 60 (xpos, ypos),
61 61 colspan=colspan,
62 62 rowspan=rowspan,
63 63 polar=polar)
64 64
65 65 matplotlib.pyplot.ion()
66 66 return axes
67 67
68 68 def setAxesText(ax, text):
69 69
70 70 ax.annotate(text,
71 71 xy = (.1, .99),
72 72 xycoords = 'figure fraction',
73 73 horizontalalignment = 'left',
74 74 verticalalignment = 'top',
75 75 fontsize = 10)
76 76
77 77 def printLabels(ax, xlabel, ylabel, title):
78 78
79 79 ax.set_xlabel(xlabel, size=11)
80 80 ax.set_ylabel(ylabel, size=11)
81 81 ax.set_title(title, size=8)
82 82
83 83 def createPline(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='',
84 84 ticksize=9, xtick_visible=True, ytick_visible=True,
85 85 nxticks=4, nyticks=10,
86 86 grid=None,color='blue'):
87 87
88 88 """
89 89
90 90 Input:
91 91 grid : None, 'both', 'x', 'y'
92 92 """
93 93
94 94 matplotlib.pyplot.ioff()
95 95
96 96 ax.set_xlim([xmin,xmax])
97 97 ax.set_ylim([ymin,ymax])
98 98
99 99 printLabels(ax, xlabel, ylabel, title)
100 100
101 101 ######################################################
102 102 if (xmax-xmin)<=1:
103 103 xtickspos = numpy.linspace(xmin,xmax,nxticks)
104 104 xtickspos = numpy.array([float("%.1f"%i) for i in xtickspos])
105 105 ax.set_xticks(xtickspos)
106 106 else:
107 107 xtickspos = numpy.arange(nxticks)*int((xmax-xmin)/(nxticks)) + int(xmin)
108 108 # xtickspos = numpy.arange(nxticks)*float(xmax-xmin)/float(nxticks) + int(xmin)
109 109 ax.set_xticks(xtickspos)
110 110
111 111 for tick in ax.get_xticklabels():
112 112 tick.set_visible(xtick_visible)
113 113
114 114 for tick in ax.xaxis.get_major_ticks():
115 115 tick.label.set_fontsize(ticksize)
116 116
117 117 ######################################################
118 118 for tick in ax.get_yticklabels():
119 119 tick.set_visible(ytick_visible)
120 120
121 121 for tick in ax.yaxis.get_major_ticks():
122 122 tick.label.set_fontsize(ticksize)
123 123
124 124 ax.plot(x, y, color=color)
125 125 iplot = ax.lines[-1]
126 126
127 127 ######################################################
128 128 if '0.' in matplotlib.__version__[0:2]:
129 129 print "The matplotlib version has to be updated to 1.1 or newer"
130 130 return iplot
131 131
132 132 if '1.0.' in matplotlib.__version__[0:4]:
133 133 print "The matplotlib version has to be updated to 1.1 or newer"
134 134 return iplot
135 135
136 136 if grid != None:
137 137 ax.grid(b=True, which='major', axis=grid)
138 138
139 139 matplotlib.pyplot.tight_layout()
140 140
141 141 matplotlib.pyplot.ion()
142 142
143 143 return iplot
144 144
145 145 def set_linedata(ax, x, y, idline):
146 146
147 147 ax.lines[idline].set_data(x,y)
148 148
149 149 def pline(iplot, x, y, xlabel='', ylabel='', title=''):
150 150
151 151 ax = iplot.get_axes()
152 152
153 153 printLabels(ax, xlabel, ylabel, title)
154 154
155 155 set_linedata(ax, x, y, idline=0)
156 156
157 157 def addpline(ax, x, y, color, linestyle, lw):
158 158
159 159 ax.plot(x,y,color=color,linestyle=linestyle,lw=lw)
160 160
161 161
162 162 def createPcolor(ax, x, y, z, xmin, xmax, ymin, ymax, zmin, zmax,
163 163 xlabel='', ylabel='', title='', ticksize = 9,
164 164 colormap='jet',cblabel='', cbsize="5%",
165 165 XAxisAsTime=False):
166 166
167 167 matplotlib.pyplot.ioff()
168 168
169 169 divider = make_axes_locatable(ax)
170 170 ax_cb = divider.new_horizontal(size=cbsize, pad=0.05)
171 171 fig = ax.get_figure()
172 172 fig.add_axes(ax_cb)
173 173
174 174 ax.set_xlim([xmin,xmax])
175 175 ax.set_ylim([ymin,ymax])
176 176
177 177 printLabels(ax, xlabel, ylabel, title)
178 178
179 179 imesh = ax.pcolormesh(x,y,z.T, vmin=zmin, vmax=zmax, cmap=matplotlib.pyplot.get_cmap(colormap))
180 180 cb = matplotlib.pyplot.colorbar(imesh, cax=ax_cb)
181 181 cb.set_label(cblabel)
182 182
183 183 # for tl in ax_cb.get_yticklabels():
184 184 # tl.set_visible(True)
185 185
186 186 for tick in ax.yaxis.get_major_ticks():
187 187 tick.label.set_fontsize(ticksize)
188 188
189 189 for tick in ax.xaxis.get_major_ticks():
190 190 tick.label.set_fontsize(ticksize)
191 191
192 192 for tick in cb.ax.get_yticklabels():
193 193 tick.set_fontsize(ticksize)
194 194
195 195 ax_cb.yaxis.tick_right()
196 196
197 197 if '0.' in matplotlib.__version__[0:2]:
198 198 print "The matplotlib version has to be updated to 1.1 or newer"
199 199 return imesh
200 200
201 201 if '1.0.' in matplotlib.__version__[0:4]:
202 202 print "The matplotlib version has to be updated to 1.1 or newer"
203 203 return imesh
204 204
205 205 matplotlib.pyplot.tight_layout()
206 206
207 207 if XAxisAsTime:
208 208
209 209 func = lambda x, pos: ('%s') %(datetime.datetime.utcfromtimestamp(x).strftime("%H:%M:%S"))
210 210 ax.xaxis.set_major_formatter(FuncFormatter(func))
211 211 ax.xaxis.set_major_locator(LinearLocator(7))
212 212
213 213 matplotlib.pyplot.ion()
214 214 return imesh
215 215
216 216 def pcolor(imesh, z, xlabel='', ylabel='', title=''):
217 217
218 218 z = z.T
219 219
220 220 ax = imesh.get_axes()
221 221
222 222 printLabels(ax, xlabel, ylabel, title)
223 223
224 224 imesh.set_array(z.ravel())
225 225
226 226 def addpcolor(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', colormap='jet'):
227 227
228 228 printLabels(ax, xlabel, ylabel, title)
229 229
230 230 ax.pcolormesh(x,y,z.T,vmin=zmin,vmax=zmax, cmap=matplotlib.pyplot.get_cmap(colormap))
231 231
232 232 def addpcolorbuffer(ax, x, y, z, zmin, zmax, xlabel='', ylabel='', title='', colormap='jet'):
233 233
234 234 printLabels(ax, xlabel, ylabel, title)
235 235
236 236 ax.collections.remove(ax.collections[0])
237 237
238 238 ax.pcolormesh(x,y,z.T,vmin=zmin,vmax=zmax, cmap=matplotlib.pyplot.get_cmap(colormap))
239 239
240 240 def createPmultiline(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='', legendlabels=None,
241 241 ticksize=9, xtick_visible=True, ytick_visible=True,
242 242 nxticks=4, nyticks=10,
243 243 grid=None):
244 244
245 245 """
246 246
247 247 Input:
248 248 grid : None, 'both', 'x', 'y'
249 249 """
250 250
251 251 matplotlib.pyplot.ioff()
252 252
253 253 lines = ax.plot(x.T, y)
254 254 leg = ax.legend(lines, legendlabels, loc='upper right')
255 255 leg.get_frame().set_alpha(0.5)
256 256 ax.set_xlim([xmin,xmax])
257 257 ax.set_ylim([ymin,ymax])
258 258 printLabels(ax, xlabel, ylabel, title)
259 259
260 260 xtickspos = numpy.arange(nxticks)*int((xmax-xmin)/(nxticks)) + int(xmin)
261 261 ax.set_xticks(xtickspos)
262 262
263 263 for tick in ax.get_xticklabels():
264 264 tick.set_visible(xtick_visible)
265 265
266 266 for tick in ax.xaxis.get_major_ticks():
267 267 tick.label.set_fontsize(ticksize)
268 268
269 269 for tick in ax.get_yticklabels():
270 270 tick.set_visible(ytick_visible)
271 271
272 272 for tick in ax.yaxis.get_major_ticks():
273 273 tick.label.set_fontsize(ticksize)
274 274
275 275 iplot = ax.lines[-1]
276 276
277 277 if '0.' in matplotlib.__version__[0:2]:
278 278 print "The matplotlib version has to be updated to 1.1 or newer"
279 279 return iplot
280 280
281 281 if '1.0.' in matplotlib.__version__[0:4]:
282 282 print "The matplotlib version has to be updated to 1.1 or newer"
283 283 return iplot
284 284
285 285 if grid != None:
286 286 ax.grid(b=True, which='major', axis=grid)
287 287
288 288 matplotlib.pyplot.tight_layout()
289 289
290 290 matplotlib.pyplot.ion()
291 291
292 292 return iplot
293 293
294 294
295 295 def pmultiline(iplot, x, y, xlabel='', ylabel='', title=''):
296 296
297 297 ax = iplot.get_axes()
298 298
299 299 printLabels(ax, xlabel, ylabel, title)
300 300
301 301 for i in range(len(ax.lines)):
302 302 line = ax.lines[i]
303 303 line.set_data(x[i,:],y)
304 304
305 305 def createPmultilineYAxis(ax, x, y, xmin, xmax, ymin, ymax, xlabel='', ylabel='', title='', legendlabels=None,
306 306 ticksize=9, xtick_visible=True, ytick_visible=True,
307 307 nxticks=4, nyticks=10, marker='.', markersize=10, linestyle="None",
308 308 grid=None, XAxisAsTime=False):
309 309
310 310 """
311 311
312 312 Input:
313 313 grid : None, 'both', 'x', 'y'
314 314 """
315 315
316 316 matplotlib.pyplot.ioff()
317 317
318 318 # lines = ax.plot(x, y.T, marker=marker,markersize=markersize,linestyle=linestyle)
319 lines = ax.plot(x, y.T, linestyle='None', marker='.', markersize=markersize)
319 lines = ax.plot(x, y.T, linestyle=linestyle, marker=marker, markersize=markersize)
320 320 leg = ax.legend(lines, legendlabels, loc='upper left', bbox_to_anchor=(1.01, 1.00), numpoints=1, handlelength=1.5, \
321 321 handletextpad=0.5, borderpad=0.5, labelspacing=0.5, borderaxespad=0.)
322 322
323 323 for label in leg.get_texts(): label.set_fontsize(9)
324 324
325 325 ax.set_xlim([xmin,xmax])
326 326 ax.set_ylim([ymin,ymax])
327 327 printLabels(ax, xlabel, ylabel, title)
328 328
329 329 # xtickspos = numpy.arange(nxticks)*int((xmax-xmin)/(nxticks)) + int(xmin)
330 330 # ax.set_xticks(xtickspos)
331 331
332 332 for tick in ax.get_xticklabels():
333 333 tick.set_visible(xtick_visible)
334 334
335 335 for tick in ax.xaxis.get_major_ticks():
336 336 tick.label.set_fontsize(ticksize)
337 337
338 338 for tick in ax.get_yticklabels():
339 339 tick.set_visible(ytick_visible)
340 340
341 341 for tick in ax.yaxis.get_major_ticks():
342 342 tick.label.set_fontsize(ticksize)
343 343
344 344 iplot = ax.lines[-1]
345 345
346 346 if '0.' in matplotlib.__version__[0:2]:
347 347 print "The matplotlib version has to be updated to 1.1 or newer"
348 348 return iplot
349 349
350 350 if '1.0.' in matplotlib.__version__[0:4]:
351 351 print "The matplotlib version has to be updated to 1.1 or newer"
352 352 return iplot
353 353
354 354 if grid != None:
355 355 ax.grid(b=True, which='major', axis=grid)
356 356
357 357 matplotlib.pyplot.tight_layout()
358 358
359 359 if XAxisAsTime:
360 360
361 361 func = lambda x, pos: ('%s') %(datetime.datetime.utcfromtimestamp(x).strftime("%H:%M:%S"))
362 362 ax.xaxis.set_major_formatter(FuncFormatter(func))
363 363 ax.xaxis.set_major_locator(LinearLocator(7))
364 364
365 365 matplotlib.pyplot.ion()
366 366
367 367 return iplot
368 368
369 369 def pmultilineyaxis(iplot, x, y, xlabel='', ylabel='', title=''):
370 370
371 371 ax = iplot.get_axes()
372 372
373 373 printLabels(ax, xlabel, ylabel, title)
374 374
375 375 for i in range(len(ax.lines)):
376 376 line = ax.lines[i]
377 377 line.set_data(x,y[i,:])
378 378
379 379 def createPolar(ax, x, y,
380 380 xlabel='', ylabel='', title='', ticksize = 9,
381 381 colormap='jet',cblabel='', cbsize="5%",
382 382 XAxisAsTime=False):
383 383
384 384 matplotlib.pyplot.ioff()
385 385
386 386 ax.plot(x,y,'bo', markersize=5)
387 387 # ax.set_rmax(90)
388 388 ax.set_ylim(0,90)
389 389 ax.set_yticks(numpy.arange(0,90,20))
390 390 ax.text(0, -110, ylabel, rotation='vertical', va ='center', ha = 'center' ,size='11')
391 391 # ax.text(100, 100, 'example', ha='left', va='center', rotation='vertical')
392 392 printLabels(ax, xlabel, '', title)
393 393 iplot = ax.lines[-1]
394 394
395 395 if '0.' in matplotlib.__version__[0:2]:
396 396 print "The matplotlib version has to be updated to 1.1 or newer"
397 397 return iplot
398 398
399 399 if '1.0.' in matplotlib.__version__[0:4]:
400 400 print "The matplotlib version has to be updated to 1.1 or newer"
401 401 return iplot
402 402
403 403 # if grid != None:
404 404 # ax.grid(b=True, which='major', axis=grid)
405 405
406 406 matplotlib.pyplot.tight_layout()
407 407
408 408 matplotlib.pyplot.ion()
409 409
410 410
411 411 return iplot
412 412
413 413 def polar(iplot, x, y, xlabel='', ylabel='', title=''):
414 414
415 415 ax = iplot.get_axes()
416 416
417 417 # ax.text(0, -110, ylabel, rotation='vertical', va ='center', ha = 'center',size='11')
418 418 printLabels(ax, xlabel, '', title)
419 419
420 420 set_linedata(ax, x, y, idline=0)
421 421
422 422 def draw(fig):
423 423
424 424 if type(fig) == 'int':
425 425 raise ValueError, "This parameter should be of tpye matplotlib figure"
426 426
427 427 fig.canvas.draw()
@@ -1,1539 +1,1749
1 1 import numpy
2 2 import math
3 3 from scipy import optimize
4 4 from scipy import interpolate
5 5 from scipy import signal
6 6 from scipy import stats
7 7 import re
8 8 import datetime
9 9 import copy
10
10 import sys
11 import importlib
12 import itertools
11 13
12 14 from jroproc_base import ProcessingUnit, Operation
13 15 from model.data.jrodata import Parameters
14 16
15 17
16 18 class ParametersProc(ProcessingUnit):
17 19
18 20 nSeconds = None
19 21
20 22 def __init__(self):
21 23 ProcessingUnit.__init__(self)
22 24
23 25 self.objectDict = {}
24 26 self.buffer = None
25 27 self.firstdatatime = None
26 28 self.profIndex = 0
27 29 self.dataOut = Parameters()
28 30
29 31 def __updateObjFromInput(self):
30 32
31 33 self.dataOut.inputUnit = self.dataIn.type
32 34
33 35 self.dataOut.timeZone = self.dataIn.timeZone
34 36 self.dataOut.dstFlag = self.dataIn.dstFlag
35 37 self.dataOut.errorCount = self.dataIn.errorCount
36 38 self.dataOut.useLocalTime = self.dataIn.useLocalTime
37 39
38 40 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
39 41 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
40 42 self.dataOut.channelList = self.dataIn.channelList
41 43 self.dataOut.heightList = self.dataIn.heightList
42 44 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
43 45 # self.dataOut.nHeights = self.dataIn.nHeights
44 46 # self.dataOut.nChannels = self.dataIn.nChannels
45 47 self.dataOut.nBaud = self.dataIn.nBaud
46 48 self.dataOut.nCode = self.dataIn.nCode
47 49 self.dataOut.code = self.dataIn.code
48 50 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
49 51 self.dataOut.flagTimeBlock = self.dataIn.flagTimeBlock
50 52 self.dataOut.utctime = self.firstdatatime
51 53 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
52 54 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
53 55 # self.dataOut.nCohInt = self.dataIn.nCohInt
54 56 # self.dataOut.nIncohInt = 1
55 57 self.dataOut.ippSeconds = self.dataIn.ippSeconds
56 58 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
57 59 self.dataOut.timeInterval = self.dataIn.timeInterval
58 60 self.dataOut.heightRange = self.dataIn.getHeiRange()
59 61 self.dataOut.frequency = self.dataIn.frequency
60 62
61 63 def run(self, nSeconds = None, nProfiles = None):
62 64
63 self.dataOut.flagNoData = True
65
64 66
65 67 if self.firstdatatime == None:
66 68 self.firstdatatime = self.dataIn.utctime
67 69
68 70 #---------------------- Voltage Data ---------------------------
69 71
70 72 if self.dataIn.type == "Voltage":
73 self.dataOut.flagNoData = True
71 74 if nSeconds != None:
72 75 self.nSeconds = nSeconds
73 76 self.nProfiles= int(numpy.floor(nSeconds/(self.dataIn.ippSeconds*self.dataIn.nCohInt)))
74 77
75 78 if self.buffer == None:
76 79 self.buffer = numpy.zeros((self.dataIn.nChannels,
77 80 self.nProfiles,
78 81 self.dataIn.nHeights),
79 82 dtype='complex')
80 83
81 84 self.buffer[:,self.profIndex,:] = self.dataIn.data.copy()
82 85 self.profIndex += 1
83 86
84 87 if self.profIndex == self.nProfiles:
85 88
86 89 self.__updateObjFromInput()
87 90 self.dataOut.data_pre = self.buffer.copy()
88 91 self.dataOut.paramInterval = nSeconds
89 92 self.dataOut.flagNoData = False
90 93
91 94 self.buffer = None
92 95 self.firstdatatime = None
93 96 self.profIndex = 0
94 97 return
95 98
96 99 #---------------------- Spectra Data ---------------------------
97 100
98 101 if self.dataIn.type == "Spectra":
99 102 self.dataOut.data_pre = self.dataIn.data_spc.copy()
100 103 self.dataOut.abscissaRange = self.dataIn.getVelRange(1)
101 104 self.dataOut.noise = self.dataIn.getNoise()
102 105 self.dataOut.normFactor = self.dataIn.normFactor
106 self.dataOut.flagNoData = False
103 107
104 108 #---------------------- Correlation Data ---------------------------
105 109
106 110 if self.dataIn.type == "Correlation":
107 111 lagRRange = self.dataIn.lagR
108 112 indR = numpy.where(lagRRange == 0)[0][0]
109 113
110 114 self.dataOut.data_pre = self.dataIn.data_corr.copy()[:,:,indR,:]
111 115 self.dataOut.abscissaRange = self.dataIn.getLagTRange(1)
112 116 self.dataOut.noise = self.dataIn.noise
113 117 self.dataOut.normFactor = self.dataIn.normFactor
114 118 self.dataOut.SNR = self.dataIn.SNR
115 self.dataOut.pairsList = self.dataIn.pairsList
119 self.dataOut.groupList = self.dataIn.pairsList
120 self.dataOut.flagNoData = False
116 121
117 122
118 123 self.__updateObjFromInput()
119 self.dataOut.flagNoData = False
120 124 self.firstdatatime = None
121 125 self.dataOut.initUtcTime = self.dataIn.ltctime
122 self.dataOut.windsInterval = self.dataIn.timeInterval
126 self.dataOut.outputInterval = self.dataIn.timeInterval
123 127
124 128 #------------------- Get Moments ----------------------------------
125 129 def GetMoments(self, channelList = None):
126 130 '''
127 131 Function GetMoments()
128 132
129 133 Input:
130 134 channelList : simple channel list to select e.g. [2,3,7]
131 135 self.dataOut.data_pre
132 136 self.dataOut.abscissaRange
133 137 self.dataOut.noise
134 138
135 139 Affected:
136 140 self.dataOut.data_param
137 141 self.dataOut.SNR
138 142
139 143 '''
140 144 data = self.dataOut.data_pre
141 145 absc = self.dataOut.abscissaRange[:-1]
142 146 noise = self.dataOut.noise
143 147
144 148 data_param = numpy.zeros((data.shape[0], 4, data.shape[2]))
145 149
146 150 if channelList== None:
147 151 channelList = self.dataIn.channelList
148 152 self.dataOut.channelList = channelList
149 153
150 154 for ind in channelList:
151 155 data_param[ind,:,:] = self.__calculateMoments(data[ind,:,:], absc, noise[ind])
152 156
153 157 self.dataOut.data_param = data_param[:,1:,:]
154 158 self.dataOut.SNR = data_param[:,0]
155 159 return
156 160
157 161 def __calculateMoments(self, oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
158 162
159 163 if (nicoh == None): nicoh = 1
160 164 if (graph == None): graph = 0
161 165 if (smooth == None): smooth = 0
162 166 elif (self.smooth < 3): smooth = 0
163 167
164 168 if (type1 == None): type1 = 0
165 169 if (fwindow == None): fwindow = numpy.zeros(oldfreq.size) + 1
166 170 if (snrth == None): snrth = -3
167 171 if (dc == None): dc = 0
168 172 if (aliasing == None): aliasing = 0
169 173 if (oldfd == None): oldfd = 0
170 174 if (wwauto == None): wwauto = 0
171 175
172 176 if (n0 < 1.e-20): n0 = 1.e-20
173 177
174 178 freq = oldfreq
175 179 vec_power = numpy.zeros(oldspec.shape[1])
176 180 vec_fd = numpy.zeros(oldspec.shape[1])
177 181 vec_w = numpy.zeros(oldspec.shape[1])
178 182 vec_snr = numpy.zeros(oldspec.shape[1])
179 183
180 184 for ind in range(oldspec.shape[1]):
181 185
182 186 spec = oldspec[:,ind]
183 187 aux = spec*fwindow
184 188 max_spec = aux.max()
185 189 m = list(aux).index(max_spec)
186 190
187 191 #Smooth
188 192 if (smooth == 0): spec2 = spec
189 193 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
190 194
191 195 # Calculo de Momentos
192 196 bb = spec2[range(m,spec2.size)]
193 197 bb = (bb<n0).nonzero()
194 198 bb = bb[0]
195 199
196 200 ss = spec2[range(0,m + 1)]
197 201 ss = (ss<n0).nonzero()
198 202 ss = ss[0]
199 203
200 204 if (bb.size == 0):
201 205 bb0 = spec.size - 1 - m
202 206 else:
203 207 bb0 = bb[0] - 1
204 208 if (bb0 < 0):
205 209 bb0 = 0
206 210
207 211 if (ss.size == 0): ss1 = 1
208 212 else: ss1 = max(ss) + 1
209 213
210 214 if (ss1 > m): ss1 = m
211 215
212 216 valid = numpy.asarray(range(int(m + bb0 - ss1 + 1))) + ss1
213 217 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
214 218 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
215 219 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
216 220 snr = (spec2.mean()-n0)/n0
217 221
218 222 if (snr < 1.e-20) :
219 223 snr = 1.e-20
220 224
221 225 vec_power[ind] = power
222 226 vec_fd[ind] = fd
223 227 vec_w[ind] = w
224 228 vec_snr[ind] = snr
225 229
226 230 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
227 231 return moments
228 232
229 233 #------------------- Get Lags ----------------------------------
230 234
231 235 def GetLags(self):
232 236 '''
233 237 Function GetMoments()
234 238
235 239 Input:
236 240 self.dataOut.data_pre
237 241 self.dataOut.abscissaRange
238 242 self.dataOut.noise
239 243 self.dataOut.normFactor
240 244 self.dataOut.SNR
241 self.dataOut.pairsList
245 self.dataOut.groupList
242 246 self.dataOut.nChannels
243 247
244 248 Affected:
245 249 self.dataOut.data_param
246 250
247 251 '''
248 252 data = self.dataOut.data_pre
249 253 normFactor = self.dataOut.normFactor
250 254 nHeights = self.dataOut.nHeights
251 255 absc = self.dataOut.abscissaRange[:-1]
252 256 noise = self.dataOut.noise
253 257 SNR = self.dataOut.SNR
254 pairsList = self.dataOut.pairsList
258 pairsList = self.dataOut.groupList
255 259 nChannels = self.dataOut.nChannels
256 260 pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
257 261 self.dataOut.data_param = numpy.zeros((len(pairsCrossCorr)*2 + 1, nHeights))
258 262
259 263 dataNorm = numpy.abs(data)
260 264 for l in range(len(pairsList)):
261 265 dataNorm[l,:,:] = dataNorm[l,:,:]/normFactor[l,:]
262 266
263 267 self.dataOut.data_param[:-1,:] = self.__calculateTaus(dataNorm, pairsCrossCorr, pairsAutoCorr, absc)
264 268 self.dataOut.data_param[-1,:] = self.__calculateLag1Phase(data, pairsAutoCorr, absc)
265 269 return
266 270
267 271 def __getPairsAutoCorr(self, pairsList, nChannels):
268 272
269 273 pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
270 274
271 275 for l in range(len(pairsList)):
272 276 firstChannel = pairsList[l][0]
273 277 secondChannel = pairsList[l][1]
274 278
275 279 #Obteniendo pares de Autocorrelacion
276 280 if firstChannel == secondChannel:
277 281 pairsAutoCorr[firstChannel] = int(l)
278 282
279 283 pairsAutoCorr = pairsAutoCorr.astype(int)
280 284
281 285 pairsCrossCorr = range(len(pairsList))
282 286 pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
283 287
284 288 return pairsAutoCorr, pairsCrossCorr
285 289
286 290 def __calculateTaus(self, data, pairsCrossCorr, pairsAutoCorr, lagTRange):
287 291
288 292 Pt0 = data.shape[1]/2
289 293 #Funcion de Autocorrelacion
290 294 dataAutoCorr = stats.nanmean(data[pairsAutoCorr,:,:], axis = 0)
291 295
292 296 #Obtencion Indice de TauCross
293 297 indCross = data[pairsCrossCorr,:,:].argmax(axis = 1)
294 298 #Obtencion Indice de TauAuto
295 299 indAuto = numpy.zeros(indCross.shape,dtype = 'int')
296 300 CCValue = data[pairsCrossCorr,Pt0,:]
297 301 for i in range(pairsCrossCorr.size):
298 302 indAuto[i,:] = numpy.abs(dataAutoCorr - CCValue[i,:]).argmin(axis = 0)
299 303
300 304 #Obtencion de TauCross y TauAuto
301 305 tauCross = lagTRange[indCross]
302 306 tauAuto = lagTRange[indAuto]
303 307
304 308 Nan1, Nan2 = numpy.where(tauCross == lagTRange[0])
305 309
306 310 tauCross[Nan1,Nan2] = numpy.nan
307 311 tauAuto[Nan1,Nan2] = numpy.nan
308 312 tau = numpy.vstack((tauCross,tauAuto))
309 313
310 314 return tau
311 315
312 316 def __calculateLag1Phase(self, data, pairs, lagTRange):
313 317 data1 = stats.nanmean(data[pairs,:,:], axis = 0)
314 318 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
315 319
316 320 phase = numpy.angle(data1[lag1,:])
317 321
318 322 return phase
319 323 #------------------- Detect Meteors ------------------------------
320 324
321 325 def DetectMeteors(self, hei_ref = None, tauindex = 0,
322 326 predefinedPhaseShifts = None, centerReceiverIndex = 2,
323 327 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
324 328 noise_timeStep = 4, noise_multiple = 4,
325 329 multDet_timeLimit = 1, multDet_rangeLimit = 3,
326 330 phaseThresh = 20, SNRThresh = 8,
327 331 hmin = 70, hmax=110, azimuth = 0) :
328 332
329 333 '''
330 334 Function DetectMeteors()
331 335 Project developed with paper:
332 336 HOLDSWORTH ET AL. 2004
333 337
334 338 Input:
335 339 self.dataOut.data_pre
336 340
337 341 centerReceiverIndex: From the channels, which is the center receiver
338 342
339 343 hei_ref: Height reference for the Beacon signal extraction
340 344 tauindex:
341 345 predefinedPhaseShifts: Predefined phase offset for the voltge signals
342 346
343 347 cohDetection: Whether to user Coherent detection or not
344 348 cohDet_timeStep: Coherent Detection calculation time step
345 349 cohDet_thresh: Coherent Detection phase threshold to correct phases
346 350
347 351 noise_timeStep: Noise calculation time step
348 352 noise_multiple: Noise multiple to define signal threshold
349 353
350 354 multDet_timeLimit: Multiple Detection Removal time limit in seconds
351 355 multDet_rangeLimit: Multiple Detection Removal range limit in km
352 356
353 357 phaseThresh: Maximum phase difference between receiver to be consider a meteor
354 358 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
355 359
356 360 hmin: Minimum Height of the meteor to use it in the further wind estimations
357 361 hmax: Maximum Height of the meteor to use it in the further wind estimations
358 362 azimuth: Azimuth angle correction
359 363
360 364 Affected:
361 365 self.dataOut.data_param
362 366
363 367 Rejection Criteria (Errors):
364 368 0: No error; analysis OK
365 369 1: SNR < SNR threshold
366 370 2: angle of arrival (AOA) ambiguously determined
367 371 3: AOA estimate not feasible
368 372 4: Large difference in AOAs obtained from different antenna baselines
369 373 5: echo at start or end of time series
370 374 6: echo less than 5 examples long; too short for analysis
371 375 7: echo rise exceeds 0.3s
372 376 8: echo decay time less than twice rise time
373 377 9: large power level before echo
374 378 10: large power level after echo
375 379 11: poor fit to amplitude for estimation of decay time
376 380 12: poor fit to CCF phase variation for estimation of radial drift velocity
377 381 13: height unresolvable echo: not valid height within 70 to 110 km
378 382 14: height ambiguous echo: more then one possible height within 70 to 110 km
379 383 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
380 384 16: oscilatory echo, indicating event most likely not an underdense echo
381 385
382 386 17: phase difference in meteor Reestimation
383 387
384 388 Data Storage:
385 389 Meteors for Wind Estimation (8):
386 390 Day Hour | Range Height
387 391 Azimuth Zenith errorCosDir
388 392 VelRad errorVelRad
389 393 TypeError
390 394
391 395 '''
392 396 #Get Beacon signal
393 397 newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
394 398
395 399 if hei_ref != None:
396 400 newheis = numpy.where(self.dataOut.heightList>hei_ref)
397 401
398 402 heiRang = self.dataOut.getHeiRange()
399 403 #Pairs List
400 404 pairslist = []
401 405 nChannel = self.dataOut.nChannels
402 406 for i in range(nChannel):
403 407 if i != centerReceiverIndex:
404 408 pairslist.append((centerReceiverIndex,i))
405 409
406 410 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
407 411 # see if the user put in pre defined phase shifts
408 412 voltsPShift = self.dataOut.data_pre.copy()
409 413
410 414 if predefinedPhaseShifts != None:
411 415 hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
412 416 else:
413 417 #get hardware phase shifts using beacon signal
414 418 hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
415 419 hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
416 420
417 421 voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
418 422 for i in range(self.dataOut.data_pre.shape[0]):
419 423 voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
420 424 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
421 425
422 426 #Remove DC
423 427 voltsDC = numpy.mean(voltsPShift,1)
424 428 voltsDC = numpy.mean(voltsDC,1)
425 429 for i in range(voltsDC.shape[0]):
426 430 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
427 431
428 432 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
429 433 voltsPShift = voltsPShift[:,:,:newheis[0][0]]
430 434
431 435 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
432 436 #Coherent Detection
433 437 if cohDetection:
434 438 #use coherent detection to get the net power
435 439 cohDet_thresh = cohDet_thresh*numpy.pi/180
436 440 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, self.dataOut.timeInterval, pairslist, cohDet_thresh)
437 441
438 442 #Non-coherent detection!
439 443 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
440 444 #********** END OF COH/NON-COH POWER CALCULATION**********************
441 445
442 446 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
443 447 #Get noise
444 448 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, self.dataOut.timeInterval)
445 449 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
446 450 #Get signal threshold
447 451 signalThresh = noise_multiple*noise
448 452 #Meteor echoes detection
449 453 listMeteors = self.__findMeteors(powerNet, signalThresh)
450 454 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
451 455
452 456 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
453 457 #Parameters
454 458 heiRange = self.dataOut.getHeiRange()
455 459 rangeInterval = heiRange[1] - heiRange[0]
456 460 rangeLimit = multDet_rangeLimit/rangeInterval
457 461 timeLimit = multDet_timeLimit/self.dataOut.timeInterval
458 462 #Multiple detection removals
459 463 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
460 464 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
461 465
462 466 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
463 467 #Parameters
464 468 phaseThresh = phaseThresh*numpy.pi/180
465 469 thresh = [phaseThresh, noise_multiple, SNRThresh]
466 470 #Meteor reestimation (Errors N 1, 6, 12, 17)
467 471 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist, thresh, noise, self.dataOut.timeInterval, self.dataOut.frequency)
468 472 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
469 473 #Estimation of decay times (Errors N 7, 8, 11)
470 474 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, self.dataOut.timeInterval, self.dataOut.frequency)
471 475 #******************* END OF METEOR REESTIMATION *******************
472 476
473 477 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
474 478 #Calculating Radial Velocity (Error N 15)
475 479 radialStdThresh = 10
476 480 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist, self.dataOut.timeInterval)
477 481
478 482 if len(listMeteors4) > 0:
479 483 #Setting New Array
480 484 date = repr(self.dataOut.datatime)
481 485 arrayMeteors4, arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
482 486
483 487 #Calculate AOA (Error N 3, 4)
484 488 #JONES ET AL. 1998
485 489 AOAthresh = numpy.pi/8
486 490 error = arrayParameters[:,-1]
487 491 phases = -arrayMeteors4[:,9:13]
488 492 pairsList = []
489 493 pairsList.append((0,3))
490 494 pairsList.append((1,2))
491 495 arrayParameters[:,4:7], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, error, AOAthresh, azimuth)
492 496
493 497 #Calculate Heights (Error N 13 and 14)
494 498 error = arrayParameters[:,-1]
495 499 Ranges = arrayParameters[:,2]
496 500 zenith = arrayParameters[:,5]
497 501 arrayParameters[:,3], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
498 502 #********************* END OF PARAMETERS CALCULATION **************************
499 503
500 504 #***************************+ SAVE DATA IN HDF5 FORMAT **********************
501 505 self.dataOut.data_param = arrayParameters
502 506
503 507 return
504 508
505 509 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
506 510
507 511 minIndex = min(newheis[0])
508 512 maxIndex = max(newheis[0])
509 513
510 514 voltage = voltage0[:,:,minIndex:maxIndex+1]
511 515 nLength = voltage.shape[1]/n
512 516 nMin = 0
513 517 nMax = 0
514 518 phaseOffset = numpy.zeros((len(pairslist),n))
515 519
516 520 for i in range(n):
517 521 nMax += nLength
518 522 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
519 523 phaseCCF = numpy.mean(phaseCCF, axis = 2)
520 524 phaseOffset[:,i] = phaseCCF.transpose()
521 525 nMin = nMax
522 526 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
523 527
524 528 #Remove Outliers
525 529 factor = 2
526 530 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
527 531 dw = numpy.std(wt,axis = 1)
528 532 dw = dw.reshape((dw.size,1))
529 533 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
530 534 phaseOffset[ind] = numpy.nan
531 535 phaseOffset = stats.nanmean(phaseOffset, axis=1)
532 536
533 537 return phaseOffset
534 538
535 539 def __shiftPhase(self, data, phaseShift):
536 540 #this will shift the phase of a complex number
537 541 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
538 542 return dataShifted
539 543
540 544 def __estimatePhaseDifference(self, array, pairslist):
541 545 nChannel = array.shape[0]
542 546 nHeights = array.shape[2]
543 547 numPairs = len(pairslist)
544 548 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
545 549 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
546 550
547 551 #Correct phases
548 552 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
549 553 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
550 554
551 555 if indDer[0].shape[0] > 0:
552 556 for i in range(indDer[0].shape[0]):
553 557 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
554 558 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
555 559
556 560 # for j in range(numSides):
557 561 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
558 562 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
559 563 #
560 564 #Linear
561 565 phaseInt = numpy.zeros((numPairs,1))
562 566 angAllCCF = phaseCCF[:,[0,1,3,4],0]
563 567 for j in range(numPairs):
564 568 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
565 569 phaseInt[j] = fit[1]
566 570 #Phase Differences
567 571 phaseDiff = phaseInt - phaseCCF[:,2,:]
568 572 phaseArrival = phaseInt.reshape(phaseInt.size)
569 573
570 574 #Dealias
571 575 indAlias = numpy.where(phaseArrival > numpy.pi)
572 576 phaseArrival[indAlias] -= 2*numpy.pi
573 577 indAlias = numpy.where(phaseArrival < -numpy.pi)
574 578 phaseArrival[indAlias] += 2*numpy.pi
575 579
576 580 return phaseDiff, phaseArrival
577 581
578 582 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
579 583 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
580 584 #find the phase shifts of each channel over 1 second intervals
581 585 #only look at ranges below the beacon signal
582 586 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
583 587 numBlocks = int(volts.shape[1]/numProfPerBlock)
584 588 numHeights = volts.shape[2]
585 589 nChannel = volts.shape[0]
586 590 voltsCohDet = volts.copy()
587 591
588 592 pairsarray = numpy.array(pairslist)
589 593 indSides = pairsarray[:,1]
590 594 # indSides = numpy.array(range(nChannel))
591 595 # indSides = numpy.delete(indSides, indCenter)
592 596 #
593 597 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
594 598 listBlocks = numpy.array_split(volts, numBlocks, 1)
595 599
596 600 startInd = 0
597 601 endInd = 0
598 602
599 603 for i in range(numBlocks):
600 604 startInd = endInd
601 605 endInd = endInd + listBlocks[i].shape[1]
602 606
603 607 arrayBlock = listBlocks[i]
604 608 # arrayBlockCenter = listCenter[i]
605 609
606 610 #Estimate the Phase Difference
607 611 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
608 612 #Phase Difference RMS
609 613 arrayPhaseRMS = numpy.abs(phaseDiff)
610 614 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
611 615 indPhase = numpy.where(phaseRMSaux==4)
612 616 #Shifting
613 617 if indPhase[0].shape[0] > 0:
614 618 for j in range(indSides.size):
615 619 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
616 620 voltsCohDet[:,startInd:endInd,:] = arrayBlock
617 621
618 622 return voltsCohDet
619 623
620 624 def __calculateCCF(self, volts, pairslist ,laglist):
621 625
622 626 nHeights = volts.shape[2]
623 627 nPoints = volts.shape[1]
624 628 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
625 629
626 630 for i in range(len(pairslist)):
627 631 volts1 = volts[pairslist[i][0]]
628 632 volts2 = volts[pairslist[i][1]]
629 633
630 634 for t in range(len(laglist)):
631 635 idxT = laglist[t]
632 636 if idxT >= 0:
633 637 vStacked = numpy.vstack((volts2[idxT:,:],
634 638 numpy.zeros((idxT, nHeights),dtype='complex')))
635 639 else:
636 640 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
637 641 volts2[:(nPoints + idxT),:]))
638 642 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
639 643
640 644 vStacked = None
641 645 return voltsCCF
642 646
643 647 def __getNoise(self, power, timeSegment, timeInterval):
644 648 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
645 649 numBlocks = int(power.shape[0]/numProfPerBlock)
646 650 numHeights = power.shape[1]
647 651
648 652 listPower = numpy.array_split(power, numBlocks, 0)
649 653 noise = numpy.zeros((power.shape[0], power.shape[1]))
650 654 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
651 655
652 656 startInd = 0
653 657 endInd = 0
654 658
655 659 for i in range(numBlocks): #split por canal
656 660 startInd = endInd
657 661 endInd = endInd + listPower[i].shape[0]
658 662
659 663 arrayBlock = listPower[i]
660 664 noiseAux = numpy.mean(arrayBlock, 0)
661 665 # noiseAux = numpy.median(noiseAux)
662 666 # noiseAux = numpy.mean(arrayBlock)
663 667 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
664 668
665 669 noiseAux1 = numpy.mean(arrayBlock)
666 670 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
667 671
668 672 return noise, noise1
669 673
670 674 def __findMeteors(self, power, thresh):
671 675 nProf = power.shape[0]
672 676 nHeights = power.shape[1]
673 677 listMeteors = []
674 678
675 679 for i in range(nHeights):
676 680 powerAux = power[:,i]
677 681 threshAux = thresh[:,i]
678 682
679 683 indUPthresh = numpy.where(powerAux > threshAux)[0]
680 684 indDNthresh = numpy.where(powerAux <= threshAux)[0]
681 685
682 686 j = 0
683 687
684 688 while (j < indUPthresh.size - 2):
685 689 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
686 690 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
687 691 indDNthresh = indDNthresh[indDNAux]
688 692
689 693 if (indDNthresh.size > 0):
690 694 indEnd = indDNthresh[0] - 1
691 695 indInit = indUPthresh[j]
692 696
693 697 meteor = powerAux[indInit:indEnd + 1]
694 698 indPeak = meteor.argmax() + indInit
695 699 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
696 700
697 701 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
698 702 j = numpy.where(indUPthresh == indEnd)[0] + 1
699 703 else: j+=1
700 704 else: j+=1
701 705
702 706 return listMeteors
703 707
704 708 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
705 709
706 710 arrayMeteors = numpy.asarray(listMeteors)
707 711 listMeteors1 = []
708 712
709 713 while arrayMeteors.shape[0] > 0:
710 714 FLAs = arrayMeteors[:,4]
711 715 maxFLA = FLAs.argmax()
712 716 listMeteors1.append(arrayMeteors[maxFLA,:])
713 717
714 718 MeteorInitTime = arrayMeteors[maxFLA,1]
715 719 MeteorEndTime = arrayMeteors[maxFLA,3]
716 720 MeteorHeight = arrayMeteors[maxFLA,0]
717 721
718 722 #Check neighborhood
719 723 maxHeightIndex = MeteorHeight + rangeLimit
720 724 minHeightIndex = MeteorHeight - rangeLimit
721 725 minTimeIndex = MeteorInitTime - timeLimit
722 726 maxTimeIndex = MeteorEndTime + timeLimit
723 727
724 728 #Check Heights
725 729 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
726 730 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
727 731 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
728 732
729 733 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
730 734
731 735 return listMeteors1
732 736
733 737 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
734 738 numHeights = volts.shape[2]
735 739 nChannel = volts.shape[0]
736 740
737 741 thresholdPhase = thresh[0]
738 742 thresholdNoise = thresh[1]
739 743 thresholdDB = float(thresh[2])
740 744
741 745 thresholdDB1 = 10**(thresholdDB/10)
742 746 pairsarray = numpy.array(pairslist)
743 747 indSides = pairsarray[:,1]
744 748
745 749 pairslist1 = list(pairslist)
746 750 pairslist1.append((0,1))
747 751 pairslist1.append((3,4))
748 752
749 753 listMeteors1 = []
750 754 listPowerSeries = []
751 755 listVoltageSeries = []
752 756 #volts has the war data
753 757
754 758 if frequency == 30e6:
755 759 timeLag = 45*10**-3
756 760 else:
757 761 timeLag = 15*10**-3
758 762 lag = numpy.ceil(timeLag/timeInterval)
759 763
760 764 for i in range(len(listMeteors)):
761 765
762 766 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
763 767 meteorAux = numpy.zeros(16)
764 768
765 769 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
766 770 mHeight = listMeteors[i][0]
767 771 mStart = listMeteors[i][1]
768 772 mPeak = listMeteors[i][2]
769 773 mEnd = listMeteors[i][3]
770 774
771 775 #get the volt data between the start and end times of the meteor
772 776 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
773 777 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
774 778
775 779 #3.6. Phase Difference estimation
776 780 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
777 781
778 782 #3.7. Phase difference removal & meteor start, peak and end times reestimated
779 783 #meteorVolts0.- all Channels, all Profiles
780 784 meteorVolts0 = volts[:,:,mHeight]
781 785 meteorThresh = noise[:,mHeight]*thresholdNoise
782 786 meteorNoise = noise[:,mHeight]
783 787 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
784 788 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
785 789
786 790 #Times reestimation
787 791 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
788 792 if mStart1.size > 0:
789 793 mStart1 = mStart1[-1] + 1
790 794
791 795 else:
792 796 mStart1 = mPeak
793 797
794 798 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
795 799 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
796 800 if mEndDecayTime1.size == 0:
797 801 mEndDecayTime1 = powerNet0.size
798 802 else:
799 803 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
800 804 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
801 805
802 806 #meteorVolts1.- all Channels, from start to end
803 807 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
804 808 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
805 809 if meteorVolts2.shape[1] == 0:
806 810 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
807 811 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
808 812 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
809 813 ##################### END PARAMETERS REESTIMATION #########################
810 814
811 815 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
812 816 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
813 817 if meteorVolts2.shape[1] > 0:
814 818 #Phase Difference re-estimation
815 819 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
816 820 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
817 821 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
818 822 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
819 823 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
820 824
821 825 #Phase Difference RMS
822 826 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
823 827 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
824 828 #Data from Meteor
825 829 mPeak1 = powerNet1.argmax() + mStart1
826 830 mPeakPower1 = powerNet1.max()
827 831 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
828 832 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
829 833 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
830 834 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
831 835 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
832 836 #Vectorize
833 837 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
834 838 meteorAux[7:11] = phaseDiffint[0:4]
835 839
836 840 #Rejection Criterions
837 841 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
838 842 meteorAux[-1] = 17
839 843 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
840 844 meteorAux[-1] = 1
841 845
842 846
843 847 else:
844 848 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
845 849 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
846 850 PowerSeries = 0
847 851
848 852 listMeteors1.append(meteorAux)
849 853 listPowerSeries.append(PowerSeries)
850 854 listVoltageSeries.append(meteorVolts1)
851 855
852 856 return listMeteors1, listPowerSeries, listVoltageSeries
853 857
854 858 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
855 859
856 860 threshError = 10
857 861 #Depending if it is 30 or 50 MHz
858 862 if frequency == 30e6:
859 863 timeLag = 45*10**-3
860 864 else:
861 865 timeLag = 15*10**-3
862 866 lag = numpy.ceil(timeLag/timeInterval)
863 867
864 868 listMeteors1 = []
865 869
866 870 for i in range(len(listMeteors)):
867 871 meteorPower = listPower[i]
868 872 meteorAux = listMeteors[i]
869 873
870 874 if meteorAux[-1] == 0:
871 875
872 876 try:
873 877 indmax = meteorPower.argmax()
874 878 indlag = indmax + lag
875 879
876 880 y = meteorPower[indlag:]
877 881 x = numpy.arange(0, y.size)*timeLag
878 882
879 883 #first guess
880 884 a = y[0]
881 885 tau = timeLag
882 886 #exponential fit
883 887 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
884 888 y1 = self.__exponential_function(x, *popt)
885 889 #error estimation
886 890 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
887 891
888 892 decayTime = popt[1]
889 893 riseTime = indmax*timeInterval
890 894 meteorAux[11:13] = [decayTime, error]
891 895
892 896 #Table items 7, 8 and 11
893 897 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
894 898 meteorAux[-1] = 7
895 899 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
896 900 meteorAux[-1] = 8
897 901 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
898 902 meteorAux[-1] = 11
899 903
900 904
901 905 except:
902 906 meteorAux[-1] = 11
903 907
904 908
905 909 listMeteors1.append(meteorAux)
906 910
907 911 return listMeteors1
908 912
909 913 #Exponential Function
910 914
911 915 def __exponential_function(self, x, a, tau):
912 916 y = a*numpy.exp(-x/tau)
913 917 return y
914 918
915 919 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
916 920
917 921 pairslist1 = list(pairslist)
918 922 pairslist1.append((0,1))
919 923 pairslist1.append((3,4))
920 924 numPairs = len(pairslist1)
921 925 #Time Lag
922 926 timeLag = 45*10**-3
923 927 c = 3e8
924 928 lag = numpy.ceil(timeLag/timeInterval)
925 929 freq = 30e6
926 930
927 931 listMeteors1 = []
928 932
929 933 for i in range(len(listMeteors)):
930 934 meteor = listMeteors[i]
931 935 meteorAux = numpy.hstack((meteor[:-1], 0, 0, meteor[-1]))
932 936 if meteor[-1] == 0:
933 937 mStart = listMeteors[i][1]
934 938 mPeak = listMeteors[i][2]
935 939 mLag = mPeak - mStart + lag
936 940
937 941 #get the volt data between the start and end times of the meteor
938 942 meteorVolts = listVolts[i]
939 943 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
940 944
941 945 #Get CCF
942 946 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
943 947
944 948 #Method 2
945 949 slopes = numpy.zeros(numPairs)
946 950 time = numpy.array([-2,-1,1,2])*timeInterval
947 951 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
948 952
949 953 #Correct phases
950 954 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
951 955 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
952 956
953 957 if indDer[0].shape[0] > 0:
954 958 for i in range(indDer[0].shape[0]):
955 959 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
956 960 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
957 961
958 962 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
959 963 for j in range(numPairs):
960 964 fit = stats.linregress(time, angAllCCF[j,:])
961 965 slopes[j] = fit[0]
962 966
963 967 #Remove Outlier
964 968 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
965 969 # slopes = numpy.delete(slopes,indOut)
966 970 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
967 971 # slopes = numpy.delete(slopes,indOut)
968 972
969 973 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
970 974 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
971 975 meteorAux[-2] = radialError
972 976 meteorAux[-3] = radialVelocity
973 977
974 978 #Setting Error
975 979 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
976 980 if numpy.abs(radialVelocity) > 200:
977 981 meteorAux[-1] = 15
978 982 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
979 983 elif radialError > radialStdThresh:
980 984 meteorAux[-1] = 12
981 985
982 986 listMeteors1.append(meteorAux)
983 987 return listMeteors1
984 988
985 989 def __setNewArrays(self, listMeteors, date, heiRang):
986 990
987 991 #New arrays
988 992 arrayMeteors = numpy.array(listMeteors)
989 993 arrayParameters = numpy.zeros((len(listMeteors),10))
990 994
991 995 #Date inclusion
992 996 date = re.findall(r'\((.*?)\)', date)
993 997 date = date[0].split(',')
994 998 date = map(int, date)
995 999 date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
996 1000 arrayDate = numpy.tile(date, (len(listMeteors), 1))
997 1001
998 1002 #Meteor array
999 1003 arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
1000 1004 arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
1001 1005
1002 1006 #Parameters Array
1003 1007 arrayParameters[:,0:3] = arrayMeteors[:,0:3]
1004 1008 arrayParameters[:,-3:] = arrayMeteors[:,-3:]
1005 1009
1006 1010 return arrayMeteors, arrayParameters
1007 1011
1008 1012 def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
1009 1013
1010 1014 arrayAOA = numpy.zeros((phases.shape[0],3))
1011 1015 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
1012 1016
1013 1017 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
1014 1018 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
1015 1019 arrayAOA[:,2] = cosDirError
1016 1020
1017 1021 azimuthAngle = arrayAOA[:,0]
1018 1022 zenithAngle = arrayAOA[:,1]
1019 1023
1020 1024 #Setting Error
1021 1025 #Number 3: AOA not fesible
1022 1026 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
1023 1027 error[indInvalid] = 3
1024 1028 #Number 4: Large difference in AOAs obtained from different antenna baselines
1025 1029 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
1026 1030 error[indInvalid] = 4
1027 1031 return arrayAOA, error
1028 1032
1029 1033 def __getDirectionCosines(self, arrayPhase, pairsList):
1030 1034
1031 1035 #Initializing some variables
1032 1036 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
1033 1037 ang_aux = ang_aux.reshape(1,ang_aux.size)
1034 1038
1035 1039 cosdir = numpy.zeros((arrayPhase.shape[0],2))
1036 1040 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
1037 1041
1038 1042
1039 1043 for i in range(2):
1040 1044 #First Estimation
1041 1045 phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
1042 1046 #Dealias
1043 1047 indcsi = numpy.where(phi0_aux > numpy.pi)
1044 1048 phi0_aux[indcsi] -= 2*numpy.pi
1045 1049 indcsi = numpy.where(phi0_aux < -numpy.pi)
1046 1050 phi0_aux[indcsi] += 2*numpy.pi
1047 1051 #Direction Cosine 0
1048 1052 cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
1049 1053
1050 1054 #Most-Accurate Second Estimation
1051 1055 phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
1052 1056 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
1053 1057 #Direction Cosine 1
1054 1058 cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
1055 1059
1056 1060 #Searching the correct Direction Cosine
1057 1061 cosdir0_aux = cosdir0[:,i]
1058 1062 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
1059 1063 #Minimum Distance
1060 1064 cosDiff = (cosdir1 - cosdir0_aux)**2
1061 1065 indcos = cosDiff.argmin(axis = 1)
1062 1066 #Saving Value obtained
1063 1067 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
1064 1068
1065 1069 return cosdir0, cosdir
1066 1070
1067 1071 def __calculateAOA(self, cosdir, azimuth):
1068 1072 cosdirX = cosdir[:,0]
1069 1073 cosdirY = cosdir[:,1]
1070 1074
1071 1075 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
1072 1076 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
1073 1077 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
1074 1078
1075 1079 return angles
1076 1080
1077 1081 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
1078 1082
1079 1083 Ramb = 375 #Ramb = c/(2*PRF)
1080 1084 Re = 6371 #Earth Radius
1081 1085 heights = numpy.zeros(Ranges.shape)
1082 1086
1083 1087 R_aux = numpy.array([0,1,2])*Ramb
1084 1088 R_aux = R_aux.reshape(1,R_aux.size)
1085 1089
1086 1090 Ranges = Ranges.reshape(Ranges.size,1)
1087 1091
1088 1092 Ri = Ranges + R_aux
1089 1093 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
1090 1094
1091 1095 #Check if there is a height between 70 and 110 km
1092 1096 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
1093 1097 ind_h = numpy.where(h_bool == 1)[0]
1094 1098
1095 1099 hCorr = hi[ind_h, :]
1096 1100 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
1097 1101
1098 1102 hCorr = hi[ind_hCorr]
1099 1103 heights[ind_h] = hCorr
1100 1104
1101 1105 #Setting Error
1102 1106 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
1103 1107 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
1104 1108
1105 1109 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
1106 1110 error[indInvalid2] = 14
1107 1111 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
1108 1112 error[indInvalid1] = 13
1109 1113
1110 1114 return heights, error
1111 1115
1116 def SpectralFitting(self, getSNR = True, path=None, file=None, groupList=None):
1117
1118 '''
1119 Function GetMoments()
1120
1121 Input:
1122 Output:
1123 Variables modified:
1124 '''
1125 if path != None:
1126 sys.path.append(path)
1127 self.dataOut.library = importlib.import_module(file)
1128
1129 #To be inserted as a parameter
1130 groupArray = numpy.array(groupList)
1131 # groupArray = numpy.array([[0,1],[2,3]])
1132 self.dataOut.groupList = groupArray
1133
1134 nGroups = groupArray.shape[0]
1135 nChannels = self.dataIn.nChannels
1136 nHeights=self.dataIn.heightList.size
1137
1138 #Parameters Array
1139 self.dataOut.data_param = None
1140
1141 #Set constants
1142 constants = self.dataOut.library.setConstants(self.dataIn)
1143 self.dataOut.constants = constants
1144 M = self.dataIn.normFactor
1145 N = self.dataIn.nFFTPoints
1146 ippSeconds = self.dataIn.ippSeconds
1147 K = self.dataIn.nIncohInt
1148 pairsArray = numpy.array(self.dataIn.pairsList)
1149
1150 #List of possible combinations
1151 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1152 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1153
1154 if getSNR:
1155 listChannels = groupArray.reshape((groupArray.size))
1156 listChannels.sort()
1157 noise = self.dataIn.getNoise()
1158 self.dataOut.SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1159
1160 for i in range(nGroups):
1161 coord = groupArray[i,:]
1162
1163 #Input data array
1164 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1165 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1166
1167 #Cross Spectra data array for Covariance Matrixes
1168 ind = 0
1169 for pairs in listComb:
1170 pairsSel = numpy.array([coord[x],coord[y]])
1171 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1172 ind += 1
1173 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1174 dataCross = dataCross**2/K
1175
1176 for h in range(nHeights):
1177 # print self.dataOut.heightList[h]
1178
1179 #Input
1180 d = data[:,h]
1181
1182 #Covariance Matrix
1183 D = numpy.diag(d**2/K)
1184 ind = 0
1185 for pairs in listComb:
1186 #Coordinates in Covariance Matrix
1187 x = pairs[0]
1188 y = pairs[1]
1189 #Channel Index
1190 S12 = dataCross[ind,:,h]
1191 D12 = numpy.diag(S12)
1192 #Completing Covariance Matrix with Cross Spectras
1193 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1194 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1195 ind += 1
1196 Dinv=numpy.linalg.inv(D)
1197 L=numpy.linalg.cholesky(Dinv)
1198 LT=L.T
1199
1200 dp = numpy.dot(LT,d)
1201
1202 #Initial values
1203 data_spc = self.dataIn.data_spc[coord,:,h]
1204 p0 = self.dataOut.library.initialValuesFunction(data_spc, constants)
1205
1206 #Least Squares
1207 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1208 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1209 #Chi square error
1210 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1211 # error0 = 0
1212 #Error with Jacobian
1213 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1214 #Save
1215 if self.dataOut.data_param == None:
1216 self.dataOut.data_param = numpy.zeros((nGroups, minp.size, nHeights))*numpy.nan
1217 self.dataOut.error = numpy.zeros((nGroups, error1.size + 1, nHeights))*numpy.nan
1218
1219 self.dataOut.error[i,:,h] = numpy.hstack((error0,error1))
1220 self.dataOut.data_param[i,:,h] = minp
1221 return
1222
1223
1224 def __residFunction(self, p, dp, LT, constants):
1225
1226 fm = self.dataOut.library.modelFunction(p, constants)
1227 fmp=numpy.dot(LT,fm)
1228
1229 return dp-fmp
1230
1231 def __getSNR(self, z, noise):
1232
1233 avg = numpy.average(z, axis=1)
1234 SNR = (avg.T-noise)/noise
1235 SNR = SNR.T
1236 return SNR
1237
1238 def __chisq(p,chindex,hindex):
1239 #similar to Resid but calculates CHI**2
1240 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1241 dp=numpy.dot(LT,d)
1242 fmp=numpy.dot(LT,fm)
1243 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1244 return chisq
1245
1246
1112 1247
1113 1248 class WindProfiler(Operation):
1114 1249
1115 1250 __isConfig = False
1116 1251
1117 1252 __initime = None
1118 1253 __lastdatatime = None
1119 1254 __integrationtime = None
1120 1255
1121 1256 __buffer = None
1122 1257
1123 1258 __dataReady = False
1124 1259
1125 1260 __firstdata = None
1126 1261
1127 1262 n = None
1128 1263
1129 1264 def __init__(self):
1130 1265 Operation.__init__(self)
1131 1266
1132 1267 def __calculateCosDir(self, elev, azim):
1133 1268 zen = (90 - elev)*numpy.pi/180
1134 1269 azim = azim*numpy.pi/180
1135 1270 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1136 1271 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1137 1272
1138 1273 signX = numpy.sign(numpy.cos(azim))
1139 1274 signY = numpy.sign(numpy.sin(azim))
1140 1275
1141 1276 cosDirX = numpy.copysign(cosDirX, signX)
1142 1277 cosDirY = numpy.copysign(cosDirY, signY)
1143 1278 return cosDirX, cosDirY
1144 1279
1145 1280 def __calculateAngles(self, theta_x, theta_y, azimuth):
1146 1281
1147 1282 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1148 1283 zenith_arr = numpy.arccos(dir_cosw)
1149 1284 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1150 1285
1151 1286 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1152 1287 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1153 1288
1154 1289 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1155 1290
1156 1291 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1157 1292
1158 1293 #
1159 1294 if horOnly:
1160 1295 A = numpy.c_[dir_cosu,dir_cosv]
1161 1296 else:
1162 1297 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1163 1298 A = numpy.asmatrix(A)
1164 1299 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1165 1300
1166 1301 return A1
1167 1302
1168 1303 def __correctValues(self, heiRang, phi, velRadial, SNR):
1169 1304 listPhi = phi.tolist()
1170 1305 maxid = listPhi.index(max(listPhi))
1171 1306 minid = listPhi.index(min(listPhi))
1172 1307
1173 1308 rango = range(len(phi))
1174 1309 # rango = numpy.delete(rango,maxid)
1175 1310
1176 1311 heiRang1 = heiRang*math.cos(phi[maxid])
1177 1312 heiRangAux = heiRang*math.cos(phi[minid])
1178 1313 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1179 1314 heiRang1 = numpy.delete(heiRang1,indOut)
1180 1315
1181 1316 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1182 1317 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1183 1318
1184 1319 for i in rango:
1185 1320 x = heiRang*math.cos(phi[i])
1186 1321 y1 = velRadial[i,:]
1187 1322 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1188 1323
1189 1324 x1 = heiRang1
1190 1325 y11 = f1(x1)
1191 1326
1192 1327 y2 = SNR[i,:]
1193 1328 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1194 1329 y21 = f2(x1)
1195 1330
1196 1331 velRadial1[i,:] = y11
1197 1332 SNR1[i,:] = y21
1198 1333
1199 1334 return heiRang1, velRadial1, SNR1
1200 1335
1201 1336 def __calculateVelUVW(self, A, velRadial):
1202 1337
1203 1338 #Operacion Matricial
1204 1339 # velUVW = numpy.zeros((velRadial.shape[1],3))
1205 1340 # for ind in range(velRadial.shape[1]):
1206 1341 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1207 1342 # velUVW = velUVW.transpose()
1208 1343 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1209 1344 velUVW[:,:] = numpy.dot(A,velRadial)
1210 1345
1211 1346
1212 1347 return velUVW
1213 1348
1214 1349 def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1215 1350 """
1216 1351 Function that implements Doppler Beam Swinging (DBS) technique.
1217 1352
1218 1353 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1219 1354 Direction correction (if necessary), Ranges and SNR
1220 1355
1221 1356 Output: Winds estimation (Zonal, Meridional and Vertical)
1222 1357
1223 1358 Parameters affected: Winds, height range, SNR
1224 1359 """
1225 1360 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(dirCosx, disrCosy, azimuth)
1226 1361 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correct*velRadial0, SNR0)
1227 1362 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1228 1363
1229 1364 #Calculo de Componentes de la velocidad con DBS
1230 1365 winds = self.__calculateVelUVW(A,velRadial1)
1231 1366
1232 1367 return winds, heiRang1, SNR1
1233 1368
1234 1369 def __calculateDistance(self, posx, posy, pairsCrossCorr, pairsList, pairs, azimuth = None):
1235 1370
1236 1371 posx = numpy.asarray(posx)
1237 1372 posy = numpy.asarray(posy)
1238 1373
1239 1374 #Rotacion Inversa para alinear con el azimuth
1240 1375 if azimuth!= None:
1241 1376 azimuth = azimuth*math.pi/180
1242 1377 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1243 1378 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1244 1379 else:
1245 1380 posx1 = posx
1246 1381 posy1 = posy
1247 1382
1248 1383 #Calculo de Distancias
1249 1384 distx = numpy.zeros(pairsCrossCorr.size)
1250 1385 disty = numpy.zeros(pairsCrossCorr.size)
1251 1386 dist = numpy.zeros(pairsCrossCorr.size)
1252 1387 ang = numpy.zeros(pairsCrossCorr.size)
1253 1388
1254 1389 for i in range(pairsCrossCorr.size):
1255 1390 distx[i] = posx1[pairsList[pairsCrossCorr[i]][1]] - posx1[pairsList[pairsCrossCorr[i]][0]]
1256 1391 disty[i] = posy1[pairsList[pairsCrossCorr[i]][1]] - posy1[pairsList[pairsCrossCorr[i]][0]]
1257 1392 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1258 1393 ang[i] = numpy.arctan2(disty[i],distx[i])
1259 1394 #Calculo de Matrices
1260 1395 nPairs = len(pairs)
1261 1396 ang1 = numpy.zeros((nPairs, 2, 1))
1262 1397 dist1 = numpy.zeros((nPairs, 2, 1))
1263 1398
1264 1399 for j in range(nPairs):
1265 1400 dist1[j,0,0] = dist[pairs[j][0]]
1266 1401 dist1[j,1,0] = dist[pairs[j][1]]
1267 1402 ang1[j,0,0] = ang[pairs[j][0]]
1268 1403 ang1[j,1,0] = ang[pairs[j][1]]
1269 1404
1270 1405 return distx,disty, dist1,ang1
1271 1406
1272 1407 def __calculateVelVer(self, phase, lagTRange, _lambda):
1273 1408
1274 1409 Ts = lagTRange[1] - lagTRange[0]
1275 1410 velW = -_lambda*phase/(4*math.pi*Ts)
1276 1411
1277 1412 return velW
1278 1413
1279 1414 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1280 1415 nPairs = tau1.shape[0]
1281 1416 vel = numpy.zeros((nPairs,3,tau1.shape[2]))
1282 1417
1283 1418 angCos = numpy.cos(ang)
1284 1419 angSin = numpy.sin(ang)
1285 1420
1286 1421 vel0 = dist*tau1/(2*tau2**2)
1287 1422 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1288 1423 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1289 1424
1290 1425 ind = numpy.where(numpy.isinf(vel))
1291 1426 vel[ind] = numpy.nan
1292 1427
1293 1428 return vel
1294 1429
1295 1430 def __getPairsAutoCorr(self, pairsList, nChannels):
1296 1431
1297 1432 pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1298 1433
1299 1434 for l in range(len(pairsList)):
1300 1435 firstChannel = pairsList[l][0]
1301 1436 secondChannel = pairsList[l][1]
1302 1437
1303 1438 #Obteniendo pares de Autocorrelacion
1304 1439 if firstChannel == secondChannel:
1305 1440 pairsAutoCorr[firstChannel] = int(l)
1306 1441
1307 1442 pairsAutoCorr = pairsAutoCorr.astype(int)
1308 1443
1309 1444 pairsCrossCorr = range(len(pairsList))
1310 1445 pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1311 1446
1312 1447 return pairsAutoCorr, pairsCrossCorr
1313 1448
1314 1449 def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1315 1450 """
1316 1451 Function that implements Spaced Antenna (SA) technique.
1317 1452
1318 1453 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1319 1454 Direction correction (if necessary), Ranges and SNR
1320 1455
1321 1456 Output: Winds estimation (Zonal, Meridional and Vertical)
1322 1457
1323 1458 Parameters affected: Winds
1324 1459 """
1325 1460 #Cross Correlation pairs obtained
1326 1461 pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1327 1462 pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1328 1463 pairsSelArray = numpy.array(pairsSelected)
1329 1464 pairs = []
1330 1465
1331 1466 #Wind estimation pairs obtained
1332 1467 for i in range(pairsSelArray.shape[0]/2):
1333 1468 ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1334 1469 ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1335 1470 pairs.append((ind1,ind2))
1336 1471
1337 1472 indtau = tau.shape[0]/2
1338 1473 tau1 = tau[:indtau,:]
1339 1474 tau2 = tau[indtau:-1,:]
1340 1475 tau1 = tau1[pairs,:]
1341 1476 tau2 = tau2[pairs,:]
1342 1477 phase1 = tau[-1,:]
1343 1478
1344 1479 #---------------------------------------------------------------------
1345 1480 #Metodo Directo
1346 1481 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairsCrossCorr, pairsList, pairs,azimuth)
1347 1482 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1348 1483 winds = stats.nanmean(winds, axis=0)
1349 1484 #---------------------------------------------------------------------
1350 1485 #Metodo General
1351 1486 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1352 1487 # #Calculo Coeficientes de Funcion de Correlacion
1353 1488 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1354 1489 # #Calculo de Velocidades
1355 1490 # winds = self.calculateVelUV(F,G,A,B,H)
1356 1491
1357 1492 #---------------------------------------------------------------------
1358 1493 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1359 1494 winds = correctFactor*winds
1360 1495 return winds
1361 1496
1362 def __checkTime(self, currentTime, paramInterval, windsInterval):
1497 def __checkTime(self, currentTime, paramInterval, outputInterval):
1363 1498
1364 1499 dataTime = currentTime + paramInterval
1365 1500 deltaTime = dataTime - self.__initime
1366 1501
1367 if deltaTime >= windsInterval or deltaTime < 0:
1502 if deltaTime >= outputInterval or deltaTime < 0:
1368 1503 self.__dataReady = True
1369 1504 return
1370 1505
1371 1506 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1372 1507 '''
1373 1508 Function that implements winds estimation technique with detected meteors.
1374 1509
1375 1510 Input: Detected meteors, Minimum meteor quantity to wind estimation
1376 1511
1377 1512 Output: Winds estimation (Zonal and Meridional)
1378 1513
1379 1514 Parameters affected: Winds
1380 1515 '''
1381 1516 #Settings
1382 1517 nInt = (heightMax - heightMin)/2
1383 1518 winds = numpy.zeros((2,nInt))*numpy.nan
1384 1519
1385 1520 #Filter errors
1386 1521 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1387 1522 finalMeteor = arrayMeteor[error,:]
1388 1523
1389 1524 #Meteor Histogram
1390 1525 finalHeights = finalMeteor[:,3]
1391 1526 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1392 1527 nMeteorsPerI = hist[0]
1393 1528 heightPerI = hist[1]
1394 1529
1395 1530 #Sort of meteors
1396 1531 indSort = finalHeights.argsort()
1397 1532 finalMeteor2 = finalMeteor[indSort,:]
1398 1533
1399 1534 # Calculating winds
1400 1535 ind1 = 0
1401 1536 ind2 = 0
1402 1537
1403 1538 for i in range(nInt):
1404 1539 nMet = nMeteorsPerI[i]
1405 1540 ind1 = ind2
1406 1541 ind2 = ind1 + nMet
1407 1542
1408 1543 meteorAux = finalMeteor2[ind1:ind2,:]
1409 1544
1410 1545 if meteorAux.shape[0] >= meteorThresh:
1411 1546 vel = meteorAux[:, 7]
1412 1547 zen = meteorAux[:, 5]*numpy.pi/180
1413 1548 azim = meteorAux[:, 4]*numpy.pi/180
1414 1549
1415 1550 n = numpy.cos(zen)
1416 1551 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1417 1552 # l = m*numpy.tan(azim)
1418 1553 l = numpy.sin(zen)*numpy.sin(azim)
1419 1554 m = numpy.sin(zen)*numpy.cos(azim)
1420 1555
1421 1556 A = numpy.vstack((l, m)).transpose()
1422 1557 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1423 1558 windsAux = numpy.dot(A1, vel)
1424 1559
1425 1560 winds[0,i] = windsAux[0]
1426 1561 winds[1,i] = windsAux[1]
1427 1562
1428 1563 return winds, heightPerI[:-1]
1429 1564
1430 1565 def run(self, dataOut, technique, **kwargs):
1431 1566
1432 1567 param = dataOut.data_param
1433 1568 if dataOut.abscissaRange != None:
1434 1569 absc = dataOut.abscissaRange[:-1]
1435 1570 noise = dataOut.noise
1436 1571 heightRange = dataOut.getHeiRange()
1437 1572 SNR = dataOut.SNR
1438 1573
1439 1574 if technique == 'DBS':
1440 1575
1441 1576 if kwargs.has_key('dirCosx') and kwargs.has_key('dirCosy'):
1442 1577 theta_x = numpy.array(kwargs['dirCosx'])
1443 1578 theta_y = numpy.array(kwargs['dirCosy'])
1444 1579 else:
1445 1580 elev = numpy.array(kwargs['elevation'])
1446 1581 azim = numpy.array(kwargs['azimuth'])
1447 1582 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1448 1583 azimuth = kwargs['correctAzimuth']
1449 1584 if kwargs.has_key('horizontalOnly'):
1450 1585 horizontalOnly = kwargs['horizontalOnly']
1451 1586 else: horizontalOnly = False
1452 1587 if kwargs.has_key('correctFactor'):
1453 1588 correctFactor = kwargs['correctFactor']
1454 1589 else: correctFactor = 1
1455 1590 if kwargs.has_key('channelList'):
1456 1591 channelList = kwargs['channelList']
1457 1592 if len(channelList) == 2:
1458 1593 horizontalOnly = True
1459 1594 arrayChannel = numpy.array(channelList)
1460 1595 param = param[arrayChannel,:,:]
1461 1596 theta_x = theta_x[arrayChannel]
1462 1597 theta_y = theta_y[arrayChannel]
1463 1598
1464 1599 velRadial0 = param[:,1,:] #Radial velocity
1465 dataOut.winds, dataOut.heightRange, dataOut.SNR = self.techniqueDBS(velRadial0, theta_x, theta_y, azimuth, correctFactor, horizontalOnly, heightRange, SNR) #DBS Function
1600 dataOut.data_output, dataOut.heightRange, dataOut.SNR = self.techniqueDBS(velRadial0, theta_x, theta_y, azimuth, correctFactor, horizontalOnly, heightRange, SNR) #DBS Function
1466 1601
1467 1602 elif technique == 'SA':
1468 1603
1469 1604 #Parameters
1470 1605 position_x = kwargs['positionX']
1471 1606 position_y = kwargs['positionY']
1472 1607 azimuth = kwargs['azimuth']
1473 1608
1474 1609 if kwargs.has_key('crosspairsList'):
1475 1610 pairs = kwargs['crosspairsList']
1476 1611 else:
1477 1612 pairs = None
1478 1613
1479 1614 if kwargs.has_key('correctFactor'):
1480 1615 correctFactor = kwargs['correctFactor']
1481 1616 else:
1482 1617 correctFactor = 1
1483 1618
1484 1619 tau = dataOut.data_param
1485 1620 _lambda = dataOut.C/dataOut.frequency
1486 pairsList = dataOut.pairsList
1621 pairsList = dataOut.groupList
1487 1622 nChannels = dataOut.nChannels
1488 1623
1489 dataOut.winds = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
1624 dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
1490 1625 dataOut.initUtcTime = dataOut.ltctime
1491 dataOut.windsInterval = dataOut.timeInterval
1626 dataOut.outputInterval = dataOut.timeInterval
1492 1627
1493 1628 elif technique == 'Meteors':
1494 1629 dataOut.flagNoData = True
1495 1630 self.__dataReady = False
1496 1631
1497 1632 if kwargs.has_key('nHours'):
1498 1633 nHours = kwargs['nHours']
1499 1634 else:
1500 1635 nHours = 1
1501 1636
1502 1637 if kwargs.has_key('meteorsPerBin'):
1503 1638 meteorThresh = kwargs['meteorsPerBin']
1504 1639 else:
1505 1640 meteorThresh = 6
1506 1641
1507 1642 if kwargs.has_key('hmin'):
1508 1643 hmin = kwargs['hmin']
1509 1644 else: hmin = 70
1510 1645 if kwargs.has_key('hmax'):
1511 1646 hmax = kwargs['hmax']
1512 1647 else: hmax = 110
1513 1648
1514 dataOut.windsInterval = nHours*3600
1649 dataOut.outputInterval = nHours*3600
1515 1650
1516 1651 if self.__isConfig == False:
1517 1652 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
1518 1653 #Get Initial LTC time
1519 1654 self.__initime = (dataOut.datatime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1520 1655 self.__isConfig = True
1521 1656
1522 1657 if self.__buffer == None:
1523 1658 self.__buffer = dataOut.data_param
1524 1659 self.__firstdata = copy.copy(dataOut)
1525 1660
1526 1661 else:
1527 1662 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
1528 1663
1529 self.__checkTime(dataOut.ltctime, dataOut.paramInterval, dataOut.windsInterval) #Check if the buffer is ready
1664 self.__checkTime(dataOut.ltctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
1530 1665
1531 1666 if self.__dataReady:
1532 1667 dataOut.initUtcTime = self.__initime
1533 self.__initime = self.__initime + dataOut.windsInterval #to erase time offset
1668 self.__initime = self.__initime + dataOut.outputInterval #to erase time offset
1534 1669
1535 dataOut.winds, dataOut.heightRange = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
1670 dataOut.data_output, dataOut.heightRange = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
1536 1671 dataOut.flagNoData = False
1537 1672 self.__buffer = None
1538 1673
1539 return No newline at end of file
1674 return
1675
1676 class EWDriftsEstimation(Operation):
1677
1678
1679 def __init__(self):
1680 Operation.__init__(self)
1681
1682 def __correctValues(self, heiRang, phi, velRadial, SNR):
1683 listPhi = phi.tolist()
1684 maxid = listPhi.index(max(listPhi))
1685 minid = listPhi.index(min(listPhi))
1686
1687 rango = range(len(phi))
1688 # rango = numpy.delete(rango,maxid)
1689
1690 heiRang1 = heiRang*math.cos(phi[maxid])
1691 heiRangAux = heiRang*math.cos(phi[minid])
1692 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1693 heiRang1 = numpy.delete(heiRang1,indOut)
1694
1695 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1696 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1697
1698 for i in rango:
1699 x = heiRang*math.cos(phi[i])
1700 y1 = velRadial[i,:]
1701 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1702
1703 x1 = heiRang1
1704 y11 = f1(x1)
1705
1706 y2 = SNR[i,:]
1707 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1708 y21 = f2(x1)
1709
1710 velRadial1[i,:] = y11
1711 SNR1[i,:] = y21
1712
1713 return heiRang1, velRadial1, SNR1
1714
1715 def run(self, dataOut, zenith, zenithCorrection):
1716 heiRang = dataOut.heightList
1717 velRadial = dataOut.data_param[:,3,:]
1718 SNR = dataOut.SNR
1719
1720 zenith = numpy.array(zenith)
1721 zenith -= zenithCorrection
1722 zenith *= numpy.pi/180
1723
1724 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
1725
1726 alp = zenith[0]
1727 bet = zenith[1]
1728
1729 w_w = velRadial1[0,:]
1730 w_e = velRadial1[1,:]
1731
1732 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
1733 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
1734
1735 winds = numpy.vstack((u,w))
1736
1737 dataOut.heightList = heiRang1
1738 dataOut.data_output = winds
1739 dataOut.SNR = SNR1
1740
1741 dataOut.initUtcTime = dataOut.ltctime
1742 dataOut.outputInterval = dataOut.timeInterval
1743 return
1744
1745
1746
1747
1748
1749 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now