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