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