##// END OF EJS Templates
Drifts tested
joabAM -
r1740:7f5b085e2124
parent child
Show More
@@ -1,1156 +1,1159
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Definition of diferent Data objects for different types of data
5 """Definition of diferent Data objects for different types of data
6
6
7 Here you will find the diferent data objects for the different types
7 Here you will find the diferent data objects for the different types
8 of data, this data objects must be used as dataIn or dataOut objects in
8 of data, this data objects must be used as dataIn or dataOut objects in
9 processing units and operations. Currently the supported data objects are:
9 processing units and operations. Currently the supported data objects are:
10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
11 """
11 """
12
12
13 import copy
13 import copy
14 import numpy
14 import numpy
15 import datetime
15 import datetime
16 import json
16 import json
17
17
18 import schainpy.admin
18 import schainpy.admin
19 from schainpy.utils import log
19 from schainpy.utils import log
20 from .jroheaderIO import SystemHeader, RadarControllerHeader,ProcessingHeader
20 from .jroheaderIO import SystemHeader, RadarControllerHeader,ProcessingHeader
21 from schainpy.model.data import _noise
21 from schainpy.model.data import _noise
22 SPEED_OF_LIGHT = 3e8
22 SPEED_OF_LIGHT = 3e8
23
23
24
24
25 def getNumpyDtype(dataTypeCode):
25 def getNumpyDtype(dataTypeCode):
26
26
27 if dataTypeCode == 0:
27 if dataTypeCode == 0:
28 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
28 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
29 elif dataTypeCode == 1:
29 elif dataTypeCode == 1:
30 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
30 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
31 elif dataTypeCode == 2:
31 elif dataTypeCode == 2:
32 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
32 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
33 elif dataTypeCode == 3:
33 elif dataTypeCode == 3:
34 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
34 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
35 elif dataTypeCode == 4:
35 elif dataTypeCode == 4:
36 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
36 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
37 elif dataTypeCode == 5:
37 elif dataTypeCode == 5:
38 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
38 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
39 else:
39 else:
40 raise ValueError('dataTypeCode was not defined')
40 raise ValueError('dataTypeCode was not defined')
41
41
42 return numpyDtype
42 return numpyDtype
43
43
44
44
45 def getDataTypeCode(numpyDtype):
45 def getDataTypeCode(numpyDtype):
46
46
47 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
47 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
48 datatype = 0
48 datatype = 0
49 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
49 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
50 datatype = 1
50 datatype = 1
51 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
51 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
52 datatype = 2
52 datatype = 2
53 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
53 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
54 datatype = 3
54 datatype = 3
55 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
55 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
56 datatype = 4
56 datatype = 4
57 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
57 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
58 datatype = 5
58 datatype = 5
59 else:
59 else:
60 datatype = None
60 datatype = None
61
61
62 return datatype
62 return datatype
63
63
64
64
65 def hildebrand_sekhon(data, navg):
65 def hildebrand_sekhon(data, navg):
66 """
66 """
67 This method is for the objective determination of the noise level in Doppler spectra. This
67 This method is for the objective determination of the noise level in Doppler spectra. This
68 implementation technique is based on the fact that the standard deviation of the spectral
68 implementation technique is based on the fact that the standard deviation of the spectral
69 densities is equal to the mean spectral density for white Gaussian noise
69 densities is equal to the mean spectral density for white Gaussian noise
70
70
71 Inputs:
71 Inputs:
72 Data : heights
72 Data : heights
73 navg : numbers of averages
73 navg : numbers of averages
74
74
75 Return:
75 Return:
76 mean : noise's level
76 mean : noise's level
77 """
77 """
78
78
79 sortdata = numpy.sort(data, axis=None)
79 sortdata = numpy.sort(data, axis=None)
80 '''
80 '''
81 lenOfData = len(sortdata)
81 lenOfData = len(sortdata)
82 nums_min = lenOfData*0.2
82 nums_min = lenOfData*0.2
83
83
84 if nums_min <= 5:
84 if nums_min <= 5:
85
85
86 nums_min = 5
86 nums_min = 5
87
87
88 sump = 0.
88 sump = 0.
89 sumq = 0.
89 sumq = 0.
90
90
91 j = 0
91 j = 0
92 cont = 1
92 cont = 1
93
93
94 while((cont == 1)and(j < lenOfData)):
94 while((cont == 1)and(j < lenOfData)):
95
95
96 sump += sortdata[j]
96 sump += sortdata[j]
97 sumq += sortdata[j]**2
97 sumq += sortdata[j]**2
98
98
99 if j > nums_min:
99 if j > nums_min:
100 rtest = float(j)/(j-1) + 1.0/navg
100 rtest = float(j)/(j-1) + 1.0/navg
101 if ((sumq*j) > (rtest*sump**2)):
101 if ((sumq*j) > (rtest*sump**2)):
102 j = j - 1
102 j = j - 1
103 sump = sump - sortdata[j]
103 sump = sump - sortdata[j]
104 sumq = sumq - sortdata[j]**2
104 sumq = sumq - sortdata[j]**2
105 cont = 0
105 cont = 0
106
106
107 j += 1
107 j += 1
108
108
109 lnoise = sump / j
109 lnoise = sump / j
110 '''
110 '''
111 return _noise.hildebrand_sekhon(sortdata, navg)
111 return _noise.hildebrand_sekhon(sortdata, navg)
112
112
113
113
114 class Beam:
114 class Beam:
115
115
116 def __init__(self):
116 def __init__(self):
117 self.codeList = []
117 self.codeList = []
118 self.azimuthList = []
118 self.azimuthList = []
119 self.zenithList = []
119 self.zenithList = []
120
120
121
121
122 class GenericData(object):
122 class GenericData(object):
123
123
124 flagNoData = True
124 flagNoData = True
125
125
126 def copy(self, inputObj=None):
126 def copy(self, inputObj=None):
127
127
128 if inputObj == None:
128 if inputObj == None:
129 return copy.deepcopy(self)
129 return copy.deepcopy(self)
130
130
131 for key in list(inputObj.__dict__.keys()):
131 for key in list(inputObj.__dict__.keys()):
132
132
133 attribute = inputObj.__dict__[key]
133 attribute = inputObj.__dict__[key]
134
134
135 # If this attribute is a tuple or list
135 # If this attribute is a tuple or list
136 if type(inputObj.__dict__[key]) in (tuple, list):
136 if type(inputObj.__dict__[key]) in (tuple, list):
137 self.__dict__[key] = attribute[:]
137 self.__dict__[key] = attribute[:]
138 continue
138 continue
139
139
140 # If this attribute is another object or instance
140 # If this attribute is another object or instance
141 if hasattr(attribute, '__dict__'):
141 if hasattr(attribute, '__dict__'):
142 self.__dict__[key] = attribute.copy()
142 self.__dict__[key] = attribute.copy()
143 continue
143 continue
144
144
145 self.__dict__[key] = inputObj.__dict__[key]
145 self.__dict__[key] = inputObj.__dict__[key]
146
146
147 def deepcopy(self):
147 def deepcopy(self):
148
148
149 return copy.deepcopy(self)
149 return copy.deepcopy(self)
150
150
151 def isEmpty(self):
151 def isEmpty(self):
152
152
153 return self.flagNoData
153 return self.flagNoData
154
154
155 def isReady(self):
155 def isReady(self):
156
156
157 return not self.flagNoData
157 return not self.flagNoData
158
158
159
159
160 class JROData(GenericData):
160 class JROData(GenericData):
161
161
162 systemHeaderObj = SystemHeader()
162 systemHeaderObj = SystemHeader()
163 radarControllerHeaderObj = RadarControllerHeader()
163 radarControllerHeaderObj = RadarControllerHeader()
164 type = None
164 type = None
165 datatype = None # dtype but in string
165 datatype = None # dtype but in string
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 flagDecodeData = False # asumo q la data no esta decodificada
176 flagDecodeData = False # asumo q la data no esta decodificada
177 flagDeflipData = False # asumo q la data no esta sin flip
177 flagDeflipData = False # asumo q la data no esta sin flip
178 flagShiftFFT = False
178 flagShiftFFT = False
179 nCohInt = None
179 nCohInt = None
180 windowOfFilter = 1
180 windowOfFilter = 1
181 C = 3e8
181 C = 3e8
182 frequency = 49.92e6
182 frequency = 49.92e6
183 realtime = False
183 realtime = False
184 beacon_heiIndexList = None
184 beacon_heiIndexList = None
185 last_block = None
185 last_block = None
186 blocknow = None
186 blocknow = None
187 azimuth = None
187 azimuth = None
188 zenith = None
188 zenith = None
189 beam = Beam()
189 beam = Beam()
190 profileIndex = None
190 profileIndex = None
191 error = None
191 error = None
192 data = None
192 data = None
193 nmodes = None
193 nmodes = None
194 metadata_list = ['heightList', 'timeZone', 'type']
194 metadata_list = ['heightList', 'timeZone', 'type']
195
195
196 ippFactor = 1 #Added to correct the freq and vel range for AMISR data
196 ippFactor = 1 #Added to correct the freq and vel range for AMISR data
197 useInputBuffer = False
197 useInputBuffer = False
198 buffer_empty = True
198 buffer_empty = True
199 codeList = []
199 codeList = []
200 azimuthList = []
200 azimuthList = []
201 elevationList = []
201 elevationList = []
202 last_noise = None
202 last_noise = None
203 __ipp = None
203 __ipp = None
204 __ippSeconds = None
204 __ippSeconds = None
205 sampled_heightsFFT = None
205 sampled_heightsFFT = None
206 pulseLength_TxA = None
206 pulseLength_TxA = None
207 deltaHeight = None
207 deltaHeight = None
208 __code = None
208 __code = None
209 __nCode = None
209 __nCode = None
210 __nBaud = None
210 __nBaud = None
211 unitsDescription = "The units of the parameters are according to the International System of units (Seconds, Meter, Hertz, ...), except \
211 unitsDescription = "The units of the parameters are according to the International System of units (Seconds, Meter, Hertz, ...), except \
212 the parameters related to distances such as heightList, or heightResolution wich are in Km"
212 the parameters related to distances such as heightList, or heightResolution wich are in Km"
213
213
214
214
215
215
216 def __str__(self):
216 def __str__(self):
217
217
218 return '{} - {}'.format(self.type, self.datatime())
218 return '{} - {}'.format(self.type, self.datatime())
219
219
220 def getNoise(self):
220 def getNoise(self):
221
221
222 raise NotImplementedError
222 raise NotImplementedError
223
223
224 @property
224 @property
225 def nChannels(self):
225 def nChannels(self):
226
226
227 return len(self.channelList)
227 return len(self.channelList)
228
228
229 @property
229 @property
230 def channelIndexList(self):
230 def channelIndexList(self):
231
231
232 return list(range(self.nChannels))
232 return list(range(self.nChannels))
233
233
234 @property
234 @property
235 def nHeights(self):
235 def nHeights(self):
236
236
237 return len(self.heightList)
237 return len(self.heightList)
238
238
239 def getDeltaH(self):
239 def getDeltaH(self):
240
240
241 return self.heightList[1] - self.heightList[0]
241 return self.heightList[1] - self.heightList[0]
242
242
243 @property
243 @property
244 def ltctime(self):
244 def ltctime(self):
245
245
246 if self.useLocalTime:
246 if self.useLocalTime:
247 return self.utctime - self.timeZone * 60
247 return self.utctime - self.timeZone * 60
248
248
249 return self.utctime
249 return self.utctime
250
250
251 @property
251 @property
252 def datatime(self):
252 def datatime(self):
253
253
254 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
254 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
255 return datatimeValue
255 return datatimeValue
256
256
257 def getTimeRange(self):
257 def getTimeRange(self):
258
258
259 datatime = []
259 datatime = []
260
260
261 datatime.append(self.ltctime)
261 datatime.append(self.ltctime)
262 datatime.append(self.ltctime + self.timeInterval + 1)
262 datatime.append(self.ltctime + self.timeInterval + 1)
263
263
264 datatime = numpy.array(datatime)
264 datatime = numpy.array(datatime)
265
265
266 return datatime
266 return datatime
267
267
268 def getFmaxTimeResponse(self):
268 def getFmaxTimeResponse(self):
269
269
270 period = (10**-6) * self.getDeltaH() / (0.15)
270 period = (10**-6) * self.getDeltaH() / (0.15)
271
271
272 PRF = 1. / (period * self.nCohInt)
272 PRF = 1. / (period * self.nCohInt)
273
273
274 fmax = PRF
274 fmax = PRF
275
275
276 return fmax
276 return fmax
277
277
278 def getFmax(self):
278 def getFmax(self):
279 PRF = 1. / (self.__ippSeconds * self.nCohInt)
279 PRF = 1. / (self.__ippSeconds * self.nCohInt)
280
280
281 fmax = PRF
281 fmax = PRF
282 return fmax
282 return fmax
283
283
284 def getVmax(self):
284 def getVmax(self):
285
285
286 _lambda = self.C / self.frequency
286 _lambda = self.C / self.frequency
287
287
288 vmax = self.getFmax() * _lambda / 2
288 vmax = self.getFmax() * _lambda / 2
289
289
290 return vmax
290 return vmax
291
291
292 ## Radar Controller Header must be immutable
292 ## Radar Controller Header must be immutable
293 @property
293 @property
294 def ippSeconds(self):
294 def ippSeconds(self):
295 '''
295 '''
296 '''
296 '''
297 #return self.radarControllerHeaderObj.ippSeconds
297 #return self.radarControllerHeaderObj.ippSeconds
298 return self.__ippSeconds
298 return self.__ippSeconds
299
299
300 @ippSeconds.setter
300 @ippSeconds.setter
301 def ippSeconds(self, ippSeconds):
301 def ippSeconds(self, ippSeconds):
302 '''
302 '''
303 '''
303 '''
304 #self.radarControllerHeaderObj.ippSeconds = ippSeconds
304 #self.radarControllerHeaderObj.ippSeconds = ippSeconds
305 self.__ippSeconds = ippSeconds
305 self.__ippSeconds = ippSeconds
306 self.__ipp = ippSeconds*SPEED_OF_LIGHT/2000.0
306 self.__ipp = ippSeconds*SPEED_OF_LIGHT/2000.0
307
307
308 @property
308 @property
309 def code(self):
309 def code(self):
310 '''
310 '''
311 '''
311 '''
312 # return self.radarControllerHeaderObj.code
312 # return self.radarControllerHeaderObj.code
313 return self.__code
313 return self.__code
314
314
315 @code.setter
315 @code.setter
316 def code(self, code):
316 def code(self, code):
317 '''
317 '''
318 '''
318 '''
319 # self.radarControllerHeaderObj.code = code
319 # self.radarControllerHeaderObj.code = code
320 self.__code = code
320 self.__code = code
321
321
322 @property
322 @property
323 def nCode(self):
323 def nCode(self):
324 '''
324 '''
325 '''
325 '''
326 # return self.radarControllerHeaderObj.nCode
326 # return self.radarControllerHeaderObj.nCode
327 return self.__nCode
327 return self.__nCode
328
328
329 @nCode.setter
329 @nCode.setter
330 def nCode(self, ncode):
330 def nCode(self, ncode):
331 '''
331 '''
332 '''
332 '''
333 # self.radarControllerHeaderObj.nCode = ncode
333 # self.radarControllerHeaderObj.nCode = ncode
334 self.__nCode = ncode
334 self.__nCode = ncode
335
335
336 @property
336 @property
337 def nBaud(self):
337 def nBaud(self):
338 '''
338 '''
339 '''
339 '''
340 # return self.radarControllerHeaderObj.nBaud
340 # return self.radarControllerHeaderObj.nBaud
341 return self.__nBaud
341 return self.__nBaud
342
342
343 @nBaud.setter
343 @nBaud.setter
344 def nBaud(self, nbaud):
344 def nBaud(self, nbaud):
345 '''
345 '''
346 '''
346 '''
347 # self.radarControllerHeaderObj.nBaud = nbaud
347 # self.radarControllerHeaderObj.nBaud = nbaud
348 self.__nBaud = nbaud
348 self.__nBaud = nbaud
349
349
350 @property
350 @property
351 def ipp(self):
351 def ipp(self):
352 '''
352 '''
353 '''
353 '''
354 # return self.radarControllerHeaderObj.ipp
354 # return self.radarControllerHeaderObj.ipp
355 return self.__ipp
355 return self.__ipp
356
356
357 @ipp.setter
357 @ipp.setter
358 def ipp(self, ipp):
358 def ipp(self, ipp):
359 '''
359 '''
360 '''
360 '''
361 # self.radarControllerHeaderObj.ipp = ipp
361 # self.radarControllerHeaderObj.ipp = ipp
362 self.__ipp = ipp
362 self.__ipp = ipp
363
363
364 @property
364 @property
365 def metadata(self):
365 def metadata(self):
366 '''
366 '''
367 '''
367 '''
368
368
369 return {attr: getattr(self, attr) for attr in self.metadata_list}
369 return {attr: getattr(self, attr) for attr in self.metadata_list}
370
370
371
371
372 class Voltage(JROData):
372 class Voltage(JROData):
373
373
374 dataPP_POW = None
374 dataPP_POW = None
375 dataPP_DOP = None
375 dataPP_DOP = None
376 dataPP_WIDTH = None
376 dataPP_WIDTH = None
377 dataPP_SNR = None
377 dataPP_SNR = None
378
378
379 # To use oper
379 # To use oper
380 flagProfilesByRange = False
380 flagProfilesByRange = False
381 nProfilesByRange = None
381 nProfilesByRange = None
382 max_nIncohInt = 1
382 max_nIncohInt = 1
383
383
384 def __init__(self):
384 def __init__(self):
385 '''
385 '''
386 Constructor
386 Constructor
387 '''
387 '''
388
388
389 self.useLocalTime = True
389 self.useLocalTime = True
390 self.radarControllerHeaderObj = RadarControllerHeader()
390 self.radarControllerHeaderObj = RadarControllerHeader()
391 self.systemHeaderObj = SystemHeader()
391 self.systemHeaderObj = SystemHeader()
392 self.processingHeaderObj = ProcessingHeader()
392 self.processingHeaderObj = ProcessingHeader()
393 self.type = "Voltage"
393 self.type = "Voltage"
394 self.data = None
394 self.data = None
395 self.nProfiles = None
395 self.nProfiles = None
396 self.heightList = None
396 self.heightList = None
397 self.channelList = None
397 self.channelList = None
398 self.flagNoData = True
398 self.flagNoData = True
399 self.flagDiscontinuousBlock = False
399 self.flagDiscontinuousBlock = False
400 self.utctime = None
400 self.utctime = None
401 self.timeZone = 0
401 self.timeZone = 0
402 self.dstFlag = None
402 self.dstFlag = None
403 self.errorCount = None
403 self.errorCount = None
404 self.nCohInt = None
404 self.nCohInt = None
405 self.blocksize = None
405 self.blocksize = None
406 self.flagCohInt = False
406 self.flagCohInt = False
407 self.flagDecodeData = False # asumo q la data no esta decodificada
407 self.flagDecodeData = False # asumo q la data no esta decodificada
408 self.flagDeflipData = False # asumo q la data no esta sin flip
408 self.flagDeflipData = False # asumo q la data no esta sin flip
409 self.flagShiftFFT = False
409 self.flagShiftFFT = False
410 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
410 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
411 self.profileIndex = 0
411 self.profileIndex = 0
412 self.ippFactor=1
412 self.ippFactor=1
413 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
413 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
414 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
414 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
415
415
416 def getNoisebyHildebrand(self, channel=None, ymin_index=None, ymax_index=None):
416 def getNoisebyHildebrand(self, channel=None, ymin_index=None, ymax_index=None):
417 """
417 """
418 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
418 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
419
419
420 Return:
420 Return:
421 noiselevel
421 noiselevel
422 """
422 """
423
423
424 if channel != None:
424 if channel != None:
425 data = self.data[channel,ymin_index:ymax_index]
425 data = self.data[channel,ymin_index:ymax_index]
426 nChannels = 1
426 nChannels = 1
427 else:
427 else:
428 data = self.data[:,ymin_index:ymax_index]
428 data = self.data[:,ymin_index:ymax_index]
429 nChannels = self.nChannels
429 nChannels = self.nChannels
430
430
431 noise = numpy.zeros(nChannels)
431 noise = numpy.zeros(nChannels)
432 power = data * numpy.conjugate(data)
432 power = data * numpy.conjugate(data)
433
433
434 for thisChannel in range(nChannels):
434 for thisChannel in range(nChannels):
435 if nChannels == 1:
435 if nChannels == 1:
436 daux = power[:].real
436 daux = power[:].real
437 else:
437 else:
438 daux = power[thisChannel, :].real
438 daux = power[thisChannel, :].real
439 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
439 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
440
440
441 return noise
441 return noise
442
442
443 def getNoise(self, type=1, channel=None,ymin_index=None, ymax_index=None):
443 def getNoise(self, type=1, channel=None,ymin_index=None, ymax_index=None):
444
444
445 if type == 1:
445 if type == 1:
446 noise = self.getNoisebyHildebrand(channel,ymin_index, ymax_index)
446 noise = self.getNoisebyHildebrand(channel,ymin_index, ymax_index)
447
447
448 return noise
448 return noise
449
449
450 def getPower(self, channel=None):
450 def getPower(self, channel=None):
451
451
452 if channel != None:
452 if channel != None:
453 data = self.data[channel]
453 data = self.data[channel]
454 else:
454 else:
455 data = self.data
455 data = self.data
456
456
457 power = data * numpy.conjugate(data)
457 power = data * numpy.conjugate(data)
458 powerdB = 10 * numpy.log10(power.real)
458 powerdB = 10 * numpy.log10(power.real)
459 powerdB = numpy.squeeze(powerdB)
459 powerdB = numpy.squeeze(powerdB)
460
460
461 return powerdB
461 return powerdB
462 @property
463 def data_pow(self):
464 return self.getPower()
462
465
463 @property
466 @property
464 def timeInterval(self):
467 def timeInterval(self):
465
468
466 return self.ippSeconds * self.nCohInt
469 return self.ippSeconds * self.nCohInt
467
470
468 noise = property(getNoise, "I'm the 'nHeights' property.")
471 noise = property(getNoise, "I'm the 'nHeights' property.")
469
472
470
473
471 class Spectra(JROData):
474 class Spectra(JROData):
472
475
473 data_outlier = None
476 data_outlier = None
474 flagProfilesByRange = False
477 flagProfilesByRange = False
475 nProfilesByRange = None
478 nProfilesByRange = None
476
479
477 def __init__(self):
480 def __init__(self):
478 '''
481 '''
479 Constructor
482 Constructor
480 '''
483 '''
481
484
482 self.data_dc = None
485 self.data_dc = None
483 self.data_spc = None
486 self.data_spc = None
484 self.data_cspc = None
487 self.data_cspc = None
485 self.useLocalTime = True
488 self.useLocalTime = True
486 self.radarControllerHeaderObj = RadarControllerHeader()
489 self.radarControllerHeaderObj = RadarControllerHeader()
487 self.systemHeaderObj = SystemHeader()
490 self.systemHeaderObj = SystemHeader()
488 self.processingHeaderObj = ProcessingHeader()
491 self.processingHeaderObj = ProcessingHeader()
489 self.type = "Spectra"
492 self.type = "Spectra"
490 self.timeZone = 0
493 self.timeZone = 0
491 self.nProfiles = None
494 self.nProfiles = None
492 self.heightList = None
495 self.heightList = None
493 self.channelList = None
496 self.channelList = None
494 self.pairsList = None
497 self.pairsList = None
495 self.flagNoData = True
498 self.flagNoData = True
496 self.flagDiscontinuousBlock = False
499 self.flagDiscontinuousBlock = False
497 self.utctime = None
500 self.utctime = None
498 self.nCohInt = None
501 self.nCohInt = None
499 self.nIncohInt = None
502 self.nIncohInt = None
500 self.blocksize = None
503 self.blocksize = None
501 self.nFFTPoints = None
504 self.nFFTPoints = None
502 self.wavelength = None
505 self.wavelength = None
503 self.flagDecodeData = False # asumo q la data no esta decodificada
506 self.flagDecodeData = False # asumo q la data no esta decodificada
504 self.flagDeflipData = False # asumo q la data no esta sin flip
507 self.flagDeflipData = False # asumo q la data no esta sin flip
505 self.flagShiftFFT = False
508 self.flagShiftFFT = False
506 self.ippFactor = 1
509 self.ippFactor = 1
507 self.beacon_heiIndexList = []
510 self.beacon_heiIndexList = []
508 self.noise_estimation = None
511 self.noise_estimation = None
509 self.codeList = []
512 self.codeList = []
510 self.azimuthList = []
513 self.azimuthList = []
511 self.elevationList = []
514 self.elevationList = []
512 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
515 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
513 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp','nIncohInt', 'nFFTPoints', 'nProfiles']
516 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp','nIncohInt', 'nFFTPoints', 'nProfiles']
514
517
515 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
518 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
516 """
519 """
517 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
520 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
518
521
519 Return:
522 Return:
520 noiselevel
523 noiselevel
521 """
524 """
522
525
523 noise = numpy.zeros(self.nChannels)
526 noise = numpy.zeros(self.nChannels)
524
527
525 for channel in range(self.nChannels):
528 for channel in range(self.nChannels):
526 daux = self.data_spc[channel,
529 daux = self.data_spc[channel,
527 xmin_index:xmax_index, ymin_index:ymax_index]
530 xmin_index:xmax_index, ymin_index:ymax_index]
528 # noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
531 # noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
529 noise[channel] = hildebrand_sekhon(daux, self.max_nIncohInt[channel])
532 noise[channel] = hildebrand_sekhon(daux, self.max_nIncohInt[channel])
530
533
531 return noise
534 return noise
532
535
533 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
536 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
534
537
535 if self.noise_estimation is not None:
538 if self.noise_estimation is not None:
536 # this was estimated by getNoise Operation defined in jroproc_spectra.py
539 # this was estimated by getNoise Operation defined in jroproc_spectra.py
537 return self.noise_estimation
540 return self.noise_estimation
538 else:
541 else:
539 noise = self.getNoisebyHildebrand(
542 noise = self.getNoisebyHildebrand(
540 xmin_index, xmax_index, ymin_index, ymax_index)
543 xmin_index, xmax_index, ymin_index, ymax_index)
541 return noise
544 return noise
542
545
543 def getFreqRangeTimeResponse(self, extrapoints=0):
546 def getFreqRangeTimeResponse(self, extrapoints=0):
544
547
545 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
548 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
546 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
547
550
548 return freqrange
551 return freqrange
549
552
550 def getAcfRange(self, extrapoints=0):
553 def getAcfRange(self, extrapoints=0):
551
554
552 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
555 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
553 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
554
557
555 return freqrange
558 return freqrange
556
559
557 def getFreqRange(self, extrapoints=0):
560 def getFreqRange(self, extrapoints=0):
558
561
559 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
562 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
560 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
563 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) -self.nFFTPoints / 2.) - deltafreq / 2
561
564
562 return freqrange
565 return freqrange
563
566
564 def getVelRange(self, extrapoints=0):
567 def getVelRange(self, extrapoints=0):
565
568
566 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
569 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
567 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
570 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
568
571
569 if self.nmodes:
572 if self.nmodes:
570 return velrange/self.nmodes
573 return velrange/self.nmodes
571 else:
574 else:
572 return velrange
575 return velrange
573
576
574 @property
577 @property
575 def nPairs(self):
578 def nPairs(self):
576
579
577 return len(self.pairsList)
580 return len(self.pairsList)
578
581
579 @property
582 @property
580 def pairsIndexList(self):
583 def pairsIndexList(self):
581
584
582 return list(range(self.nPairs))
585 return list(range(self.nPairs))
583
586
584 @property
587 @property
585 def normFactor(self):
588 def normFactor(self):
586
589
587 pwcode = 1
590 pwcode = 1
588 if self.flagDecodeData:
591 if self.flagDecodeData:
589 try:
592 try:
590 pwcode = numpy.sum(self.code[0]**2)
593 pwcode = numpy.sum(self.code[0]**2)
591 except Exception as e:
594 except Exception as e:
592 log.warning("Failed pwcode read, setting to 1")
595 log.warning("Failed pwcode read, setting to 1")
593 pwcode = 1
596 pwcode = 1
594 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
597 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
595 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
598 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
596 if self.flagProfilesByRange:
599 if self.flagProfilesByRange:
597 normFactor *= (self.nProfilesByRange/self.nProfilesByRange.max())
600 normFactor *= (self.nProfilesByRange/self.nProfilesByRange.max())
598 return normFactor
601 return normFactor
599
602
600 @property
603 @property
601 def flag_cspc(self):
604 def flag_cspc(self):
602
605
603 if self.data_cspc is None:
606 if self.data_cspc is None:
604 return True
607 return True
605
608
606 return False
609 return False
607
610
608 @property
611 @property
609 def flag_dc(self):
612 def flag_dc(self):
610
613
611 if self.data_dc is None:
614 if self.data_dc is None:
612 return True
615 return True
613
616
614 return False
617 return False
615
618
616 @property
619 @property
617 def timeInterval(self):
620 def timeInterval(self):
618
621
619 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
622 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
620 if self.nmodes:
623 if self.nmodes:
621 return self.nmodes*timeInterval
624 return self.nmodes*timeInterval
622 else:
625 else:
623 return timeInterval
626 return timeInterval
624
627
625 def getPower(self):
628 def getPower(self):
626
629
627 factor = self.normFactor
630 factor = self.normFactor
628 power = numpy.zeros( (self.nChannels,self.nHeights) )
631 power = numpy.zeros( (self.nChannels,self.nHeights) )
629 for ch in range(self.nChannels):
632 for ch in range(self.nChannels):
630 z = None
633 z = None
631 if hasattr(factor,'shape'):
634 if hasattr(factor,'shape'):
632 if factor.ndim > 1:
635 if factor.ndim > 1:
633 z = self.data_spc[ch]/factor[ch]
636 z = self.data_spc[ch]/factor[ch]
634 else:
637 else:
635 z = self.data_spc[ch]/factor
638 z = self.data_spc[ch]/factor
636 else:
639 else:
637 z = self.data_spc[ch]/factor
640 z = self.data_spc[ch]/factor
638 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
641 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
639 avg = numpy.average(z, axis=0)
642 avg = numpy.average(z, axis=0)
640 power[ch] = 10 * numpy.log10(avg)
643 power[ch] = 10 * numpy.log10(avg)
641 return power
644 return power
642
645
643 @property
646 @property
644 def max_nIncohInt(self):
647 def max_nIncohInt(self):
645
648
646 ints = numpy.zeros(self.nChannels)
649 ints = numpy.zeros(self.nChannels)
647 for ch in range(self.nChannels):
650 for ch in range(self.nChannels):
648 if hasattr(self.nIncohInt,'shape'):
651 if hasattr(self.nIncohInt,'shape'):
649 if self.nIncohInt.ndim > 1:
652 if self.nIncohInt.ndim > 1:
650 ints[ch,] = self.nIncohInt[ch].max()
653 ints[ch,] = self.nIncohInt[ch].max()
651 else:
654 else:
652 ints[ch,] = self.nIncohInt
655 ints[ch,] = self.nIncohInt
653 self.nIncohInt = int(self.nIncohInt)
656 self.nIncohInt = int(self.nIncohInt)
654 else:
657 else:
655 ints[ch,] = self.nIncohInt
658 ints[ch,] = self.nIncohInt
656
659
657 return ints
660 return ints
658
661
659 def getCoherence(self, pairsList=None, phase=False):
662 def getCoherence(self, pairsList=None, phase=False):
660
663
661 z = []
664 z = []
662 if pairsList is None:
665 if pairsList is None:
663 pairsIndexList = self.pairsIndexList
666 pairsIndexList = self.pairsIndexList
664 else:
667 else:
665 pairsIndexList = []
668 pairsIndexList = []
666 for pair in pairsList:
669 for pair in pairsList:
667 if pair not in self.pairsList:
670 if pair not in self.pairsList:
668 raise ValueError("Pair %s is not in dataOut.pairsList" % (
671 raise ValueError("Pair %s is not in dataOut.pairsList" % (
669 pair))
672 pair))
670 pairsIndexList.append(self.pairsList.index(pair))
673 pairsIndexList.append(self.pairsList.index(pair))
671 for i in range(len(pairsIndexList)):
674 for i in range(len(pairsIndexList)):
672 pair = self.pairsList[pairsIndexList[i]]
675 pair = self.pairsList[pairsIndexList[i]]
673 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
676 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
674 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
677 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
675 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
678 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
676 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
679 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
677 if phase:
680 if phase:
678 data = numpy.arctan2(avgcoherenceComplex.imag,
681 data = numpy.arctan2(avgcoherenceComplex.imag,
679 avgcoherenceComplex.real) * 180 / numpy.pi
682 avgcoherenceComplex.real) * 180 / numpy.pi
680 else:
683 else:
681 data = numpy.abs(avgcoherenceComplex)
684 data = numpy.abs(avgcoherenceComplex)
682
685
683 z.append(data)
686 z.append(data)
684
687
685 return numpy.array(z)
688 return numpy.array(z)
686
689
687 def setValue(self, value):
690 def setValue(self, value):
688
691
689 print("This property should not be initialized", value)
692 print("This property should not be initialized", value)
690
693
691 return
694 return
692
695
693 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
696 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
694
697
695
698
696 class SpectraHeis(Spectra):
699 class SpectraHeis(Spectra):
697
700
698 def __init__(self):
701 def __init__(self):
699
702
700 self.radarControllerHeaderObj = RadarControllerHeader()
703 self.radarControllerHeaderObj = RadarControllerHeader()
701 self.systemHeaderObj = SystemHeader()
704 self.systemHeaderObj = SystemHeader()
702 self.type = "SpectraHeis"
705 self.type = "SpectraHeis"
703 self.nProfiles = None
706 self.nProfiles = None
704 self.heightList = None
707 self.heightList = None
705 self.channelList = None
708 self.channelList = None
706 self.flagNoData = True
709 self.flagNoData = True
707 self.flagDiscontinuousBlock = False
710 self.flagDiscontinuousBlock = False
708 self.utctime = None
711 self.utctime = None
709 self.blocksize = None
712 self.blocksize = None
710 self.profileIndex = 0
713 self.profileIndex = 0
711 self.nCohInt = 1
714 self.nCohInt = 1
712 self.nIncohInt = 1
715 self.nIncohInt = 1
713
716
714 @property
717 @property
715 def normFactor(self):
718 def normFactor(self):
716 pwcode = 1
719 pwcode = 1
717 if self.flagDecodeData:
720 if self.flagDecodeData:
718 pwcode = numpy.sum(self.code[0]**2)
721 pwcode = numpy.sum(self.code[0]**2)
719
722
720 normFactor = self.nIncohInt * self.nCohInt * pwcode
723 normFactor = self.nIncohInt * self.nCohInt * pwcode
721
724
722 return normFactor
725 return normFactor
723
726
724 @property
727 @property
725 def timeInterval(self):
728 def timeInterval(self):
726
729
727 return self.ippSeconds * self.nCohInt * self.nIncohInt
730 return self.ippSeconds * self.nCohInt * self.nIncohInt
728
731
729
732
730 class Fits(JROData):
733 class Fits(JROData):
731
734
732 def __init__(self):
735 def __init__(self):
733
736
734 self.type = "Fits"
737 self.type = "Fits"
735 self.nProfiles = None
738 self.nProfiles = None
736 self.heightList = None
739 self.heightList = None
737 self.channelList = None
740 self.channelList = None
738 self.flagNoData = True
741 self.flagNoData = True
739 self.utctime = None
742 self.utctime = None
740 self.nCohInt = 1
743 self.nCohInt = 1
741 self.nIncohInt = 1
744 self.nIncohInt = 1
742 self.useLocalTime = True
745 self.useLocalTime = True
743 self.profileIndex = 0
746 self.profileIndex = 0
744 self.timeZone = 0
747 self.timeZone = 0
745
748
746 def getTimeRange(self):
749 def getTimeRange(self):
747
750
748 datatime = []
751 datatime = []
749
752
750 datatime.append(self.ltctime)
753 datatime.append(self.ltctime)
751 datatime.append(self.ltctime + self.timeInterval)
754 datatime.append(self.ltctime + self.timeInterval)
752
755
753 datatime = numpy.array(datatime)
756 datatime = numpy.array(datatime)
754
757
755 return datatime
758 return datatime
756
759
757 def getChannelIndexList(self):
760 def getChannelIndexList(self):
758
761
759 return list(range(self.nChannels))
762 return list(range(self.nChannels))
760
763
761 def getNoise(self, type=1):
764 def getNoise(self, type=1):
762
765
763
766
764 if type == 1:
767 if type == 1:
765 noise = self.getNoisebyHildebrand()
768 noise = self.getNoisebyHildebrand()
766
769
767 if type == 2:
770 if type == 2:
768 noise = self.getNoisebySort()
771 noise = self.getNoisebySort()
769
772
770 if type == 3:
773 if type == 3:
771 noise = self.getNoisebyWindow()
774 noise = self.getNoisebyWindow()
772
775
773 return noise
776 return noise
774
777
775 @property
778 @property
776 def timeInterval(self):
779 def timeInterval(self):
777
780
778 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
781 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
779
782
780 return timeInterval
783 return timeInterval
781
784
782 @property
785 @property
783 def ippSeconds(self):
786 def ippSeconds(self):
784 '''
787 '''
785 '''
788 '''
786 return self.ipp_sec
789 return self.ipp_sec
787
790
788 noise = property(getNoise, "I'm the 'nHeights' property.")
791 noise = property(getNoise, "I'm the 'nHeights' property.")
789
792
790
793
791 class Correlation(JROData):
794 class Correlation(JROData):
792
795
793 def __init__(self):
796 def __init__(self):
794 '''
797 '''
795 Constructor
798 Constructor
796 '''
799 '''
797 self.radarControllerHeaderObj = RadarControllerHeader()
800 self.radarControllerHeaderObj = RadarControllerHeader()
798 self.systemHeaderObj = SystemHeader()
801 self.systemHeaderObj = SystemHeader()
799 self.type = "Correlation"
802 self.type = "Correlation"
800 self.data = None
803 self.data = None
801 self.dtype = None
804 self.dtype = None
802 self.nProfiles = None
805 self.nProfiles = None
803 self.heightList = None
806 self.heightList = None
804 self.channelList = None
807 self.channelList = None
805 self.flagNoData = True
808 self.flagNoData = True
806 self.flagDiscontinuousBlock = False
809 self.flagDiscontinuousBlock = False
807 self.utctime = None
810 self.utctime = None
808 self.timeZone = 0
811 self.timeZone = 0
809 self.dstFlag = None
812 self.dstFlag = None
810 self.errorCount = None
813 self.errorCount = None
811 self.blocksize = None
814 self.blocksize = None
812 self.flagDecodeData = False # asumo q la data no esta decodificada
815 self.flagDecodeData = False # asumo q la data no esta decodificada
813 self.flagDeflipData = False # asumo q la data no esta sin flip
816 self.flagDeflipData = False # asumo q la data no esta sin flip
814 self.pairsList = None
817 self.pairsList = None
815 self.nPoints = None
818 self.nPoints = None
816
819
817 def getPairsList(self):
820 def getPairsList(self):
818
821
819 return self.pairsList
822 return self.pairsList
820
823
821 def getNoise(self, mode=2):
824 def getNoise(self, mode=2):
822
825
823 indR = numpy.where(self.lagR == 0)[0][0]
826 indR = numpy.where(self.lagR == 0)[0][0]
824 indT = numpy.where(self.lagT == 0)[0][0]
827 indT = numpy.where(self.lagT == 0)[0][0]
825
828
826 jspectra0 = self.data_corr[:, :, indR, :]
829 jspectra0 = self.data_corr[:, :, indR, :]
827 jspectra = copy.copy(jspectra0)
830 jspectra = copy.copy(jspectra0)
828
831
829 num_chan = jspectra.shape[0]
832 num_chan = jspectra.shape[0]
830 num_hei = jspectra.shape[2]
833 num_hei = jspectra.shape[2]
831
834
832 freq_dc = jspectra.shape[1] / 2
835 freq_dc = jspectra.shape[1] / 2
833 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
836 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
834
837
835 if ind_vel[0] < 0:
838 if ind_vel[0] < 0:
836 ind_vel[list(range(0, 1))] = ind_vel[list(
839 ind_vel[list(range(0, 1))] = ind_vel[list(
837 range(0, 1))] + self.num_prof
840 range(0, 1))] + self.num_prof
838
841
839 if mode == 1:
842 if mode == 1:
840 jspectra[:, freq_dc, :] = (
843 jspectra[:, freq_dc, :] = (
841 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
844 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
842
845
843 if mode == 2:
846 if mode == 2:
844
847
845 vel = numpy.array([-2, -1, 1, 2])
848 vel = numpy.array([-2, -1, 1, 2])
846 xx = numpy.zeros([4, 4])
849 xx = numpy.zeros([4, 4])
847
850
848 for fil in range(4):
851 for fil in range(4):
849 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
852 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
850
853
851 xx_inv = numpy.linalg.inv(xx)
854 xx_inv = numpy.linalg.inv(xx)
852 xx_aux = xx_inv[0, :]
855 xx_aux = xx_inv[0, :]
853
856
854 for ich in range(num_chan):
857 for ich in range(num_chan):
855 yy = jspectra[ich, ind_vel, :]
858 yy = jspectra[ich, ind_vel, :]
856 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
859 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
857
860
858 junkid = jspectra[ich, freq_dc, :] <= 0
861 junkid = jspectra[ich, freq_dc, :] <= 0
859 cjunkid = sum(junkid)
862 cjunkid = sum(junkid)
860
863
861 if cjunkid.any():
864 if cjunkid.any():
862 jspectra[ich, freq_dc, junkid.nonzero()] = (
865 jspectra[ich, freq_dc, junkid.nonzero()] = (
863 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
866 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
864
867
865 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
868 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
866
869
867 return noise
870 return noise
868
871
869 @property
872 @property
870 def timeInterval(self):
873 def timeInterval(self):
871
874
872 return self.ippSeconds * self.nCohInt * self.nProfiles
875 return self.ippSeconds * self.nCohInt * self.nProfiles
873
876
874 def splitFunctions(self):
877 def splitFunctions(self):
875
878
876 pairsList = self.pairsList
879 pairsList = self.pairsList
877 ccf_pairs = []
880 ccf_pairs = []
878 acf_pairs = []
881 acf_pairs = []
879 ccf_ind = []
882 ccf_ind = []
880 acf_ind = []
883 acf_ind = []
881 for l in range(len(pairsList)):
884 for l in range(len(pairsList)):
882 chan0 = pairsList[l][0]
885 chan0 = pairsList[l][0]
883 chan1 = pairsList[l][1]
886 chan1 = pairsList[l][1]
884
887
885 # Obteniendo pares de Autocorrelacion
888 # Obteniendo pares de Autocorrelacion
886 if chan0 == chan1:
889 if chan0 == chan1:
887 acf_pairs.append(chan0)
890 acf_pairs.append(chan0)
888 acf_ind.append(l)
891 acf_ind.append(l)
889 else:
892 else:
890 ccf_pairs.append(pairsList[l])
893 ccf_pairs.append(pairsList[l])
891 ccf_ind.append(l)
894 ccf_ind.append(l)
892
895
893 data_acf = self.data_cf[acf_ind]
896 data_acf = self.data_cf[acf_ind]
894 data_ccf = self.data_cf[ccf_ind]
897 data_ccf = self.data_cf[ccf_ind]
895
898
896 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
899 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
897
900
898 @property
901 @property
899 def normFactor(self):
902 def normFactor(self):
900 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
903 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
901 acf_pairs = numpy.array(acf_pairs)
904 acf_pairs = numpy.array(acf_pairs)
902 normFactor = numpy.zeros((self.nPairs, self.nHeights))
905 normFactor = numpy.zeros((self.nPairs, self.nHeights))
903
906
904 for p in range(self.nPairs):
907 for p in range(self.nPairs):
905 pair = self.pairsList[p]
908 pair = self.pairsList[p]
906
909
907 ch0 = pair[0]
910 ch0 = pair[0]
908 ch1 = pair[1]
911 ch1 = pair[1]
909
912
910 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
913 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
911 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
914 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
912 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
915 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
913
916
914 return normFactor
917 return normFactor
915
918
916
919
917 class Parameters(Spectra):
920 class Parameters(Spectra):
918
921
919 groupList = None # List of Pairs, Groups, etc
922 groupList = None # List of Pairs, Groups, etc
920 data_param = None # Parameters obtained
923 data_param = None # Parameters obtained
921 data_pre = None # Data Pre Parametrization
924 data_pre = None # Data Pre Parametrization
922 data_SNR = None # Signal to Noise Ratio
925 data_SNR = None # Signal to Noise Ratio
923 abscissaList = None # Abscissa, can be velocities, lags or time
926 abscissaList = None # Abscissa, can be velocities, lags or time
924 utctimeInit = None # Initial UTC time
927 utctimeInit = None # Initial UTC time
925 paramInterval = None # Time interval to calculate Parameters in seconds
928 paramInterval = None # Time interval to calculate Parameters in seconds
926 useLocalTime = True
929 useLocalTime = True
927 # Fitting
930 # Fitting
928 data_error = None # Error of the estimation
931 data_error = None # Error of the estimation
929 constants = None
932 constants = None
930 library = None
933 library = None
931 # Output signal
934 # Output signal
932 outputInterval = None # Time interval to calculate output signal in seconds
935 outputInterval = None # Time interval to calculate output signal in seconds
933 data_output = None # Out signal
936 data_output = None # Out signal
934 nAvg = None
937 nAvg = None
935 noise_estimation = None
938 noise_estimation = None
936 GauSPC = None # Fit gaussian SPC
939 GauSPC = None # Fit gaussian SPC
937
940
938 data_outlier = None
941 data_outlier = None
939 data_vdrift = None
942 data_vdrift = None
940 radarControllerHeaderTxt=None #header Controller like text
943 radarControllerHeaderTxt=None #header Controller like text
941 txPower = None
944 txPower = None
942 flagProfilesByRange = False
945 flagProfilesByRange = False
943 nProfilesByRange = None
946 nProfilesByRange = None
944
947
945
948
946 def __init__(self):
949 def __init__(self):
947 '''
950 '''
948 Constructor
951 Constructor
949 '''
952 '''
950 self.radarControllerHeaderObj = RadarControllerHeader()
953 self.radarControllerHeaderObj = RadarControllerHeader()
951 self.systemHeaderObj = SystemHeader()
954 self.systemHeaderObj = SystemHeader()
952 self.processingHeaderObj = ProcessingHeader()
955 self.processingHeaderObj = ProcessingHeader()
953 self.type = "Parameters"
956 self.type = "Parameters"
954 self.timeZone = 0
957 self.timeZone = 0
955
958
956 def getTimeRange1(self, interval):
959 def getTimeRange1(self, interval):
957
960
958 datatime = []
961 datatime = []
959
962
960 if self.useLocalTime:
963 if self.useLocalTime:
961 time1 = self.utctimeInit - self.timeZone * 60
964 time1 = self.utctimeInit - self.timeZone * 60
962 else:
965 else:
963 time1 = self.utctimeInit
966 time1 = self.utctimeInit
964
967
965 datatime.append(time1)
968 datatime.append(time1)
966 datatime.append(time1 + interval)
969 datatime.append(time1 + interval)
967 datatime = numpy.array(datatime)
970 datatime = numpy.array(datatime)
968
971
969 return datatime
972 return datatime
970
973
971 @property
974 @property
972 def timeInterval(self):
975 def timeInterval(self):
973
976
974 if hasattr(self, 'timeInterval1'):
977 if hasattr(self, 'timeInterval1'):
975 return self.timeInterval1
978 return self.timeInterval1
976 else:
979 else:
977 return self.paramInterval
980 return self.paramInterval
978
981
979 def setValue(self, value):
982 def setValue(self, value):
980
983
981 print("This property should not be initialized")
984 print("This property should not be initialized")
982
985
983 return
986 return
984
987
985 def getNoise(self):
988 def getNoise(self):
986
989
987 return self.spc_noise
990 return self.spc_noise
988
991
989 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
992 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
990
993
991
994
992 class PlotterData(object):
995 class PlotterData(object):
993 '''
996 '''
994 Object to hold data to be plotted
997 Object to hold data to be plotted
995 '''
998 '''
996
999
997 MAXNUMX = 200
1000 MAXNUMX = 200
998 MAXNUMY = 200
1001 MAXNUMY = 200
999
1002
1000 def __init__(self, code, exp_code, localtime=True):
1003 def __init__(self, code, exp_code, localtime=True):
1001
1004
1002 self.key = code
1005 self.key = code
1003 self.exp_code = exp_code
1006 self.exp_code = exp_code
1004 self.ready = False
1007 self.ready = False
1005 self.flagNoData = False
1008 self.flagNoData = False
1006 self.localtime = localtime
1009 self.localtime = localtime
1007 self.data = {}
1010 self.data = {}
1008 self.meta = {}
1011 self.meta = {}
1009 self.__heights = []
1012 self.__heights = []
1010
1013
1011 def __str__(self):
1014 def __str__(self):
1012 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1015 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1013 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
1016 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
1014
1017
1015 def __len__(self):
1018 def __len__(self):
1016 return len(self.data)
1019 return len(self.data)
1017
1020
1018 def __getitem__(self, key):
1021 def __getitem__(self, key):
1019 if isinstance(key, int):
1022 if isinstance(key, int):
1020 return self.data[self.times[key]]
1023 return self.data[self.times[key]]
1021 elif isinstance(key, str):
1024 elif isinstance(key, str):
1022 ret = numpy.array([self.data[x][key] for x in self.times])
1025 ret = numpy.array([self.data[x][key] for x in self.times])
1023 if ret.ndim > 1:
1026 if ret.ndim > 1:
1024 ret = numpy.swapaxes(ret, 0, 1)
1027 ret = numpy.swapaxes(ret, 0, 1)
1025 return ret
1028 return ret
1026
1029
1027 def __contains__(self, key):
1030 def __contains__(self, key):
1028 return key in self.data[self.min_time]
1031 return key in self.data[self.min_time]
1029
1032
1030 def setup(self):
1033 def setup(self):
1031 '''
1034 '''
1032 Configure object
1035 Configure object
1033 '''
1036 '''
1034 self.type = ''
1037 self.type = ''
1035 self.ready = False
1038 self.ready = False
1036 del self.data
1039 del self.data
1037 self.data = {}
1040 self.data = {}
1038 self.__heights = []
1041 self.__heights = []
1039 self.__all_heights = set()
1042 self.__all_heights = set()
1040
1043
1041 def shape(self, key):
1044 def shape(self, key):
1042 '''
1045 '''
1043 Get the shape of the one-element data for the given key
1046 Get the shape of the one-element data for the given key
1044 '''
1047 '''
1045
1048
1046 if len(self.data[self.min_time][key]):
1049 if len(self.data[self.min_time][key]):
1047 return self.data[self.min_time][key].shape
1050 return self.data[self.min_time][key].shape
1048 return (0,)
1051 return (0,)
1049
1052
1050 def update(self, data, tm, meta={}):
1053 def update(self, data, tm, meta={}):
1051 '''
1054 '''
1052 Update data object with new dataOut
1055 Update data object with new dataOut
1053 '''
1056 '''
1054
1057
1055 self.data[tm] = data
1058 self.data[tm] = data
1056
1059
1057 for key, value in meta.items():
1060 for key, value in meta.items():
1058 setattr(self, key, value)
1061 setattr(self, key, value)
1059
1062
1060 def normalize_heights(self):
1063 def normalize_heights(self):
1061 '''
1064 '''
1062 Ensure same-dimension of the data for different heighList
1065 Ensure same-dimension of the data for different heighList
1063 '''
1066 '''
1064
1067
1065 H = numpy.array(list(self.__all_heights))
1068 H = numpy.array(list(self.__all_heights))
1066 H.sort()
1069 H.sort()
1067 for key in self.data:
1070 for key in self.data:
1068 shape = self.shape(key)[:-1] + H.shape
1071 shape = self.shape(key)[:-1] + H.shape
1069 for tm, obj in list(self.data[key].items()):
1072 for tm, obj in list(self.data[key].items()):
1070 h = self.__heights[self.times.tolist().index(tm)]
1073 h = self.__heights[self.times.tolist().index(tm)]
1071 if H.size == h.size:
1074 if H.size == h.size:
1072 continue
1075 continue
1073 index = numpy.where(numpy.in1d(H, h))[0]
1076 index = numpy.where(numpy.in1d(H, h))[0]
1074 dummy = numpy.zeros(shape) + numpy.nan
1077 dummy = numpy.zeros(shape) + numpy.nan
1075 if len(shape) == 2:
1078 if len(shape) == 2:
1076 dummy[:, index] = obj
1079 dummy[:, index] = obj
1077 else:
1080 else:
1078 dummy[index] = obj
1081 dummy[index] = obj
1079 self.data[key][tm] = dummy
1082 self.data[key][tm] = dummy
1080
1083
1081 self.__heights = [H for tm in self.times]
1084 self.__heights = [H for tm in self.times]
1082
1085
1083 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1086 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1084 '''
1087 '''
1085 Convert data to json
1088 Convert data to json
1086 '''
1089 '''
1087
1090
1088 meta = {}
1091 meta = {}
1089 meta['xrange'] = []
1092 meta['xrange'] = []
1090 dy = int(len(self.yrange)/self.MAXNUMY) + 1
1093 dy = int(len(self.yrange)/self.MAXNUMY) + 1
1091 tmp = self.data[tm][self.key]
1094 tmp = self.data[tm][self.key]
1092 shape = tmp.shape
1095 shape = tmp.shape
1093 if len(shape) == 2:
1096 if len(shape) == 2:
1094 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1097 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1095 elif len(shape) == 3:
1098 elif len(shape) == 3:
1096 dx = int(self.data[tm][self.key].shape[1]/self.MAXNUMX) + 1
1099 dx = int(self.data[tm][self.key].shape[1]/self.MAXNUMX) + 1
1097 data = self.roundFloats(
1100 data = self.roundFloats(
1098 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1101 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1099 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1102 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1100 else:
1103 else:
1101 data = self.roundFloats(self.data[tm][self.key].tolist())
1104 data = self.roundFloats(self.data[tm][self.key].tolist())
1102
1105
1103 ret = {
1106 ret = {
1104 'plot': plot_name,
1107 'plot': plot_name,
1105 'code': self.exp_code,
1108 'code': self.exp_code,
1106 'time': float(tm),
1109 'time': float(tm),
1107 'data': data,
1110 'data': data,
1108 }
1111 }
1109 meta['type'] = plot_type
1112 meta['type'] = plot_type
1110 meta['interval'] = float(self.interval)
1113 meta['interval'] = float(self.interval)
1111 meta['localtime'] = self.localtime
1114 meta['localtime'] = self.localtime
1112 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1115 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1113 meta.update(self.meta)
1116 meta.update(self.meta)
1114 ret['metadata'] = meta
1117 ret['metadata'] = meta
1115 return json.dumps(ret)
1118 return json.dumps(ret)
1116
1119
1117 @property
1120 @property
1118 def times(self):
1121 def times(self):
1119 '''
1122 '''
1120 Return the list of times of the current data
1123 Return the list of times of the current data
1121 '''
1124 '''
1122
1125
1123 ret = [t for t in self.data]
1126 ret = [t for t in self.data]
1124 ret.sort()
1127 ret.sort()
1125 return numpy.array(ret)
1128 return numpy.array(ret)
1126
1129
1127 @property
1130 @property
1128 def min_time(self):
1131 def min_time(self):
1129 '''
1132 '''
1130 Return the minimun time value
1133 Return the minimun time value
1131 '''
1134 '''
1132
1135
1133 return self.times[0]
1136 return self.times[0]
1134
1137
1135 @property
1138 @property
1136 def max_time(self):
1139 def max_time(self):
1137 '''
1140 '''
1138 Return the maximun time value
1141 Return the maximun time value
1139 '''
1142 '''
1140
1143
1141 return self.times[-1]
1144 return self.times[-1]
1142
1145
1143 # @property
1146 # @property
1144 # def heights(self):
1147 # def heights(self):
1145 # '''
1148 # '''
1146 # Return the list of heights of the current data
1149 # Return the list of heights of the current data
1147 # '''
1150 # '''
1148
1151
1149 # return numpy.array(self.__heights[-1])
1152 # return numpy.array(self.__heights[-1])
1150
1153
1151 @staticmethod
1154 @staticmethod
1152 def roundFloats(obj):
1155 def roundFloats(obj):
1153 if isinstance(obj, list):
1156 if isinstance(obj, list):
1154 return list(map(PlotterData.roundFloats, obj))
1157 return list(map(PlotterData.roundFloats, obj))
1155 elif isinstance(obj, float):
1158 elif isinstance(obj, float):
1156 return round(obj, 2)
1159 return round(obj, 2)
@@ -1,437 +1,437
1 import os
1 import os
2 import datetime
2 import datetime
3 import numpy
3 import numpy
4
4
5 from schainpy.model.graphics.jroplot_base import Plot, plt
5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
7 from schainpy.utils import log
7 from schainpy.utils import log
8
8
9 EARTH_RADIUS = 6.3710e3
9 EARTH_RADIUS = 6.3710e3
10
10
11
11
12 def ll2xy(lat1, lon1, lat2, lon2):
12 def ll2xy(lat1, lon1, lat2, lon2):
13
13
14 p = 0.017453292519943295
14 p = 0.017453292519943295
15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
20 theta = -theta + numpy.pi/2
20 theta = -theta + numpy.pi/2
21 return r*numpy.cos(theta), r*numpy.sin(theta)
21 return r*numpy.cos(theta), r*numpy.sin(theta)
22
22
23
23
24 def km2deg(km):
24 def km2deg(km):
25 '''
25 '''
26 Convert distance in km to degrees
26 Convert distance in km to degrees
27 '''
27 '''
28
28
29 return numpy.rad2deg(km/EARTH_RADIUS)
29 return numpy.rad2deg(km/EARTH_RADIUS)
30
30
31
31
32
32
33 class SpectralMomentsPlot(SpectraPlot):
33 class SpectralMomentsPlot(SpectraPlot):
34 '''
34 '''
35 Plot for Spectral Moments
35 Plot for Spectral Moments
36 '''
36 '''
37 CODE = 'spc_moments'
37 CODE = 'spc_moments'
38 # colormap = 'jet'
38 # colormap = 'jet'
39 # plot_type = 'pcolor'
39 # plot_type = 'pcolor'
40
40
41 class DobleGaussianPlot(SpectraPlot):
41 class DobleGaussianPlot(SpectraPlot):
42 '''
42 '''
43 Plot for Double Gaussian Plot
43 Plot for Double Gaussian Plot
44 '''
44 '''
45 CODE = 'gaussian_fit'
45 CODE = 'gaussian_fit'
46 # colormap = 'jet'
46 # colormap = 'jet'
47 # plot_type = 'pcolor'
47 # plot_type = 'pcolor'
48
48
49 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
49 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
50 '''
50 '''
51 Plot SpectraCut with Double Gaussian Fit
51 Plot SpectraCut with Double Gaussian Fit
52 '''
52 '''
53 CODE = 'cut_gaussian_fit'
53 CODE = 'cut_gaussian_fit'
54
54
55
55
56 class SpectralFitObliquePlot(SpectraPlot):
56 class SpectralFitObliquePlot(SpectraPlot):
57 '''
57 '''
58 Plot for Spectral Oblique
58 Plot for Spectral Oblique
59 '''
59 '''
60 CODE = 'spc_moments'
60 CODE = 'spc_moments'
61 colormap = 'jet'
61 colormap = 'jet'
62 plot_type = 'pcolor'
62 plot_type = 'pcolor'
63
63
64
64
65 class SnrPlot(RTIPlot):
65 class SnrPlot(RTIPlot):
66 '''
66 '''
67 Plot for SNR Data
67 Plot for SNR Data
68 '''
68 '''
69
69
70 CODE = 'snr'
70 CODE = 'snr'
71 colormap = 'jet'
71 colormap = 'jet'
72
72
73 def update(self, dataOut):
73 def update(self, dataOut):
74 if len(self.channelList) == 0:
74 if len(self.channelList) == 0:
75 self.update_list(dataOut)
75 self.update_list(dataOut)
76
76
77 meta = {}
77 meta = {}
78 data = {
78 data = {
79 'snr': 10 * numpy.log10(dataOut.data_snr)
79 'snr': 10 * numpy.log10(dataOut.data_snr)
80 }
80 }
81 return data, meta
81 return data, meta
82
82
83 class DopplerPlot(RTIPlot):
83 class DopplerPlot(RTIPlot):
84 '''
84 '''
85 Plot for DOPPLER Data (1st moment)
85 Plot for DOPPLER Data (1st moment)
86 '''
86 '''
87
87
88 CODE = 'dop'
88 CODE = 'dop'
89 colormap = 'RdBu_r'
89 colormap = 'RdBu_r'
90
90
91 def update(self, dataOut):
91 def update(self, dataOut):
92 self.update_list(dataOut)
92 self.update_list(dataOut)
93 data = {
93 data = {
94 'dop': dataOut.data_dop
94 'dop': dataOut.data_dop
95 }
95 }
96
96
97 return data, {}
97 return data, {}
98
98
99 class PowerPlot(RTIPlot):
99 class PowerPlot(RTIPlot):
100 '''
100 '''
101 Plot for Power Data (0 moment)
101 Plot for Power Data (0 moment)
102 '''
102 '''
103
103
104 CODE = 'pow'
104 CODE = 'pow'
105 colormap = 'jet'
105 colormap = 'jet'
106
106
107 def update(self, dataOut):
107 def update(self, dataOut):
108 self.update_list(dataOut)
108 self.update_list(dataOut)
109 data = {
109 data = {
110 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
110 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
111 }
111 }
112 try:
112 try:
113 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
113 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
114 except:
114 except:
115 pass
115 pass
116 return data, {}
116 return data, {}
117
117
118 class SpectralWidthPlot(RTIPlot):
118 class SpectralWidthPlot(RTIPlot):
119 '''
119 '''
120 Plot for Spectral Width Data (2nd moment)
120 Plot for Spectral Width Data (2nd moment)
121 '''
121 '''
122
122
123 CODE = 'width'
123 CODE = 'width'
124 colormap = 'jet'
124 colormap = 'jet'
125
125
126 def update(self, dataOut):
126 def update(self, dataOut):
127 self.update_list(dataOut)
127 self.update_list(dataOut)
128 data = {
128 data = {
129 'width': dataOut.data_width
129 'width': dataOut.data_width
130 }
130 }
131 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
131 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
132 return data, {}
132 return data, {}
133
133
134 class SkyMapPlot(Plot):
134 class SkyMapPlot(Plot):
135 '''
135 '''
136 Plot for meteors detection data
136 Plot for meteors detection data
137 '''
137 '''
138
138
139 CODE = 'param'
139 CODE = 'param'
140
140
141 def setup(self):
141 def setup(self):
142
142
143 self.ncols = 1
143 self.ncols = 1
144 self.nrows = 1
144 self.nrows = 1
145 self.width = 7.2
145 self.width = 7.2
146 self.height = 7.2
146 self.height = 7.2
147 self.nplots = 1
147 self.nplots = 1
148 self.xlabel = 'Zonal Zenith Angle (deg)'
148 self.xlabel = 'Zonal Zenith Angle (deg)'
149 self.ylabel = 'Meridional Zenith Angle (deg)'
149 self.ylabel = 'Meridional Zenith Angle (deg)'
150 self.polar = True
150 self.polar = True
151 self.ymin = -180
151 self.ymin = -180
152 self.ymax = 180
152 self.ymax = 180
153 self.colorbar = False
153 self.colorbar = False
154
154
155 def plot(self):
155 def plot(self):
156
156
157 arrayParameters = numpy.concatenate(self.data['param'])
157 arrayParameters = numpy.concatenate(self.data['param'])
158 error = arrayParameters[:, -1]
158 error = arrayParameters[:, -1]
159 indValid = numpy.where(error == 0)[0]
159 indValid = numpy.where(error == 0)[0]
160 finalMeteor = arrayParameters[indValid, :]
160 finalMeteor = arrayParameters[indValid, :]
161 finalAzimuth = finalMeteor[:, 3]
161 finalAzimuth = finalMeteor[:, 3]
162 finalZenith = finalMeteor[:, 4]
162 finalZenith = finalMeteor[:, 4]
163
163
164 x = finalAzimuth * numpy.pi / 180
164 x = finalAzimuth * numpy.pi / 180
165 y = finalZenith
165 y = finalZenith
166
166
167 ax = self.axes[0]
167 ax = self.axes[0]
168
168
169 if ax.firsttime:
169 if ax.firsttime:
170 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
170 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
171 else:
171 else:
172 ax.plot.set_data(x, y)
172 ax.plot.set_data(x, y)
173
173
174 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
174 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
175 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
175 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
176 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
176 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
177 dt2,
177 dt2,
178 len(x))
178 len(x))
179 self.titles[0] = title
179 self.titles[0] = title
180
180
181 class GenericRTIPlot(Plot):
181 class GenericRTIPlot(Plot):
182 '''
182 '''
183 Plot for data_xxxx object
183 Plot for data_xxxx object
184 '''
184 '''
185
185
186 CODE = 'param'
186 CODE = 'param'
187 colormap = 'viridis'
187 colormap = 'viridis'
188 plot_type = 'pcolorbuffer'
188 plot_type = 'pcolorbuffer'
189
189
190 def setup(self):
190 def setup(self):
191 self.xaxis = 'time'
191 self.xaxis = 'time'
192 self.ncols = 1
192 self.ncols = 1
193 self.nrows = self.data.shape('param')[0]
193 self.nrows = self.data.shape('param')[0]
194 self.nplots = self.nrows
194 self.nplots = self.nrows
195 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
195 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
196
196
197 if not self.xlabel:
197 if not self.xlabel:
198 self.xlabel = 'Time'
198 self.xlabel = 'Time'
199
199
200 self.ylabel = 'Range [km]'
200 self.ylabel = 'Range [km]'
201 if not self.titles:
201 if not self.titles:
202 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
202 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
203
203
204 def update(self, dataOut):
204 def update(self, dataOut):
205
205
206 data = {
206 data = {
207 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
207 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
208 }
208 }
209
209
210 meta = {}
210 meta = {}
211
211
212 return data, meta
212 return data, meta
213
213
214 def plot(self):
214 def plot(self):
215 # self.data.normalize_heights()
215 # self.data.normalize_heights()
216 self.x = self.data.times
216 self.x = self.data.times
217 self.y = self.data.yrange
217 self.y = self.data.yrange
218 self.z = self.data['param']
218 self.z = self.data['param']
219
219
220 self.z = numpy.ma.masked_invalid(self.z)
220 self.z = numpy.ma.masked_invalid(self.z)
221
221
222 if self.decimation is None:
222 if self.decimation is None:
223 x, y, z = self.fill_gaps(self.x, self.y, self.z)
223 x, y, z = self.fill_gaps(self.x, self.y, self.z)
224 else:
224 else:
225 x, y, z = self.fill_gaps(*self.decimate())
225 x, y, z = self.fill_gaps(*self.decimate())
226
226
227 for n, ax in enumerate(self.axes):
227 for n, ax in enumerate(self.axes):
228
228
229 self.zmax = self.zmax if self.zmax is not None else numpy.max(
229 self.zmax = self.zmax if self.zmax is not None else numpy.max(
230 self.z[n])
230 self.z[n])
231 self.zmin = self.zmin if self.zmin is not None else numpy.min(
231 self.zmin = self.zmin if self.zmin is not None else numpy.min(
232 self.z[n])
232 self.z[n])
233
233
234 if ax.firsttime:
234 if ax.firsttime:
235 if self.zlimits is not None:
235 if self.zlimits is not None:
236 self.zmin, self.zmax = self.zlimits[n]
236 self.zmin, self.zmax = self.zlimits[n]
237
237
238 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
238 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
239 vmin=self.zmin,
239 vmin=self.zmin,
240 vmax=self.zmax,
240 vmax=self.zmax,
241 cmap=self.cmaps[n]
241 cmap=self.cmaps[n]
242 )
242 )
243 else:
243 else:
244 if self.zlimits is not None:
244 if self.zlimits is not None:
245 self.zmin, self.zmax = self.zlimits[n]
245 self.zmin, self.zmax = self.zlimits[n]
246 try:
246 try:
247 ax.collections.remove(ax.collections[0])
247 ax.collections.remove(ax.collections[0])
248 except:
248 except:
249 pass
249 pass
250 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
250 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
251 vmin=self.zmin,
251 vmin=self.zmin,
252 vmax=self.zmax,
252 vmax=self.zmax,
253 cmap=self.cmaps[n]
253 cmap=self.cmaps[n]
254 )
254 )
255
255
256
256
257 class PolarMapPlot(Plot):
257 class PolarMapPlot(Plot):
258 '''
258 '''
259 Plot for weather radar
259 Plot for weather radar
260 '''
260 '''
261
261
262 CODE = 'param'
262 CODE = 'param'
263 colormap = 'seismic'
263 colormap = 'seismic'
264
264
265 def setup(self):
265 def setup(self):
266 self.ncols = 1
266 self.ncols = 1
267 self.nrows = 1
267 self.nrows = 1
268 self.width = 9
268 self.width = 9
269 self.height = 8
269 self.height = 8
270 self.mode = self.data.meta['mode']
270 self.mode = self.data.meta['mode']
271 if self.channels is not None:
271 if self.channels is not None:
272 self.nplots = len(self.channels)
272 self.nplots = len(self.channels)
273 self.nrows = len(self.channels)
273 self.nrows = len(self.channels)
274 else:
274 else:
275 self.nplots = self.data.shape(self.CODE)[0]
275 self.nplots = self.data.shape(self.CODE)[0]
276 self.nrows = self.nplots
276 self.nrows = self.nplots
277 self.channels = list(range(self.nplots))
277 self.channels = list(range(self.nplots))
278 if self.mode == 'E':
278 if self.mode == 'E':
279 self.xlabel = 'Longitude'
279 self.xlabel = 'Longitude'
280 self.ylabel = 'Latitude'
280 self.ylabel = 'Latitude'
281 else:
281 else:
282 self.xlabel = 'Range (km)'
282 self.xlabel = 'Range (km)'
283 self.ylabel = 'Height (km)'
283 self.ylabel = 'Height (km)'
284 self.bgcolor = 'white'
284 self.bgcolor = 'white'
285 self.cb_labels = self.data.meta['units']
285 self.cb_labels = self.data.meta['units']
286 self.lat = self.data.meta['latitude']
286 self.lat = self.data.meta['latitude']
287 self.lon = self.data.meta['longitude']
287 self.lon = self.data.meta['longitude']
288 self.xmin, self.xmax = float(
288 self.xmin, self.xmax = float(
289 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
289 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
290 self.ymin, self.ymax = float(
290 self.ymin, self.ymax = float(
291 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
291 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
292 # self.polar = True
292 # self.polar = True
293
293
294 def plot(self):
294 def plot(self):
295
295
296 for n, ax in enumerate(self.axes):
296 for n, ax in enumerate(self.axes):
297 data = self.data['param'][self.channels[n]]
297 data = self.data['param'][self.channels[n]]
298
298
299 zeniths = numpy.linspace(
299 zeniths = numpy.linspace(
300 0, self.data.meta['max_range'], data.shape[1])
300 0, self.data.meta['max_range'], data.shape[1])
301 if self.mode == 'E':
301 if self.mode == 'E':
302 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
302 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
303 r, theta = numpy.meshgrid(zeniths, azimuths)
303 r, theta = numpy.meshgrid(zeniths, azimuths)
304 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
304 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
305 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
305 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
306 x = km2deg(x) + self.lon
306 x = km2deg(x) + self.lon
307 y = km2deg(y) + self.lat
307 y = km2deg(y) + self.lat
308 else:
308 else:
309 azimuths = numpy.radians(self.data.yrange)
309 azimuths = numpy.radians(self.data.yrange)
310 r, theta = numpy.meshgrid(zeniths, azimuths)
310 r, theta = numpy.meshgrid(zeniths, azimuths)
311 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
311 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
312 self.y = zeniths
312 self.y = zeniths
313
313
314 if ax.firsttime:
314 if ax.firsttime:
315 if self.zlimits is not None:
315 if self.zlimits is not None:
316 self.zmin, self.zmax = self.zlimits[n]
316 self.zmin, self.zmax = self.zlimits[n]
317 ax.plt = ax.pcolormesh(# r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
317 ax.plt = ax.pcolormesh(# r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
318 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
318 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
319 vmin=self.zmin,
319 vmin=self.zmin,
320 vmax=self.zmax,
320 vmax=self.zmax,
321 cmap=self.cmaps[n])
321 cmap=self.cmaps[n])
322 else:
322 else:
323 if self.zlimits is not None:
323 if self.zlimits is not None:
324 self.zmin, self.zmax = self.zlimits[n]
324 self.zmin, self.zmax = self.zlimits[n]
325 ax.collections.remove(ax.collections[0])
325 ax.collections.remove(ax.collections[0])
326 ax.plt = ax.pcolormesh(# r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
326 ax.plt = ax.pcolormesh(# r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
327 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
327 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
328 vmin=self.zmin,
328 vmin=self.zmin,
329 vmax=self.zmax,
329 vmax=self.zmax,
330 cmap=self.cmaps[n])
330 cmap=self.cmaps[n])
331
331
332 if self.mode == 'A':
332 if self.mode == 'A':
333 continue
333 continue
334
334
335 # plot district names
335 # plot district names
336 f = open('/data/workspace/schain_scripts/distrito.csv')
336 f = open('/data/workspace/schain_scripts/distrito.csv')
337 for line in f:
337 for line in f:
338 label, lon, lat = [s.strip() for s in line.split(',') if s]
338 label, lon, lat = [s.strip() for s in line.split(',') if s]
339 lat = float(lat)
339 lat = float(lat)
340 lon = float(lon)
340 lon = float(lon)
341 # ax.plot(lon, lat, '.b', ms=2)
341 # ax.plot(lon, lat, '.b', ms=2)
342 ax.text(lon, lat, label.decode('utf8'), ha='center',
342 ax.text(lon, lat, label.decode('utf8'), ha='center',
343 va='bottom', size='8', color='black')
343 va='bottom', size='8', color='black')
344
344
345 # plot limites
345 # plot limites
346 limites = []
346 limites = []
347 tmp = []
347 tmp = []
348 for line in open('/data/workspace/schain_scripts/lima.csv'):
348 for line in open('/data/workspace/schain_scripts/lima.csv'):
349 if '#' in line:
349 if '#' in line:
350 if tmp:
350 if tmp:
351 limites.append(tmp)
351 limites.append(tmp)
352 tmp = []
352 tmp = []
353 continue
353 continue
354 values = line.strip().split(',')
354 values = line.strip().split(',')
355 tmp.append((float(values[0]), float(values[1])))
355 tmp.append((float(values[0]), float(values[1])))
356 for points in limites:
356 for points in limites:
357 ax.add_patch(
357 ax.add_patch(
358 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
358 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
359
359
360 # plot Cuencas
360 # plot Cuencas
361 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
361 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
362 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
362 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
363 values = [line.strip().split(',') for line in f]
363 values = [line.strip().split(',') for line in f]
364 points = [(float(s[0]), float(s[1])) for s in values]
364 points = [(float(s[0]), float(s[1])) for s in values]
365 ax.add_patch(Polygon(points, ec='b', fc='none'))
365 ax.add_patch(Polygon(points, ec='b', fc='none'))
366
366
367 # plot grid
367 # plot grid
368 for r in (15, 30, 45, 60):
368 for r in (15, 30, 45, 60):
369 ax.add_artist(plt.Circle((self.lon, self.lat),
369 ax.add_artist(plt.Circle((self.lon, self.lat),
370 km2deg(r), color='0.6', fill=False, lw=0.2))
370 km2deg(r), color='0.6', fill=False, lw=0.2))
371 ax.text(
371 ax.text(
372 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
372 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
373 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
373 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
374 '{}km'.format(r),
374 '{}km'.format(r),
375 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
375 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
376
376
377 if self.mode == 'E':
377 if self.mode == 'E':
378 title = 'El={}\N{DEGREE SIGN}'.format(self.data.meta['elevation'])
378 title = 'El={}\N{DEGREE SIGN}'.format(self.data.meta['elevation'])
379 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
379 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
380 else:
380 else:
381 title = 'Az={}\N{DEGREE SIGN}'.format(self.data.meta['azimuth'])
381 title = 'Az={}\N{DEGREE SIGN}'.format(self.data.meta['azimuth'])
382 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
382 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
383
383
384 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
384 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
385 self.titles = ['{} {}'.format(
385 self.titles = ['{} {}'.format(
386 self.data.parameters[x], title) for x in self.channels]
386 self.data.parameters[x], title) for x in self.channels]
387
387
388
388
389
389
390 class TxPowerPlot(Plot):
390 class TxPowerPlot(Plot):
391 '''
391 '''
392 Plot for TX Power from external file
392 Plot for TX Power from external file
393 '''
393 '''
394
394
395 CODE = 'tx_power'
395 CODE = 'tx_power'
396 plot_type = 'scatterbuffer'
396 plot_type = 'scatterbuffer'
397
397
398 def setup(self):
398 def setup(self):
399 self.xaxis = 'time'
399 self.xaxis = 'time'
400 self.ncols = 1
400 self.ncols = 1
401 self.nrows = 1
401 self.nrows = 1
402 self.nplots = 1
402 self.nplots = 1
403 self.ylabel = 'Power [kW]'
403 self.ylabel = 'Power [kW]'
404 self.xlabel = 'Time'
404 self.xlabel = 'Time'
405 self.titles = ['TX power']
405 self.titles = ['TX power']
406 self.colorbar = False
406 self.colorbar = False
407 self.plots_adjust.update({'right': 0.85 })
407 self.plots_adjust.update({'right': 0.85 })
408 #if not self.titles:
408 #if not self.titles:
409 self.titles = ['TX Power Plot']
409 self.titles = ['TX Power Plot']
410
410
411 def update(self, dataOut):
411 def update(self, dataOut):
412
412
413 data = {}
413 data = {}
414 meta = {}
414 meta = {}
415
415
416 data['tx_power'] = dataOut.txPower/1000
416 data['tx_power'] = dataOut.txPower/1000
417 meta['yrange'] = numpy.array([])
417 meta['yrange'] = numpy.array([])
418 #print(dataOut.txPower/1000)
418 #print(dataOut.txPower/1000)
419 return data, meta
419 return data, meta
420
420
421 def plot(self):
421 def plot(self):
422
422
423 x = self.data.times
423 x = self.data.times
424 xmin = self.data.min_time
424 xmin = self.data.min_time
425 xmax = xmin + self.xrange * 60 * 60
425 xmax = xmin + self.xrange * 60 * 60
426 Y = self.data['tx_power']
426 Y = self.data['tx_power']
427
427
428 if self.axes[0].firsttime:
428 if self.axes[0].firsttime:
429 if self.ymin is None: self.ymin = 0
429 if self.ymin is None: self.ymin = 0
430 if self.ymax is None: self.ymax = numpy.nanmax(Y) + 5
430 if self.ymax is None: self.ymax = numpy.nanmax(Y) + 5
431 if self.ymax == 5:
431 if self.ymax == 5:
432 self.ymax = 250
432 self.ymax = 250
433 self.ymin = 100
433 self.ymin = 100
434 self.axes[0].plot(x, Y, lw=1, label='Power')
434 self.axes[0].plot(x, Y, lw=1, label='Power')
435 plt.legend(bbox_to_anchor=(1.18, 1.0))
435 plt.legend(bbox_to_anchor=(1.18, 1.0))
436 else:
436 else:
437 self.axes[0].lines[0].set_data(x, Y) No newline at end of file
437 self.axes[0].lines[0].set_data(x, Y)
@@ -1,1928 +1,1935
1 # Copyright (c) 2012-2021 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2021 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Classes to plot Spectra data
5 """Classes to plot Spectra data
6
6
7 """
7 """
8
8
9 import os
9 import os
10 import numpy
10 import numpy
11 import datetime
11 import datetime
12
12
13 from schainpy.model.graphics.jroplot_base import Plot, plt, log
13 from schainpy.model.graphics.jroplot_base import Plot, plt, log
14 from itertools import combinations
14 from itertools import combinations
15 from matplotlib.ticker import LinearLocator
15 from matplotlib.ticker import LinearLocator
16
16
17 from schainpy.model.utils.BField import BField
17 from schainpy.model.utils.BField import BField
18 from scipy.interpolate import splrep
18 from scipy.interpolate import splrep
19 from scipy.interpolate import splev
19 from scipy.interpolate import splev
20
20
21 from matplotlib import __version__ as plt_version
21 from matplotlib import __version__ as plt_version
22
22
23 if plt_version >='3.3.4':
23 if plt_version >='3.3.4':
24 EXTRA_POINTS = 0
24 EXTRA_POINTS = 0
25 else:
25 else:
26 EXTRA_POINTS = 1
26 EXTRA_POINTS = 1
27 class SpectraPlot(Plot):
27 class SpectraPlot(Plot):
28 '''
28 '''
29 Plot for Spectra data
29 Plot for Spectra data
30 '''
30 '''
31
31
32 CODE = 'spc'
32 CODE = 'spc'
33 colormap = 'jet'
33 colormap = 'jet'
34 plot_type = 'pcolor'
34 plot_type = 'pcolor'
35 buffering = False
35 buffering = False
36 channelList = []
36 channelList = []
37 elevationList = []
37 elevationList = []
38 azimuthList = []
38 azimuthList = []
39
39
40 def setup(self):
40 def setup(self):
41
41
42 self.nplots = len(self.data.channels)
42 self.nplots = len(self.data.channels)
43 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
43 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
44 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
44 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
45 self.height = 3.4 * self.nrows
45 self.height = 3.4 * self.nrows
46 self.cb_label = 'dB'
46 self.cb_label = 'dB'
47 if self.showprofile:
47 if self.showprofile:
48 self.width = 5.2 * self.ncols
48 self.width = 5.2 * self.ncols
49 else:
49 else:
50 self.width = 4.2* self.ncols
50 self.width = 4.2* self.ncols
51 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.12})
51 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.12})
52 self.ylabel = 'Range [km]'
52 self.ylabel = 'Range [km]'
53
53
54 def update_list(self,dataOut):
54 def update_list(self,dataOut):
55
55
56 if len(self.channelList) == 0:
56 if len(self.channelList) == 0:
57 self.channelList = dataOut.channelList
57 self.channelList = dataOut.channelList
58 if len(self.elevationList) == 0:
58 if len(self.elevationList) == 0:
59 self.elevationList = dataOut.elevationList
59 self.elevationList = dataOut.elevationList
60 if len(self.azimuthList) == 0:
60 if len(self.azimuthList) == 0:
61 self.azimuthList = dataOut.azimuthList
61 self.azimuthList = dataOut.azimuthList
62
62
63 def update(self, dataOut):
63 def update(self, dataOut):
64
64
65 self.update_list(dataOut)
65 self.update_list(dataOut)
66 data = {}
66 data = {}
67 meta = {}
67 meta = {}
68
69 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
68 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
70 noise = 10*numpy.log10(dataOut.getNoise()/norm)
69 if dataOut.type == "Parameters":
71 z = numpy.zeros((dataOut.nChannels, dataOut.nFFTPoints, dataOut.nHeights))
70 noise = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
72 for ch in range(dataOut.nChannels):
71 spc = 10*numpy.log10(dataOut.data_spc/(dataOut.nProfiles))
73 if hasattr(dataOut.normFactor,'ndim'):
72 else:
74 if dataOut.normFactor.ndim > 1:
73 noise = 10*numpy.log10(dataOut.getNoise()/norm)
75 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor[ch]))
74
75 z = numpy.zeros((dataOut.nChannels, dataOut.nFFTPoints, dataOut.nHeights))
76 for ch in range(dataOut.nChannels):
77 if hasattr(dataOut.normFactor,'ndim'):
78 if dataOut.normFactor.ndim > 1:
79 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor[ch]))
76
80
81 else:
82 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
77 else:
83 else:
78 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
84 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
79 else:
80 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
81
85
82 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
86 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
83 spc = 10*numpy.log10(z)
87 spc = 10*numpy.log10(z)
84
88
85 data['spc'] = spc
89 data['spc'] = spc
86 data['rti'] = spc.mean(axis=1)
90 data['rti'] = spc.mean(axis=1)
87 data['noise'] = noise
91 data['noise'] = noise
88 meta['xrange'] = (dataOut.getFreqRange(EXTRA_POINTS)/1000., dataOut.getAcfRange(EXTRA_POINTS), dataOut.getVelRange(EXTRA_POINTS))
92 meta['xrange'] = (dataOut.getFreqRange(EXTRA_POINTS)/1000., dataOut.getAcfRange(EXTRA_POINTS), dataOut.getVelRange(EXTRA_POINTS))
89 if self.CODE == 'spc_moments':
93 if self.CODE == 'spc_moments':
90 data['moments'] = dataOut.moments
94 data['moments'] = dataOut.moments
91
95
92 return data, meta
96 return data, meta
93
97
94 def plot(self):
98 def plot(self):
95
99
96 if self.xaxis == "frequency":
100 if self.xaxis == "frequency":
97 x = self.data.xrange[0]
101 x = self.data.xrange[0]
98 self.xlabel = "Frequency (kHz)"
102 self.xlabel = "Frequency (kHz)"
99 elif self.xaxis == "time":
103 elif self.xaxis == "time":
100 x = self.data.xrange[1]
104 x = self.data.xrange[1]
101 self.xlabel = "Time (ms)"
105 self.xlabel = "Time (ms)"
102 else:
106 else:
103 x = self.data.xrange[2]
107 x = self.data.xrange[2]
104 self.xlabel = "Velocity (m/s)"
108 self.xlabel = "Velocity (m/s)"
105
109
106 if (self.CODE == 'spc_moments') | (self.CODE == 'gaussian_fit'):
110 if (self.CODE == 'spc_moments') | (self.CODE == 'gaussian_fit'):
107 x = self.data.xrange[2]
111 x = self.data.xrange[2]
108 self.xlabel = "Velocity (m/s)"
112 self.xlabel = "Velocity (m/s)"
109
113
110 self.titles = []
114 self.titles = []
111
115
112 y = self.data.yrange
116 y = self.data.yrange
113 self.y = y
117 self.y = y
114
118
115 data = self.data[-1]
119 data = self.data[-1]
116 z = data['spc']
120 z = data['spc']
117
121
118 for n, ax in enumerate(self.axes):
122 for n, ax in enumerate(self.axes):
119 noise = self.data['noise'][n][0]
123 noise = self.data['noise'][n][0]
120 # noise = data['noise'][n]
124 # noise = data['noise'][n]
121
125
122 if self.CODE == 'spc_moments':
126 if self.CODE == 'spc_moments':
123 mean = data['moments'][n, 1]
127 mean = data['moments'][n, 1]
124 if self.CODE == 'gaussian_fit':
128 if self.CODE == 'gaussian_fit':
125 gau0 = data['gaussfit'][n][2,:,0]
129 gau0 = data['gaussfit'][n][2,:,0]
126 gau1 = data['gaussfit'][n][2,:,1]
130 gau1 = data['gaussfit'][n][2,:,1]
127 if ax.firsttime:
131 if ax.firsttime:
128 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
132 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
129 self.xmin = self.xmin if self.xmin else -self.xmax
133 self.xmin = self.xmin if self.xmin else -self.xmax
130 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
134 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
131 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
135 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
132 ax.plt = ax.pcolormesh(x, y, z[n].T,
136 ax.plt = ax.pcolormesh(x, y, z[n].T,
133 vmin=self.zmin,
137 vmin=self.zmin,
134 vmax=self.zmax,
138 vmax=self.zmax,
135 cmap=plt.get_cmap(self.colormap)
139 cmap=plt.get_cmap(self.colormap)
136 )
140 )
137
141
138 if self.showprofile:
142 if self.showprofile:
139 ax.plt_profile = self.pf_axes[n].plot(
143 ax.plt_profile = self.pf_axes[n].plot(
140 data['rti'][n], y)[0]
144 data['rti'][n], y)[0]
141 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
145 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
142 color="k", linestyle="dashed", lw=1)[0]
146 color="k", linestyle="dashed", lw=1)[0]
143 if self.CODE == 'spc_moments':
147 if self.CODE == 'spc_moments':
144 ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
148 ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
145 if self.CODE == 'gaussian_fit':
149 if self.CODE == 'gaussian_fit':
146 ax.plt_gau0 = ax.plot(gau0, y, color='r', lw=1)[0]
150 ax.plt_gau0 = ax.plot(gau0, y, color='r', lw=1)[0]
147 ax.plt_gau1 = ax.plot(gau1, y, color='y', lw=1)[0]
151 ax.plt_gau1 = ax.plot(gau1, y, color='y', lw=1)[0]
148 else:
152 else:
149 ax.plt.set_array(z[n].T.ravel())
153 ax.plt.set_array(z[n].T.ravel())
150 if self.showprofile:
154 if self.showprofile:
151 ax.plt_profile.set_data(data['rti'][n], y)
155 ax.plt_profile.set_data(data['rti'][n], y)
152 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
156 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
153 if self.CODE == 'spc_moments':
157 if self.CODE == 'spc_moments':
154 ax.plt_mean.set_data(mean, y)
158 ax.plt_mean.set_data(mean, y)
155 if self.CODE == 'gaussian_fit':
159 if self.CODE == 'gaussian_fit':
156 ax.plt_gau0.set_data(gau0, y)
160 ax.plt_gau0.set_data(gau0, y)
157 ax.plt_gau1.set_data(gau1, y)
161 ax.plt_gau1.set_data(gau1, y)
158 if len(self.azimuthList) > 0 and len(self.elevationList) > 0:
162 if len(self.azimuthList) > 0 and len(self.elevationList) > 0:
159 self.titles.append('CH {}: {:2.1f}elv {:2.1f}az {:3.2f}dB'.format(self.channelList[n], noise, self.elevationList[n], self.azimuthList[n]))
163 self.titles.append('CH {}: {:2.1f}elv {:2.1f}az {:3.2f}dB'.format(self.channelList[n], noise, self.elevationList[n], self.azimuthList[n]))
160 else:
164 else:
161 self.titles.append('CH {}: {:3.2f}dB'.format(self.channelList[n], noise))
165 self.titles.append('CH {}: {:3.2f}dB'.format(self.channelList[n], noise))
162
166
163 class SpectraObliquePlot(Plot):
167 class SpectraObliquePlot(Plot):
164 '''
168 '''
165 Plot for Spectra data
169 Plot for Spectra data
166 '''
170 '''
167
171
168 CODE = 'spc_oblique'
172 CODE = 'spc_oblique'
169 colormap = 'jet'
173 colormap = 'jet'
170 plot_type = 'pcolor'
174 plot_type = 'pcolor'
171
175
172 def setup(self):
176 def setup(self):
173 self.xaxis = "oblique"
177 self.xaxis = "oblique"
174 self.nplots = len(self.data.channels)
178 self.nplots = len(self.data.channels)
175 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
179 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
176 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
180 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
177 self.height = 2.6 * self.nrows
181 self.height = 2.6 * self.nrows
178 self.cb_label = 'dB'
182 self.cb_label = 'dB'
179 if self.showprofile:
183 if self.showprofile:
180 self.width = 4 * self.ncols
184 self.width = 4 * self.ncols
181 else:
185 else:
182 self.width = 3.5 * self.ncols
186 self.width = 3.5 * self.ncols
183 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
187 self.plots_adjust.update({'wspace': 0.8, 'hspace':0.2, 'left': 0.2, 'right': 0.9, 'bottom': 0.18})
184 self.ylabel = 'Range [km]'
188 self.ylabel = 'Range [km]'
185
189
186 def update(self, dataOut):
190 def update(self, dataOut):
187
191
188 data = {}
192 data = {}
189 meta = {}
193 meta = {}
190
194
191 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
195 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
192 data['spc'] = spc
196 data['spc'] = spc
193 data['rti'] = dataOut.getPower()
197 data['rti'] = dataOut.getPower()
194 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
198 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
195 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
199 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
196
200
197 data['shift1'] = dataOut.Dop_EEJ_T1[0]
201 data['shift1'] = dataOut.Dop_EEJ_T1[0]
198 data['shift2'] = dataOut.Dop_EEJ_T2[0]
202 data['shift2'] = dataOut.Dop_EEJ_T2[0]
199 data['max_val_2'] = dataOut.Oblique_params[0,-1,:]
203 data['max_val_2'] = dataOut.Oblique_params[0,-1,:]
200 data['shift1_error'] = dataOut.Err_Dop_EEJ_T1[0]
204 data['shift1_error'] = dataOut.Err_Dop_EEJ_T1[0]
201 data['shift2_error'] = dataOut.Err_Dop_EEJ_T2[0]
205 data['shift2_error'] = dataOut.Err_Dop_EEJ_T2[0]
202
206
203 return data, meta
207 return data, meta
204
208
205 def plot(self):
209 def plot(self):
206
210
207 if self.xaxis == "frequency":
211 if self.xaxis == "frequency":
208 x = self.data.xrange[0]
212 x = self.data.xrange[0]
209 self.xlabel = "Frequency (kHz)"
213 self.xlabel = "Frequency (kHz)"
210 elif self.xaxis == "time":
214 elif self.xaxis == "time":
211 x = self.data.xrange[1]
215 x = self.data.xrange[1]
212 self.xlabel = "Time (ms)"
216 self.xlabel = "Time (ms)"
213 else:
217 else:
214 x = self.data.xrange[2]
218 x = self.data.xrange[2]
215 self.xlabel = "Velocity (m/s)"
219 self.xlabel = "Velocity (m/s)"
216
220
217 self.titles = []
221 self.titles = []
218
222
219 y = self.data.yrange
223 y = self.data.yrange
220 self.y = y
224 self.y = y
221
225
222 data = self.data[-1]
226 data = self.data[-1]
223 z = data['spc']
227 z = data['spc']
224
228
225 for n, ax in enumerate(self.axes):
229 for n, ax in enumerate(self.axes):
226 noise = self.data['noise'][n][-1]
230 noise = self.data['noise'][n][-1]
227 shift1 = data['shift1']
231 shift1 = data['shift1']
228 shift2 = data['shift2']
232 shift2 = data['shift2']
229 max_val_2 = data['max_val_2']
233 max_val_2 = data['max_val_2']
230 err1 = data['shift1_error']
234 err1 = data['shift1_error']
231 err2 = data['shift2_error']
235 err2 = data['shift2_error']
232 if ax.firsttime:
236 if ax.firsttime:
233
237
234 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
238 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
235 self.xmin = self.xmin if self.xmin else -self.xmax
239 self.xmin = self.xmin if self.xmin else -self.xmax
236 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
240 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
237 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
241 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
238 ax.plt = ax.pcolormesh(x, y, z[n].T,
242 ax.plt = ax.pcolormesh(x, y, z[n].T,
239 vmin=self.zmin,
243 vmin=self.zmin,
240 vmax=self.zmax,
244 vmax=self.zmax,
241 cmap=plt.get_cmap(self.colormap)
245 cmap=plt.get_cmap(self.colormap)
242 )
246 )
243
247
244 if self.showprofile:
248 if self.showprofile:
245 ax.plt_profile = self.pf_axes[n].plot(
249 ax.plt_profile = self.pf_axes[n].plot(
246 self.data['rti'][n][-1], y)[0]
250 self.data['rti'][n][-1], y)[0]
247 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
251 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
248 color="k", linestyle="dashed", lw=1)[0]
252 color="k", linestyle="dashed", lw=1)[0]
249
253
250 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
254 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
251 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
255 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
252 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
256 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
253
257
254 else:
258 else:
255 self.ploterr1.remove()
259 self.ploterr1.remove()
256 self.ploterr2.remove()
260 self.ploterr2.remove()
257 self.ploterr3.remove()
261 self.ploterr3.remove()
258 ax.plt.set_array(z[n].T.ravel())
262 ax.plt.set_array(z[n].T.ravel())
259 if self.showprofile:
263 if self.showprofile:
260 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
264 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
261 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
265 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
262 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
266 self.ploterr1 = ax.errorbar(shift1, y, xerr=err1, fmt='k^', elinewidth=2.2, marker='o', linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
263 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
267 self.ploterr2 = ax.errorbar(shift2, y, xerr=err2, fmt='m^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
264 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
268 self.ploterr3 = ax.errorbar(max_val_2, y, xerr=0, fmt='g^',elinewidth=2.2,marker='o',linestyle='None',markersize=2.5,capsize=0.3,markeredgewidth=0.2)
265
269
266 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
270 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
267
271
268
272
269 class CrossSpectraPlot(Plot):
273 class CrossSpectraPlot(Plot):
270
274
271 CODE = 'cspc'
275 CODE = 'cspc'
272 colormap = 'jet'
276 colormap = 'jet'
273 plot_type = 'pcolor'
277 plot_type = 'pcolor'
274 zmin_coh = None
278 zmin_coh = None
275 zmax_coh = None
279 zmax_coh = None
276 zmin_phase = None
280 zmin_phase = None
277 zmax_phase = None
281 zmax_phase = None
278 realChannels = None
282 realChannels = None
279 crossPairs = None
283 crossPairs = None
280
284
281 def setup(self):
285 def setup(self):
282
286
283 self.ncols = 4
287 self.ncols = 4
284 self.nplots = len(self.data.pairs) * 2
288 self.nplots = len(self.data.pairs) * 2
285 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
289 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
286 self.width = 3.1 * self.ncols
290 self.width = 3.1 * self.ncols
287 self.height = 2.6 * self.nrows
291 self.height = 2.6 * self.nrows
288 self.ylabel = 'Range [km]'
292 self.ylabel = 'Range [km]'
289 self.showprofile = False
293 self.showprofile = False
290 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
294 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
291
295
292 def update(self, dataOut):
296 def update(self, dataOut):
293
297
294 data = {}
298 data = {}
295 meta = {}
299 meta = {}
296
300
297 spc = dataOut.data_spc
301 spc = dataOut.data_spc
298 cspc = dataOut.data_cspc
302 cspc = dataOut.data_cspc
299 meta['xrange'] = (dataOut.getFreqRange(EXTRA_POINTS)/1000., dataOut.getAcfRange(EXTRA_POINTS), dataOut.getVelRange(EXTRA_POINTS))
303 meta['xrange'] = (dataOut.getFreqRange(EXTRA_POINTS)/1000., dataOut.getAcfRange(EXTRA_POINTS), dataOut.getVelRange(EXTRA_POINTS))
300 rawPairs = list(combinations(list(range(dataOut.nChannels)), 2))
304 rawPairs = list(combinations(list(range(dataOut.nChannels)), 2))
301 meta['pairs'] = rawPairs
305 meta['pairs'] = rawPairs
302 if self.crossPairs == None:
306 if self.crossPairs == None:
303 self.crossPairs = dataOut.pairsList
307 self.crossPairs = dataOut.pairsList
304 tmp = []
308 tmp = []
305
309
306 for n, pair in enumerate(meta['pairs']):
310 for n, pair in enumerate(meta['pairs']):
307 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
311 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
308 coh = numpy.abs(out)
312 coh = numpy.abs(out)
309 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
313 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
310 tmp.append(coh)
314 tmp.append(coh)
311 tmp.append(phase)
315 tmp.append(phase)
312
316
313 data['cspc'] = numpy.array(tmp)
317 data['cspc'] = numpy.array(tmp)
314
318
315 return data, meta
319 return data, meta
316
320
317 def plot(self):
321 def plot(self):
318
322
319 if self.xaxis == "frequency":
323 if self.xaxis == "frequency":
320 x = self.data.xrange[0]
324 x = self.data.xrange[0]
321 self.xlabel = "Frequency (kHz)"
325 self.xlabel = "Frequency (kHz)"
322 elif self.xaxis == "time":
326 elif self.xaxis == "time":
323 x = self.data.xrange[1]
327 x = self.data.xrange[1]
324 self.xlabel = "Time (ms)"
328 self.xlabel = "Time (ms)"
325 else:
329 else:
326 x = self.data.xrange[2]
330 x = self.data.xrange[2]
327 self.xlabel = "Velocity (m/s)"
331 self.xlabel = "Velocity (m/s)"
328
332
329 self.titles = []
333 self.titles = []
330
334
331 y = self.data.yrange
335 y = self.data.yrange
332 self.y = y
336 self.y = y
333
337
334 data = self.data[-1]
338 data = self.data[-1]
335 cspc = data['cspc']
339 cspc = data['cspc']
336
340
337 for n in range(len(self.data.pairs)):
341 for n in range(len(self.data.pairs)):
338 pair = self.crossPairs[n]
342 pair = self.crossPairs[n]
339 coh = cspc[n*2]
343 coh = cspc[n*2]
340 phase = cspc[n*2+1]
344 phase = cspc[n*2+1]
341 ax = self.axes[2 * n]
345 ax = self.axes[2 * n]
342 if ax.firsttime:
346 if ax.firsttime:
343 ax.plt = ax.pcolormesh(x, y, coh.T,
347 ax.plt = ax.pcolormesh(x, y, coh.T,
344 vmin=self.zmin_coh,
348 vmin=self.zmin_coh,
345 vmax=self.zmax_coh,
349 vmax=self.zmax_coh,
346 cmap=plt.get_cmap(self.colormap_coh)
350 cmap=plt.get_cmap(self.colormap_coh)
347 )
351 )
348 else:
352 else:
349 ax.plt.set_array(coh.T.ravel())
353 ax.plt.set_array(coh.T.ravel())
350 self.titles.append(
354 self.titles.append(
351 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
355 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
352
356
353 ax = self.axes[2 * n + 1]
357 ax = self.axes[2 * n + 1]
354 if ax.firsttime:
358 if ax.firsttime:
355 ax.plt = ax.pcolormesh(x, y, phase.T,
359 ax.plt = ax.pcolormesh(x, y, phase.T,
356 vmin=-180,
360 vmin=-180,
357 vmax=180,
361 vmax=180,
358 cmap=plt.get_cmap(self.colormap_phase)
362 cmap=plt.get_cmap(self.colormap_phase)
359 )
363 )
360 else:
364 else:
361 ax.plt.set_array(phase.T.ravel())
365 ax.plt.set_array(phase.T.ravel())
362 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
366 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
363
367
364
368
365 class CrossSpectra4Plot(Plot):
369 class CrossSpectra4Plot(Plot):
366
370
367 CODE = 'cspc'
371 CODE = 'cspc'
368 colormap = 'jet'
372 colormap = 'jet'
369 plot_type = 'pcolor'
373 plot_type = 'pcolor'
370 zmin_coh = None
374 zmin_coh = None
371 zmax_coh = None
375 zmax_coh = None
372 zmin_phase = None
376 zmin_phase = None
373 zmax_phase = None
377 zmax_phase = None
374
378
375 def setup(self):
379 def setup(self):
376
380
377 self.ncols = 4
381 self.ncols = 4
378 self.nrows = len(self.data.pairs)
382 self.nrows = len(self.data.pairs)
379 self.nplots = self.nrows * 4
383 self.nplots = self.nrows * 4
380 self.width = 3.1 * self.ncols
384 self.width = 3.1 * self.ncols
381 self.height = 5 * self.nrows
385 self.height = 5 * self.nrows
382 self.ylabel = 'Range [km]'
386 self.ylabel = 'Range [km]'
383 self.showprofile = False
387 self.showprofile = False
384 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
388 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
385
389
386 def plot(self):
390 def plot(self):
387
391
388 if self.xaxis == "frequency":
392 if self.xaxis == "frequency":
389 x = self.data.xrange[0]
393 x = self.data.xrange[0]
390 self.xlabel = "Frequency (kHz)"
394 self.xlabel = "Frequency (kHz)"
391 elif self.xaxis == "time":
395 elif self.xaxis == "time":
392 x = self.data.xrange[1]
396 x = self.data.xrange[1]
393 self.xlabel = "Time (ms)"
397 self.xlabel = "Time (ms)"
394 else:
398 else:
395 x = self.data.xrange[2]
399 x = self.data.xrange[2]
396 self.xlabel = "Velocity (m/s)"
400 self.xlabel = "Velocity (m/s)"
397
401
398 self.titles = []
402 self.titles = []
399
403
400
404
401 y = self.data.heights
405 y = self.data.heights
402 self.y = y
406 self.y = y
403 nspc = self.data['spc']
407 nspc = self.data['spc']
404 spc = self.data['cspc'][0]
408 spc = self.data['cspc'][0]
405 cspc = self.data['cspc'][1]
409 cspc = self.data['cspc'][1]
406
410
407 for n in range(self.nrows):
411 for n in range(self.nrows):
408 noise = self.data['noise'][:,-1]
412 noise = self.data['noise'][:,-1]
409 pair = self.data.pairs[n]
413 pair = self.data.pairs[n]
410
414
411 ax = self.axes[4 * n]
415 ax = self.axes[4 * n]
412 if ax.firsttime:
416 if ax.firsttime:
413 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
417 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
414 self.xmin = self.xmin if self.xmin else -self.xmax
418 self.xmin = self.xmin if self.xmin else -self.xmax
415 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
419 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
416 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
420 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
417 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
421 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
418 vmin=self.zmin,
422 vmin=self.zmin,
419 vmax=self.zmax,
423 vmax=self.zmax,
420 cmap=plt.get_cmap(self.colormap)
424 cmap=plt.get_cmap(self.colormap)
421 )
425 )
422 else:
426 else:
423
427
424 ax.plt.set_array(nspc[pair[0]].T.ravel())
428 ax.plt.set_array(nspc[pair[0]].T.ravel())
425 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
429 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
426
430
427 ax = self.axes[4 * n + 1]
431 ax = self.axes[4 * n + 1]
428
432
429 if ax.firsttime:
433 if ax.firsttime:
430 ax.plt = ax.pcolormesh(x , y, numpy.flip(nspc[pair[1]],axis=0).T,
434 ax.plt = ax.pcolormesh(x , y, numpy.flip(nspc[pair[1]],axis=0).T,
431 vmin=self.zmin,
435 vmin=self.zmin,
432 vmax=self.zmax,
436 vmax=self.zmax,
433 cmap=plt.get_cmap(self.colormap)
437 cmap=plt.get_cmap(self.colormap)
434 )
438 )
435 else:
439 else:
436
440
437 ax.plt.set_array(numpy.flip(nspc[pair[1]],axis=0).T.ravel())
441 ax.plt.set_array(numpy.flip(nspc[pair[1]],axis=0).T.ravel())
438 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
442 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
439
443
440 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
444 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
441 coh = numpy.abs(out)
445 coh = numpy.abs(out)
442 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
446 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
443
447
444 ax = self.axes[4 * n + 2]
448 ax = self.axes[4 * n + 2]
445 if ax.firsttime:
449 if ax.firsttime:
446 ax.plt = ax.pcolormesh(x, y, numpy.flip(coh,axis=0).T,
450 ax.plt = ax.pcolormesh(x, y, numpy.flip(coh,axis=0).T,
447 vmin=0,
451 vmin=0,
448 vmax=1,
452 vmax=1,
449 cmap=plt.get_cmap(self.colormap_coh)
453 cmap=plt.get_cmap(self.colormap_coh)
450 )
454 )
451 else:
455 else:
452 ax.plt.set_array(numpy.flip(coh,axis=0).T.ravel())
456 ax.plt.set_array(numpy.flip(coh,axis=0).T.ravel())
453 self.titles.append(
457 self.titles.append(
454 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
458 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
455
459
456 ax = self.axes[4 * n + 3]
460 ax = self.axes[4 * n + 3]
457 if ax.firsttime:
461 if ax.firsttime:
458 ax.plt = ax.pcolormesh(x, y, numpy.flip(phase,axis=0).T,
462 ax.plt = ax.pcolormesh(x, y, numpy.flip(phase,axis=0).T,
459 vmin=-180,
463 vmin=-180,
460 vmax=180,
464 vmax=180,
461 cmap=plt.get_cmap(self.colormap_phase)
465 cmap=plt.get_cmap(self.colormap_phase)
462 )
466 )
463 else:
467 else:
464 ax.plt.set_array(numpy.flip(phase,axis=0).T.ravel())
468 ax.plt.set_array(numpy.flip(phase,axis=0).T.ravel())
465 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
469 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
466
470
467
471
468 class CrossSpectra2Plot(Plot):
472 class CrossSpectra2Plot(Plot):
469
473
470 CODE = 'cspc'
474 CODE = 'cspc'
471 colormap = 'jet'
475 colormap = 'jet'
472 plot_type = 'pcolor'
476 plot_type = 'pcolor'
473 zmin_coh = None
477 zmin_coh = None
474 zmax_coh = None
478 zmax_coh = None
475 zmin_phase = None
479 zmin_phase = None
476 zmax_phase = None
480 zmax_phase = None
477
481
478 def setup(self):
482 def setup(self):
479
483
480 self.ncols = 1
484 self.ncols = 1
481 self.nrows = len(self.data.pairs)
485 self.nrows = len(self.data.pairs)
482 self.nplots = self.nrows * 1
486 self.nplots = self.nrows * 1
483 self.width = 3.1 * self.ncols
487 self.width = 3.1 * self.ncols
484 self.height = 5 * self.nrows
488 self.height = 5 * self.nrows
485 self.ylabel = 'Range [km]'
489 self.ylabel = 'Range [km]'
486 self.showprofile = False
490 self.showprofile = False
487 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
491 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
488
492
489 def plot(self):
493 def plot(self):
490
494
491 if self.xaxis == "frequency":
495 if self.xaxis == "frequency":
492 x = self.data.xrange[0]
496 x = self.data.xrange[0]
493 self.xlabel = "Frequency (kHz)"
497 self.xlabel = "Frequency (kHz)"
494 elif self.xaxis == "time":
498 elif self.xaxis == "time":
495 x = self.data.xrange[1]
499 x = self.data.xrange[1]
496 self.xlabel = "Time (ms)"
500 self.xlabel = "Time (ms)"
497 else:
501 else:
498 x = self.data.xrange[2]
502 x = self.data.xrange[2]
499 self.xlabel = "Velocity (m/s)"
503 self.xlabel = "Velocity (m/s)"
500
504
501 self.titles = []
505 self.titles = []
502
506
503
507
504 y = self.data.heights
508 y = self.data.heights
505 self.y = y
509 self.y = y
506 cspc = self.data['cspc'][1]
510 cspc = self.data['cspc'][1]
507
511
508 for n in range(self.nrows):
512 for n in range(self.nrows):
509 noise = self.data['noise'][:,-1]
513 noise = self.data['noise'][:,-1]
510 pair = self.data.pairs[n]
514 pair = self.data.pairs[n]
511 out = cspc[n]
515 out = cspc[n]
512 cross = numpy.abs(out)
516 cross = numpy.abs(out)
513 z = cross/self.data.nFactor
517 z = cross/self.data.nFactor
514 cross = 10*numpy.log10(z)
518 cross = 10*numpy.log10(z)
515
519
516 ax = self.axes[1 * n]
520 ax = self.axes[1 * n]
517 if ax.firsttime:
521 if ax.firsttime:
518 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
522 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
519 self.xmin = self.xmin if self.xmin else -self.xmax
523 self.xmin = self.xmin if self.xmin else -self.xmax
520 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
524 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
521 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
525 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
522 ax.plt = ax.pcolormesh(x, y, cross.T,
526 ax.plt = ax.pcolormesh(x, y, cross.T,
523 vmin=self.zmin,
527 vmin=self.zmin,
524 vmax=self.zmax,
528 vmax=self.zmax,
525 cmap=plt.get_cmap(self.colormap)
529 cmap=plt.get_cmap(self.colormap)
526 )
530 )
527 else:
531 else:
528 ax.plt.set_array(cross.T.ravel())
532 ax.plt.set_array(cross.T.ravel())
529 self.titles.append(
533 self.titles.append(
530 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
534 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
531
535
532
536
533 class CrossSpectra3Plot(Plot):
537 class CrossSpectra3Plot(Plot):
534
538
535 CODE = 'cspc'
539 CODE = 'cspc'
536 colormap = 'jet'
540 colormap = 'jet'
537 plot_type = 'pcolor'
541 plot_type = 'pcolor'
538 zmin_coh = None
542 zmin_coh = None
539 zmax_coh = None
543 zmax_coh = None
540 zmin_phase = None
544 zmin_phase = None
541 zmax_phase = None
545 zmax_phase = None
542
546
543 def setup(self):
547 def setup(self):
544
548
545 self.ncols = 3
549 self.ncols = 3
546 self.nrows = len(self.data.pairs)
550 self.nrows = len(self.data.pairs)
547 self.nplots = self.nrows * 3
551 self.nplots = self.nrows * 3
548 self.width = 3.1 * self.ncols
552 self.width = 3.1 * self.ncols
549 self.height = 5 * self.nrows
553 self.height = 5 * self.nrows
550 self.ylabel = 'Range [km]'
554 self.ylabel = 'Range [km]'
551 self.showprofile = False
555 self.showprofile = False
552 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
556 self.plots_adjust.update({'left': 0.22, 'right': .90, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
553
557
554 def plot(self):
558 def plot(self):
555
559
556 if self.xaxis == "frequency":
560 if self.xaxis == "frequency":
557 x = self.data.xrange[0]
561 x = self.data.xrange[0]
558 self.xlabel = "Frequency (kHz)"
562 self.xlabel = "Frequency (kHz)"
559 elif self.xaxis == "time":
563 elif self.xaxis == "time":
560 x = self.data.xrange[1]
564 x = self.data.xrange[1]
561 self.xlabel = "Time (ms)"
565 self.xlabel = "Time (ms)"
562 else:
566 else:
563 x = self.data.xrange[2]
567 x = self.data.xrange[2]
564 self.xlabel = "Velocity (m/s)"
568 self.xlabel = "Velocity (m/s)"
565
569
566 self.titles = []
570 self.titles = []
567
571
568
572
569 y = self.data.heights
573 y = self.data.heights
570 self.y = y
574 self.y = y
571
575
572 cspc = self.data['cspc'][1]
576 cspc = self.data['cspc'][1]
573
577
574 for n in range(self.nrows):
578 for n in range(self.nrows):
575 noise = self.data['noise'][:,-1]
579 noise = self.data['noise'][:,-1]
576 pair = self.data.pairs[n]
580 pair = self.data.pairs[n]
577 out = cspc[n]
581 out = cspc[n]
578
582
579 cross = numpy.abs(out)
583 cross = numpy.abs(out)
580 z = cross/self.data.nFactor
584 z = cross/self.data.nFactor
581 cross = 10*numpy.log10(z)
585 cross = 10*numpy.log10(z)
582
586
583 out_r= out.real/self.data.nFactor
587 out_r= out.real/self.data.nFactor
584
588
585 out_i= out.imag/self.data.nFactor
589 out_i= out.imag/self.data.nFactor
586
590
587 ax = self.axes[3 * n]
591 ax = self.axes[3 * n]
588 if ax.firsttime:
592 if ax.firsttime:
589 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
593 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
590 self.xmin = self.xmin if self.xmin else -self.xmax
594 self.xmin = self.xmin if self.xmin else -self.xmax
591 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
595 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
592 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
596 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
593 ax.plt = ax.pcolormesh(x, y, cross.T,
597 ax.plt = ax.pcolormesh(x, y, cross.T,
594 vmin=self.zmin,
598 vmin=self.zmin,
595 vmax=self.zmax,
599 vmax=self.zmax,
596 cmap=plt.get_cmap(self.colormap)
600 cmap=plt.get_cmap(self.colormap)
597 )
601 )
598 else:
602 else:
599 ax.plt.set_array(cross.T.ravel())
603 ax.plt.set_array(cross.T.ravel())
600 self.titles.append(
604 self.titles.append(
601 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
605 'Cross Spectra Power Ch{} * Ch{}'.format(pair[0], pair[1]))
602
606
603 ax = self.axes[3 * n + 1]
607 ax = self.axes[3 * n + 1]
604 if ax.firsttime:
608 if ax.firsttime:
605 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
609 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
606 self.xmin = self.xmin if self.xmin else -self.xmax
610 self.xmin = self.xmin if self.xmin else -self.xmax
607 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
611 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
608 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
612 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
609 ax.plt = ax.pcolormesh(x, y, out_r.T,
613 ax.plt = ax.pcolormesh(x, y, out_r.T,
610 vmin=-1.e6,
614 vmin=-1.e6,
611 vmax=0,
615 vmax=0,
612 cmap=plt.get_cmap(self.colormap)
616 cmap=plt.get_cmap(self.colormap)
613 )
617 )
614 else:
618 else:
615 ax.plt.set_array(out_r.T.ravel())
619 ax.plt.set_array(out_r.T.ravel())
616 self.titles.append(
620 self.titles.append(
617 'Cross Spectra Real Ch{} * Ch{}'.format(pair[0], pair[1]))
621 'Cross Spectra Real Ch{} * Ch{}'.format(pair[0], pair[1]))
618
622
619 ax = self.axes[3 * n + 2]
623 ax = self.axes[3 * n + 2]
620
624
621
625
622 if ax.firsttime:
626 if ax.firsttime:
623 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
627 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
624 self.xmin = self.xmin if self.xmin else -self.xmax
628 self.xmin = self.xmin if self.xmin else -self.xmax
625 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
629 self.zmin = self.zmin if self.zmin else numpy.nanmin(cross)
626 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
630 self.zmax = self.zmax if self.zmax else numpy.nanmax(cross)
627 ax.plt = ax.pcolormesh(x, y, out_i.T,
631 ax.plt = ax.pcolormesh(x, y, out_i.T,
628 vmin=-1.e6,
632 vmin=-1.e6,
629 vmax=1.e6,
633 vmax=1.e6,
630 cmap=plt.get_cmap(self.colormap)
634 cmap=plt.get_cmap(self.colormap)
631 )
635 )
632 else:
636 else:
633 ax.plt.set_array(out_i.T.ravel())
637 ax.plt.set_array(out_i.T.ravel())
634 self.titles.append(
638 self.titles.append(
635 'Cross Spectra Imag Ch{} * Ch{}'.format(pair[0], pair[1]))
639 'Cross Spectra Imag Ch{} * Ch{}'.format(pair[0], pair[1]))
636
640
637 class RTIPlot(Plot):
641 class RTIPlot(Plot):
638 '''
642 '''
639 Plot for RTI data
643 Plot for RTI data
640 '''
644 '''
641
645
642 CODE = 'rti'
646 CODE = 'rti'
643 colormap = 'jet'
647 colormap = 'jet'
644 plot_type = 'pcolorbuffer'
648 plot_type = 'pcolorbuffer'
645 titles = None
649 titles = None
646 channelList = []
650 channelList = []
647 elevationList = []
651 elevationList = []
648 azimuthList = []
652 azimuthList = []
649
653
650 def setup(self):
654 def setup(self):
651 self.xaxis = 'time'
655 self.xaxis = 'time'
652 self.ncols = 1
656 self.ncols = 1
653 self.nrows = len(self.data.channels)
657 self.nrows = len(self.data.channels)
654 self.nplots = len(self.data.channels)
658 self.nplots = len(self.data.channels)
655 self.ylabel = 'Range [km]'
659 self.ylabel = 'Range [km]'
656 #self.xlabel = 'Time'
660 #self.xlabel = 'Time'
657 self.cb_label = 'dB'
661 self.cb_label = 'dB'
658 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
662 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.1, 'right':0.95})
659 self.titles = ['{} Channel {}'.format(
663 self.titles = ['{} Channel {}'.format(
660 self.CODE.upper(), x) for x in range(self.nplots)]
664 self.CODE.upper(), x) for x in range(self.nplots)]
661
665
662 def update_list(self,dataOut):
666 def update_list(self,dataOut):
663
667
664 if len(self.channelList) == 0:
668 if len(self.channelList) == 0:
665 self.channelList = dataOut.channelList
669 self.channelList = dataOut.channelList
666 if len(self.elevationList) == 0:
670 if len(self.elevationList) == 0:
667 self.elevationList = dataOut.elevationList
671 self.elevationList = dataOut.elevationList
668 if len(self.azimuthList) == 0:
672 if len(self.azimuthList) == 0:
669 self.azimuthList = dataOut.azimuthList
673 self.azimuthList = dataOut.azimuthList
670
674
671
675
672 def update(self, dataOut):
676 def update(self, dataOut):
673
677
674 if len(self.channelList) == 0:
678 if len(self.channelList) == 0:
675 self.update_list(dataOut)
679 self.update_list(dataOut)
676 data = {}
680 data = {}
677 meta = {}
681 meta = {}
678 data['rti'] = dataOut.getPower()
682 data['rti'] = dataOut.getPower()
679 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
683 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
680 noise = 10*numpy.log10(dataOut.getNoise()/norm)
684 noise = 10*numpy.log10(dataOut.getNoise()/norm)
681 data['noise'] = noise
685 data['noise'] = noise
682
686
683 return data, meta
687 return data, meta
684
688
685 def plot(self):
689 def plot(self):
686
690
687 self.x = self.data.times
691 self.x = self.data.times
688 self.y = self.data.yrange
692 self.y = self.data.yrange
689 self.z = self.data[self.CODE]
693 self.z = self.data[self.CODE]
690 self.z = numpy.array(self.z, dtype=float)
694 self.z = numpy.array(self.z, dtype=float)
691 self.z = numpy.ma.masked_invalid(self.z)
695 self.z = numpy.ma.masked_invalid(self.z)
692
696
693 try:
697 try:
694 if self.channelList != None:
698 if self.channelList != None:
695 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
699 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
696 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
700 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
697 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
701 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
698 else:
702 else:
699 self.titles = ['{} Channel {}'.format(
703 self.titles = ['{} Channel {}'.format(
700 self.CODE.upper(), x) for x in self.channelList]
704 self.CODE.upper(), x) for x in self.channelList]
701 except:
705 except:
702 if self.channelList.any() != None:
706 if self.channelList.any() != None:
703 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
707 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
704 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
708 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
705 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
709 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
706 else:
710 else:
707 self.titles = ['{} Channel {}'.format(
711 self.titles = ['{} Channel {}'.format(
708 self.CODE.upper(), x) for x in self.channelList]
712 self.CODE.upper(), x) for x in self.channelList]
709
713
710 if self.decimation is None:
714 if self.decimation is None:
711 x, y, z = self.fill_gaps(self.x, self.y, self.z)
715 x, y, z = self.fill_gaps(self.x, self.y, self.z)
712 else:
716 else:
713 x, y, z = self.fill_gaps(*self.decimate())
717 x, y, z = self.fill_gaps(*self.decimate())
714
718
715 for n, ax in enumerate(self.axes):
719 for n, ax in enumerate(self.axes):
716
720
717 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
721 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
718 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
722 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
719 data = self.data[-1]
723 data = self.data[-1]
720 if ax.firsttime:
724 if ax.firsttime:
721 ax.plt = ax.pcolormesh(x, y, z[n].T,
725 ax.plt = ax.pcolormesh(x, y, z[n].T,
722 vmin=self.zmin,
726 vmin=self.zmin,
723 vmax=self.zmax,
727 vmax=self.zmax,
724 cmap=plt.get_cmap(self.colormap)
728 cmap=plt.get_cmap(self.colormap)
725 )
729 )
726 if self.showprofile:
730 if self.showprofile:
727 ax.plot_profile = self.pf_axes[n].plot(
731 ax.plot_profile = self.pf_axes[n].plot(
728 data['rti'][n], self.y)[0]
732 data[self.CODE][n], self.y)[0]
729 if "noise" in self.data:
733 if "noise" in self.data:
730 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
734 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
731 color="k", linestyle="dashed", lw=1)[0]
735 color="k", linestyle="dashed", lw=1)[0]
732 else:
736 else:
733 # ax.collections.remove(ax.collections[0]) # error while running
737 # ax.collections.remove(ax.collections[0]) # error while running
734 ax.plt = ax.pcolormesh(x, y, z[n].T,
738 ax.plt = ax.pcolormesh(x, y, z[n].T,
735 vmin=self.zmin,
739 vmin=self.zmin,
736 vmax=self.zmax,
740 vmax=self.zmax,
737 cmap=plt.get_cmap(self.colormap)
741 cmap=plt.get_cmap(self.colormap)
738 )
742 )
739 if self.showprofile:
743 if self.showprofile:
740 ax.plot_profile.set_data(data['rti'][n], self.y)
744 ax.plot_profile.set_data(data[self.CODE][n], self.y)
741 if "noise" in self.data:
745 if "noise" in self.data:
742 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
746 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
743 color="k", linestyle="dashed", lw=1)[0]
747 color="k", linestyle="dashed", lw=1)[0]
744
748
745 class SpectrogramPlot(Plot):
749 class SpectrogramPlot(Plot):
746 '''
750 '''
747 Plot for Spectrogram data
751 Plot for Spectrogram data
748 '''
752 '''
749
753
750 CODE = 'Spectrogram_Profile'
754 CODE = 'Spectrogram_Profile'
751 colormap = 'binary'
755 colormap = 'binary'
752 plot_type = 'pcolorbuffer'
756 plot_type = 'pcolorbuffer'
753
757
754 def setup(self):
758 def setup(self):
755 self.xaxis = 'time'
759 self.xaxis = 'time'
756 self.ncols = 1
760 self.ncols = 1
757 self.nrows = len(self.data.channels)
761 self.nrows = len(self.data.channels)
758 self.nplots = len(self.data.channels)
762 self.nplots = len(self.data.channels)
759 self.xlabel = 'Time'
763 self.xlabel = 'Time'
760 self.plots_adjust.update({'hspace':1.2, 'left': 0.1, 'bottom': 0.12, 'right':0.95})
764 self.plots_adjust.update({'hspace':1.2, 'left': 0.1, 'bottom': 0.12, 'right':0.95})
761 self.titles = []
765 self.titles = []
762
766
763 self.titles = ['{} Channel {}'.format(
767 self.titles = ['{} Channel {}'.format(
764 self.CODE.upper(), x) for x in range(self.nrows)]
768 self.CODE.upper(), x) for x in range(self.nrows)]
765
769
766
770
767 def update(self, dataOut):
771 def update(self, dataOut):
768 data = {}
772 data = {}
769 meta = {}
773 meta = {}
770
774
771 maxHei = 1620#+12000
775 maxHei = 1620#+12000
772 indb = numpy.where(dataOut.heightList <= maxHei)
776 indb = numpy.where(dataOut.heightList <= maxHei)
773 hei = indb[0][-1]
777 hei = indb[0][-1]
774
778
775 factor = dataOut.nIncohInt
779 factor = dataOut.nIncohInt
776 z = dataOut.data_spc[:,:,hei] / factor
780 z = dataOut.data_spc[:,:,hei] / factor
777 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
781 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
778
782
779 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
783 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
780 data['Spectrogram_Profile'] = 10 * numpy.log10(z)
784 data['Spectrogram_Profile'] = 10 * numpy.log10(z)
781
785
782 data['hei'] = hei
786 data['hei'] = hei
783 data['DH'] = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
787 data['DH'] = (dataOut.heightList[1] - dataOut.heightList[0])/dataOut.step
784 data['nProfiles'] = dataOut.nProfiles
788 data['nProfiles'] = dataOut.nProfiles
785
789
786 return data, meta
790 return data, meta
787
791
788 def plot(self):
792 def plot(self):
789
793
790 self.x = self.data.times
794 self.x = self.data.times
791 self.z = self.data[self.CODE]
795 self.z = self.data[self.CODE]
792 self.y = self.data.xrange[0]
796 self.y = self.data.xrange[0]
793
797
794 hei = self.data['hei'][-1]
798 hei = self.data['hei'][-1]
795 DH = self.data['DH'][-1]
799 DH = self.data['DH'][-1]
796 nProfiles = self.data['nProfiles'][-1]
800 nProfiles = self.data['nProfiles'][-1]
797
801
798 self.ylabel = "Frequency (kHz)"
802 self.ylabel = "Frequency (kHz)"
799
803
800 self.z = numpy.ma.masked_invalid(self.z)
804 self.z = numpy.ma.masked_invalid(self.z)
801
805
802 if self.decimation is None:
806 if self.decimation is None:
803 x, y, z = self.fill_gaps(self.x, self.y, self.z)
807 x, y, z = self.fill_gaps(self.x, self.y, self.z)
804 else:
808 else:
805 x, y, z = self.fill_gaps(*self.decimate())
809 x, y, z = self.fill_gaps(*self.decimate())
806
810
807 for n, ax in enumerate(self.axes):
811 for n, ax in enumerate(self.axes):
808 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
812 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
809 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
813 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
810 data = self.data[-1]
814 data = self.data[-1]
811 if ax.firsttime:
815 if ax.firsttime:
812 ax.plt = ax.pcolormesh(x, y, z[n].T,
816 ax.plt = ax.pcolormesh(x, y, z[n].T,
813 vmin=self.zmin,
817 vmin=self.zmin,
814 vmax=self.zmax,
818 vmax=self.zmax,
815 cmap=plt.get_cmap(self.colormap)
819 cmap=plt.get_cmap(self.colormap)
816 )
820 )
817 else:
821 else:
818 # ax.collections.remove(ax.collections[0]) # error while running
822 # ax.collections.remove(ax.collections[0]) # error while running
819 ax.plt = ax.pcolormesh(x, y, z[n].T,
823 ax.plt = ax.pcolormesh(x, y, z[n].T,
820 vmin=self.zmin,
824 vmin=self.zmin,
821 vmax=self.zmax,
825 vmax=self.zmax,
822 cmap=plt.get_cmap(self.colormap)
826 cmap=plt.get_cmap(self.colormap)
823 )
827 )
824
828
825
829
826
830
827 class CoherencePlot(RTIPlot):
831 class CoherencePlot(RTIPlot):
828 '''
832 '''
829 Plot for Coherence data
833 Plot for Coherence data
830 '''
834 '''
831
835
832 CODE = 'coh'
836 CODE = 'coh'
833 titles = None
837 titles = None
834
838
835 def setup(self):
839 def setup(self):
836 self.xaxis = 'time'
840 self.xaxis = 'time'
837 self.ncols = 1
841 self.ncols = 1
838 self.nrows = len(self.data.pairs)
842 self.nrows = len(self.data.pairs)
839 self.nplots = len(self.data.pairs)
843 self.nplots = len(self.data.pairs)
840 self.ylabel = 'Range [km]'
844 self.ylabel = 'Range [km]'
841 self.xlabel = 'Time'
845 self.xlabel = 'Time'
842 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
846 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
843 if self.CODE == 'coh':
847 if self.CODE == 'coh':
844 self.cb_label = ''
848 self.cb_label = ''
845 self.titles = [
849 self.titles = [
846 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
850 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
847 else:
851 else:
848 self.cb_label = 'Degrees'
852 self.cb_label = 'Degrees'
849 self.titles = [
853 self.titles = [
850 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
854 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
851
855
852 def update(self, dataOut):
856 def update(self, dataOut):
853
857
854 data = {}
858 data = {}
855 meta = {}
859 meta = {}
856 data['coh'] = dataOut.getCoherence()
860 data['coh'] = dataOut.getCoherence()
857 meta['pairs'] = dataOut.pairsList
861 meta['pairs'] = dataOut.pairsList
858
862
859 return data, meta
863 return data, meta
860
864
861 class PhasePlot(CoherencePlot):
865 class PhasePlot(CoherencePlot):
862 '''
866 '''
863 Plot for Phase map data
867 Plot for Phase map data
864 '''
868 '''
865
869
866 CODE = 'phase'
870 CODE = 'phase'
867 colormap = 'seismic'
871 colormap = 'seismic'
868
872
869 def update(self, dataOut):
873 def update(self, dataOut):
870
874
871 data = {}
875 data = {}
872 meta = {}
876 meta = {}
873 data['phase'] = dataOut.getCoherence(phase=True)
877 data['phase'] = dataOut.getCoherence(phase=True)
874 meta['pairs'] = dataOut.pairsList
878 meta['pairs'] = dataOut.pairsList
875
879
876 return data, meta
880 return data, meta
877
881
878 class NoisePlot(Plot):
882 class NoisePlot(Plot):
879 '''
883 '''
880 Plot for noise
884 Plot for noise
881 '''
885 '''
882
886
883 CODE = 'noise'
887 CODE = 'noise'
884 plot_type = 'scatterbuffer'
888 plot_type = 'scatterbuffer'
885
889
886 def setup(self):
890 def setup(self):
887 self.xaxis = 'time'
891 self.xaxis = 'time'
888 self.ncols = 1
892 self.ncols = 1
889 self.nrows = 1
893 self.nrows = 1
890 self.nplots = 1
894 self.nplots = 1
891 self.ylabel = 'Intensity [dB]'
895 self.ylabel = 'Intensity [dB]'
892 self.xlabel = 'Time'
896 self.xlabel = 'Time'
893 self.titles = ['Noise']
897 self.titles = ['Noise']
894 self.colorbar = False
898 self.colorbar = False
895 self.plots_adjust.update({'right': 0.85 })
899 self.plots_adjust.update({'right': 0.85 })
900 self.titles = ['Noise Plot']
896
901
897 def update(self, dataOut):
902 def update(self, dataOut):
898
903
899 data = {}
904 data = {}
900 meta = {}
905 meta = {}
901 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
906 noise = 10*numpy.log10(dataOut.getNoise())
907 noise = noise.reshape(dataOut.nChannels, 1)
908 data['noise'] = noise
902 meta['yrange'] = numpy.array([])
909 meta['yrange'] = numpy.array([])
903
910
904 return data, meta
911 return data, meta
905
912
906 def plot(self):
913 def plot(self):
907
914
908 x = self.data.times
915 x = self.data.times
909 xmin = self.data.min_time
916 xmin = self.data.min_time
910 xmax = xmin + self.xrange * 60 * 60
917 xmax = xmin + self.xrange * 60 * 60
911 Y = self.data['noise']
918 Y = self.data['noise']
912
919
913 if self.axes[0].firsttime:
920 if self.axes[0].firsttime:
914 self.ymin = numpy.nanmin(Y) - 5
921 self.ymin = numpy.nanmin(Y) - 5
915 self.ymax = numpy.nanmax(Y) + 5
922 self.ymax = numpy.nanmax(Y) + 5
916 for ch in self.data.channels:
923 for ch in self.data.channels:
917 y = Y[ch]
924 y = Y[ch]
918 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
925 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
919 plt.legend(bbox_to_anchor=(1.18, 1.0))
926 plt.legend(bbox_to_anchor=(1.18, 1.0))
920 else:
927 else:
921 for ch in self.data.channels:
928 for ch in self.data.channels:
922 y = Y[ch]
929 y = Y[ch]
923 self.axes[0].lines[ch].set_data(x, y)
930 self.axes[0].lines[ch].set_data(x, y)
924
931
925 class PowerProfilePlot(Plot):
932 class PowerProfilePlot(Plot):
926
933
927 CODE = 'pow_profile'
934 CODE = 'pow_profile'
928 plot_type = 'scatter'
935 plot_type = 'scatter'
929
936
930 def setup(self):
937 def setup(self):
931
938
932 self.ncols = 1
939 self.ncols = 1
933 self.nrows = 1
940 self.nrows = 1
934 self.nplots = 1
941 self.nplots = 1
935 self.height = 4
942 self.height = 4
936 self.width = 3
943 self.width = 3
937 self.ylabel = 'Range [km]'
944 self.ylabel = 'Range [km]'
938 self.xlabel = 'Intensity [dB]'
945 self.xlabel = 'Intensity [dB]'
939 self.titles = ['Power Profile']
946 self.titles = ['Power Profile']
940 self.colorbar = False
947 self.colorbar = False
941
948
942 def update(self, dataOut):
949 def update(self, dataOut):
943
950
944 data = {}
951 data = {}
945 meta = {}
952 meta = {}
946 data[self.CODE] = dataOut.getPower()
953 data[self.CODE] = dataOut.getPower()
947
954
948 return data, meta
955 return data, meta
949
956
950 def plot(self):
957 def plot(self):
951
958
952 y = self.data.yrange
959 y = self.data.yrange
953 self.y = y
960 self.y = y
954
961
955 x = self.data[-1][self.CODE]
962 x = self.data[-1][self.CODE]
956
963
957 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
964 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
958 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
965 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
959
966
960 if self.axes[0].firsttime:
967 if self.axes[0].firsttime:
961 for ch in self.data.channels:
968 for ch in self.data.channels:
962 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
969 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
963 plt.legend()
970 plt.legend()
964 else:
971 else:
965 for ch in self.data.channels:
972 for ch in self.data.channels:
966 self.axes[0].lines[ch].set_data(x[ch], y)
973 self.axes[0].lines[ch].set_data(x[ch], y)
967
974
968
975
969 class SpectraCutPlot(Plot):
976 class SpectraCutPlot(Plot):
970
977
971 CODE = 'spc_cut'
978 CODE = 'spc_cut'
972 plot_type = 'scatter'
979 plot_type = 'scatter'
973 buffering = False
980 buffering = False
974 heights = []
981 heights = []
975 channelList = []
982 channelList = []
976 maintitle = "Spectra Cuts"
983 maintitle = "Spectra Cuts"
977 flag_setIndex = False
984 flag_setIndex = False
978
985
979 def setup(self):
986 def setup(self):
980
987
981 self.nplots = len(self.data.channels)
988 self.nplots = len(self.data.channels)
982 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
989 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
983 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
990 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
984 self.width = 4.5 * self.ncols + 2.5
991 self.width = 4.5 * self.ncols + 2.5
985 self.height = 4.8 * self.nrows
992 self.height = 4.8 * self.nrows
986 self.ylabel = 'Power [dB]'
993 self.ylabel = 'Power [dB]'
987 self.colorbar = False
994 self.colorbar = False
988 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.9, 'bottom':0.08})
995 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.9, 'bottom':0.08})
989
996
990 if len(self.selectedHeightsList) > 0:
997 if len(self.selectedHeightsList) > 0:
991 self.maintitle = "Spectra Cut"# for %d km " %(int(self.selectedHeight))
998 self.maintitle = "Spectra Cut"# for %d km " %(int(self.selectedHeight))
992
999
993
1000
994
1001
995 def update(self, dataOut):
1002 def update(self, dataOut):
996 if len(self.channelList) == 0:
1003 if len(self.channelList) == 0:
997 self.channelList = dataOut.channelList
1004 self.channelList = dataOut.channelList
998
1005
999 self.heights = dataOut.heightList
1006 self.heights = dataOut.heightList
1000 #print("sels: ",self.selectedHeightsList)
1007 #print("sels: ",self.selectedHeightsList)
1001 if len(self.selectedHeightsList)>0 and not self.flag_setIndex:
1008 if len(self.selectedHeightsList)>0 and not self.flag_setIndex:
1002
1009
1003 for sel_height in self.selectedHeightsList:
1010 for sel_height in self.selectedHeightsList:
1004 index_list = numpy.where(self.heights >= sel_height)
1011 index_list = numpy.where(self.heights >= sel_height)
1005 index_list = index_list[0]
1012 index_list = index_list[0]
1006 self.height_index.append(index_list[0])
1013 self.height_index.append(index_list[0])
1007 #print("sels i:"", self.height_index)
1014 #print("sels i:"", self.height_index)
1008 self.flag_setIndex = True
1015 self.flag_setIndex = True
1009 #print(self.height_index)
1016 #print(self.height_index)
1010 data = {}
1017 data = {}
1011 meta = {}
1018 meta = {}
1012
1019
1013 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter#*dataOut.nFFTPoints
1020 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter#*dataOut.nFFTPoints
1014 n0 = 10*numpy.log10(dataOut.getNoise()/norm)
1021 n0 = 10*numpy.log10(dataOut.getNoise()/norm)
1015 noise = numpy.repeat(n0,(dataOut.nFFTPoints*dataOut.nHeights)).reshape(dataOut.nChannels,dataOut.nFFTPoints,dataOut.nHeights)
1022 noise = numpy.repeat(n0,(dataOut.nFFTPoints*dataOut.nHeights)).reshape(dataOut.nChannels,dataOut.nFFTPoints,dataOut.nHeights)
1016
1023
1017
1024
1018 z = []
1025 z = []
1019 for ch in range(dataOut.nChannels):
1026 for ch in range(dataOut.nChannels):
1020 if hasattr(dataOut.normFactor,'shape'):
1027 if hasattr(dataOut.normFactor,'shape'):
1021 z.append(numpy.divide(dataOut.data_spc[ch],dataOut.normFactor[ch]))
1028 z.append(numpy.divide(dataOut.data_spc[ch],dataOut.normFactor[ch]))
1022 else:
1029 else:
1023 z.append(numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
1030 z.append(numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
1024
1031
1025 z = numpy.asarray(z)
1032 z = numpy.asarray(z)
1026 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1033 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1027 spc = 10*numpy.log10(z)
1034 spc = 10*numpy.log10(z)
1028
1035
1029
1036
1030 data['spc'] = spc - noise
1037 data['spc'] = spc - noise
1031 meta['xrange'] = (dataOut.getFreqRange(EXTRA_POINTS)/1000., dataOut.getAcfRange(EXTRA_POINTS), dataOut.getVelRange(EXTRA_POINTS))
1038 meta['xrange'] = (dataOut.getFreqRange(EXTRA_POINTS)/1000., dataOut.getAcfRange(EXTRA_POINTS), dataOut.getVelRange(EXTRA_POINTS))
1032
1039
1033 return data, meta
1040 return data, meta
1034
1041
1035 def plot(self):
1042 def plot(self):
1036 if self.xaxis == "frequency":
1043 if self.xaxis == "frequency":
1037 x = self.data.xrange[0][0:]
1044 x = self.data.xrange[0][0:]
1038 self.xlabel = "Frequency (kHz)"
1045 self.xlabel = "Frequency (kHz)"
1039 elif self.xaxis == "time":
1046 elif self.xaxis == "time":
1040 x = self.data.xrange[1]
1047 x = self.data.xrange[1]
1041 self.xlabel = "Time (ms)"
1048 self.xlabel = "Time (ms)"
1042 else:
1049 else:
1043 x = self.data.xrange[2]
1050 x = self.data.xrange[2]
1044 self.xlabel = "Velocity (m/s)"
1051 self.xlabel = "Velocity (m/s)"
1045
1052
1046 self.titles = []
1053 self.titles = []
1047
1054
1048 y = self.data.yrange
1055 y = self.data.yrange
1049 z = self.data[-1]['spc']
1056 z = self.data[-1]['spc']
1050 #print(z.shape)
1057 #print(z.shape)
1051 if len(self.height_index) > 0:
1058 if len(self.height_index) > 0:
1052 index = self.height_index
1059 index = self.height_index
1053 else:
1060 else:
1054 index = numpy.arange(0, len(y), int((len(y))/9))
1061 index = numpy.arange(0, len(y), int((len(y))/9))
1055 #print("inde x ", index, self.axes)
1062 #print("inde x ", index, self.axes)
1056
1063
1057 for n, ax in enumerate(self.axes):
1064 for n, ax in enumerate(self.axes):
1058
1065
1059 if ax.firsttime:
1066 if ax.firsttime:
1060
1067
1061
1068
1062 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
1069 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
1063 self.xmin = self.xmin if self.xmin else -self.xmax
1070 self.xmin = self.xmin if self.xmin else -self.xmax
1064 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
1071 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
1065 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
1072 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
1066
1073
1067
1074
1068 ax.plt = ax.plot(x, z[n, :, index].T)
1075 ax.plt = ax.plot(x, z[n, :, index].T)
1069 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
1076 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
1070 self.figures[0].legend(ax.plt, labels, loc='center right', prop={'size': 8})
1077 self.figures[0].legend(ax.plt, labels, loc='center right', prop={'size': 8})
1071 ax.minorticks_on()
1078 ax.minorticks_on()
1072 ax.grid(which='major', axis='both')
1079 ax.grid(which='major', axis='both')
1073 ax.grid(which='minor', axis='x')
1080 ax.grid(which='minor', axis='x')
1074 else:
1081 else:
1075 for i, line in enumerate(ax.plt):
1082 for i, line in enumerate(ax.plt):
1076 line.set_data(x, z[n, :, index[i]])
1083 line.set_data(x, z[n, :, index[i]])
1077
1084
1078
1085
1079 self.titles.append('CH {}'.format(self.channelList[n]))
1086 self.titles.append('CH {}'.format(self.channelList[n]))
1080 plt.suptitle(self.maintitle, fontsize=10)
1087 plt.suptitle(self.maintitle, fontsize=10)
1081
1088
1082
1089
1083 class BeaconPhase(Plot):
1090 class BeaconPhase(Plot):
1084
1091
1085 __isConfig = None
1092 __isConfig = None
1086 __nsubplots = None
1093 __nsubplots = None
1087
1094
1088 PREFIX = 'beacon_phase'
1095 PREFIX = 'beacon_phase'
1089
1096
1090 def __init__(self):
1097 def __init__(self):
1091 Plot.__init__(self)
1098 Plot.__init__(self)
1092 self.timerange = 24*60*60
1099 self.timerange = 24*60*60
1093 self.isConfig = False
1100 self.isConfig = False
1094 self.__nsubplots = 1
1101 self.__nsubplots = 1
1095 self.counter_imagwr = 0
1102 self.counter_imagwr = 0
1096 self.WIDTH = 800
1103 self.WIDTH = 800
1097 self.HEIGHT = 400
1104 self.HEIGHT = 400
1098 self.WIDTHPROF = 120
1105 self.WIDTHPROF = 120
1099 self.HEIGHTPROF = 0
1106 self.HEIGHTPROF = 0
1100 self.xdata = None
1107 self.xdata = None
1101 self.ydata = None
1108 self.ydata = None
1102
1109
1103 self.PLOT_CODE = BEACON_CODE
1110 self.PLOT_CODE = BEACON_CODE
1104
1111
1105 self.FTP_WEI = None
1112 self.FTP_WEI = None
1106 self.EXP_CODE = None
1113 self.EXP_CODE = None
1107 self.SUB_EXP_CODE = None
1114 self.SUB_EXP_CODE = None
1108 self.PLOT_POS = None
1115 self.PLOT_POS = None
1109
1116
1110 self.filename_phase = None
1117 self.filename_phase = None
1111
1118
1112 self.figfile = None
1119 self.figfile = None
1113
1120
1114 self.xmin = None
1121 self.xmin = None
1115 self.xmax = None
1122 self.xmax = None
1116
1123
1117 def getSubplots(self):
1124 def getSubplots(self):
1118
1125
1119 ncol = 1
1126 ncol = 1
1120 nrow = 1
1127 nrow = 1
1121
1128
1122 return nrow, ncol
1129 return nrow, ncol
1123
1130
1124 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1131 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
1125
1132
1126 self.__showprofile = showprofile
1133 self.__showprofile = showprofile
1127 self.nplots = nplots
1134 self.nplots = nplots
1128
1135
1129 ncolspan = 7
1136 ncolspan = 7
1130 colspan = 6
1137 colspan = 6
1131 self.__nsubplots = 2
1138 self.__nsubplots = 2
1132
1139
1133 self.createFigure(id = id,
1140 self.createFigure(id = id,
1134 wintitle = wintitle,
1141 wintitle = wintitle,
1135 widthplot = self.WIDTH+self.WIDTHPROF,
1142 widthplot = self.WIDTH+self.WIDTHPROF,
1136 heightplot = self.HEIGHT+self.HEIGHTPROF,
1143 heightplot = self.HEIGHT+self.HEIGHTPROF,
1137 show=show)
1144 show=show)
1138
1145
1139 nrow, ncol = self.getSubplots()
1146 nrow, ncol = self.getSubplots()
1140
1147
1141 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1148 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
1142
1149
1143 def save_phase(self, filename_phase):
1150 def save_phase(self, filename_phase):
1144 f = open(filename_phase,'w+')
1151 f = open(filename_phase,'w+')
1145 f.write('\n\n')
1152 f.write('\n\n')
1146 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
1153 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
1147 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
1154 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
1148 f.close()
1155 f.close()
1149
1156
1150 def save_data(self, filename_phase, data, data_datetime):
1157 def save_data(self, filename_phase, data, data_datetime):
1151 f=open(filename_phase,'a')
1158 f=open(filename_phase,'a')
1152 timetuple_data = data_datetime.timetuple()
1159 timetuple_data = data_datetime.timetuple()
1153 day = str(timetuple_data.tm_mday)
1160 day = str(timetuple_data.tm_mday)
1154 month = str(timetuple_data.tm_mon)
1161 month = str(timetuple_data.tm_mon)
1155 year = str(timetuple_data.tm_year)
1162 year = str(timetuple_data.tm_year)
1156 hour = str(timetuple_data.tm_hour)
1163 hour = str(timetuple_data.tm_hour)
1157 minute = str(timetuple_data.tm_min)
1164 minute = str(timetuple_data.tm_min)
1158 second = str(timetuple_data.tm_sec)
1165 second = str(timetuple_data.tm_sec)
1159 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
1166 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
1160 f.close()
1167 f.close()
1161
1168
1162 def plot(self):
1169 def plot(self):
1163 log.warning('TODO: Not yet implemented...')
1170 log.warning('TODO: Not yet implemented...')
1164
1171
1165 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1172 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
1166 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
1173 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
1167 timerange=None,
1174 timerange=None,
1168 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1175 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
1169 server=None, folder=None, username=None, password=None,
1176 server=None, folder=None, username=None, password=None,
1170 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1177 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
1171
1178
1172 if dataOut.flagNoData:
1179 if dataOut.flagNoData:
1173 return dataOut
1180 return dataOut
1174
1181
1175 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1182 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
1176 return
1183 return
1177
1184
1178 if pairsList == None:
1185 if pairsList == None:
1179 pairsIndexList = dataOut.pairsIndexList[:10]
1186 pairsIndexList = dataOut.pairsIndexList[:10]
1180 else:
1187 else:
1181 pairsIndexList = []
1188 pairsIndexList = []
1182 for pair in pairsList:
1189 for pair in pairsList:
1183 if pair not in dataOut.pairsList:
1190 if pair not in dataOut.pairsList:
1184 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
1191 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
1185 pairsIndexList.append(dataOut.pairsList.index(pair))
1192 pairsIndexList.append(dataOut.pairsList.index(pair))
1186
1193
1187 if pairsIndexList == []:
1194 if pairsIndexList == []:
1188 return
1195 return
1189
1196
1190 # if len(pairsIndexList) > 4:
1197 # if len(pairsIndexList) > 4:
1191 # pairsIndexList = pairsIndexList[0:4]
1198 # pairsIndexList = pairsIndexList[0:4]
1192
1199
1193 hmin_index = None
1200 hmin_index = None
1194 hmax_index = None
1201 hmax_index = None
1195
1202
1196 if hmin != None and hmax != None:
1203 if hmin != None and hmax != None:
1197 indexes = numpy.arange(dataOut.nHeights)
1204 indexes = numpy.arange(dataOut.nHeights)
1198 hmin_list = indexes[dataOut.heightList >= hmin]
1205 hmin_list = indexes[dataOut.heightList >= hmin]
1199 hmax_list = indexes[dataOut.heightList <= hmax]
1206 hmax_list = indexes[dataOut.heightList <= hmax]
1200
1207
1201 if hmin_list.any():
1208 if hmin_list.any():
1202 hmin_index = hmin_list[0]
1209 hmin_index = hmin_list[0]
1203
1210
1204 if hmax_list.any():
1211 if hmax_list.any():
1205 hmax_index = hmax_list[-1]+1
1212 hmax_index = hmax_list[-1]+1
1206
1213
1207 x = dataOut.getTimeRange()
1214 x = dataOut.getTimeRange()
1208
1215
1209 thisDatetime = dataOut.datatime
1216 thisDatetime = dataOut.datatime
1210
1217
1211 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1218 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
1212 xlabel = "Local Time"
1219 xlabel = "Local Time"
1213 ylabel = "Phase (degrees)"
1220 ylabel = "Phase (degrees)"
1214
1221
1215 update_figfile = False
1222 update_figfile = False
1216
1223
1217 nplots = len(pairsIndexList)
1224 nplots = len(pairsIndexList)
1218 phase_beacon = numpy.zeros(len(pairsIndexList))
1225 phase_beacon = numpy.zeros(len(pairsIndexList))
1219 for i in range(nplots):
1226 for i in range(nplots):
1220 pair = dataOut.pairsList[pairsIndexList[i]]
1227 pair = dataOut.pairsList[pairsIndexList[i]]
1221 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
1228 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
1222 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
1229 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
1223 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
1230 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
1224 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
1231 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
1225 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
1232 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
1226
1233
1227 if dataOut.beacon_heiIndexList:
1234 if dataOut.beacon_heiIndexList:
1228 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
1235 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
1229 else:
1236 else:
1230 phase_beacon[i] = numpy.average(phase)
1237 phase_beacon[i] = numpy.average(phase)
1231
1238
1232 if not self.isConfig:
1239 if not self.isConfig:
1233
1240
1234 nplots = len(pairsIndexList)
1241 nplots = len(pairsIndexList)
1235
1242
1236 self.setup(id=id,
1243 self.setup(id=id,
1237 nplots=nplots,
1244 nplots=nplots,
1238 wintitle=wintitle,
1245 wintitle=wintitle,
1239 showprofile=showprofile,
1246 showprofile=showprofile,
1240 show=show)
1247 show=show)
1241
1248
1242 if timerange != None:
1249 if timerange != None:
1243 self.timerange = timerange
1250 self.timerange = timerange
1244
1251
1245 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1252 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
1246
1253
1247 if ymin == None: ymin = 0
1254 if ymin == None: ymin = 0
1248 if ymax == None: ymax = 360
1255 if ymax == None: ymax = 360
1249
1256
1250 self.FTP_WEI = ftp_wei
1257 self.FTP_WEI = ftp_wei
1251 self.EXP_CODE = exp_code
1258 self.EXP_CODE = exp_code
1252 self.SUB_EXP_CODE = sub_exp_code
1259 self.SUB_EXP_CODE = sub_exp_code
1253 self.PLOT_POS = plot_pos
1260 self.PLOT_POS = plot_pos
1254
1261
1255 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1262 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
1256 self.isConfig = True
1263 self.isConfig = True
1257 self.figfile = figfile
1264 self.figfile = figfile
1258 self.xdata = numpy.array([])
1265 self.xdata = numpy.array([])
1259 self.ydata = numpy.array([])
1266 self.ydata = numpy.array([])
1260
1267
1261 update_figfile = True
1268 update_figfile = True
1262
1269
1263 #open file beacon phase
1270 #open file beacon phase
1264 path = '%s%03d' %(self.PREFIX, self.id)
1271 path = '%s%03d' %(self.PREFIX, self.id)
1265 beacon_file = os.path.join(path,'%s.txt'%self.name)
1272 beacon_file = os.path.join(path,'%s.txt'%self.name)
1266 self.filename_phase = os.path.join(figpath,beacon_file)
1273 self.filename_phase = os.path.join(figpath,beacon_file)
1267
1274
1268 self.setWinTitle(title)
1275 self.setWinTitle(title)
1269
1276
1270
1277
1271 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1278 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
1272
1279
1273 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
1280 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
1274
1281
1275 axes = self.axesList[0]
1282 axes = self.axesList[0]
1276
1283
1277 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1284 self.xdata = numpy.hstack((self.xdata, x[0:1]))
1278
1285
1279 if len(self.ydata)==0:
1286 if len(self.ydata)==0:
1280 self.ydata = phase_beacon.reshape(-1,1)
1287 self.ydata = phase_beacon.reshape(-1,1)
1281 else:
1288 else:
1282 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1289 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
1283
1290
1284
1291
1285 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1292 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
1286 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1293 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
1287 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1294 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
1288 XAxisAsTime=True, grid='both'
1295 XAxisAsTime=True, grid='both'
1289 )
1296 )
1290
1297
1291 self.draw()
1298 self.draw()
1292
1299
1293 if dataOut.ltctime >= self.xmax:
1300 if dataOut.ltctime >= self.xmax:
1294 self.counter_imagwr = wr_period
1301 self.counter_imagwr = wr_period
1295 self.isConfig = False
1302 self.isConfig = False
1296 update_figfile = True
1303 update_figfile = True
1297
1304
1298 self.save(figpath=figpath,
1305 self.save(figpath=figpath,
1299 figfile=figfile,
1306 figfile=figfile,
1300 save=save,
1307 save=save,
1301 ftp=ftp,
1308 ftp=ftp,
1302 wr_period=wr_period,
1309 wr_period=wr_period,
1303 thisDatetime=thisDatetime,
1310 thisDatetime=thisDatetime,
1304 update_figfile=update_figfile)
1311 update_figfile=update_figfile)
1305
1312
1306 return dataOut
1313 return dataOut
1307
1314
1308 #####################################
1315 #####################################
1309 class NoiselessSpectraPlot(Plot):
1316 class NoiselessSpectraPlot(Plot):
1310 '''
1317 '''
1311 Plot for Spectra data, subtracting
1318 Plot for Spectra data, subtracting
1312 the noise in all channels, using for
1319 the noise in all channels, using for
1313 amisr-14 data
1320 amisr-14 data
1314 '''
1321 '''
1315
1322
1316 CODE = 'noiseless_spc'
1323 CODE = 'noiseless_spc'
1317 colormap = 'jet'
1324 colormap = 'jet'
1318 plot_type = 'pcolor'
1325 plot_type = 'pcolor'
1319 buffering = False
1326 buffering = False
1320 channelList = []
1327 channelList = []
1321 last_noise = None
1328 last_noise = None
1322
1329
1323 def setup(self):
1330 def setup(self):
1324
1331
1325 self.nplots = len(self.data.channels)
1332 self.nplots = len(self.data.channels)
1326 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
1333 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
1327 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
1334 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
1328 self.height = 3.5 * self.nrows
1335 self.height = 3.5 * self.nrows
1329
1336
1330 self.cb_label = 'dB'
1337 self.cb_label = 'dB'
1331 if self.showprofile:
1338 if self.showprofile:
1332 self.width = 5.8 * self.ncols
1339 self.width = 5.8 * self.ncols
1333 else:
1340 else:
1334 self.width = 4.8* self.ncols
1341 self.width = 4.8* self.ncols
1335 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.92, 'bottom': 0.12})
1342 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.92, 'bottom': 0.12})
1336
1343
1337 self.ylabel = 'Range [km]'
1344 self.ylabel = 'Range [km]'
1338
1345
1339
1346
1340 def update_list(self,dataOut):
1347 def update_list(self,dataOut):
1341 if len(self.channelList) == 0:
1348 if len(self.channelList) == 0:
1342 self.channelList = dataOut.channelList
1349 self.channelList = dataOut.channelList
1343
1350
1344 def update(self, dataOut):
1351 def update(self, dataOut):
1345
1352
1346 self.update_list(dataOut)
1353 self.update_list(dataOut)
1347 data = {}
1354 data = {}
1348 meta = {}
1355 meta = {}
1349
1356
1350 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
1357 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
1351 n0 = (dataOut.getNoise()/norm)
1358 n0 = (dataOut.getNoise()/norm)
1352 noise = numpy.repeat(n0,(dataOut.nFFTPoints*dataOut.nHeights)).reshape(dataOut.nChannels,dataOut.nFFTPoints,dataOut.nHeights)
1359 noise = numpy.repeat(n0,(dataOut.nFFTPoints*dataOut.nHeights)).reshape(dataOut.nChannels,dataOut.nFFTPoints,dataOut.nHeights)
1353 noise = 10*numpy.log10(noise)
1360 noise = 10*numpy.log10(noise)
1354
1361
1355 z = numpy.zeros((dataOut.nChannels, dataOut.nFFTPoints, dataOut.nHeights))
1362 z = numpy.zeros((dataOut.nChannels, dataOut.nFFTPoints, dataOut.nHeights))
1356 for ch in range(dataOut.nChannels):
1363 for ch in range(dataOut.nChannels):
1357 if hasattr(dataOut.normFactor,'ndim'):
1364 if hasattr(dataOut.normFactor,'ndim'):
1358 if dataOut.normFactor.ndim > 1:
1365 if dataOut.normFactor.ndim > 1:
1359 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor[ch]))
1366 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor[ch]))
1360 else:
1367 else:
1361 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
1368 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
1362 else:
1369 else:
1363 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
1370 z[ch] = (numpy.divide(dataOut.data_spc[ch],dataOut.normFactor))
1364
1371
1365 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1372 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1366 spc = 10*numpy.log10(z)
1373 spc = 10*numpy.log10(z)
1367
1374
1368
1375
1369 data['spc'] = spc - noise
1376 data['spc'] = spc - noise
1370 #print(spc.shape)
1377 #print(spc.shape)
1371 data['rti'] = spc.mean(axis=1)
1378 data['rti'] = spc.mean(axis=1)
1372 data['noise'] = noise
1379 data['noise'] = noise
1373
1380
1374
1381
1375
1382
1376 # data['noise'] = noise
1383 # data['noise'] = noise
1377 meta['xrange'] = (dataOut.getFreqRange(EXTRA_POINTS)/1000., dataOut.getAcfRange(EXTRA_POINTS), dataOut.getVelRange(EXTRA_POINTS))
1384 meta['xrange'] = (dataOut.getFreqRange(EXTRA_POINTS)/1000., dataOut.getAcfRange(EXTRA_POINTS), dataOut.getVelRange(EXTRA_POINTS))
1378
1385
1379 return data, meta
1386 return data, meta
1380
1387
1381 def plot(self):
1388 def plot(self):
1382 if self.xaxis == "frequency":
1389 if self.xaxis == "frequency":
1383 x = self.data.xrange[0]
1390 x = self.data.xrange[0]
1384 self.xlabel = "Frequency (kHz)"
1391 self.xlabel = "Frequency (kHz)"
1385 elif self.xaxis == "time":
1392 elif self.xaxis == "time":
1386 x = self.data.xrange[1]
1393 x = self.data.xrange[1]
1387 self.xlabel = "Time (ms)"
1394 self.xlabel = "Time (ms)"
1388 else:
1395 else:
1389 x = self.data.xrange[2]
1396 x = self.data.xrange[2]
1390 self.xlabel = "Velocity (m/s)"
1397 self.xlabel = "Velocity (m/s)"
1391
1398
1392 self.titles = []
1399 self.titles = []
1393 y = self.data.yrange
1400 y = self.data.yrange
1394 self.y = y
1401 self.y = y
1395
1402
1396 data = self.data[-1]
1403 data = self.data[-1]
1397 z = data['spc']
1404 z = data['spc']
1398
1405
1399 for n, ax in enumerate(self.axes):
1406 for n, ax in enumerate(self.axes):
1400 #noise = data['noise'][n]
1407 #noise = data['noise'][n]
1401
1408
1402 if ax.firsttime:
1409 if ax.firsttime:
1403 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
1410 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
1404 self.xmin = self.xmin if self.xmin else -self.xmax
1411 self.xmin = self.xmin if self.xmin else -self.xmax
1405 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
1412 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
1406 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
1413 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
1407 ax.plt = ax.pcolormesh(x, y, z[n].T,
1414 ax.plt = ax.pcolormesh(x, y, z[n].T,
1408 vmin=self.zmin,
1415 vmin=self.zmin,
1409 vmax=self.zmax,
1416 vmax=self.zmax,
1410 cmap=plt.get_cmap(self.colormap)
1417 cmap=plt.get_cmap(self.colormap)
1411 )
1418 )
1412
1419
1413 if self.showprofile:
1420 if self.showprofile:
1414 ax.plt_profile = self.pf_axes[n].plot(
1421 ax.plt_profile = self.pf_axes[n].plot(
1415 data['rti'][n], y)[0]
1422 data['rti'][n], y)[0]
1416
1423
1417
1424
1418 else:
1425 else:
1419 ax.plt.set_array(z[n].T.ravel())
1426 ax.plt.set_array(z[n].T.ravel())
1420 if self.showprofile:
1427 if self.showprofile:
1421 ax.plt_profile.set_data(data['rti'][n], y)
1428 ax.plt_profile.set_data(data['rti'][n], y)
1422
1429
1423
1430
1424 self.titles.append('CH {}'.format(self.channelList[n]))
1431 self.titles.append('CH {}'.format(self.channelList[n]))
1425
1432
1426
1433
1427 class NoiselessRTIPlot(RTIPlot):
1434 class NoiselessRTIPlot(RTIPlot):
1428 '''
1435 '''
1429 Plot for RTI data
1436 Plot for RTI data
1430 '''
1437 '''
1431
1438
1432 CODE = 'noiseless_rti'
1439 CODE = 'noiseless_rti'
1433 colormap = 'jet'
1440 colormap = 'jet'
1434 plot_type = 'pcolorbuffer'
1441 plot_type = 'pcolorbuffer'
1435 titles = None
1442 titles = None
1436 channelList = []
1443 channelList = []
1437 elevationList = []
1444 elevationList = []
1438 azimuthList = []
1445 azimuthList = []
1439 last_noise = None
1446 last_noise = None
1440
1447
1441 def setup(self):
1448 def setup(self):
1442 self.xaxis = 'time'
1449 self.xaxis = 'time'
1443 self.ncols = 1
1450 self.ncols = 1
1444 #print("dataChannels ",self.data.channels)
1451 #print("dataChannels ",self.data.channels)
1445 self.nrows = len(self.data.channels)
1452 self.nrows = len(self.data.channels)
1446 self.nplots = len(self.data.channels)
1453 self.nplots = len(self.data.channels)
1447 self.ylabel = 'Range [km]'
1454 self.ylabel = 'Range [km]'
1448 #self.xlabel = 'Time'
1455 #self.xlabel = 'Time'
1449 self.cb_label = 'dB'
1456 self.cb_label = 'dB'
1450 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
1457 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
1451 self.titles = ['{} Channel {}'.format(
1458 self.titles = ['{} Channel {}'.format(
1452 self.CODE.upper(), x) for x in range(self.nplots)]
1459 self.CODE.upper(), x) for x in range(self.nplots)]
1453
1460
1454 def update_list(self,dataOut):
1461 def update_list(self,dataOut):
1455 if len(self.channelList) == 0:
1462 if len(self.channelList) == 0:
1456 self.channelList = dataOut.channelList
1463 self.channelList = dataOut.channelList
1457 if len(self.elevationList) == 0:
1464 if len(self.elevationList) == 0:
1458 self.elevationList = dataOut.elevationList
1465 self.elevationList = dataOut.elevationList
1459 if len(self.azimuthList) == 0:
1466 if len(self.azimuthList) == 0:
1460 self.azimuthList = dataOut.azimuthList
1467 self.azimuthList = dataOut.azimuthList
1461
1468
1462 def update(self, dataOut):
1469 def update(self, dataOut):
1463 if len(self.channelList) == 0:
1470 if len(self.channelList) == 0:
1464 self.update_list(dataOut)
1471 self.update_list(dataOut)
1465
1472
1466 data = {}
1473 data = {}
1467 meta = {}
1474 meta = {}
1468 #print(dataOut.max_nIncohInt, dataOut.nIncohInt)
1475 #print(dataOut.max_nIncohInt, dataOut.nIncohInt)
1469 #print(dataOut.windowOfFilter,dataOut.nCohInt,dataOut.nProfiles,dataOut.max_nIncohInt,dataOut.nIncohInt
1476 #print(dataOut.windowOfFilter,dataOut.nCohInt,dataOut.nProfiles,dataOut.max_nIncohInt,dataOut.nIncohInt
1470 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
1477 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
1471 n0 = 10*numpy.log10(dataOut.getNoise()/norm)
1478 n0 = 10*numpy.log10(dataOut.getNoise()/norm)
1472 data['noise'] = n0
1479 data['noise'] = n0
1473 noise = numpy.repeat(n0,dataOut.nHeights).reshape(dataOut.nChannels,dataOut.nHeights)
1480 noise = numpy.repeat(n0,dataOut.nHeights).reshape(dataOut.nChannels,dataOut.nHeights)
1474 noiseless_data = dataOut.getPower() - noise
1481 noiseless_data = dataOut.getPower() - noise
1475
1482
1476 #print("power, noise:", dataOut.getPower(), n0)
1483 #print("power, noise:", dataOut.getPower(), n0)
1477 #print(noise)
1484 #print(noise)
1478 #print(noiseless_data)
1485 #print(noiseless_data)
1479
1486
1480 data['noiseless_rti'] = noiseless_data
1487 data['noiseless_rti'] = noiseless_data
1481
1488
1482 return data, meta
1489 return data, meta
1483
1490
1484 def plot(self):
1491 def plot(self):
1485 from matplotlib import pyplot as plt
1492 from matplotlib import pyplot as plt
1486 self.x = self.data.times
1493 self.x = self.data.times
1487 self.y = self.data.yrange
1494 self.y = self.data.yrange
1488 self.z = self.data['noiseless_rti']
1495 self.z = self.data['noiseless_rti']
1489 self.z = numpy.array(self.z, dtype=float)
1496 self.z = numpy.array(self.z, dtype=float)
1490 self.z = numpy.ma.masked_invalid(self.z)
1497 self.z = numpy.ma.masked_invalid(self.z)
1491
1498
1492
1499
1493 try:
1500 try:
1494 if self.channelList != None:
1501 if self.channelList != None:
1495 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
1502 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
1496 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
1503 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
1497 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
1504 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
1498 else:
1505 else:
1499 self.titles = ['{} Channel {}'.format(
1506 self.titles = ['{} Channel {}'.format(
1500 self.CODE.upper(), x) for x in self.channelList]
1507 self.CODE.upper(), x) for x in self.channelList]
1501 except:
1508 except:
1502 if self.channelList.any() != None:
1509 if self.channelList.any() != None:
1503 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
1510 if len(self.elevationList) > 0 and len(self.azimuthList) > 0:
1504 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
1511 self.titles = ['{} Channel {} ({:2.1f} Elev, {:2.1f} Azth)'.format(
1505 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
1512 self.CODE.upper(), x, self.elevationList[x], self.azimuthList[x]) for x in self.channelList]
1506 else:
1513 else:
1507 self.titles = ['{} Channel {}'.format(
1514 self.titles = ['{} Channel {}'.format(
1508 self.CODE.upper(), x) for x in self.channelList]
1515 self.CODE.upper(), x) for x in self.channelList]
1509
1516
1510
1517
1511 if self.decimation is None:
1518 if self.decimation is None:
1512 x, y, z = self.fill_gaps(self.x, self.y, self.z)
1519 x, y, z = self.fill_gaps(self.x, self.y, self.z)
1513 else:
1520 else:
1514 x, y, z = self.fill_gaps(*self.decimate())
1521 x, y, z = self.fill_gaps(*self.decimate())
1515
1522
1516 dummy_var = self.axes #ExtraΓ±amente esto actualiza el valor axes
1523 dummy_var = self.axes #ExtraΓ±amente esto actualiza el valor axes
1517 #print("plot shapes ", z.shape, x.shape, y.shape)
1524 #print("plot shapes ", z.shape, x.shape, y.shape)
1518 #print(self.axes)
1525 #print(self.axes)
1519 for n, ax in enumerate(self.axes):
1526 for n, ax in enumerate(self.axes):
1520
1527
1521
1528
1522 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
1529 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
1523 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
1530 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
1524 data = self.data[-1]
1531 data = self.data[-1]
1525 if ax.firsttime:
1532 if ax.firsttime:
1526 if (n+1) == len(self.channelList):
1533 if (n+1) == len(self.channelList):
1527 ax.set_xlabel('Time')
1534 ax.set_xlabel('Time')
1528 ax.plt = ax.pcolormesh(x, y, z[n].T,
1535 ax.plt = ax.pcolormesh(x, y, z[n].T,
1529 vmin=self.zmin,
1536 vmin=self.zmin,
1530 vmax=self.zmax,
1537 vmax=self.zmax,
1531 cmap=plt.get_cmap(self.colormap)
1538 cmap=plt.get_cmap(self.colormap)
1532 )
1539 )
1533 if self.showprofile:
1540 if self.showprofile:
1534 ax.plot_profile = self.pf_axes[n].plot(data['noiseless_rti'][n], self.y)[0]
1541 ax.plot_profile = self.pf_axes[n].plot(data['noiseless_rti'][n], self.y)[0]
1535
1542
1536 else:
1543 else:
1537 # ax.collections.remove(ax.collections[0]) # error while running
1544 # ax.collections.remove(ax.collections[0]) # error while running
1538 ax.plt = ax.pcolormesh(x, y, z[n].T,
1545 ax.plt = ax.pcolormesh(x, y, z[n].T,
1539 vmin=self.zmin,
1546 vmin=self.zmin,
1540 vmax=self.zmax,
1547 vmax=self.zmax,
1541 cmap=plt.get_cmap(self.colormap)
1548 cmap=plt.get_cmap(self.colormap)
1542 )
1549 )
1543 if self.showprofile:
1550 if self.showprofile:
1544 ax.plot_profile.set_data(data['noiseless_rti'][n], self.y)
1551 ax.plot_profile.set_data(data['noiseless_rti'][n], self.y)
1545 # if "noise" in self.data:
1552 # if "noise" in self.data:
1546 # #ax.plot_noise.set_data(numpy.repeat(data['noise'][n], len(self.y)), self.y)
1553 # #ax.plot_noise.set_data(numpy.repeat(data['noise'][n], len(self.y)), self.y)
1547 # ax.plot_noise.set_data(data['noise'][n], self.y)
1554 # ax.plot_noise.set_data(data['noise'][n], self.y)
1548
1555
1549
1556
1550 class OutliersRTIPlot(Plot):
1557 class OutliersRTIPlot(Plot):
1551 '''
1558 '''
1552 Plot for data_xxxx object
1559 Plot for data_xxxx object
1553 '''
1560 '''
1554
1561
1555 CODE = 'outlier_rtc' # Range Time Counts
1562 CODE = 'outlier_rtc' # Range Time Counts
1556 colormap = 'cool'
1563 colormap = 'cool'
1557 plot_type = 'pcolorbuffer'
1564 plot_type = 'pcolorbuffer'
1558
1565
1559 def setup(self):
1566 def setup(self):
1560 self.xaxis = 'time'
1567 self.xaxis = 'time'
1561 self.ncols = 1
1568 self.ncols = 1
1562 self.nrows = self.data.shape('outlier_rtc')[0]
1569 self.nrows = self.data.shape('outlier_rtc')[0]
1563 self.nplots = self.nrows
1570 self.nplots = self.nrows
1564 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
1571 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
1565
1572
1566
1573
1567 if not self.xlabel:
1574 if not self.xlabel:
1568 self.xlabel = 'Time'
1575 self.xlabel = 'Time'
1569
1576
1570 self.ylabel = 'Height [km]'
1577 self.ylabel = 'Height [km]'
1571 if not self.titles:
1578 if not self.titles:
1572 self.titles = ['Outliers Ch:{}'.format(x) for x in range(self.nrows)]
1579 self.titles = ['Outliers Ch:{}'.format(x) for x in range(self.nrows)]
1573
1580
1574 def update(self, dataOut):
1581 def update(self, dataOut):
1575
1582
1576 data = {}
1583 data = {}
1577 data['outlier_rtc'] = dataOut.data_outlier
1584 data['outlier_rtc'] = dataOut.data_outlier
1578
1585
1579 meta = {}
1586 meta = {}
1580
1587
1581 return data, meta
1588 return data, meta
1582
1589
1583 def plot(self):
1590 def plot(self):
1584 # self.data.normalize_heights()
1591 # self.data.normalize_heights()
1585 self.x = self.data.times
1592 self.x = self.data.times
1586 self.y = self.data.yrange
1593 self.y = self.data.yrange
1587 self.z = self.data['outlier_rtc']
1594 self.z = self.data['outlier_rtc']
1588
1595
1589 #self.z = numpy.ma.masked_invalid(self.z)
1596 #self.z = numpy.ma.masked_invalid(self.z)
1590
1597
1591 if self.decimation is None:
1598 if self.decimation is None:
1592 x, y, z = self.fill_gaps(self.x, self.y, self.z)
1599 x, y, z = self.fill_gaps(self.x, self.y, self.z)
1593 else:
1600 else:
1594 x, y, z = self.fill_gaps(*self.decimate())
1601 x, y, z = self.fill_gaps(*self.decimate())
1595
1602
1596 for n, ax in enumerate(self.axes):
1603 for n, ax in enumerate(self.axes):
1597
1604
1598 self.zmax = self.zmax if self.zmax is not None else numpy.max(
1605 self.zmax = self.zmax if self.zmax is not None else numpy.max(
1599 self.z[n])
1606 self.z[n])
1600 self.zmin = self.zmin if self.zmin is not None else numpy.min(
1607 self.zmin = self.zmin if self.zmin is not None else numpy.min(
1601 self.z[n])
1608 self.z[n])
1602 data = self.data[-1]
1609 data = self.data[-1]
1603 if ax.firsttime:
1610 if ax.firsttime:
1604 if self.zlimits is not None:
1611 if self.zlimits is not None:
1605 self.zmin, self.zmax = self.zlimits[n]
1612 self.zmin, self.zmax = self.zlimits[n]
1606
1613
1607 ax.plt = ax.pcolormesh(x, y, z[n].T,
1614 ax.plt = ax.pcolormesh(x, y, z[n].T,
1608 vmin=self.zmin,
1615 vmin=self.zmin,
1609 vmax=self.zmax,
1616 vmax=self.zmax,
1610 cmap=self.cmaps[n]
1617 cmap=self.cmaps[n]
1611 )
1618 )
1612 if self.showprofile:
1619 if self.showprofile:
1613 ax.plot_profile = self.pf_axes[n].plot(data['outlier_rtc'][n], self.y)[0]
1620 ax.plot_profile = self.pf_axes[n].plot(data['outlier_rtc'][n], self.y)[0]
1614 self.pf_axes[n].set_xlabel('')
1621 self.pf_axes[n].set_xlabel('')
1615 else:
1622 else:
1616 if self.zlimits is not None:
1623 if self.zlimits is not None:
1617 self.zmin, self.zmax = self.zlimits[n]
1624 self.zmin, self.zmax = self.zlimits[n]
1618 # ax.collections.remove(ax.collections[0]) # error while running
1625 # ax.collections.remove(ax.collections[0]) # error while running
1619 ax.plt = ax.pcolormesh(x, y, z[n].T ,
1626 ax.plt = ax.pcolormesh(x, y, z[n].T ,
1620 vmin=self.zmin,
1627 vmin=self.zmin,
1621 vmax=self.zmax,
1628 vmax=self.zmax,
1622 cmap=self.cmaps[n]
1629 cmap=self.cmaps[n]
1623 )
1630 )
1624 if self.showprofile:
1631 if self.showprofile:
1625 ax.plot_profile.set_data(data['outlier_rtc'][n], self.y)
1632 ax.plot_profile.set_data(data['outlier_rtc'][n], self.y)
1626 self.pf_axes[n].set_xlabel('')
1633 self.pf_axes[n].set_xlabel('')
1627
1634
1628 class NIncohIntRTIPlot(Plot):
1635 class NIncohIntRTIPlot(Plot):
1629 '''
1636 '''
1630 Plot for data_xxxx object
1637 Plot for data_xxxx object
1631 '''
1638 '''
1632
1639
1633 CODE = 'integrations_rtc' # Range Time Counts
1640 CODE = 'integrations_rtc' # Range Time Counts
1634 colormap = 'BuGn'
1641 colormap = 'BuGn'
1635 plot_type = 'pcolorbuffer'
1642 plot_type = 'pcolorbuffer'
1636
1643
1637 def setup(self):
1644 def setup(self):
1638 self.xaxis = 'time'
1645 self.xaxis = 'time'
1639 self.ncols = 1
1646 self.ncols = 1
1640 self.nrows = self.data.shape('integrations_rtc')[0]
1647 self.nrows = self.data.shape('integrations_rtc')[0]
1641 self.nplots = self.nrows
1648 self.nplots = self.nrows
1642 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
1649 self.plots_adjust.update({'hspace':0.8, 'left': 0.08, 'bottom': 0.2, 'right':0.94})
1643
1650
1644
1651
1645 if not self.xlabel:
1652 if not self.xlabel:
1646 self.xlabel = 'Time'
1653 self.xlabel = 'Time'
1647
1654
1648 self.ylabel = 'Height [km]'
1655 self.ylabel = 'Height [km]'
1649 if not self.titles:
1656 if not self.titles:
1650 self.titles = ['Integration Ch:{}'.format(x) for x in range(self.nrows)]
1657 self.titles = ['Integration Ch:{}'.format(x) for x in range(self.nrows)]
1651
1658
1652 def update(self, dataOut):
1659 def update(self, dataOut):
1653
1660
1654 data = {}
1661 data = {}
1655 data['integrations_rtc'] = dataOut.nIncohInt
1662 data['integrations_rtc'] = dataOut.nIncohInt
1656
1663
1657 meta = {}
1664 meta = {}
1658
1665
1659 return data, meta
1666 return data, meta
1660
1667
1661 def plot(self):
1668 def plot(self):
1662 # self.data.normalize_heights()
1669 # self.data.normalize_heights()
1663 self.x = self.data.times
1670 self.x = self.data.times
1664 self.y = self.data.yrange
1671 self.y = self.data.yrange
1665 self.z = self.data['integrations_rtc']
1672 self.z = self.data['integrations_rtc']
1666
1673
1667 #self.z = numpy.ma.masked_invalid(self.z)
1674 #self.z = numpy.ma.masked_invalid(self.z)
1668
1675
1669 if self.decimation is None:
1676 if self.decimation is None:
1670 x, y, z = self.fill_gaps(self.x, self.y, self.z)
1677 x, y, z = self.fill_gaps(self.x, self.y, self.z)
1671 else:
1678 else:
1672 x, y, z = self.fill_gaps(*self.decimate())
1679 x, y, z = self.fill_gaps(*self.decimate())
1673
1680
1674 for n, ax in enumerate(self.axes):
1681 for n, ax in enumerate(self.axes):
1675
1682
1676 self.zmax = self.zmax if self.zmax is not None else numpy.max(
1683 self.zmax = self.zmax if self.zmax is not None else numpy.max(
1677 self.z[n])
1684 self.z[n])
1678 self.zmin = self.zmin if self.zmin is not None else numpy.min(
1685 self.zmin = self.zmin if self.zmin is not None else numpy.min(
1679 self.z[n])
1686 self.z[n])
1680 data = self.data[-1]
1687 data = self.data[-1]
1681 if ax.firsttime:
1688 if ax.firsttime:
1682 if self.zlimits is not None:
1689 if self.zlimits is not None:
1683 self.zmin, self.zmax = self.zlimits[n]
1690 self.zmin, self.zmax = self.zlimits[n]
1684
1691
1685 ax.plt = ax.pcolormesh(x, y, z[n].T,
1692 ax.plt = ax.pcolormesh(x, y, z[n].T,
1686 vmin=self.zmin,
1693 vmin=self.zmin,
1687 vmax=self.zmax,
1694 vmax=self.zmax,
1688 cmap=self.cmaps[n]
1695 cmap=self.cmaps[n]
1689 )
1696 )
1690 if self.showprofile:
1697 if self.showprofile:
1691 ax.plot_profile = self.pf_axes[n].plot(data['integrations_rtc'][n], self.y)[0]
1698 ax.plot_profile = self.pf_axes[n].plot(data['integrations_rtc'][n], self.y)[0]
1692 self.pf_axes[n].set_xlabel('')
1699 self.pf_axes[n].set_xlabel('')
1693 else:
1700 else:
1694 if self.zlimits is not None:
1701 if self.zlimits is not None:
1695 self.zmin, self.zmax = self.zlimits[n]
1702 self.zmin, self.zmax = self.zlimits[n]
1696 # ax.collections.remove(ax.collections[0]) # error while running
1703 # ax.collections.remove(ax.collections[0]) # error while running
1697 ax.plt = ax.pcolormesh(x, y, z[n].T ,
1704 ax.plt = ax.pcolormesh(x, y, z[n].T ,
1698 vmin=self.zmin,
1705 vmin=self.zmin,
1699 vmax=self.zmax,
1706 vmax=self.zmax,
1700 cmap=self.cmaps[n]
1707 cmap=self.cmaps[n]
1701 )
1708 )
1702 if self.showprofile:
1709 if self.showprofile:
1703 ax.plot_profile.set_data(data['integrations_rtc'][n], self.y)
1710 ax.plot_profile.set_data(data['integrations_rtc'][n], self.y)
1704 self.pf_axes[n].set_xlabel('')
1711 self.pf_axes[n].set_xlabel('')
1705
1712
1706
1713
1707
1714
1708 class RTIMapPlot(Plot):
1715 class RTIMapPlot(Plot):
1709 '''
1716 '''
1710 Plot for RTI data
1717 Plot for RTI data
1711
1718
1712 Example:
1719 Example:
1713
1720
1714 controllerObj = Project()
1721 controllerObj = Project()
1715 controllerObj.setup(id = '11', name='eej_proc', description=desc)
1722 controllerObj.setup(id = '11', name='eej_proc', description=desc)
1716 ##.......................................................................................
1723 ##.......................................................................................
1717 ##.......................................................................................
1724 ##.......................................................................................
1718 readUnitConfObj = controllerObj.addReadUnit(datatype='AMISRReader', path=inPath, startDate='2023/05/24',endDate='2023/05/24',
1725 readUnitConfObj = controllerObj.addReadUnit(datatype='AMISRReader', path=inPath, startDate='2023/05/24',endDate='2023/05/24',
1719 startTime='12:00:00',endTime='12:45:59',walk=1,timezone='lt',margin_days=1,code = code,nCode = nCode,
1726 startTime='12:00:00',endTime='12:45:59',walk=1,timezone='lt',margin_days=1,code = code,nCode = nCode,
1720 nBaud = nBaud,nOsamp = nosamp,nChannels=nChannels,nFFT=NFFT,
1727 nBaud = nBaud,nOsamp = nosamp,nChannels=nChannels,nFFT=NFFT,
1721 syncronization=False,shiftChannels=0)
1728 syncronization=False,shiftChannels=0)
1722
1729
1723 volts_proc = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
1730 volts_proc = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
1724
1731
1725 opObj01 = volts_proc.addOperation(name='Decoder', optype='other')
1732 opObj01 = volts_proc.addOperation(name='Decoder', optype='other')
1726 opObj01.addParameter(name='code', value=code, format='floatlist')
1733 opObj01.addParameter(name='code', value=code, format='floatlist')
1727 opObj01.addParameter(name='nCode', value=1, format='int')
1734 opObj01.addParameter(name='nCode', value=1, format='int')
1728 opObj01.addParameter(name='nBaud', value=nBaud, format='int')
1735 opObj01.addParameter(name='nBaud', value=nBaud, format='int')
1729 opObj01.addParameter(name='osamp', value=nosamp, format='int')
1736 opObj01.addParameter(name='osamp', value=nosamp, format='int')
1730
1737
1731 opObj12 = volts_proc.addOperation(name='selectHeights', optype='self')
1738 opObj12 = volts_proc.addOperation(name='selectHeights', optype='self')
1732 opObj12.addParameter(name='minHei', value='90', format='float')
1739 opObj12.addParameter(name='minHei', value='90', format='float')
1733 opObj12.addParameter(name='maxHei', value='150', format='float')
1740 opObj12.addParameter(name='maxHei', value='150', format='float')
1734
1741
1735 proc_spc = controllerObj.addProcUnit(datatype='SpectraProc', inputId=volts_proc.getId())
1742 proc_spc = controllerObj.addProcUnit(datatype='SpectraProc', inputId=volts_proc.getId())
1736 proc_spc.addParameter(name='nFFTPoints', value='8', format='int')
1743 proc_spc.addParameter(name='nFFTPoints', value='8', format='int')
1737
1744
1738 opObj11 = proc_spc.addOperation(name='IncohInt', optype='other')
1745 opObj11 = proc_spc.addOperation(name='IncohInt', optype='other')
1739 opObj11.addParameter(name='n', value='1', format='int')
1746 opObj11.addParameter(name='n', value='1', format='int')
1740
1747
1741 beamMapFile = "/home/japaza/Documents/AMISR_sky_mapper/UMET_beamcodes.csv"
1748 beamMapFile = "/home/japaza/Documents/AMISR_sky_mapper/UMET_beamcodes.csv"
1742
1749
1743 opObj12 = proc_spc.addOperation(name='RTIMapPlot', optype='external')
1750 opObj12 = proc_spc.addOperation(name='RTIMapPlot', optype='external')
1744 opObj12.addParameter(name='selectedHeightsList', value='95, 100, 105, 110 ', format='int')
1751 opObj12.addParameter(name='selectedHeightsList', value='95, 100, 105, 110 ', format='int')
1745 opObj12.addParameter(name='bField', value='100', format='int')
1752 opObj12.addParameter(name='bField', value='100', format='int')
1746 opObj12.addParameter(name='filename', value=beamMapFile, format='str')
1753 opObj12.addParameter(name='filename', value=beamMapFile, format='str')
1747
1754
1748 '''
1755 '''
1749
1756
1750 CODE = 'rti_skymap'
1757 CODE = 'rti_skymap'
1751
1758
1752 plot_type = 'scatter'
1759 plot_type = 'scatter'
1753 titles = None
1760 titles = None
1754 colormap = 'jet'
1761 colormap = 'jet'
1755 channelList = []
1762 channelList = []
1756 elevationList = []
1763 elevationList = []
1757 azimuthList = []
1764 azimuthList = []
1758 last_noise = None
1765 last_noise = None
1759 flag_setIndex = False
1766 flag_setIndex = False
1760 heights = []
1767 heights = []
1761 dcosx = []
1768 dcosx = []
1762 dcosy = []
1769 dcosy = []
1763 fullDcosy = None
1770 fullDcosy = None
1764 fullDcosy = None
1771 fullDcosy = None
1765 hindex = []
1772 hindex = []
1766 mapFile = False
1773 mapFile = False
1767 ##### BField ####
1774 ##### BField ####
1768 flagBField = False
1775 flagBField = False
1769 dcosxB = []
1776 dcosxB = []
1770 dcosyB = []
1777 dcosyB = []
1771 Bmarker = ['+','*','D','x','s','>','o','^']
1778 Bmarker = ['+','*','D','x','s','>','o','^']
1772
1779
1773
1780
1774 def setup(self):
1781 def setup(self):
1775
1782
1776 self.xaxis = 'Range (Km)'
1783 self.xaxis = 'Range (Km)'
1777 if len(self.selectedHeightsList) > 0:
1784 if len(self.selectedHeightsList) > 0:
1778 self.nplots = len(self.selectedHeightsList)
1785 self.nplots = len(self.selectedHeightsList)
1779 else:
1786 else:
1780 self.nplots = 4
1787 self.nplots = 4
1781 self.ncols = int(numpy.ceil(self.nplots/2))
1788 self.ncols = int(numpy.ceil(self.nplots/2))
1782 self.nrows = int(numpy.ceil(self.nplots/self.ncols))
1789 self.nrows = int(numpy.ceil(self.nplots/self.ncols))
1783 self.ylabel = 'dcosy'
1790 self.ylabel = 'dcosy'
1784 self.xlabel = 'dcosx'
1791 self.xlabel = 'dcosx'
1785 self.colorbar = True
1792 self.colorbar = True
1786 self.width = 6 + 4.1*self.nrows
1793 self.width = 6 + 4.1*self.nrows
1787 self.height = 3 + 3.5*self.ncols
1794 self.height = 3 + 3.5*self.ncols
1788
1795
1789
1796
1790 if self.extFile!=None:
1797 if self.extFile!=None:
1791 try:
1798 try:
1792 pointings = numpy.genfromtxt(self.extFile, delimiter=',')
1799 pointings = numpy.genfromtxt(self.extFile, delimiter=',')
1793 full_azi = pointings[:,1]
1800 full_azi = pointings[:,1]
1794 full_elev = pointings[:,2]
1801 full_elev = pointings[:,2]
1795 self.fullDcosx = numpy.cos(numpy.radians(full_elev))*numpy.sin(numpy.radians(full_azi))
1802 self.fullDcosx = numpy.cos(numpy.radians(full_elev))*numpy.sin(numpy.radians(full_azi))
1796 self.fullDcosy = numpy.cos(numpy.radians(full_elev))*numpy.cos(numpy.radians(full_azi))
1803 self.fullDcosy = numpy.cos(numpy.radians(full_elev))*numpy.cos(numpy.radians(full_azi))
1797 mapFile = True
1804 mapFile = True
1798 except Exception as e:
1805 except Exception as e:
1799 self.extFile = None
1806 self.extFile = None
1800 print(e)
1807 print(e)
1801
1808
1802
1809
1803 def update_list(self,dataOut):
1810 def update_list(self,dataOut):
1804 if len(self.channelList) == 0:
1811 if len(self.channelList) == 0:
1805 self.channelList = dataOut.channelList
1812 self.channelList = dataOut.channelList
1806 if len(self.elevationList) == 0:
1813 if len(self.elevationList) == 0:
1807 self.elevationList = dataOut.elevationList
1814 self.elevationList = dataOut.elevationList
1808 if len(self.azimuthList) == 0:
1815 if len(self.azimuthList) == 0:
1809 self.azimuthList = dataOut.azimuthList
1816 self.azimuthList = dataOut.azimuthList
1810 a = numpy.radians(numpy.asarray(self.azimuthList))
1817 a = numpy.radians(numpy.asarray(self.azimuthList))
1811 e = numpy.radians(numpy.asarray(self.elevationList))
1818 e = numpy.radians(numpy.asarray(self.elevationList))
1812 self.heights = dataOut.heightList
1819 self.heights = dataOut.heightList
1813 self.dcosx = numpy.cos(e)*numpy.sin(a)
1820 self.dcosx = numpy.cos(e)*numpy.sin(a)
1814 self.dcosy = numpy.cos(e)*numpy.cos(a)
1821 self.dcosy = numpy.cos(e)*numpy.cos(a)
1815
1822
1816 if len(self.bFieldList)>0:
1823 if len(self.bFieldList)>0:
1817 datetObj = datetime.datetime.fromtimestamp(dataOut.utctime)
1824 datetObj = datetime.datetime.fromtimestamp(dataOut.utctime)
1818 doy = datetObj.timetuple().tm_yday
1825 doy = datetObj.timetuple().tm_yday
1819 year = datetObj.year
1826 year = datetObj.year
1820 # self.dcosxB, self.dcosyB
1827 # self.dcosxB, self.dcosyB
1821 ObjB = BField(year=year,doy=doy,site=2,heights=self.bFieldList)
1828 ObjB = BField(year=year,doy=doy,site=2,heights=self.bFieldList)
1822 [dcos, alpha, nlon, nlat] = ObjB.getBField()
1829 [dcos, alpha, nlon, nlat] = ObjB.getBField()
1823
1830
1824 alpha_location = numpy.zeros((nlon,2,len(self.bFieldList)))
1831 alpha_location = numpy.zeros((nlon,2,len(self.bFieldList)))
1825 for ih in range(len(self.bFieldList)):
1832 for ih in range(len(self.bFieldList)):
1826 alpha_location[:,0,ih] = dcos[:,0,ih,0]
1833 alpha_location[:,0,ih] = dcos[:,0,ih,0]
1827 for ilon in numpy.arange(nlon):
1834 for ilon in numpy.arange(nlon):
1828 myx = (alpha[ilon,:,ih])[::-1]
1835 myx = (alpha[ilon,:,ih])[::-1]
1829 myy = (dcos[ilon,:,ih,0])[::-1]
1836 myy = (dcos[ilon,:,ih,0])[::-1]
1830 tck = splrep(myx,myy,s=0)
1837 tck = splrep(myx,myy,s=0)
1831 mydcosx = splev(ObjB.alpha_i,tck,der=0)
1838 mydcosx = splev(ObjB.alpha_i,tck,der=0)
1832
1839
1833 myx = (alpha[ilon,:,ih])[::-1]
1840 myx = (alpha[ilon,:,ih])[::-1]
1834 myy = (dcos[ilon,:,ih,1])[::-1]
1841 myy = (dcos[ilon,:,ih,1])[::-1]
1835 tck = splrep(myx,myy,s=0)
1842 tck = splrep(myx,myy,s=0)
1836 mydcosy = splev(ObjB.alpha_i,tck,der=0)
1843 mydcosy = splev(ObjB.alpha_i,tck,der=0)
1837 alpha_location[ilon,:,ih] = numpy.array([mydcosx, mydcosy])
1844 alpha_location[ilon,:,ih] = numpy.array([mydcosx, mydcosy])
1838 self.dcosxB.append(alpha_location[:,0,ih])
1845 self.dcosxB.append(alpha_location[:,0,ih])
1839 self.dcosyB.append(alpha_location[:,1,ih])
1846 self.dcosyB.append(alpha_location[:,1,ih])
1840 self.flagBField = True
1847 self.flagBField = True
1841
1848
1842 if len(self.celestialList)>0:
1849 if len(self.celestialList)>0:
1843 #getBField(self.bFieldList, date)
1850 #getBField(self.bFieldList, date)
1844 #pass = kwargs.get('celestial', [])
1851 #pass = kwargs.get('celestial', [])
1845 pass
1852 pass
1846
1853
1847
1854
1848 def update(self, dataOut):
1855 def update(self, dataOut):
1849
1856
1850 if len(self.channelList) == 0:
1857 if len(self.channelList) == 0:
1851 self.update_list(dataOut)
1858 self.update_list(dataOut)
1852
1859
1853 if not self.flag_setIndex:
1860 if not self.flag_setIndex:
1854 if len(self.selectedHeightsList)>0:
1861 if len(self.selectedHeightsList)>0:
1855 for sel_height in self.selectedHeightsList:
1862 for sel_height in self.selectedHeightsList:
1856 index_list = numpy.where(self.heights >= sel_height)
1863 index_list = numpy.where(self.heights >= sel_height)
1857 index_list = index_list[0]
1864 index_list = index_list[0]
1858 self.hindex.append(index_list[0])
1865 self.hindex.append(index_list[0])
1859 self.flag_setIndex = True
1866 self.flag_setIndex = True
1860
1867
1861 data = {}
1868 data = {}
1862 meta = {}
1869 meta = {}
1863
1870
1864 data['rti_skymap'] = dataOut.getPower()
1871 data['rti_skymap'] = dataOut.getPower()
1865 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
1872 norm = dataOut.nProfiles * dataOut.max_nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
1866 noise = 10*numpy.log10(dataOut.getNoise()/norm)
1873 noise = 10*numpy.log10(dataOut.getNoise()/norm)
1867 data['noise'] = noise
1874 data['noise'] = noise
1868
1875
1869 return data, meta
1876 return data, meta
1870
1877
1871 def plot(self):
1878 def plot(self):
1872
1879
1873 self.x = self.dcosx
1880 self.x = self.dcosx
1874 self.y = self.dcosy
1881 self.y = self.dcosy
1875 self.z = self.data[-1]['rti_skymap']
1882 self.z = self.data[-1]['rti_skymap']
1876 self.z = numpy.array(self.z, dtype=float)
1883 self.z = numpy.array(self.z, dtype=float)
1877
1884
1878 if len(self.hindex) > 0:
1885 if len(self.hindex) > 0:
1879 index = self.hindex
1886 index = self.hindex
1880 else:
1887 else:
1881 index = numpy.arange(0, len(self.heights), int((len(self.heights))/4.2))
1888 index = numpy.arange(0, len(self.heights), int((len(self.heights))/4.2))
1882
1889
1883 self.titles = ['Height {:.2f} km '.format(self.heights[i])+" " for i in index]
1890 self.titles = ['Height {:.2f} km '.format(self.heights[i])+" " for i in index]
1884 for n, ax in enumerate(self.axes):
1891 for n, ax in enumerate(self.axes):
1885
1892
1886 if ax.firsttime:
1893 if ax.firsttime:
1887
1894
1888 self.xmax = self.xmax if self.xmax else numpy.nanmax(self.x)
1895 self.xmax = self.xmax if self.xmax else numpy.nanmax(self.x)
1889 self.xmin = self.xmin if self.xmin else numpy.nanmin(self.x)
1896 self.xmin = self.xmin if self.xmin else numpy.nanmin(self.x)
1890 self.ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
1897 self.ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
1891 self.ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
1898 self.ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
1892 self.zmax = self.zmax if self.zmax else numpy.nanmax(self.z)
1899 self.zmax = self.zmax if self.zmax else numpy.nanmax(self.z)
1893 self.zmin = self.zmin if self.zmin else numpy.nanmin(self.z)
1900 self.zmin = self.zmin if self.zmin else numpy.nanmin(self.z)
1894
1901
1895 if self.extFile!=None:
1902 if self.extFile!=None:
1896 ax.scatter(self.fullDcosx, self.fullDcosy, marker="+", s=20)
1903 ax.scatter(self.fullDcosx, self.fullDcosy, marker="+", s=20)
1897
1904
1898 ax.plt = ax.scatter(self.x, self.y, c=self.z[:,index[n]], cmap = 'jet',vmin = self.zmin,
1905 ax.plt = ax.scatter(self.x, self.y, c=self.z[:,index[n]], cmap = 'jet',vmin = self.zmin,
1899 s=60, marker="s", vmax = self.zmax)
1906 s=60, marker="s", vmax = self.zmax)
1900
1907
1901
1908
1902 ax.minorticks_on()
1909 ax.minorticks_on()
1903 ax.grid(which='major', axis='both')
1910 ax.grid(which='major', axis='both')
1904 ax.grid(which='minor', axis='x')
1911 ax.grid(which='minor', axis='x')
1905
1912
1906 if self.flagBField :
1913 if self.flagBField :
1907
1914
1908 for ih in range(len(self.bFieldList)):
1915 for ih in range(len(self.bFieldList)):
1909 label = str(self.bFieldList[ih]) + ' km'
1916 label = str(self.bFieldList[ih]) + ' km'
1910 ax.plot(self.dcosxB[ih], self.dcosyB[ih], color='k', marker=self.Bmarker[ih % 8],
1917 ax.plot(self.dcosxB[ih], self.dcosyB[ih], color='k', marker=self.Bmarker[ih % 8],
1911 label=label, linestyle='--', ms=4.0,lw=0.5)
1918 label=label, linestyle='--', ms=4.0,lw=0.5)
1912 handles, labels = ax.get_legend_handles_labels()
1919 handles, labels = ax.get_legend_handles_labels()
1913 a = -0.05
1920 a = -0.05
1914 b = 1.15 - 1.19*(self.nrows)
1921 b = 1.15 - 1.19*(self.nrows)
1915 self.axes[0].legend(handles,labels, bbox_to_anchor=(a,b), prop={'size': (5.8+ 1.1*self.nplots)}, title='B Field βŠ₯')
1922 self.axes[0].legend(handles,labels, bbox_to_anchor=(a,b), prop={'size': (5.8+ 1.1*self.nplots)}, title='B Field βŠ₯')
1916
1923
1917 else:
1924 else:
1918
1925
1919 ax.plt = ax.scatter(self.x, self.y, c=self.z[:,index[n]], cmap = 'jet',vmin = self.zmin,
1926 ax.plt = ax.scatter(self.x, self.y, c=self.z[:,index[n]], cmap = 'jet',vmin = self.zmin,
1920 s=80, marker="s", vmax = self.zmax)
1927 s=80, marker="s", vmax = self.zmax)
1921
1928
1922 if self.flagBField :
1929 if self.flagBField :
1923 for ih in range(len(self.bFieldList)):
1930 for ih in range(len(self.bFieldList)):
1924 ax.plot (self.dcosxB[ih], self.dcosyB[ih], color='k', marker=self.Bmarker[ih % 8],
1931 ax.plot (self.dcosxB[ih], self.dcosyB[ih], color='k', marker=self.Bmarker[ih % 8],
1925 linestyle='--', ms=4.0,lw=0.5)
1932 linestyle='--', ms=4.0,lw=0.5)
1926
1933
1927
1934
1928
1935
@@ -1,815 +1,819
1 import os
1 import os
2 import time
2 import time
3 import datetime
3 import datetime
4
4
5 import numpy
5 import numpy
6 import h5py
6 import h5py
7
7
8 import schainpy.admin
8 import schainpy.admin
9 from schainpy.model.data.jrodata import *
9 from schainpy.model.data.jrodata import *
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 from schainpy.model.io.jroIO_base import *
11 from schainpy.model.io.jroIO_base import *
12 from schainpy.utils import log
12 from schainpy.utils import log
13
13
14
14
15 class HDFReader(Reader, ProcessingUnit):
15 class HDFReader(Reader, ProcessingUnit):
16 """Processing unit to read HDF5 format files
16 """Processing unit to read HDF5 format files
17
17
18 This unit reads HDF5 files created with `HDFWriter` operation contains
18 This unit reads HDF5 files created with `HDFWriter` operation contains
19 by default two groups Data and Metadata all variables would be saved as `dataOut`
19 by default two groups Data and Metadata all variables would be saved as `dataOut`
20 attributes.
20 attributes.
21 It is possible to read any HDF5 file by given the structure in the `description`
21 It is possible to read any HDF5 file by given the structure in the `description`
22 parameter, also you can add extra values to metadata with the parameter `extras`.
22 parameter, also you can add extra values to metadata with the parameter `extras`.
23
23
24 Parameters:
24 Parameters:
25 -----------
25 -----------
26 path : str
26 path : str
27 Path where files are located.
27 Path where files are located.
28 startDate : date
28 startDate : date
29 Start date of the files
29 Start date of the files
30 endDate : list
30 endDate : list
31 End date of the files
31 End date of the files
32 startTime : time
32 startTime : time
33 Start time of the files
33 Start time of the files
34 endTime : time
34 endTime : time
35 End time of the files
35 End time of the files
36 description : dict, optional
36 description : dict, optional
37 Dictionary with the description of the HDF5 file
37 Dictionary with the description of the HDF5 file
38 extras : dict, optional
38 extras : dict, optional
39 Dictionary with extra metadata to be be added to `dataOut`
39 Dictionary with extra metadata to be be added to `dataOut`
40
40
41 Attention: Be carefull, add attribute utcoffset, in the last part of reader in order to work in Local Time without time problems.
41 Attention: Be carefull, add attribute utcoffset, in the last part of reader in order to work in Local Time without time problems.
42
42
43 -----------
43 -----------
44 utcoffset='-18000'
44 utcoffset='-18000'
45
45
46
46
47 Examples
47 Examples
48 --------
48 --------
49
49
50 desc = {
50 desc = {
51 'Data': {
51 'Data': {
52 'data_output': ['u', 'v', 'w'],
52 'data_output': ['u', 'v', 'w'],
53 'utctime': 'timestamps',
53 'utctime': 'timestamps',
54 } ,
54 } ,
55 'Metadata': {
55 'Metadata': {
56 'heightList': 'heights'
56 'heightList': 'heights'
57 }
57 }
58 }
58 }
59
59
60 desc = {
60 desc = {
61 'Data': {
61 'Data': {
62 'data_output': 'winds',
62 'data_output': 'winds',
63 'utctime': 'timestamps'
63 'utctime': 'timestamps'
64 },
64 },
65 'Metadata': {
65 'Metadata': {
66 'heightList': 'heights'
66 'heightList': 'heights'
67 }
67 }
68 }
68 }
69
69
70 extras = {
70 extras = {
71 'timeZone': 300
71 'timeZone': 300
72 }
72 }
73
73
74 reader = project.addReadUnit(
74 reader = project.addReadUnit(
75 name='HDFReader',
75 name='HDFReader',
76 path='/path/to/files',
76 path='/path/to/files',
77 startDate='2019/01/01',
77 startDate='2019/01/01',
78 endDate='2019/01/31',
78 endDate='2019/01/31',
79 startTime='00:00:00',
79 startTime='00:00:00',
80 endTime='23:59:59',
80 endTime='23:59:59',
81 utcoffset='-18000'
81 utcoffset='-18000'
82 # description=json.dumps(desc),
82 # description=json.dumps(desc),
83 # extras=json.dumps(extras),
83 # extras=json.dumps(extras),
84 )
84 )
85
85
86 """
86 """
87
87
88 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
88 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
89
89
90 def __init__(self):
90 def __init__(self):
91
91
92 ProcessingUnit.__init__(self)
92 ProcessingUnit.__init__(self)
93 self.ext = ".hdf5"
93 self.ext = ".hdf5"
94 self.optchar = "D"
94 self.optchar = "D"
95 self.meta = {}
95 self.meta = {}
96 self.data = {}
96 self.data = {}
97 self.open_file = h5py.File
97 self.open_file = h5py.File
98 self.open_mode = 'r'
98 self.open_mode = 'r'
99 self.description = {}
99 self.description = {}
100 self.extras = {}
100 self.extras = {}
101 self.filefmt = "*%Y%j***"
101 self.filefmt = "*%Y%j***"
102 self.folderfmt = "*%Y%j"
102 self.folderfmt = "*%Y%j"
103 self.utcoffset = 0
103 self.utcoffset = 0
104 self.flagUpdateDataOut = False
104 self.flagUpdateDataOut = False
105 self.dataOut = Parameters()
105 self.dataOut = Parameters()
106 self.dataOut.error=False ## NOTE: Importante definir esto antes inicio
106 self.dataOut.error=False ## NOTE: Importante definir esto antes inicio
107 self.dataOut.flagNoData = True
107 self.dataOut.flagNoData = True
108
108
109 def setup(self, **kwargs):
109 def setup(self, **kwargs):
110
110
111 self.set_kwargs(**kwargs)
111 self.set_kwargs(**kwargs)
112 if not self.ext.startswith('.'):
112 if not self.ext.startswith('.'):
113 self.ext = '.{}'.format(self.ext)
113 self.ext = '.{}'.format(self.ext)
114
114
115 if self.online:
115 if self.online:
116 log.log("Searching files in online mode...", self.name)
116 log.log("Searching files in online mode...", self.name)
117
117
118 for nTries in range(self.nTries):
118 for nTries in range(self.nTries):
119 fullpath = self.searchFilesOnLine(self.path, self.startDate,
119 fullpath = self.searchFilesOnLine(self.path, self.startDate,
120 self.endDate, self.expLabel, self.ext, self.walk,
120 self.endDate, self.expLabel, self.ext, self.walk,
121 self.filefmt, self.folderfmt)
121 self.filefmt, self.folderfmt)
122 pathname, filename = os.path.split(fullpath)
122 pathname, filename = os.path.split(fullpath)
123 try:
123 try:
124 fullpath = next(fullpath)
124 fullpath = next(fullpath)
125 except:
125 except:
126 fullpath = None
126 fullpath = None
127
127
128 if fullpath:
128 if fullpath:
129 break
129 break
130
130
131 log.warning(
131 log.warning(
132 'Waiting {} sec for a valid file in {}: try {} ...'.format(
132 'Waiting {} sec for a valid file in {}: try {} ...'.format(
133 self.delay, self.path, nTries + 1),
133 self.delay, self.path, nTries + 1),
134 self.name)
134 self.name)
135 time.sleep(self.delay)
135 time.sleep(self.delay)
136
136
137 if not(fullpath):
137 if not(fullpath):
138 raise schainpy.admin.SchainError(
138 raise schainpy.admin.SchainError(
139 'There isn\'t any valid file in {}'.format(self.path))
139 'There isn\'t any valid file in {}'.format(self.path))
140
140
141 pathname, filename = os.path.split(fullpath)
141 pathname, filename = os.path.split(fullpath)
142 self.year = int(filename[1:5])
142 self.year = int(filename[1:5])
143 self.doy = int(filename[5:8])
143 self.doy = int(filename[5:8])
144 self.set = int(filename[8:11]) - 1
144 self.set = int(filename[8:11]) - 1
145 else:
145 else:
146 log.log("Searching files in {}".format(self.path), self.name)
146 log.log("Searching files in {}".format(self.path), self.name)
147 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
147 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
148 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
148 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
149
149
150 self.setNextFile()
150 self.setNextFile()
151
151
152 return
152 return
153
153
154 # def readFirstHeader(self):
154 # def readFirstHeader(self):
155 # '''Read metadata and data'''
155 # '''Read metadata and data'''
156
156
157 # self.__readMetadata()
157 # self.__readMetadata()
158 # self.__readData()
158 # self.__readData()
159 # self.__setBlockList()
159 # self.__setBlockList()
160
160
161 # if 'type' in self.meta:
161 # if 'type' in self.meta:
162 # self.dataOut = eval(self.meta['type'])()
162 # self.dataOut = eval(self.meta['type'])()
163
163
164 # for attr in self.meta:
164 # for attr in self.meta:
165 # setattr(self.dataOut, attr, self.meta[attr])
165 # setattr(self.dataOut, attr, self.meta[attr])
166
166
167 # self.blockIndex = 0
167 # self.blockIndex = 0
168
168
169 # return
169 # return
170
170
171 def readFirstHeader(self):
171 def readFirstHeader(self):
172 '''Read metadata and data'''
172 '''Read metadata and data'''
173
173
174 self.__readMetadata2()
174 self.__readMetadata2()
175 self.__readData()
175 self.__readData()
176 self.__setBlockList()
176 self.__setBlockList()
177 if 'type' in self.meta:
177 if 'type' in self.meta:
178 self.dataOut = eval(self.meta['type'])()
178 self.dataOut = eval(self.meta['type'])()
179
179
180 for attr in self.meta:
180 for attr in self.meta:
181 if "processingHeaderObj" in attr:
181 if "processingHeaderObj" in attr:
182 self.flagUpdateDataOut=True
182 self.flagUpdateDataOut=True
183 at = attr.split('.')
183 at = attr.split('.')
184 if len(at) > 1:
184 if len(at) > 1:
185 setattr(eval("self.dataOut."+at[0]),at[1], self.meta[attr])
185 setattr(eval("self.dataOut."+at[0]),at[1], self.meta[attr])
186 else:
186 else:
187 setattr(self.dataOut, attr, self.meta[attr])
187 setattr(self.dataOut, attr, self.meta[attr])
188 self.blockIndex = 0
188 self.blockIndex = 0
189
189
190 if self.flagUpdateDataOut:
190 if self.flagUpdateDataOut:
191 self.updateDataOut()
191 self.updateDataOut()
192
192
193 return
193 return
194
194
195 def updateDataOut(self):
195 def updateDataOut(self):
196
196
197 self.dataOut.azimuthList = self.dataOut.processingHeaderObj.azimuthList
197 self.dataOut.azimuthList = self.dataOut.processingHeaderObj.azimuthList
198 self.dataOut.elevationList = self.dataOut.processingHeaderObj.elevationList
198 self.dataOut.elevationList = self.dataOut.processingHeaderObj.elevationList
199 self.dataOut.heightList = self.dataOut.processingHeaderObj.heightList
199 self.dataOut.heightList = self.dataOut.processingHeaderObj.heightList
200 self.dataOut.ippSeconds = self.dataOut.processingHeaderObj.ipp
200 self.dataOut.ippSeconds = self.dataOut.processingHeaderObj.ipp
201 self.dataOut.elevationList = self.dataOut.processingHeaderObj.elevationList
201 self.dataOut.elevationList = self.dataOut.processingHeaderObj.elevationList
202 self.dataOut.channelList = self.dataOut.processingHeaderObj.channelList
202 self.dataOut.channelList = self.dataOut.processingHeaderObj.channelList
203 self.dataOut.nCohInt = self.dataOut.processingHeaderObj.nCohInt
203 self.dataOut.nCohInt = self.dataOut.processingHeaderObj.nCohInt
204 self.dataOut.nFFTPoints = self.dataOut.processingHeaderObj.nFFTPoints
204 self.dataOut.nFFTPoints = self.dataOut.processingHeaderObj.nFFTPoints
205 self.flagUpdateDataOut = False
205 self.flagUpdateDataOut = False
206 self.dataOut.frequency = self.dataOut.radarControllerHeaderObj.frequency
206 self.dataOut.frequency = self.dataOut.radarControllerHeaderObj.frequency
207 #self.dataOut.heightList = self.dataOut.processingHeaderObj.heightList
207 #self.dataOut.heightList = self.dataOut.processingHeaderObj.heightList
208
208
209 def __setBlockList(self):
209 def __setBlockList(self):
210 '''
210 '''
211 Selects the data within the times defined
211 Selects the data within the times defined
212
212
213 self.fp
213 self.fp
214 self.startTime
214 self.startTime
215 self.endTime
215 self.endTime
216 self.blockList
216 self.blockList
217 self.blocksPerFile
217 self.blocksPerFile
218
218
219 '''
219 '''
220
220
221 startTime = self.startTime
221 startTime = self.startTime
222 endTime = self.endTime
222 endTime = self.endTime
223 thisUtcTime = self.data['utctime'] + self.utcoffset
223 thisUtcTime = self.data['utctime'] + self.utcoffset
224 # self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
224 # self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
225 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
225 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
226 self.startFileDatetime = thisDatetime
226 self.startFileDatetime = thisDatetime
227 thisDate = thisDatetime.date()
227 thisDate = thisDatetime.date()
228 thisTime = thisDatetime.time()
228 thisTime = thisDatetime.time()
229 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
229 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
230 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
230 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
231 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
231 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
232
232
233 self.blockList = ind
233 self.blockList = ind
234 self.blocksPerFile = len(ind)
234 self.blocksPerFile = len(ind)
235 # self.blocksPerFile = len(thisUtcTime)
235 # self.blocksPerFile = len(thisUtcTime)
236 if len(ind)==0:
236 if len(ind)==0:
237 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.blockIndex,
237 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.blockIndex,
238 self.blocksPerFile,
238 self.blocksPerFile,
239 thisDatetime))
239 thisDatetime))
240 self.setNextFile()
240 self.setNextFile()
241
241
242 return
242 return
243
243
244 def __readMetadata(self):
244 def __readMetadata(self):
245 '''
245 '''
246 Reads Metadata
246 Reads Metadata
247 '''
247 '''
248
248
249 meta = {}
249 meta = {}
250
250
251 if self.description:
251 if self.description:
252 for key, value in self.description['Metadata'].items():
252 for key, value in self.description['Metadata'].items():
253 meta[key] = self.fp[value][()]
253 meta[key] = self.fp[value][()]
254 else:
254 else:
255 grp = self.fp['Metadata']
255 grp = self.fp['Metadata']
256 for name in grp:
256 for name in grp:
257 meta[name] = grp[name][()]
257 meta[name] = grp[name][()]
258
258
259 if self.extras:
259 if self.extras:
260 for key, value in self.extras.items():
260 for key, value in self.extras.items():
261 meta[key] = value
261 meta[key] = value
262 self.meta = meta
262 self.meta = meta
263
263
264 return
264 return
265
265
266 def __readMetadata2(self):
266 def __readMetadata2(self):
267 '''
267 '''
268 Reads Metadata
268 Reads Metadata
269 '''
269 '''
270 meta = {}
270 meta = {}
271 if self.description:
271 if self.description:
272 for key, value in self.description['Metadata'].items():
272 for key, value in self.description['Metadata'].items():
273 meta[key] = self.fp[value][()]
273 meta[key] = self.fp[value][()]
274 else:
274 else:
275 grp = self.fp['Metadata']
275 grp = self.fp['Metadata']
276 for item in grp.values():
276 for item in grp.values():
277 name = item.name
277 name = item.name
278 if isinstance(item, h5py.Dataset):
278 if isinstance(item, h5py.Dataset):
279 name = name.split("/")[-1]
279 name = name.split("/")[-1]
280 meta[name] = item[()]
280 meta[name] = item[()]
281 else:
281 else:
282 grp2 = self.fp[name]
282 grp2 = self.fp[name]
283 Obj = name.split("/")[-1]
283 Obj = name.split("/")[-1]
284
284
285 for item2 in grp2.values():
285 for item2 in grp2.values():
286 name2 = Obj+"."+item2.name.split("/")[-1]
286 name2 = Obj+"."+item2.name.split("/")[-1]
287 meta[name2] = item2[()]
287 meta[name2] = item2[()]
288
288
289 if self.extras:
289 if self.extras:
290 for key, value in self.extras.items():
290 for key, value in self.extras.items():
291 meta[key] = value
291 meta[key] = value
292 self.meta = meta
292 self.meta = meta
293
293
294 return
294 return
295
295
296 def __readData(self):
296 def __readData(self):
297
297
298 data = {}
298 data = {}
299
299
300 if self.description:
300 if self.description:
301 for key, value in self.description['Data'].items():
301 for key, value in self.description['Data'].items():
302 if isinstance(value, str):
302 if isinstance(value, str):
303 if isinstance(self.fp[value], h5py.Dataset):
303 if isinstance(self.fp[value], h5py.Dataset):
304 data[key] = self.fp[value][()]
304 data[key] = self.fp[value][()]
305 elif isinstance(self.fp[value], h5py.Group):
305 elif isinstance(self.fp[value], h5py.Group):
306 array = []
306 array = []
307 for ch in self.fp[value]:
307 for ch in self.fp[value]:
308 array.append(self.fp[value][ch][()])
308 array.append(self.fp[value][ch][()])
309 data[key] = numpy.array(array)
309 data[key] = numpy.array(array)
310 elif isinstance(value, list):
310 elif isinstance(value, list):
311 array = []
311 array = []
312 for ch in value:
312 for ch in value:
313 array.append(self.fp[ch][()])
313 array.append(self.fp[ch][()])
314 data[key] = numpy.array(array)
314 data[key] = numpy.array(array)
315 else:
315 else:
316 grp = self.fp['Data']
316 grp = self.fp['Data']
317 for name in grp:
317 for name in grp:
318 if isinstance(grp[name], h5py.Dataset):
318 if isinstance(grp[name], h5py.Dataset):
319 array = grp[name][()]
319 array = grp[name][()]
320 elif isinstance(grp[name], h5py.Group):
320 elif isinstance(grp[name], h5py.Group):
321 array = []
321 array = []
322 for ch in grp[name]:
322 for ch in grp[name]:
323 array.append(grp[name][ch][()])
323 array.append(grp[name][ch][()])
324 array = numpy.array(array)
324 array = numpy.array(array)
325 else:
325 else:
326 log.warning('Unknown type: {}'.format(name))
326 log.warning('Unknown type: {}'.format(name))
327
327
328 if name in self.description:
328 if name in self.description:
329 key = self.description[name]
329 key = self.description[name]
330 else:
330 else:
331 key = name
331 key = name
332 data[key] = array
332 data[key] = array
333
333
334 self.data = data
334 self.data = data
335 return
335 return
336
336
337 def getData(self):
337 def getData(self):
338
338
339 if not self.isDateTimeInRange(self.startFileDatetime, self.startDate, self.endDate, self.startTime, self.endTime):
339 if not self.isDateTimeInRange(self.startFileDatetime, self.startDate, self.endDate, self.startTime, self.endTime):
340 self.dataOut.flagNoData = True
340 self.dataOut.flagNoData = True
341 self.blockIndex = self.blocksPerFile
341 self.blockIndex = self.blocksPerFile
342 self.dataOut.error = True # TERMINA EL PROGRAMA
342 self.dataOut.error = True # TERMINA EL PROGRAMA
343 return
343 return
344 for attr in self.data:
344 for attr in self.data:
345
345
346 if self.data[attr].ndim == 1:
346 if self.data[attr].ndim == 1:
347 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
347 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
348 else:
348 else:
349 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
349 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
350
350
351
351
352 self.blockIndex += 1
352 self.blockIndex += 1
353
353
354 if self.blockIndex == 1:
354 if self.blockIndex == 1:
355 log.log("Block No. {}/{} -> {}".format(
355 log.log("Block No. {}/{} -> {}".format(
356 self.blockIndex,
356 self.blockIndex,
357 self.blocksPerFile,
357 self.blocksPerFile,
358 self.dataOut.datatime.ctime()), self.name)
358 self.dataOut.datatime.ctime()), self.name)
359 else:
359 else:
360 log.log("Block No. {}/{} ".format(
360 log.log("Block No. {}/{} ".format(
361 self.blockIndex,
361 self.blockIndex,
362 self.blocksPerFile),self.name)
362 self.blocksPerFile),self.name)
363
363
364 if self.blockIndex == self.blocksPerFile:
364 if self.blockIndex == self.blocksPerFile:
365 self.setNextFile()
365 self.setNextFile()
366
366
367 self.dataOut.flagNoData = False
367 self.dataOut.flagNoData = False
368
368
369 return
369 return
370
370
371 def run(self, **kwargs):
371 def run(self, **kwargs):
372
372
373 if not(self.isConfig):
373 if not(self.isConfig):
374 self.setup(**kwargs)
374 self.setup(**kwargs)
375 self.isConfig = True
375 self.isConfig = True
376
376
377 if self.blockIndex == self.blocksPerFile:
377 if self.blockIndex == self.blocksPerFile:
378 self.setNextFile()
378 self.setNextFile()
379
379
380 self.getData()
380 self.getData()
381
381
382 return
382 return
383
383
384 @MPDecorator
384 @MPDecorator
385 class HDFWriter(Operation):
385 class HDFWriter(Operation):
386 """Operation to write HDF5 files.
386 """Operation to write HDF5 files.
387
387
388 The HDF5 file contains by default two groups Data and Metadata where
388 The HDF5 file contains by default two groups Data and Metadata where
389 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
389 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
390 parameters, data attributes are normaly time dependent where the metadata
390 parameters, data attributes are normaly time dependent where the metadata
391 are not.
391 are not.
392 It is possible to customize the structure of the HDF5 file with the
392 It is possible to customize the structure of the HDF5 file with the
393 optional description parameter see the examples.
393 optional description parameter see the examples.
394
394
395 Parameters:
395 Parameters:
396 -----------
396 -----------
397 path : str
397 path : str
398 Path where files will be saved.
398 Path where files will be saved.
399 blocksPerFile : int
399 blocksPerFile : int
400 Number of blocks per file
400 Number of blocks per file
401 metadataList : list
401 metadataList : list
402 List of the dataOut attributes that will be saved as metadata
402 List of the dataOut attributes that will be saved as metadata
403 dataList : int
403 dataList : int
404 List of the dataOut attributes that will be saved as data
404 List of the dataOut attributes that will be saved as data
405 setType : bool
405 setType : bool
406 If True the name of the files corresponds to the timestamp of the data
406 If True the name of the files corresponds to the timestamp of the data
407 description : dict, optional
407 description : dict, optional
408 Dictionary with the desired description of the HDF5 file
408 Dictionary with the desired description of the HDF5 file
409
409
410 Examples
410 Examples
411 --------
411 --------
412
412
413 desc = {
413 desc = {
414 'data_output': {'winds': ['z', 'w', 'v']},
414 'data_output': {'winds': ['z', 'w', 'v']},
415 'utctime': 'timestamps',
415 'utctime': 'timestamps',
416 'heightList': 'heights'
416 'heightList': 'heights'
417 }
417 }
418 desc = {
418 desc = {
419 'data_output': ['z', 'w', 'v'],
419 'data_output': ['z', 'w', 'v'],
420 'utctime': 'timestamps',
420 'utctime': 'timestamps',
421 'heightList': 'heights'
421 'heightList': 'heights'
422 }
422 }
423 desc = {
423 desc = {
424 'Data': {
424 'Data': {
425 'data_output': 'winds',
425 'data_output': 'winds',
426 'utctime': 'timestamps'
426 'utctime': 'timestamps'
427 },
427 },
428 'Metadata': {
428 'Metadata': {
429 'heightList': 'heights'
429 'heightList': 'heights'
430 }
430 }
431 }
431 }
432
432
433 writer = proc_unit.addOperation(name='HDFWriter')
433 writer = proc_unit.addOperation(name='HDFWriter')
434 writer.addParameter(name='path', value='/path/to/file')
434 writer.addParameter(name='path', value='/path/to/file')
435 writer.addParameter(name='blocksPerFile', value='32')
435 writer.addParameter(name='blocksPerFile', value='32')
436 writer.addParameter(name='metadataList', value='heightList,timeZone')
436 writer.addParameter(name='metadataList', value='heightList,timeZone')
437 writer.addParameter(name='dataList',value='data_output,utctime')
437 writer.addParameter(name='dataList',value='data_output,utctime')
438 # writer.addParameter(name='description',value=json.dumps(desc))
438 # writer.addParameter(name='description',value=json.dumps(desc))
439
439
440 """
440 """
441
441
442 ext = ".hdf5"
442 ext = ".hdf5"
443 optchar = "D"
443 optchar = "D"
444 filename = None
444 filename = None
445 path = None
445 path = None
446 setFile = None
446 setFile = None
447 fp = None
447 fp = None
448 ds = None
448 firsttime = True
449 firsttime = True
449 #Configurations
450 #Configurations
450 blocksPerFile = None
451 blocksPerFile = None
451 blockIndex = None
452 blockIndex = None
452 dataOut = None #eval ??????
453 dataOut = None #eval ??????
453 #Data Arrays
454 #Data Arrays
454 dataList = None
455 dataList = None
455 metadataList = None
456 metadataList = None
456 currentDay = None
457 currentDay = None
457 lastTime = None
458 lastTime = None
458 timeZone = "ut"
459 timeZone = "ut"
459 hourLimit = 3
460 hourLimit = 3
460 breakDays = True
461 breakDays = True
461
462
462 def __init__(self):
463 def __init__(self):
463
464
464 Operation.__init__(self)
465 Operation.__init__(self)
465 return
466 return
466
467
467 def set_kwargs(self, **kwargs):
468 def set_kwargs(self, **kwargs):
468
469
469 for key, value in kwargs.items():
470 for key, value in kwargs.items():
470 setattr(self, key, value)
471 setattr(self, key, value)
471
472
472 def set_kwargs_obj(self, obj, **kwargs):
473 def set_kwargs_obj(self, obj, **kwargs):
473
474
474 for key, value in kwargs.items():
475 for key, value in kwargs.items():
475 setattr(obj, key, value)
476 setattr(obj, key, value)
476
477
477 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None,
478 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None,
478 description={},timeZone = "ut",hourLimit = 3, breakDays=True, **kwargs):
479 description={},timeZone = "ut",hourLimit = 3, breakDays=True, **kwargs):
479 self.path = path
480 self.path = path
480 self.blocksPerFile = blocksPerFile
481 self.blocksPerFile = blocksPerFile
481 self.metadataList = metadataList
482 self.metadataList = metadataList
482 self.dataList = [s.strip() for s in dataList]
483 self.dataList = [s.strip() for s in dataList]
483 self.setType = setType
484 self.setType = setType
484 self.description = description
485 self.description = description
485 self.timeZone = timeZone
486 self.timeZone = timeZone
486 self.hourLimit = hourLimit
487 self.hourLimit = hourLimit
487 self.breakDays = breakDays
488 self.breakDays = breakDays
488 self.set_kwargs(**kwargs)
489 self.set_kwargs(**kwargs)
489
490
490 if self.metadataList is None:
491 if self.metadataList is None:
491 self.metadataList = self.dataOut.metadata_list
492 self.metadataList = self.dataOut.metadata_list
492
493
494 self.metadataList = list(set(self.metadataList))
495
493 tableList = []
496 tableList = []
494 dsList = []
497 dsList = []
495
498
496 for i in range(len(self.dataList)):
499 for i in range(len(self.dataList)):
497 dsDict = {}
500 dsDict = {}
498 if hasattr(self.dataOut, self.dataList[i]):
501 if hasattr(self.dataOut, self.dataList[i]):
499 dataAux = getattr(self.dataOut, self.dataList[i])
502 dataAux = getattr(self.dataOut, self.dataList[i])
500 dsDict['variable'] = self.dataList[i]
503 dsDict['variable'] = self.dataList[i]
501 else:
504 else:
502 log.warning('Attribute {} not found in dataOut'.format(self.dataList[i]),self.name)
505 log.warning('Attribute {} not found in dataOut'.format(self.dataList[i]),self.name)
503 continue
506 continue
504
507
505 if dataAux is None:
508 if dataAux is None:
506 continue
509 continue
507 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
510 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float_)):
508 dsDict['nDim'] = 0
511 dsDict['nDim'] = 0
509 else:
512 else:
510 dsDict['nDim'] = len(dataAux.shape)
513 dsDict['nDim'] = len(dataAux.shape)
511 dsDict['shape'] = dataAux.shape
514 dsDict['shape'] = dataAux.shape
512 dsDict['dsNumber'] = dataAux.shape[0]
515 dsDict['dsNumber'] = dataAux.shape[0]
513 dsDict['dtype'] = dataAux.dtype
516 dsDict['dtype'] = dataAux.dtype
514
517
515 dsList.append(dsDict)
518 dsList.append(dsDict)
516
519
520 self.blockIndex = 0
517 self.dsList = dsList
521 self.dsList = dsList
518 self.currentDay = self.dataOut.datatime.date()
522 self.currentDay = self.dataOut.datatime.date()
519
523
520 def timeFlag(self):
524 def timeFlag(self):
521 currentTime = self.dataOut.utctime
525 currentTime = self.dataOut.utctime
522 timeTuple = None
526 timeTuple = None
523 if self.timeZone == "lt":
527 if self.timeZone == "lt":
524 timeTuple = time.localtime(currentTime)
528 timeTuple = time.localtime(currentTime)
525 else :
529 else :
526 timeTuple = time.gmtime(currentTime)
530 timeTuple = time.gmtime(currentTime)
527 dataDay = timeTuple.tm_yday
531 dataDay = timeTuple.tm_yday
528
532
529 if self.lastTime is None:
533 if self.lastTime is None:
530 self.lastTime = currentTime
534 self.lastTime = currentTime
531 self.currentDay = dataDay
535 self.currentDay = dataDay
532 return False
536 return False
533
537
534 timeDiff = currentTime - self.lastTime
538 timeDiff = currentTime - self.lastTime
535
539
536 # Si el dia es diferente o si la diferencia entre un
540 # Si el dia es diferente o si la diferencia entre un
537 # dato y otro supera self.hourLimit
541 # dato y otro supera self.hourLimit
538 if (dataDay != self.currentDay) and self.breakDays:
542 if (dataDay != self.currentDay) and self.breakDays:
539 self.currentDay = dataDay
543 self.currentDay = dataDay
540 return True
544 return True
541 elif timeDiff > self.hourLimit*60*60:
545 elif timeDiff > self.hourLimit*60*60:
542 self.lastTime = currentTime
546 self.lastTime = currentTime
543 return True
547 return True
544 else:
548 else:
545 self.lastTime = currentTime
549 self.lastTime = currentTime
546 return False
550 return False
547
551
548 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
552 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
549 dataList=[], setType=None, description={}, **kwargs):
553 dataList=[], setType=None, description={}, **kwargs):
550
554
551 self.dataOut = dataOut
555 self.dataOut = dataOut
552 self.set_kwargs_obj(self.dataOut, **kwargs)
556 self.set_kwargs_obj(self.dataOut, **kwargs)
553 if not(self.isConfig):
557 if not(self.isConfig):
554 self.setup(path=path, blocksPerFile=blocksPerFile,
558 self.setup(path=path, blocksPerFile=blocksPerFile,
555 metadataList=metadataList, dataList=dataList,
559 metadataList=metadataList, dataList=dataList,
556 setType=setType, description=description, **kwargs)
560 setType=setType, description=description, **kwargs)
557
561
558 self.isConfig = True
562 self.isConfig = True
559 self.setNextFile()
563 self.setNextFile()
560
564
561 self.putData()
565 self.putData()
562 return
566 return
563
567
564 def setNextFile(self):
568 def setNextFile(self):
565
569
566 ext = self.ext
570 ext = self.ext
567 path = self.path
571 path = self.path
568 setFile = self.setFile
572 setFile = self.setFile
569 timeTuple = None
573 timeTuple = None
570 if self.timeZone == "lt":
574 if self.timeZone == "lt":
571 timeTuple = time.localtime(self.dataOut.utctime)
575 timeTuple = time.localtime(self.dataOut.utctime)
572 elif self.timeZone == "ut":
576 elif self.timeZone == "ut":
573 timeTuple = time.gmtime(self.dataOut.utctime)
577 timeTuple = time.gmtime(self.dataOut.utctime)
574 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
578 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
575 fullpath = os.path.join(path, subfolder)
579 fullpath = os.path.join(path, subfolder)
576
580
577 if os.path.exists(fullpath):
581 if os.path.exists(fullpath):
578 filesList = os.listdir(fullpath)
582 filesList = os.listdir(fullpath)
579 filesList = [k for k in filesList if k.startswith(self.optchar)]
583 filesList = [k for k in filesList if k.startswith(self.optchar)]
580 if len(filesList) > 0:
584 if len(filesList) > 0:
581 filesList = sorted(filesList, key=str.lower)
585 filesList = sorted(filesList, key=str.lower)
582 filen = filesList[-1]
586 filen = filesList[-1]
583 # el filename debera tener el siguiente formato
587 # el filename debera tener el siguiente formato
584 # 0 1234 567 89A BCDE (hex)
588 # 0 1234 567 89A BCDE (hex)
585 # x YYYY DDD SSS .ext
589 # x YYYY DDD SSS .ext
586 if isNumber(filen[8:11]):
590 if isNumber(filen[8:11]):
587 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
591 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
588 else:
592 else:
589 setFile = -1
593 setFile = -1
590 else:
594 else:
591 setFile = -1 #inicializo mi contador de seteo
595 setFile = -1 #inicializo mi contador de seteo
592 else:
596 else:
593 os.makedirs(fullpath)
597 os.makedirs(fullpath)
594 setFile = -1 #inicializo mi contador de seteo
598 setFile = -1 #inicializo mi contador de seteo
595
599
596 if self.setType is None:
600 if self.setType is None:
597 setFile += 1
601 setFile += 1
598 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
602 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
599 timeTuple.tm_year,
603 timeTuple.tm_year,
600 timeTuple.tm_yday,
604 timeTuple.tm_yday,
601 setFile,
605 setFile,
602 ext)
606 ext)
603 else:
607 else:
604 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
608 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
605 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
609 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
606 timeTuple.tm_year,
610 timeTuple.tm_year,
607 timeTuple.tm_yday,
611 timeTuple.tm_yday,
608 setFile,
612 setFile,
609 ext)
613 ext)
610
614
611 self.filename = os.path.join(path, subfolder, file)
615 self.filename = os.path.join(path, subfolder, file)
612
616
613
617
614
618
615 def getLabel(self, name, x=None):
619 def getLabel(self, name, x=None):
616
620
617 if x is None:
621 if x is None:
618 if 'Data' in self.description:
622 if 'Data' in self.description:
619 data = self.description['Data']
623 data = self.description['Data']
620 if 'Metadata' in self.description:
624 if 'Metadata' in self.description:
621 data.update(self.description['Metadata'])
625 data.update(self.description['Metadata'])
622 else:
626 else:
623 data = self.description
627 data = self.description
624 if name in data:
628 if name in data:
625 if isinstance(data[name], str):
629 if isinstance(data[name], str):
626 return data[name]
630 return data[name]
627 elif isinstance(data[name], list):
631 elif isinstance(data[name], list):
628 return None
632 return None
629 elif isinstance(data[name], dict):
633 elif isinstance(data[name], dict):
630 for key, value in data[name].items():
634 for key, value in data[name].items():
631 return key
635 return key
632 return name
636 return name
633 else:
637 else:
634 if 'Metadata' in self.description:
638 if 'Metadata' in self.description:
635 meta = self.description['Metadata']
639 meta = self.description['Metadata']
636 else:
640 else:
637 meta = self.description
641 meta = self.description
638 if name in meta:
642 if name in meta:
639 if isinstance(meta[name], list):
643 if isinstance(meta[name], list):
640 return meta[name][x]
644 return meta[name][x]
641 elif isinstance(meta[name], dict):
645 elif isinstance(meta[name], dict):
642 for key, value in meta[name].items():
646 for key, value in meta[name].items():
643 return value[x]
647 return value[x]
644 if 'cspc' in name:
648 if 'cspc' in name:
645 return 'pair{:02d}'.format(x)
649 return 'pair{:02d}'.format(x)
646 else:
650 else:
647 return 'channel{:02d}'.format(x)
651 return 'channel{:02d}'.format(x)
648
652
649 def writeMetadata(self, fp):
653 def writeMetadata(self, fp):
650
654
651 if self.description:
655 if self.description:
652 if 'Metadata' in self.description:
656 if 'Metadata' in self.description:
653 grp = fp.create_group('Metadata')
657 grp = fp.create_group('Metadata')
654 else:
658 else:
655 grp = fp
659 grp = fp
656 else:
660 else:
657 grp = fp.create_group('Metadata')
661 grp = fp.create_group('Metadata')
658
662
659 for i in range(len(self.metadataList)):
663 for i in range(len(self.metadataList)):
660 if not hasattr(self.dataOut, self.metadataList[i]):
664 if not hasattr(self.dataOut, self.metadataList[i]):
661 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
665 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
662 continue
666 continue
663 value = getattr(self.dataOut, self.metadataList[i])
667 value = getattr(self.dataOut, self.metadataList[i])
664 if isinstance(value, bool):
668 if isinstance(value, bool):
665 if value is True:
669 if value is True:
666 value = 1
670 value = 1
667 else:
671 else:
668 value = 0
672 value = 0
669 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
673 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
670 return
674 return
671
675
672 def writeMetadata2(self, fp):
676 def writeMetadata2(self, fp):
673
677
674 if self.description:
678 if self.description:
675 if 'Metadata' in self.description:
679 if 'Metadata' in self.description:
676 grp = fp.create_group('Metadata')
680 grp = fp.create_group('Metadata')
677 else:
681 else:
678 grp = fp
682 grp = fp
679 else:
683 else:
680 grp = fp.create_group('Metadata')
684 grp = fp.create_group('Metadata')
681
685
682 for i in range(len(self.metadataList)):
686 for i in range(len(self.metadataList)):
683
687
684 attribute = self.metadataList[i]
688 attribute = self.metadataList[i]
685 attr = attribute.split('.')
689 attr = attribute.split('.')
686 if len(attr) > 1:
690 if len(attr) > 1:
687 if not hasattr(eval("self.dataOut."+attr[0]),attr[1]):
691 if not hasattr(eval("self.dataOut."+attr[0]),attr[1]):
688 log.warning('Metadata: {}.{} not found'.format(attr[0],attr[1]), self.name)
692 log.warning('Metadata: {}.{} not found'.format(attr[0],attr[1]), self.name)
689 continue
693 continue
690 value = getattr(eval("self.dataOut."+attr[0]),attr[1])
694 value = getattr(eval("self.dataOut."+attr[0]),attr[1])
691 if isinstance(value, bool):
695 if isinstance(value, bool):
692 if value is True:
696 if value is True:
693 value = 1
697 value = 1
694 else:
698 else:
695 value = 0
699 value = 0
696 if isinstance(value,type(None)):
700 if isinstance(value,type(None)):
697 log.warning("Invalid value detected, {} is None".format(attribute), self.name)
701 log.warning("Invalid value detected, {} is None".format(attribute), self.name)
698 value = 0
702 value = 0
699 grp2 = None
703 grp2 = None
700 if not 'Metadata/'+attr[0] in fp:
704 if not 'Metadata/'+attr[0] in fp:
701 grp2 = fp.create_group('Metadata/'+attr[0])
705 grp2 = fp.create_group('Metadata/'+attr[0])
702 else:
706 else:
703 grp2 = fp['Metadata/'+attr[0]]
707 grp2 = fp['Metadata/'+attr[0]]
704 grp2.create_dataset(attr[1], data=value)
708 grp2.create_dataset(attr[1], data=value)
705
709
706 else:
710 else:
707 if not hasattr(self.dataOut, attr[0] ):
711 if not hasattr(self.dataOut, attr[0] ):
708 log.warning('Metadata: `{}` not found'.format(attribute), self.name)
712 log.warning('Metadata: `{}` not found'.format(attribute), self.name)
709 continue
713 continue
710 value = getattr(self.dataOut, attr[0])
714 value = getattr(self.dataOut, attr[0])
711 if isinstance(value, bool):
715 if isinstance(value, bool):
712 if value is True:
716 if value is True:
713 value = 1
717 value = 1
714 else:
718 else:
715 value = 0
719 value = 0
716 if isinstance(value, type(None)):
720 if isinstance(value, type(None)):
717 log.error("Value {} is None".format(attribute),self.name)
721 log.error("Value {} is None".format(attribute),self.name)
718
722
719 grp.create_dataset(self.getLabel(attribute), data=value)
723 grp.create_dataset(self.getLabel(attribute), data=value)
720
724
721 return
725 return
722
726
723 def writeData(self, fp):
727 def writeData(self, fp):
724
728
725 if self.description:
729 if self.description:
726 if 'Data' in self.description:
730 if 'Data' in self.description:
727 grp = fp.create_group('Data')
731 grp = fp.create_group('Data')
728 else:
732 else:
729 grp = fp
733 grp = fp
730 else:
734 else:
731 grp = fp.create_group('Data')
735 grp = fp.create_group('Data')
732
736
733 dtsets = []
737 dtsets = []
734 data = []
738 data = []
735
739
736 for dsInfo in self.dsList:
740 for dsInfo in self.dsList:
737 if dsInfo['nDim'] == 0:
741 if dsInfo['nDim'] == 0:
738 ds = grp.create_dataset(
742 ds = grp.create_dataset(
739 self.getLabel(dsInfo['variable']),
743 self.getLabel(dsInfo['variable']),
740 (self.blocksPerFile,),
744 (self.blocksPerFile,),
741 chunks=True,
745 chunks=True,
742 dtype=numpy.float64)
746 dtype=numpy.float64)
743 dtsets.append(ds)
747 dtsets.append(ds)
744 data.append((dsInfo['variable'], -1))
748 data.append((dsInfo['variable'], -1))
745 else:
749 else:
746 label = self.getLabel(dsInfo['variable'])
750 label = self.getLabel(dsInfo['variable'])
747 if label is not None:
751 if label is not None:
748 sgrp = grp.create_group(label)
752 sgrp = grp.create_group(label)
749 else:
753 else:
750 sgrp = grp
754 sgrp = grp
751 for i in range(dsInfo['dsNumber']):
755 for i in range(dsInfo['dsNumber']):
752 ds = sgrp.create_dataset(
756 ds = sgrp.create_dataset(
753 self.getLabel(dsInfo['variable'], i),
757 self.getLabel(dsInfo['variable'], i),
754 (self.blocksPerFile,) + dsInfo['shape'][1:],
758 (self.blocksPerFile,) + dsInfo['shape'][1:],
755 chunks=True,
759 chunks=True,
756 dtype=dsInfo['dtype'])
760 dtype=dsInfo['dtype'])
757 dtsets.append(ds)
761 dtsets.append(ds)
758 data.append((dsInfo['variable'], i))
762 data.append((dsInfo['variable'], i))
759 fp.flush()
763 fp.flush()
760
764
761 log.log('Creating file: {}'.format(fp.filename), self.name)
765 log.log('Creating file: {}'.format(fp.filename), self.name)
762
766
763 self.ds = dtsets
767 self.ds = dtsets
764 self.data = data
768 self.data = data
765 self.firsttime = True
769 self.firsttime = True
766 self.blockIndex = 0
770
767 return
771 return
768
772
769 def putData(self):
773 def putData(self):
770
774
771 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
775 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
772 self.closeFile()
776 self.closeFile()
773 self.setNextFile()
777 self.setNextFile()
774 self.dataOut.flagNoData = False
778 self.dataOut.flagNoData = False
775 self.blockIndex = 0
779 self.blockIndex = 0
776
780
777 if self.blockIndex == 0:
781 if self.blockIndex == 0:
778 #Setting HDF5 File
782 #Setting HDF5 File
779 self.fp = h5py.File(self.filename, 'w')
783 self.fp = h5py.File(self.filename, 'w')
780 #write metadata
784 #write metadata
781 self.writeMetadata2(self.fp)
785 self.writeMetadata2(self.fp)
782 #Write data
786 #Write data
783 self.writeData(self.fp)
787 self.writeData(self.fp)
784 log.log('Block No. {}/{} --> {}'.format(self.blockIndex+1, self.blocksPerFile,self.dataOut.datatime.ctime()), self.name)
788 log.log('Block No. {}/{} --> {}'.format(self.blockIndex+1, self.blocksPerFile,self.dataOut.datatime.ctime()), self.name)
785 elif (self.blockIndex % 10 ==0):
789 elif (self.blockIndex % 10 ==0):
786 log.log('Block No. {}/{} --> {}'.format(self.blockIndex+1, self.blocksPerFile,self.dataOut.datatime.ctime()), self.name)
790 log.log('Block No. {}/{} --> {}'.format(self.blockIndex+1, self.blocksPerFile,self.dataOut.datatime.ctime()), self.name)
787 else:
791 else:
788
792
789 log.log('Block No. {}/{}'.format(self.blockIndex+1, self.blocksPerFile), self.name)
793 log.log('Block No. {}/{}'.format(self.blockIndex+1, self.blocksPerFile), self.name)
790
794
791 for i, ds in enumerate(self.ds):
795 for i, ds in enumerate(self.ds):
792 attr, ch = self.data[i]
796 attr, ch = self.data[i]
793 if ch == -1:
797 if ch == -1:
794 ds[self.blockIndex] = getattr(self.dataOut, attr)
798 ds[self.blockIndex] = getattr(self.dataOut, attr)
795 else:
799 else:
796 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
800 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
797
801
798 self.blockIndex += 1
802 self.blockIndex += 1
799
803
800 self.fp.flush()
804 self.fp.flush()
801 self.dataOut.flagNoData = True
805 self.dataOut.flagNoData = True
802
806
803 def closeFile(self):
807 def closeFile(self):
804
808
805 if self.blockIndex != self.blocksPerFile:
809 if self.blockIndex != self.blocksPerFile:
806 for ds in self.ds:
810 for ds in self.ds:
807 ds.resize(self.blockIndex, axis=0)
811 ds.resize(self.blockIndex, axis=0)
808
812
809 if self.fp:
813 if self.fp:
810 self.fp.flush()
814 self.fp.flush()
811 self.fp.close()
815 self.fp.close()
812
816
813 def close(self):
817 def close(self):
814
818
815 self.closeFile()
819 self.closeFile()
This diff has been collapsed as it changes many lines, (840 lines changed) Show them Hide them
@@ -1,6328 +1,6674
1 import numpy
1 import numpy
2 import math
2 import math
3 from scipy import optimize, interpolate, signal, stats, ndimage
3 from scipy import optimize, interpolate, signal, stats, ndimage
4 from scipy.fftpack import fft
4 from scipy.fftpack import fft
5 import scipy
5 import scipy
6 import re
6 import re
7 import datetime
7 import datetime
8 import copy
8 import copy
9 import sys
9 import sys
10 import importlib
10 import importlib
11 import itertools
11 import itertools
12 from multiprocessing import Pool, TimeoutError
12 from multiprocessing import Pool, TimeoutError
13 from multiprocessing.pool import ThreadPool
13 from multiprocessing.pool import ThreadPool
14 import time
14 import time
15
15
16 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
17 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
18 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
19 from schainpy.model.data.jrodata import Spectra
19 from schainpy.model.data.jrodata import Spectra
20 from numpy import asarray as ar,exp
20 from numpy import asarray as ar,exp
21 from scipy.optimize import fmin, curve_fit
21 from scipy.optimize import fmin, curve_fit
22 from schainpy.utils import log
22 from schainpy.utils import log
23 import warnings
23 import warnings
24 from numpy import NaN
24 from numpy import NaN
25 from scipy.optimize.optimize import OptimizeWarning
25 from scipy.optimize.optimize import OptimizeWarning
26 warnings.filterwarnings('ignore')
26 warnings.filterwarnings('ignore')
27
27 import json
28 import os
28 import os
29 import csv
29 import csv
30 from scipy import signal
30 from scipy import signal
31 import matplotlib.pyplot as plt
31 import matplotlib.pyplot as plt
32
32
33 SPEED_OF_LIGHT = 299792458
33 SPEED_OF_LIGHT = 299792458
34
34
35 '''solving pickling issue'''
35 '''solving pickling issue'''
36
36
37 def _pickle_method(method):
37 def _pickle_method(method):
38 func_name = method.__func__.__name__
38 func_name = method.__func__.__name__
39 obj = method.__self__
39 obj = method.__self__
40 cls = method.__self__.__class__
40 cls = method.__self__.__class__
41 return _unpickle_method, (func_name, obj, cls)
41 return _unpickle_method, (func_name, obj, cls)
42
42
43 def _unpickle_method(func_name, obj, cls):
43 def _unpickle_method(func_name, obj, cls):
44 for cls in cls.mro():
44 for cls in cls.mro():
45 try:
45 try:
46 func = cls.__dict__[func_name]
46 func = cls.__dict__[func_name]
47 except KeyError:
47 except KeyError:
48 pass
48 pass
49 else:
49 else:
50 break
50 break
51 return func.__get__(obj, cls)
51 return func.__get__(obj, cls)
52
52
53
53
54 class ParametersProc(ProcessingUnit):
54 class ParametersProc(ProcessingUnit):
55
55
56 METHODS = {}
56 METHODS = {}
57 nSeconds = None
57 nSeconds = None
58
58
59 def __init__(self):
59 def __init__(self):
60 ProcessingUnit.__init__(self)
60 ProcessingUnit.__init__(self)
61
61
62 self.buffer = None
62 self.buffer = None
63 self.firstdatatime = None
63 self.firstdatatime = None
64 self.profIndex = 0
64 self.profIndex = 0
65 self.dataOut = Parameters()
65 self.dataOut = Parameters()
66 self.setupReq = False #Agregar a todas las unidades de proc
66 self.setupReq = False #Agregar a todas las unidades de proc
67
67
68 def __updateObjFromInput(self):
68 def __updateObjFromInput(self):
69
69
70 self.dataOut.inputUnit = self.dataIn.type
70 self.dataOut.inputUnit = self.dataIn.type
71
71
72 self.dataOut.timeZone = self.dataIn.timeZone
72 self.dataOut.timeZone = self.dataIn.timeZone
73 self.dataOut.dstFlag = self.dataIn.dstFlag
73 self.dataOut.dstFlag = self.dataIn.dstFlag
74 self.dataOut.errorCount = self.dataIn.errorCount
74 self.dataOut.errorCount = self.dataIn.errorCount
75 self.dataOut.useLocalTime = self.dataIn.useLocalTime
75 self.dataOut.useLocalTime = self.dataIn.useLocalTime
76
76
77 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
77 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
78 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
78 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
79 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
79 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
80 self.dataOut.channelList = self.dataIn.channelList
80 self.dataOut.channelList = self.dataIn.channelList
81 self.dataOut.heightList = self.dataIn.heightList
81 self.dataOut.heightList = self.dataIn.heightList
82 self.dataOut.ipp = self.dataIn.ipp
82 self.dataOut.ipp = self.dataIn.ipp
83 self.dataOut.ippSeconds = self.dataIn.ippSeconds
83 self.dataOut.ippSeconds = self.dataIn.ippSeconds
84 self.dataOut.deltaHeight = self.dataIn.deltaHeight
84 self.dataOut.deltaHeight = self.dataIn.deltaHeight
85 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
85 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
86
86
87 self.dataOut.nBaud = self.dataIn.nBaud
87 self.dataOut.nBaud = self.dataIn.nBaud
88 self.dataOut.nCode = self.dataIn.nCode
88 self.dataOut.nCode = self.dataIn.nCode
89 self.dataOut.code = self.dataIn.code
89 self.dataOut.code = self.dataIn.code
90 self.dataOut.nProfiles = self.dataIn.nProfiles
90 self.dataOut.nProfiles = self.dataIn.nProfiles
91 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
91 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
92 self.dataOut.utctime = self.dataIn.utctime
92 self.dataOut.utctime = self.dataIn.utctime
93 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
93 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
94 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
94 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
95 self.dataOut.nCohInt = self.dataIn.nCohInt
95 self.dataOut.nCohInt = self.dataIn.nCohInt
96 self.dataOut.nIncohInt = self.dataIn.nIncohInt
96 self.dataOut.nIncohInt = self.dataIn.nIncohInt
97 self.dataOut.ippSeconds = self.dataIn.ippSeconds
97 self.dataOut.ippSeconds = self.dataIn.ippSeconds
98 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
98 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
99 self.dataOut.timeInterval1 = self.dataIn.timeInterval
99 self.dataOut.timeInterval1 = self.dataIn.timeInterval
100 self.dataOut.heightList = self.dataIn.heightList
100 self.dataOut.heightList = self.dataIn.heightList
101 self.dataOut.frequency = self.dataIn.frequency
101 self.dataOut.frequency = self.dataIn.frequency
102 self.dataOut.codeList = self.dataIn.codeList
102 self.dataOut.codeList = self.dataIn.codeList
103 self.dataOut.azimuthList = self.dataIn.azimuthList
103 self.dataOut.azimuthList = self.dataIn.azimuthList
104 self.dataOut.elevationList = self.dataIn.elevationList
104 self.dataOut.elevationList = self.dataIn.elevationList
105 self.dataOut.runNextUnit = self.dataIn.runNextUnit
105 self.dataOut.runNextUnit = self.dataIn.runNextUnit
106
106
107 def run(self, runNextUnit=0):
107 def run(self, runNextUnit=0):
108
108
109 self.dataIn.runNextUnit = runNextUnit
109 self.dataIn.runNextUnit = runNextUnit
110 #---------------------- Voltage Data ---------------------------
110 #---------------------- Voltage Data ---------------------------
111 try:
111 try:
112 intype = self.dataIn.type.decode("utf-8")
112 intype = self.dataIn.type.decode("utf-8")
113 self.dataIn.type = intype
113 self.dataIn.type = intype
114 except:
114 except:
115 pass
115 pass
116
116
117 if self.dataIn.type == "Voltage":
117 if self.dataIn.type == "Voltage":
118
118
119 self.__updateObjFromInput()
119 self.__updateObjFromInput()
120 self.dataOut.data_pre = self.dataIn.data.copy()
120 self.dataOut.data_pre = self.dataIn.data.copy()
121 self.dataOut.flagNoData = False
121 self.dataOut.flagNoData = False
122 self.dataOut.utctimeInit = self.dataIn.utctime
122 self.dataOut.utctimeInit = self.dataIn.utctime
123 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
123 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
124 if hasattr(self.dataIn, 'dataPP_POW'):
124 if hasattr(self.dataIn, 'dataPP_POW'):
125 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
125 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
126
126
127 if hasattr(self.dataIn, 'dataPP_POWER'):
127 if hasattr(self.dataIn, 'dataPP_POWER'):
128 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
128 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
129
129
130 if hasattr(self.dataIn, 'dataPP_DOP'):
130 if hasattr(self.dataIn, 'dataPP_DOP'):
131 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
131 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
132
132
133 if hasattr(self.dataIn, 'dataPP_SNR'):
133 if hasattr(self.dataIn, 'dataPP_SNR'):
134 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
134 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
135
135
136 if hasattr(self.dataIn, 'dataPP_WIDTH'):
136 if hasattr(self.dataIn, 'dataPP_WIDTH'):
137 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
137 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
138 return
138 return
139
139
140 #---------------------- Spectra Data ---------------------------
140 #---------------------- Spectra Data ---------------------------
141
141
142 if self.dataIn.type == "Spectra":
142 if self.dataIn.type == "Spectra":
143
143
144 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
144 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
145 self.dataOut.data_spc = self.dataIn.data_spc
145 self.dataOut.data_spc = self.dataIn.data_spc
146 self.dataOut.data_cspc = self.dataIn.data_cspc
146 self.dataOut.data_cspc = self.dataIn.data_cspc
147 self.dataOut.data_outlier = self.dataIn.data_outlier
147 self.dataOut.data_outlier = self.dataIn.data_outlier
148 self.dataOut.nProfiles = self.dataIn.nProfiles
148 self.dataOut.nProfiles = self.dataIn.nProfiles
149 self.dataOut.nIncohInt = self.dataIn.nIncohInt
149 self.dataOut.nIncohInt = self.dataIn.nIncohInt
150 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
150 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
151 self.dataOut.ippFactor = self.dataIn.ippFactor
151 self.dataOut.ippFactor = self.dataIn.ippFactor
152 self.dataOut.flagProfilesByRange = self.dataIn.flagProfilesByRange
152 self.dataOut.flagProfilesByRange = self.dataIn.flagProfilesByRange
153 self.dataOut.nProfilesByRange = self.dataIn.nProfilesByRange
153 self.dataOut.nProfilesByRange = self.dataIn.nProfilesByRange
154 self.dataOut.deltaHeight = self.dataIn.deltaHeight
154 self.dataOut.deltaHeight = self.dataIn.deltaHeight
155 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
155 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
156 self.dataOut.spc_noise = self.dataIn.getNoise()
156 self.dataOut.spc_noise = self.dataIn.getNoise()
157 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
157 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
158 # self.dataOut.normFactor = self.dataIn.normFactor
158 # self.dataOut.normFactor = self.dataIn.normFactor
159 if hasattr(self.dataIn, 'channelList'):
159 if hasattr(self.dataIn, 'channelList'):
160 self.dataOut.channelList = self.dataIn.channelList
160 self.dataOut.channelList = self.dataIn.channelList
161 if hasattr(self.dataIn, 'pairsList'):
161 if hasattr(self.dataIn, 'pairsList'):
162 self.dataOut.pairsList = self.dataIn.pairsList
162 self.dataOut.pairsList = self.dataIn.pairsList
163 self.dataOut.groupList = self.dataIn.pairsList
163 self.dataOut.groupList = self.dataIn.pairsList
164
164
165 self.dataOut.flagNoData = False
165 self.dataOut.flagNoData = False
166
166
167 self.dataOut.noise_estimation = self.dataIn.noise_estimation
167 self.dataOut.noise_estimation = self.dataIn.noise_estimation
168 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
168 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
169 self.dataOut.ChanDist = self.dataIn.ChanDist
169 self.dataOut.ChanDist = self.dataIn.ChanDist
170 else: self.dataOut.ChanDist = None
170 else: self.dataOut.ChanDist = None
171
171
172 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
172 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
173 # self.dataOut.VelRange = self.dataIn.VelRange
173 # self.dataOut.VelRange = self.dataIn.VelRange
174 #else: self.dataOut.VelRange = None
174 #else: self.dataOut.VelRange = None
175
175
176 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
176 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
177 self.dataOut.RadarConst = self.dataIn.RadarConst
177 self.dataOut.RadarConst = self.dataIn.RadarConst
178
178
179 if hasattr(self.dataIn, 'NPW'): #NPW
179 if hasattr(self.dataIn, 'NPW'): #NPW
180 self.dataOut.NPW = self.dataIn.NPW
180 self.dataOut.NPW = self.dataIn.NPW
181
181
182 if hasattr(self.dataIn, 'COFA'): #COFA
182 if hasattr(self.dataIn, 'COFA'): #COFA
183 self.dataOut.COFA = self.dataIn.COFA
183 self.dataOut.COFA = self.dataIn.COFA
184
184
185
185
186
186
187 #---------------------- Correlation Data ---------------------------
187 #---------------------- Correlation Data ---------------------------
188
188
189 if self.dataIn.type == "Correlation":
189 if self.dataIn.type == "Correlation":
190 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
190 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
191
191
192 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
192 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
193 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
193 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
194 self.dataOut.groupList = (acf_pairs, ccf_pairs)
194 self.dataOut.groupList = (acf_pairs, ccf_pairs)
195
195
196 self.dataOut.abscissaList = self.dataIn.lagRange
196 self.dataOut.abscissaList = self.dataIn.lagRange
197 self.dataOut.noise = self.dataIn.noise
197 self.dataOut.noise = self.dataIn.noise
198 self.dataOut.data_snr = self.dataIn.SNR
198 self.dataOut.data_snr = self.dataIn.SNR
199 self.dataOut.flagNoData = False
199 self.dataOut.flagNoData = False
200 self.dataOut.nAvg = self.dataIn.nAvg
200 self.dataOut.nAvg = self.dataIn.nAvg
201
201
202 #---------------------- Parameters Data ---------------------------
202 #---------------------- Parameters Data ---------------------------
203
203
204 if self.dataIn.type == "Parameters":
204 if self.dataIn.type == "Parameters":
205 self.dataOut.copy(self.dataIn)
205 self.dataOut.copy(self.dataIn)
206 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
206 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
207 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
207 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
208 self.dataOut.flagNoData = False
208 self.dataOut.flagNoData = False
209 if isinstance(self.dataIn.nIncohInt,numpy.ndarray):
209 if isinstance(self.dataIn.nIncohInt,numpy.ndarray):
210 nch, nheis = self.dataIn.nIncohInt.shape
210 nch, nheis = self.dataIn.nIncohInt.shape
211 if nch != self.dataIn.nChannels:
211 if nch != self.dataIn.nChannels:
212 aux = numpy.repeat(self.dataIn.nIncohInt, self.dataIn.nChannels, axis=0)
212 aux = numpy.repeat(self.dataIn.nIncohInt, self.dataIn.nChannels, axis=0)
213 self.dataOut.nIncohInt = aux
213 self.dataOut.nIncohInt = aux
214 return True
214 return True
215
215
216 self.__updateObjFromInput()
216 self.__updateObjFromInput()
217 self.dataOut.utctimeInit = self.dataIn.utctime
217 self.dataOut.utctimeInit = self.dataIn.utctime
218 self.dataOut.paramInterval = self.dataIn.timeInterval
218 self.dataOut.paramInterval = self.dataIn.timeInterval
219
219
220 return
220 return
221
221
222
222
223 def target(tups):
223 def target(tups):
224
224
225 obj, args = tups
225 obj, args = tups
226
226
227 return obj.FitGau(args)
227 return obj.FitGau(args)
228
228
229 class RemoveWideGC(Operation):
229 class RemoveWideGC(Operation):
230 ''' This class remove the wide clutter and replace it with a simple interpolation points
230 ''' This class remove the wide clutter and replace it with a simple interpolation points
231 This mainly applies to CLAIRE radar
231 This mainly applies to CLAIRE radar
232
232
233 ClutterWidth : Width to look for the clutter peak
233 ClutterWidth : Width to look for the clutter peak
234
234
235 Input:
235 Input:
236
236
237 self.dataOut.data_pre : SPC and CSPC
237 self.dataOut.data_pre : SPC and CSPC
238 self.dataOut.spc_range : To select wind and rainfall velocities
238 self.dataOut.spc_range : To select wind and rainfall velocities
239
239
240 Affected:
240 Affected:
241
241
242 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
242 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
243
243
244 Written by D. ScipiΓ³n 25.02.2021
244 Written by D. ScipiΓ³n 25.02.2021
245 '''
245 '''
246 def __init__(self):
246 def __init__(self):
247 Operation.__init__(self)
247 Operation.__init__(self)
248 self.i = 0
248 self.i = 0
249 self.ich = 0
249 self.ich = 0
250 self.ir = 0
250 self.ir = 0
251
251
252 def run(self, dataOut, ClutterWidth=2.5):
252 def run(self, dataOut, ClutterWidth=2.5):
253
253
254 self.spc = dataOut.data_pre[0].copy()
254 self.spc = dataOut.data_pre[0].copy()
255 self.spc_out = dataOut.data_pre[0].copy()
255 self.spc_out = dataOut.data_pre[0].copy()
256 self.Num_Chn = self.spc.shape[0]
256 self.Num_Chn = self.spc.shape[0]
257 self.Num_Hei = self.spc.shape[2]
257 self.Num_Hei = self.spc.shape[2]
258 VelRange = dataOut.spc_range[2][:-1]
258 VelRange = dataOut.spc_range[2][:-1]
259 dv = VelRange[1]-VelRange[0]
259 dv = VelRange[1]-VelRange[0]
260
260
261 # Find the velocities that corresponds to zero
261 # Find the velocities that corresponds to zero
262 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
262 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
263
263
264 # Removing novalid data from the spectra
264 # Removing novalid data from the spectra
265 for ich in range(self.Num_Chn) :
265 for ich in range(self.Num_Chn) :
266 for ir in range(self.Num_Hei) :
266 for ir in range(self.Num_Hei) :
267 # Estimate the noise at each range
267 # Estimate the noise at each range
268 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
268 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
269
269
270 # Removing the noise floor at each range
270 # Removing the noise floor at each range
271 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
271 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
272 self.spc[ich,novalid,ir] = HSn
272 self.spc[ich,novalid,ir] = HSn
273
273
274 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
274 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
275 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
275 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
276 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
276 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
277 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
277 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
278 continue
278 continue
279 junk3 = numpy.squeeze(numpy.diff(j1index))
279 junk3 = numpy.squeeze(numpy.diff(j1index))
280 junk4 = numpy.squeeze(numpy.diff(j2index))
280 junk4 = numpy.squeeze(numpy.diff(j2index))
281
281
282 valleyindex = j2index[numpy.where(junk4>1)]
282 valleyindex = j2index[numpy.where(junk4>1)]
283 peakindex = j1index[numpy.where(junk3>1)]
283 peakindex = j1index[numpy.where(junk3>1)]
284
284
285 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
285 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
286 if numpy.size(isvalid) == 0 :
286 if numpy.size(isvalid) == 0 :
287 continue
287 continue
288 if numpy.size(isvalid) >1 :
288 if numpy.size(isvalid) >1 :
289 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
289 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
290 isvalid = isvalid[vindex]
290 isvalid = isvalid[vindex]
291
291
292 # clutter peak
292 # clutter peak
293 gcpeak = peakindex[isvalid]
293 gcpeak = peakindex[isvalid]
294 vl = numpy.where(valleyindex < gcpeak)
294 vl = numpy.where(valleyindex < gcpeak)
295 if numpy.size(vl) == 0:
295 if numpy.size(vl) == 0:
296 continue
296 continue
297 gcvl = valleyindex[vl[0][-1]]
297 gcvl = valleyindex[vl[0][-1]]
298 vr = numpy.where(valleyindex > gcpeak)
298 vr = numpy.where(valleyindex > gcpeak)
299 if numpy.size(vr) == 0:
299 if numpy.size(vr) == 0:
300 continue
300 continue
301 gcvr = valleyindex[vr[0][0]]
301 gcvr = valleyindex[vr[0][0]]
302
302
303 # Removing the clutter
303 # Removing the clutter
304 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
304 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
305 gcindex = gc_values[gcvl+1:gcvr-1]
305 gcindex = gc_values[gcvl+1:gcvr-1]
306 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
306 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
307
307
308 dataOut.data_pre[0] = self.spc_out
308 dataOut.data_pre[0] = self.spc_out
309
309
310 return dataOut
310 return dataOut
311
311
312 class SpectralFilters(Operation):
312 class SpectralFilters(Operation):
313 ''' This class allows to replace the novalid values with noise for each channel
313 ''' This class allows to replace the novalid values with noise for each channel
314 This applies to CLAIRE RADAR
314 This applies to CLAIRE RADAR
315
315
316 PositiveLimit : RightLimit of novalid data
316 PositiveLimit : RightLimit of novalid data
317 NegativeLimit : LeftLimit of novalid data
317 NegativeLimit : LeftLimit of novalid data
318
318
319 Input:
319 Input:
320
320
321 self.dataOut.data_pre : SPC and CSPC
321 self.dataOut.data_pre : SPC and CSPC
322 self.dataOut.spc_range : To select wind and rainfall velocities
322 self.dataOut.spc_range : To select wind and rainfall velocities
323
323
324 Affected:
324 Affected:
325
325
326 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
326 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
327
327
328 Written by D. ScipiΓ³n 29.01.2021
328 Written by D. ScipiΓ³n 29.01.2021
329 '''
329 '''
330 def __init__(self):
330 def __init__(self):
331 Operation.__init__(self)
331 Operation.__init__(self)
332 self.i = 0
332 self.i = 0
333
333
334 def run(self, dataOut, ):
334 def run(self, dataOut, ):
335
335
336 self.spc = dataOut.data_pre[0].copy()
336 self.spc = dataOut.data_pre[0].copy()
337 self.Num_Chn = self.spc.shape[0]
337 self.Num_Chn = self.spc.shape[0]
338 VelRange = dataOut.spc_range[2]
338 VelRange = dataOut.spc_range[2]
339
339
340 # novalid corresponds to data within the Negative and PositiveLimit
340 # novalid corresponds to data within the Negative and PositiveLimit
341
341
342
342
343 # Removing novalid data from the spectra
343 # Removing novalid data from the spectra
344 for i in range(self.Num_Chn):
344 for i in range(self.Num_Chn):
345 self.spc[i,novalid,:] = dataOut.noise[i]
345 self.spc[i,novalid,:] = dataOut.noise[i]
346 dataOut.data_pre[0] = self.spc
346 dataOut.data_pre[0] = self.spc
347 return dataOut
347 return dataOut
348
348
349
349
350 class GaussianFit(Operation):
350 class GaussianFit(Operation):
351
351
352 '''
352 '''
353 Function that fit of one and two generalized gaussians (gg) based
353 Function that fit of one and two generalized gaussians (gg) based
354 on the PSD shape across an "power band" identified from a cumsum of
354 on the PSD shape across an "power band" identified from a cumsum of
355 the measured spectrum - noise.
355 the measured spectrum - noise.
356
356
357 Input:
357 Input:
358 self.dataOut.data_pre : SelfSpectra
358 self.dataOut.data_pre : SelfSpectra
359
359
360 Output:
360 Output:
361 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
361 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
362
362
363 '''
363 '''
364 def __init__(self):
364 def __init__(self):
365 Operation.__init__(self)
365 Operation.__init__(self)
366 self.i=0
366 self.i=0
367
367
368 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
368 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
369 """This routine will find a couple of generalized Gaussians to a power spectrum
369 """This routine will find a couple of generalized Gaussians to a power spectrum
370 methods: generalized, squared
370 methods: generalized, squared
371 input: spc
371 input: spc
372 output:
372 output:
373 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
373 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
374 """
374 """
375 print ('Entering ',method,' double Gaussian fit')
375 print ('Entering ',method,' double Gaussian fit')
376 self.spc = dataOut.data_pre[0].copy()
376 self.spc = dataOut.data_pre[0].copy()
377 self.Num_Hei = self.spc.shape[2]
377 self.Num_Hei = self.spc.shape[2]
378 self.Num_Bin = self.spc.shape[1]
378 self.Num_Bin = self.spc.shape[1]
379 self.Num_Chn = self.spc.shape[0]
379 self.Num_Chn = self.spc.shape[0]
380
380
381 start_time = time.time()
381 start_time = time.time()
382
382
383 pool = Pool(processes=self.Num_Chn)
383 pool = Pool(processes=self.Num_Chn)
384 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
384 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
385 objs = [self for __ in range(self.Num_Chn)]
385 objs = [self for __ in range(self.Num_Chn)]
386 attrs = list(zip(objs, args))
386 attrs = list(zip(objs, args))
387 DGauFitParam = pool.map(target, attrs)
387 DGauFitParam = pool.map(target, attrs)
388 # Parameters:
388 # Parameters:
389 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
389 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
390 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
390 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
391
391
392 # Double Gaussian Curves
392 # Double Gaussian Curves
393 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
393 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
394 gau0[:] = numpy.NaN
394 gau0[:] = numpy.NaN
395 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
395 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
396 gau1[:] = numpy.NaN
396 gau1[:] = numpy.NaN
397 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
397 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
398 for iCh in range(self.Num_Chn):
398 for iCh in range(self.Num_Chn):
399 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
399 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
400 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
400 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
401 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
401 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
402 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
402 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
403 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
403 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
404 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
404 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
405 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
405 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
406 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
406 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
407 if method == 'generalized':
407 if method == 'generalized':
408 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
408 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
409 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
409 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
410 elif method == 'squared':
410 elif method == 'squared':
411 p0 = 2.
411 p0 = 2.
412 p1 = 2.
412 p1 = 2.
413 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
413 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
414 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
414 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
415 dataOut.GaussFit0 = gau0
415 dataOut.GaussFit0 = gau0
416 dataOut.GaussFit1 = gau1
416 dataOut.GaussFit1 = gau1
417
417
418 print('Leaving ',method ,' double Gaussian fit')
418 print('Leaving ',method ,' double Gaussian fit')
419 return dataOut
419 return dataOut
420
420
421 def FitGau(self, X):
421 def FitGau(self, X):
422 # print('Entering FitGau')
422 # print('Entering FitGau')
423 # Assigning the variables
423 # Assigning the variables
424 Vrange, ch, wnoise, num_intg, SNRlimit = X
424 Vrange, ch, wnoise, num_intg, SNRlimit = X
425 # Noise Limits
425 # Noise Limits
426 noisebl = wnoise * 0.9
426 noisebl = wnoise * 0.9
427 noisebh = wnoise * 1.1
427 noisebh = wnoise * 1.1
428 # Radar Velocity
428 # Radar Velocity
429 Va = max(Vrange)
429 Va = max(Vrange)
430 deltav = Vrange[1] - Vrange[0]
430 deltav = Vrange[1] - Vrange[0]
431 x = numpy.arange(self.Num_Bin)
431 x = numpy.arange(self.Num_Bin)
432
432
433 # print ('stop 0')
433 # print ('stop 0')
434
434
435 # 5 parameters, 2 Gaussians
435 # 5 parameters, 2 Gaussians
436 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
436 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
437 DGauFitParam[:] = numpy.NaN
437 DGauFitParam[:] = numpy.NaN
438
438
439 # SPCparam = []
439 # SPCparam = []
440 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
440 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
441 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
441 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
442 # SPC_ch1[:] = 0 #numpy.NaN
442 # SPC_ch1[:] = 0 #numpy.NaN
443 # SPC_ch2[:] = 0 #numpy.NaN
443 # SPC_ch2[:] = 0 #numpy.NaN
444 # print ('stop 1')
444 # print ('stop 1')
445 for ht in range(self.Num_Hei):
445 for ht in range(self.Num_Hei):
446 # print (ht)
446 # print (ht)
447 # print ('stop 2')
447 # print ('stop 2')
448 # Spectra at each range
448 # Spectra at each range
449 spc = numpy.asarray(self.spc)[ch,:,ht]
449 spc = numpy.asarray(self.spc)[ch,:,ht]
450 snr = ( spc.mean() - wnoise ) / wnoise
450 snr = ( spc.mean() - wnoise ) / wnoise
451 snrdB = 10.*numpy.log10(snr)
451 snrdB = 10.*numpy.log10(snr)
452
452
453 #print ('stop 3')
453 #print ('stop 3')
454 if snrdB < SNRlimit :
454 if snrdB < SNRlimit :
455 # snr = numpy.NaN
455 # snr = numpy.NaN
456 # SPC_ch1[:,ht] = 0#numpy.NaN
456 # SPC_ch1[:,ht] = 0#numpy.NaN
457 # SPC_ch1[:,ht] = 0#numpy.NaN
457 # SPC_ch1[:,ht] = 0#numpy.NaN
458 # SPCparam = (SPC_ch1,SPC_ch2)
458 # SPCparam = (SPC_ch1,SPC_ch2)
459 # print ('SNR less than SNRth')
459 # print ('SNR less than SNRth')
460 continue
460 continue
461 # wnoise = hildebrand_sekhon(spc,num_intg)
461 # wnoise = hildebrand_sekhon(spc,num_intg)
462 # print ('stop 2.01')
462 # print ('stop 2.01')
463 #############################################
463 #############################################
464 # normalizing spc and noise
464 # normalizing spc and noise
465 # This part differs from gg1
465 # This part differs from gg1
466 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
466 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
467 #spc = spc / spc_norm_max
467 #spc = spc / spc_norm_max
468 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
468 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
469 #############################################
469 #############################################
470
470
471 # print ('stop 2.1')
471 # print ('stop 2.1')
472 fatspectra=1.0
472 fatspectra=1.0
473 # noise per channel.... we might want to use the noise at each range
473 # noise per channel.... we might want to use the noise at each range
474
474
475 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
475 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
476 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
476 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
477 #if wnoise>1.1*pnoise: # to be tested later
477 #if wnoise>1.1*pnoise: # to be tested later
478 # wnoise=pnoise
478 # wnoise=pnoise
479 # noisebl = wnoise*0.9
479 # noisebl = wnoise*0.9
480 # noisebh = wnoise*1.1
480 # noisebh = wnoise*1.1
481 spc = spc - wnoise # signal
481 spc = spc - wnoise # signal
482
482
483 # print ('stop 2.2')
483 # print ('stop 2.2')
484 minx = numpy.argmin(spc)
484 minx = numpy.argmin(spc)
485 #spcs=spc.copy()
485 #spcs=spc.copy()
486 spcs = numpy.roll(spc,-minx)
486 spcs = numpy.roll(spc,-minx)
487 cum = numpy.cumsum(spcs)
487 cum = numpy.cumsum(spcs)
488 # tot_noise = wnoise * self.Num_Bin #64;
488 # tot_noise = wnoise * self.Num_Bin #64;
489
489
490 # print ('stop 2.3')
490 # print ('stop 2.3')
491 # snr = sum(spcs) / tot_noise
491 # snr = sum(spcs) / tot_noise
492 # snrdB = 10.*numpy.log10(snr)
492 # snrdB = 10.*numpy.log10(snr)
493 #print ('stop 3')
493 #print ('stop 3')
494 # if snrdB < SNRlimit :
494 # if snrdB < SNRlimit :
495 # snr = numpy.NaN
495 # snr = numpy.NaN
496 # SPC_ch1[:,ht] = 0#numpy.NaN
496 # SPC_ch1[:,ht] = 0#numpy.NaN
497 # SPC_ch1[:,ht] = 0#numpy.NaN
497 # SPC_ch1[:,ht] = 0#numpy.NaN
498 # SPCparam = (SPC_ch1,SPC_ch2)
498 # SPCparam = (SPC_ch1,SPC_ch2)
499 # print ('SNR less than SNRth')
499 # print ('SNR less than SNRth')
500 # continue
500 # continue
501
501
502
502
503 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
503 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
504 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
504 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
505 # print ('stop 4')
505 # print ('stop 4')
506 cummax = max(cum)
506 cummax = max(cum)
507 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
507 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
508 cumlo = cummax * epsi
508 cumlo = cummax * epsi
509 cumhi = cummax * (1-epsi)
509 cumhi = cummax * (1-epsi)
510 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
510 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
511
511
512 # print ('stop 5')
512 # print ('stop 5')
513 if len(powerindex) < 1:# case for powerindex 0
513 if len(powerindex) < 1:# case for powerindex 0
514 # print ('powerindex < 1')
514 # print ('powerindex < 1')
515 continue
515 continue
516 powerlo = powerindex[0]
516 powerlo = powerindex[0]
517 powerhi = powerindex[-1]
517 powerhi = powerindex[-1]
518 powerwidth = powerhi-powerlo
518 powerwidth = powerhi-powerlo
519 if powerwidth <= 1:
519 if powerwidth <= 1:
520 # print('powerwidth <= 1')
520 # print('powerwidth <= 1')
521 continue
521 continue
522
522
523 # print ('stop 6')
523 # print ('stop 6')
524 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
524 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
525 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
525 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
526 midpeak = (firstpeak + secondpeak)/2.
526 midpeak = (firstpeak + secondpeak)/2.
527 firstamp = spcs[int(firstpeak)]
527 firstamp = spcs[int(firstpeak)]
528 secondamp = spcs[int(secondpeak)]
528 secondamp = spcs[int(secondpeak)]
529 midamp = spcs[int(midpeak)]
529 midamp = spcs[int(midpeak)]
530
530
531 y_data = spc + wnoise
531 y_data = spc + wnoise
532
532
533 ''' single Gaussian '''
533 ''' single Gaussian '''
534 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
534 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
535 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
535 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
536 power0 = 2.
536 power0 = 2.
537 amplitude0 = midamp
537 amplitude0 = midamp
538 state0 = [shift0,width0,amplitude0,power0,wnoise]
538 state0 = [shift0,width0,amplitude0,power0,wnoise]
539 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
539 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
540 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
540 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
541 # print ('stop 7.1')
541 # print ('stop 7.1')
542 # print (bnds)
542 # print (bnds)
543
543
544 chiSq1=lsq1[1]
544 chiSq1=lsq1[1]
545
545
546 # print ('stop 8')
546 # print ('stop 8')
547 if fatspectra<1.0 and powerwidth<4:
547 if fatspectra<1.0 and powerwidth<4:
548 choice=0
548 choice=0
549 Amplitude0=lsq1[0][2]
549 Amplitude0=lsq1[0][2]
550 shift0=lsq1[0][0]
550 shift0=lsq1[0][0]
551 width0=lsq1[0][1]
551 width0=lsq1[0][1]
552 p0=lsq1[0][3]
552 p0=lsq1[0][3]
553 Amplitude1=0.
553 Amplitude1=0.
554 shift1=0.
554 shift1=0.
555 width1=0.
555 width1=0.
556 p1=0.
556 p1=0.
557 noise=lsq1[0][4]
557 noise=lsq1[0][4]
558 #return (numpy.array([shift0,width0,Amplitude0,p0]),
558 #return (numpy.array([shift0,width0,Amplitude0,p0]),
559 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
559 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
560 # print ('stop 9')
560 # print ('stop 9')
561 ''' two Gaussians '''
561 ''' two Gaussians '''
562 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
562 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
563 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
563 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
564 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
564 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
565 width0 = powerwidth/6.
565 width0 = powerwidth/6.
566 width1 = width0
566 width1 = width0
567 power0 = 2.
567 power0 = 2.
568 power1 = power0
568 power1 = power0
569 amplitude0 = firstamp
569 amplitude0 = firstamp
570 amplitude1 = secondamp
570 amplitude1 = secondamp
571 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
571 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
572 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
572 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
573 bnds=((0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
573 bnds=((0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(0,self.Num_Bin-1),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
574 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
574 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
575
575
576 # print ('stop 10')
576 # print ('stop 10')
577 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
577 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
578
578
579 # print ('stop 11')
579 # print ('stop 11')
580 chiSq2 = lsq2[1]
580 chiSq2 = lsq2[1]
581
581
582 # print ('stop 12')
582 # print ('stop 12')
583
583
584 oneG = (chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
584 oneG = (chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
585
585
586 # print ('stop 13')
586 # print ('stop 13')
587 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
587 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
588 if oneG:
588 if oneG:
589 choice = 0
589 choice = 0
590 else:
590 else:
591 w1 = lsq2[0][1]; w2 = lsq2[0][5]
591 w1 = lsq2[0][1]; w2 = lsq2[0][5]
592 a1 = lsq2[0][2]; a2 = lsq2[0][6]
592 a1 = lsq2[0][2]; a2 = lsq2[0][6]
593 p1 = lsq2[0][3]; p2 = lsq2[0][7]
593 p1 = lsq2[0][3]; p2 = lsq2[0][7]
594 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
594 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
595 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
595 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
596 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
596 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
597
597
598 if gp1>gp2:
598 if gp1>gp2:
599 if a1>0.7*a2:
599 if a1>0.7*a2:
600 choice = 1
600 choice = 1
601 else:
601 else:
602 choice = 2
602 choice = 2
603 elif gp2>gp1:
603 elif gp2>gp1:
604 if a2>0.7*a1:
604 if a2>0.7*a1:
605 choice = 2
605 choice = 2
606 else:
606 else:
607 choice = 1
607 choice = 1
608 else:
608 else:
609 choice = numpy.argmax([a1,a2])+1
609 choice = numpy.argmax([a1,a2])+1
610 #else:
610 #else:
611 #choice=argmin([std2a,std2b])+1
611 #choice=argmin([std2a,std2b])+1
612
612
613 else: # with low SNR go to the most energetic peak
613 else: # with low SNR go to the most energetic peak
614 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
614 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
615
615
616 # print ('stop 14')
616 # print ('stop 14')
617 shift0 = lsq2[0][0]
617 shift0 = lsq2[0][0]
618 vel0 = Vrange[0] + shift0 * deltav
618 vel0 = Vrange[0] + shift0 * deltav
619 shift1 = lsq2[0][4]
619 shift1 = lsq2[0][4]
620 # vel1=Vrange[0] + shift1 * deltav
620 # vel1=Vrange[0] + shift1 * deltav
621
621
622 # max_vel = 1.0
622 # max_vel = 1.0
623 # Va = max(Vrange)
623 # Va = max(Vrange)
624 # deltav = Vrange[1]-Vrange[0]
624 # deltav = Vrange[1]-Vrange[0]
625 # print ('stop 15')
625 # print ('stop 15')
626 #first peak will be 0, second peak will be 1
626 #first peak will be 0, second peak will be 1
627 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
627 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
628 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
628 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
629 shift0 = lsq2[0][0]
629 shift0 = lsq2[0][0]
630 width0 = lsq2[0][1]
630 width0 = lsq2[0][1]
631 Amplitude0 = lsq2[0][2]
631 Amplitude0 = lsq2[0][2]
632 p0 = lsq2[0][3]
632 p0 = lsq2[0][3]
633
633
634 shift1 = lsq2[0][4]
634 shift1 = lsq2[0][4]
635 width1 = lsq2[0][5]
635 width1 = lsq2[0][5]
636 Amplitude1 = lsq2[0][6]
636 Amplitude1 = lsq2[0][6]
637 p1 = lsq2[0][7]
637 p1 = lsq2[0][7]
638 noise = lsq2[0][8]
638 noise = lsq2[0][8]
639 else:
639 else:
640 shift1 = lsq2[0][0]
640 shift1 = lsq2[0][0]
641 width1 = lsq2[0][1]
641 width1 = lsq2[0][1]
642 Amplitude1 = lsq2[0][2]
642 Amplitude1 = lsq2[0][2]
643 p1 = lsq2[0][3]
643 p1 = lsq2[0][3]
644
644
645 shift0 = lsq2[0][4]
645 shift0 = lsq2[0][4]
646 width0 = lsq2[0][5]
646 width0 = lsq2[0][5]
647 Amplitude0 = lsq2[0][6]
647 Amplitude0 = lsq2[0][6]
648 p0 = lsq2[0][7]
648 p0 = lsq2[0][7]
649 noise = lsq2[0][8]
649 noise = lsq2[0][8]
650
650
651 if Amplitude0<0.05: # in case the peak is noise
651 if Amplitude0<0.05: # in case the peak is noise
652 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
652 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
653 if Amplitude1<0.05:
653 if Amplitude1<0.05:
654 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
654 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
655
655
656 # print ('stop 16 ')
656 # print ('stop 16 ')
657 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
657 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
658 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
658 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
659 # SPCparam = (SPC_ch1,SPC_ch2)
659 # SPCparam = (SPC_ch1,SPC_ch2)
660
660
661 DGauFitParam[0,ht,0] = noise
661 DGauFitParam[0,ht,0] = noise
662 DGauFitParam[0,ht,1] = noise
662 DGauFitParam[0,ht,1] = noise
663 DGauFitParam[1,ht,0] = Amplitude0
663 DGauFitParam[1,ht,0] = Amplitude0
664 DGauFitParam[1,ht,1] = Amplitude1
664 DGauFitParam[1,ht,1] = Amplitude1
665 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
665 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
666 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
666 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
667 DGauFitParam[3,ht,0] = width0 * deltav
667 DGauFitParam[3,ht,0] = width0 * deltav
668 DGauFitParam[3,ht,1] = width1 * deltav
668 DGauFitParam[3,ht,1] = width1 * deltav
669 DGauFitParam[4,ht,0] = p0
669 DGauFitParam[4,ht,0] = p0
670 DGauFitParam[4,ht,1] = p1
670 DGauFitParam[4,ht,1] = p1
671
671
672 return DGauFitParam
672 return DGauFitParam
673
673
674 def y_model1(self,x,state):
674 def y_model1(self,x,state):
675 shift0, width0, amplitude0, power0, noise = state
675 shift0, width0, amplitude0, power0, noise = state
676 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
676 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
677 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
677 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
678 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
678 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
679 return model0 + model0u + model0d + noise
679 return model0 + model0u + model0d + noise
680
680
681 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
681 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
682 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
682 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
683 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
683 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
684 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
684 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
685 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
685 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
686
686
687 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
687 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
688 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
688 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
689 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
689 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
690 return model0 + model0u + model0d + model1 + model1u + model1d + noise
690 return model0 + model0u + model0d + model1 + model1u + model1d + noise
691
691
692 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
692 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
693
693
694 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
694 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
695
695
696 def misfit2(self,state,y_data,x,num_intg):
696 def misfit2(self,state,y_data,x,num_intg):
697 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
697 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
698
698
699 class Oblique_Gauss_Fit(Operation):
699 class Oblique_Gauss_Fit(Operation):
700 '''
700 '''
701 Written by R. Flores
701 Written by R. Flores
702 '''
702 '''
703 def __init__(self):
703 def __init__(self):
704 Operation.__init__(self)
704 Operation.__init__(self)
705
705
706 def Gauss_fit(self,spc,x,nGauss):
706 def Gauss_fit(self,spc,x,nGauss):
707
707
708
708
709 def gaussian(x, a, b, c, d):
709 def gaussian(x, a, b, c, d):
710 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
710 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
711 return val
711 return val
712
712
713 if nGauss == 'first':
713 if nGauss == 'first':
714 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
714 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
715 spc_2_aux = numpy.flip(spc_1_aux)
715 spc_2_aux = numpy.flip(spc_1_aux)
716 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
716 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
717
717
718 len_dif = len(x)-len(spc_3_aux)
718 len_dif = len(x)-len(spc_3_aux)
719
719
720 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
720 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
721
721
722 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
722 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
723
723
724 y = spc_new
724 y = spc_new
725
725
726 elif nGauss == 'second':
726 elif nGauss == 'second':
727 y = spc
727 y = spc
728
728
729
729
730 # estimate starting values from the data
730 # estimate starting values from the data
731 a = y.max()
731 a = y.max()
732 b = x[numpy.argmax(y)]
732 b = x[numpy.argmax(y)]
733 if nGauss == 'first':
733 if nGauss == 'first':
734 c = 1.#b#b#numpy.std(spc)
734 c = 1.#b#b#numpy.std(spc)
735 elif nGauss == 'second':
735 elif nGauss == 'second':
736 c = b
736 c = b
737 else:
737 else:
738 print("ERROR")
738 print("ERROR")
739
739
740 d = numpy.mean(y[-100:])
740 d = numpy.mean(y[-100:])
741
741
742 # define a least squares function to optimize
742 # define a least squares function to optimize
743 def minfunc(params):
743 def minfunc(params):
744 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
744 return sum((y-gaussian(x,params[0],params[1],params[2],params[3]))**2)
745
745
746 # fit
746 # fit
747 popt = fmin(minfunc,[a,b,c,d],disp=False)
747 popt = fmin(minfunc,[a,b,c,d],disp=False)
748 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
748 #popt,fopt,niter,funcalls = fmin(minfunc,[a,b,c,d])
749
749
750
750
751 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
751 return gaussian(x, popt[0], popt[1], popt[2], popt[3]), popt[0], popt[1], popt[2], popt[3]
752
752
753
753
754 def Gauss_fit_2(self,spc,x,nGauss):
754 def Gauss_fit_2(self,spc,x,nGauss):
755
755
756
756
757 def gaussian(x, a, b, c, d):
757 def gaussian(x, a, b, c, d):
758 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
758 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
759 return val
759 return val
760
760
761 if nGauss == 'first':
761 if nGauss == 'first':
762 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
762 spc_1_aux = numpy.copy(spc[:numpy.argmax(spc)+1])
763 spc_2_aux = numpy.flip(spc_1_aux)
763 spc_2_aux = numpy.flip(spc_1_aux)
764 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
764 spc_3_aux = numpy.concatenate((spc_1_aux,spc_2_aux[1:]))
765
765
766 len_dif = len(x)-len(spc_3_aux)
766 len_dif = len(x)-len(spc_3_aux)
767
767
768 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
768 spc_zeros = numpy.ones(len_dif)*spc_1_aux[0]
769
769
770 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
770 spc_new = numpy.concatenate((spc_3_aux,spc_zeros))
771
771
772 y = spc_new
772 y = spc_new
773
773
774 elif nGauss == 'second':
774 elif nGauss == 'second':
775 y = spc
775 y = spc
776
776
777
777
778 # estimate starting values from the data
778 # estimate starting values from the data
779 a = y.max()
779 a = y.max()
780 b = x[numpy.argmax(y)]
780 b = x[numpy.argmax(y)]
781 if nGauss == 'first':
781 if nGauss == 'first':
782 c = 1.#b#b#numpy.std(spc)
782 c = 1.#b#b#numpy.std(spc)
783 elif nGauss == 'second':
783 elif nGauss == 'second':
784 c = b
784 c = b
785 else:
785 else:
786 print("ERROR")
786 print("ERROR")
787
787
788 d = numpy.mean(y[-100:])
788 d = numpy.mean(y[-100:])
789 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
789 popt,pcov = curve_fit(gaussian,x,y,p0=[a,b,c,d])
790 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
790 return gaussian(x, popt[0], popt[1], popt[2], popt[3]),popt[0], popt[1], popt[2], popt[3]
791
791
792 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
792 def Double_Gauss_fit(self,spc,x,A1,B1,C1,A2,B2,C2,D):
793
793
794 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
794 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
795 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
795 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
796 return val
796 return val
797
797
798
798
799 y = spc
799 y = spc
800
800
801 # estimate starting values from the data
801 # estimate starting values from the data
802 a1 = A1
802 a1 = A1
803 b1 = B1
803 b1 = B1
804 c1 = C1#numpy.std(spc)
804 c1 = C1#numpy.std(spc)
805
805
806 a2 = A2#y.max()
806 a2 = A2#y.max()
807 b2 = B2#x[numpy.argmax(y)]
807 b2 = B2#x[numpy.argmax(y)]
808 c2 = C2#numpy.std(spc)
808 c2 = C2#numpy.std(spc)
809 d = D
809 d = D
810
810
811 # define a least squares function to optimize
811 # define a least squares function to optimize
812 def minfunc(params):
812 def minfunc(params):
813 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
813 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2)
814
814
815 # fit
815 # fit
816 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
816 popt = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],disp=False)
817
817
818 return double_gaussian(x, popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
818 return double_gaussian(x, popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
819
819
820 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
820 def Double_Gauss_fit_2(self,spc,x,A1,B1,C1,A2,B2,C2,D):
821
821
822 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
822 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
823 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
823 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
824 return val
824 return val
825
825
826
826
827 y = spc
827 y = spc
828
828
829 # estimate starting values from the data
829 # estimate starting values from the data
830 a1 = A1
830 a1 = A1
831 b1 = B1
831 b1 = B1
832 c1 = C1#numpy.std(spc)
832 c1 = C1#numpy.std(spc)
833
833
834 a2 = A2#y.max()
834 a2 = A2#y.max()
835 b2 = B2#x[numpy.argmax(y)]
835 b2 = B2#x[numpy.argmax(y)]
836 c2 = C2#numpy.std(spc)
836 c2 = C2#numpy.std(spc)
837 d = D
837 d = D
838
838
839 # fit
839 # fit
840 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
840 popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
841 error = numpy.sqrt(numpy.diag(pcov))
841 error = numpy.sqrt(numpy.diag(pcov))
842
842
843 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6], error[0], error[1], error[2], error[3], error[4], error[5], error[6]
843 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6], error[0], error[1], error[2], error[3], error[4], error[5], error[6]
844
844
845 def windowing_double(self,spc,x,A1,B1,C1,A2,B2,C2,D):
845 def windowing_double(self,spc,x,A1,B1,C1,A2,B2,C2,D):
846 from scipy.optimize import curve_fit,fmin
846 from scipy.optimize import curve_fit,fmin
847
847
848 def R_gaussian(x, a, b, c):
848 def R_gaussian(x, a, b, c):
849 N = int(numpy.shape(x)[0])
849 N = int(numpy.shape(x)[0])
850 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
850 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
851 return val
851 return val
852
852
853 def T(x,N):
853 def T(x,N):
854 T = 1-abs(x)/N
854 T = 1-abs(x)/N
855 return T
855 return T
856
856
857 def R_T_spc_fun(x, a1, b1, c1, a2, b2, c2, d):
857 def R_T_spc_fun(x, a1, b1, c1, a2, b2, c2, d):
858
858
859 N = int(numpy.shape(x)[0])
859 N = int(numpy.shape(x)[0])
860
860
861 x_max = x[-1]
861 x_max = x[-1]
862
862
863 x_pos = x[1600:]
863 x_pos = x[1600:]
864 x_neg = x[:1600]
864 x_neg = x[:1600]
865
865
866 R_T_neg_1 = R_gaussian(x, a1, b1, c1)[:1600]*T(x_neg,-x[0])
866 R_T_neg_1 = R_gaussian(x, a1, b1, c1)[:1600]*T(x_neg,-x[0])
867 R_T_pos_1 = R_gaussian(x, a1, b1, c1)[1600:]*T(x_pos,x[-1])
867 R_T_pos_1 = R_gaussian(x, a1, b1, c1)[1600:]*T(x_pos,x[-1])
868 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
868 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
869 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
869 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
870 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
870 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
871 max_val_1 = numpy.max(R_T_spc_1)
871 max_val_1 = numpy.max(R_T_spc_1)
872 R_T_spc_1 = R_T_spc_1*a1/max_val_1
872 R_T_spc_1 = R_T_spc_1*a1/max_val_1
873
873
874 R_T_neg_2 = R_gaussian(x, a2, b2, c2)[:1600]*T(x_neg,-x[0])
874 R_T_neg_2 = R_gaussian(x, a2, b2, c2)[:1600]*T(x_neg,-x[0])
875 R_T_pos_2 = R_gaussian(x, a2, b2, c2)[1600:]*T(x_pos,x[-1])
875 R_T_pos_2 = R_gaussian(x, a2, b2, c2)[1600:]*T(x_pos,x[-1])
876 R_T_sum_2 = R_T_pos_2 + R_T_neg_2
876 R_T_sum_2 = R_T_pos_2 + R_T_neg_2
877 R_T_spc_2 = numpy.fft.fft(R_T_sum_2).real
877 R_T_spc_2 = numpy.fft.fft(R_T_sum_2).real
878 R_T_spc_2 = numpy.fft.fftshift(R_T_spc_2)
878 R_T_spc_2 = numpy.fft.fftshift(R_T_spc_2)
879 max_val_2 = numpy.max(R_T_spc_2)
879 max_val_2 = numpy.max(R_T_spc_2)
880 R_T_spc_2 = R_T_spc_2*a2/max_val_2
880 R_T_spc_2 = R_T_spc_2*a2/max_val_2
881
881
882 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
882 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
883 R_T_d_neg = R_T_d[:1600]*T(x_neg,-x[0])
883 R_T_d_neg = R_T_d[:1600]*T(x_neg,-x[0])
884 R_T_d_pos = R_T_d[1600:]*T(x_pos,x[-1])
884 R_T_d_pos = R_T_d[1600:]*T(x_pos,x[-1])
885 R_T_d_sum = R_T_d_pos + R_T_d_neg
885 R_T_d_sum = R_T_d_pos + R_T_d_neg
886 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
886 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
887 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
887 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
888
888
889 R_T_final = R_T_spc_1 + R_T_spc_2 + R_T_spc_3
889 R_T_final = R_T_spc_1 + R_T_spc_2 + R_T_spc_3
890
890
891 return R_T_final
891 return R_T_final
892
892
893 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
893 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
894
894
895 from scipy.stats import norm
895 from scipy.stats import norm
896 mean,std=norm.fit(spc)
896 mean,std=norm.fit(spc)
897
897
898 # estimate starting values from the data
898 # estimate starting values from the data
899 a1 = A1
899 a1 = A1
900 b1 = B1
900 b1 = B1
901 c1 = C1#numpy.std(spc)
901 c1 = C1#numpy.std(spc)
902
902
903 a2 = A2#y.max()
903 a2 = A2#y.max()
904 b2 = B2#x[numpy.argmax(y)]
904 b2 = B2#x[numpy.argmax(y)]
905 c2 = C2#numpy.std(spc)
905 c2 = C2#numpy.std(spc)
906 d = D
906 d = D
907
907
908 ippSeconds = 250*20*1.e-6/3
908 ippSeconds = 250*20*1.e-6/3
909
909
910 x_t = ippSeconds * (numpy.arange(1600) -1600 / 2.)
910 x_t = ippSeconds * (numpy.arange(1600) -1600 / 2.)
911
911
912 x_t = numpy.linspace(x_t[0],x_t[-1],3200)
912 x_t = numpy.linspace(x_t[0],x_t[-1],3200)
913
913
914 x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
914 x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
915 x_freq = numpy.fft.fftshift(x_freq)
915 x_freq = numpy.fft.fftshift(x_freq)
916
916
917 # define a least squares function to optimize
917 # define a least squares function to optimize
918 def minfunc(params):
918 def minfunc(params):
919 return sum((y-R_T_spc_fun(x_t,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/1)#y**2)
919 return sum((y-R_T_spc_fun(x_t,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/1)#y**2)
920
920
921 # fit
921 # fit
922 popt_full = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],full_output=True)
922 popt_full = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d],full_output=True)
923 popt = popt_full[0]
923 popt = popt_full[0]
924
924
925 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
925 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
926
926
927 def Double_Gauss_fit_weight(self,spc,x,A1,B1,C1,A2,B2,C2,D):
927 def Double_Gauss_fit_weight(self,spc,x,A1,B1,C1,A2,B2,C2,D):
928 from scipy.optimize import curve_fit,fmin
928 from scipy.optimize import curve_fit,fmin
929
929
930 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
930 def double_gaussian(x, a1, b1, c1, a2, b2, c2, d):
931 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
931 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
932 return val
932 return val
933
933
934 y = spc
934 y = spc
935
935
936 from scipy.stats import norm
936 from scipy.stats import norm
937 mean,std=norm.fit(spc)
937 mean,std=norm.fit(spc)
938
938
939 # estimate starting values from the data
939 # estimate starting values from the data
940 a1 = A1
940 a1 = A1
941 b1 = B1
941 b1 = B1
942 c1 = C1#numpy.std(spc)
942 c1 = C1#numpy.std(spc)
943
943
944 a2 = A2#y.max()
944 a2 = A2#y.max()
945 b2 = B2#x[numpy.argmax(y)]
945 b2 = B2#x[numpy.argmax(y)]
946 c2 = C2#numpy.std(spc)
946 c2 = C2#numpy.std(spc)
947 d = D
947 d = D
948
948
949 y_clean = signal.medfilt(y)
949 y_clean = signal.medfilt(y)
950 # define a least squares function to optimize
950 # define a least squares function to optimize
951 def minfunc(params):
951 def minfunc(params):
952 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/(y_clean**2/1))
952 return sum((y-double_gaussian(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/(y_clean**2/1))
953
953
954 # fit
954 # fit
955 popt_full = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d], disp =False, full_output=True)
955 popt_full = fmin(minfunc,[a1,b1,c1,a2,b2,c2,d], disp =False, full_output=True)
956 #print("nIter", popt_full[2])
956 #print("nIter", popt_full[2])
957 popt = popt_full[0]
957 popt = popt_full[0]
958 #popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
958 #popt,pcov = curve_fit(double_gaussian,x,y,p0=[a1,b1,c1,a2,b2,c2,d])
959
959
960 #return double_gaussian(x, popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
960 #return double_gaussian(x, popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
961 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
961 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
962
962
963 def DH_mode(self,spectra,VelRange):
963 def DH_mode(self,spectra,VelRange):
964
964
965 from scipy.optimize import curve_fit
965 from scipy.optimize import curve_fit
966
966
967 def double_gauss(x, a1,b1,c1, a2,b2,c2, d):
967 def double_gauss(x, a1,b1,c1, a2,b2,c2, d):
968 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
968 val = a1 * numpy.exp(-(x - b1)**2 / (2*c1**2)) + a2 * numpy.exp(-(x - b2)**2 / (2*c2**2)) + d
969 return val
969 return val
970
970
971 spec = (spectra.copy()).flatten()
971 spec = (spectra.copy()).flatten()
972 amp=spec.max()
972 amp=spec.max()
973 params=numpy.array([amp,-400,30,amp/4,-200,150,1.0e7])
973 params=numpy.array([amp,-400,30,amp/4,-200,150,1.0e7])
974 #try:
974 #try:
975 popt,pcov=curve_fit(double_gauss, VelRange, spec, p0=params,bounds=([0,-460,0,0,-400,120,0],[numpy.inf,-340,50,numpy.inf,0,250,numpy.inf]))
975 popt,pcov=curve_fit(double_gauss, VelRange, spec, p0=params,bounds=([0,-460,0,0,-400,120,0],[numpy.inf,-340,50,numpy.inf,0,250,numpy.inf]))
976
976
977 error = numpy.sqrt(numpy.diag(pcov))
977 error = numpy.sqrt(numpy.diag(pcov))
978 #doppler_2=popt[4]
978 #doppler_2=popt[4]
979 #err_2 = numpy.sqrt(pcov[4][4])
979 #err_2 = numpy.sqrt(pcov[4][4])
980
980
981 #except:
981 #except:
982 #pass
982 #pass
983 #doppler_2=numpy.NAN
983 #doppler_2=numpy.NAN
984 #err_2 = numpy.NAN
984 #err_2 = numpy.NAN
985
985
986 #return doppler_2, err_2
986 #return doppler_2, err_2
987
987
988 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6], error[0], error[1], error[2], error[3], error[4], error[5], error[6]
988 return popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6], error[0], error[1], error[2], error[3], error[4], error[5], error[6]
989
989
990 def Tri_Marco(self,spc,freq,a1,b1,c1,a2,b2,c2,d):
990 def Tri_Marco(self,spc,freq,a1,b1,c1,a2,b2,c2,d):
991
991
992 from scipy.optimize import least_squares
992 from scipy.optimize import least_squares
993
993
994 freq_max = numpy.max(numpy.abs(freq))
994 freq_max = numpy.max(numpy.abs(freq))
995 spc_max = numpy.max(spc)
995 spc_max = numpy.max(spc)
996
996
997 def tri_gaussian(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, d):
997 def tri_gaussian(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, d):
998 z1 = (x-b1)/c1
998 z1 = (x-b1)/c1
999 z2 = (x-b2)/c2
999 z2 = (x-b2)/c2
1000 z3 = (x-b3)/c3
1000 z3 = (x-b3)/c3
1001 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + a3 * numpy.exp(-z3**2/2) + d
1001 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + a3 * numpy.exp(-z3**2/2) + d
1002 return val
1002 return val
1003
1003
1004 from scipy.signal import medfilt
1004 from scipy.signal import medfilt
1005 Nincoh = 20
1005 Nincoh = 20
1006 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1006 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1007 c1 = abs(c1)
1007 c1 = abs(c1)
1008 c2 = abs(c2)
1008 c2 = abs(c2)
1009
1009
1010 # define a least squares function to optimize
1010 # define a least squares function to optimize
1011 def lsq_func(params):
1011 def lsq_func(params):
1012 return (spc-tri_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9]))/spcm
1012 return (spc-tri_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9]))/spcm
1013
1013
1014 # fit
1014 # fit
1015 bounds=([0,-numpy.inf,0,0,-numpy.inf,0,0,0,0,0],[numpy.inf,-100,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,600,numpy.inf,numpy.inf])
1015 bounds=([0,-numpy.inf,0,0,-numpy.inf,0,0,0,0,0],[numpy.inf,-100,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,600,numpy.inf,numpy.inf])
1016
1016
1017 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1017 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1018 #print(a1,b1,c1,a2,b2,c2,d)
1018 #print(a1,b1,c1,a2,b2,c2,d)
1019 popt = least_squares(lsq_func,[a1,b1,c1,a2,b2,c2,a2/4,-b1,c1,d],x_scale=params_scale,bounds=bounds)
1019 popt = least_squares(lsq_func,[a1,b1,c1,a2,b2,c2,a2/4,-b1,c1,d],x_scale=params_scale,bounds=bounds)
1020
1020
1021 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1021 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1022 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1022 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1023 A3f = popt.x[6]; B3f = popt.x[7]; C3f = popt.x[8]
1023 A3f = popt.x[6]; B3f = popt.x[7]; C3f = popt.x[8]
1024 Df = popt.x[9]
1024 Df = popt.x[9]
1025
1025
1026 return A1f, B1f, C1f, A2f, B2f, C2f, Df
1026 return A1f, B1f, C1f, A2f, B2f, C2f, Df
1027
1027
1028 def Tri_Marco(self,spc,freq,a1,b1,c1,a2,b2,c2,d):
1028 def Tri_Marco(self,spc,freq,a1,b1,c1,a2,b2,c2,d):
1029
1029
1030 from scipy.optimize import least_squares
1030 from scipy.optimize import least_squares
1031
1031
1032 freq_max = numpy.max(numpy.abs(freq))
1032 freq_max = numpy.max(numpy.abs(freq))
1033 spc_max = numpy.max(spc)
1033 spc_max = numpy.max(spc)
1034
1034
1035 def duo_gaussian(x, a1, b1, c1, a2, b2, c2, d):
1035 def duo_gaussian(x, a1, b1, c1, a2, b2, c2, d):
1036 z1 = (x-b1)/c1
1036 z1 = (x-b1)/c1
1037 z2 = (x-b2)/c2
1037 z2 = (x-b2)/c2
1038 #z3 = (x-b3)/c3
1038 #z3 = (x-b3)/c3
1039 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + d
1039 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + d
1040 return val
1040 return val
1041
1041
1042 from scipy.signal import medfilt
1042 from scipy.signal import medfilt
1043 Nincoh = 20
1043 Nincoh = 20
1044 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1044 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1045 c1 = abs(c1)
1045 c1 = abs(c1)
1046 c2 = abs(c2)
1046 c2 = abs(c2)
1047
1047
1048 # define a least squares function to optimize
1048 # define a least squares function to optimize
1049 def lsq_func(params):
1049 def lsq_func(params):
1050 return (spc-tri_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))/spcm
1050 return (spc-tri_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))/spcm
1051
1051
1052 # fit
1052 # fit
1053 bounds=([0,-numpy.inf,0,0,-numpy.inf,0,0],[numpy.inf,-100,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf])
1053 bounds=([0,-numpy.inf,0,0,-numpy.inf,0,0],[numpy.inf,-100,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf])
1054
1054
1055 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1055 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1056 popt = least_squares(lsq_func,[a1,b1,c1,a2,b2,c2,d],x_scale=params_scale,bounds=bounds)
1056 popt = least_squares(lsq_func,[a1,b1,c1,a2,b2,c2,d],x_scale=params_scale,bounds=bounds)
1057
1057
1058 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1058 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1059 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1059 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1060 #A3f = popt.x[6]; B3f = popt.x[7]; C3f = popt.x[8]
1060 #A3f = popt.x[6]; B3f = popt.x[7]; C3f = popt.x[8]
1061 Df = popt.x[9]
1061 Df = popt.x[9]
1062
1062
1063 return A1f, B1f, C1f, A2f, B2f, C2f, Df
1063 return A1f, B1f, C1f, A2f, B2f, C2f, Df
1064
1064
1065 def double_gaussian_skew(self,x, a1, b1, c1, a2, b2, c2, k2, d):
1065 def double_gaussian_skew(self,x, a1, b1, c1, a2, b2, c2, k2, d):
1066 z1 = (x-b1)/c1
1066 z1 = (x-b1)/c1
1067 z2 = (x-b2)/c2
1067 z2 = (x-b2)/c2
1068 h2 = 1-k2*z2
1068 h2 = 1-k2*z2
1069 h2[h2<0] = 0
1069 h2[h2<0] = 0
1070 y2 = -1/k2*numpy.log(h2)
1070 y2 = -1/k2*numpy.log(h2)
1071 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1071 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1072 return val
1072 return val
1073
1073
1074 def gaussian(self, x, a, b, c, d):
1074 def gaussian(self, x, a, b, c, d):
1075 z = (x-b)/c
1075 z = (x-b)/c
1076 val = a * numpy.exp(-z**2/2) + d
1076 val = a * numpy.exp(-z**2/2) + d
1077 return val
1077 return val
1078
1078
1079 def double_gaussian(self, x, a1, b1, c1, a2, b2, c2, d):
1079 def double_gaussian(self, x, a1, b1, c1, a2, b2, c2, d):
1080 z1 = (x-b1)/c1
1080 z1 = (x-b1)/c1
1081 z2 = (x-b2)/c2
1081 z2 = (x-b2)/c2
1082 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + d
1082 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-z2**2/2) + d
1083 return val
1083 return val
1084
1084
1085 def double_gaussian_double_skew(self,x, a1, b1, c1, k1, a2, b2, c2, k2, d):
1085 def double_gaussian_double_skew(self,x, a1, b1, c1, k1, a2, b2, c2, k2, d):
1086
1086
1087 z1 = (x-b1)/c1
1087 z1 = (x-b1)/c1
1088 h1 = 1-k1*z1
1088 h1 = 1-k1*z1
1089 h1[h1<0] = 0
1089 h1[h1<0] = 0
1090 y1 = -1/k1*numpy.log(h1)
1090 y1 = -1/k1*numpy.log(h1)
1091
1091
1092 z2 = (x-b2)/c2
1092 z2 = (x-b2)/c2
1093 h2 = 1-k2*z2
1093 h2 = 1-k2*z2
1094 h2[h2<0] = 0
1094 h2[h2<0] = 0
1095 y2 = -1/k2*numpy.log(h2)
1095 y2 = -1/k2*numpy.log(h2)
1096
1096
1097 val = a1 * numpy.exp(-y1**2/2)/(1-k1*z1) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1097 val = a1 * numpy.exp(-y1**2/2)/(1-k1*z1) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1098 return val
1098 return val
1099
1099
1100 def gaussian_skew(self,x, a2, b2, c2, k2, d):
1100 def gaussian_skew(self,x, a2, b2, c2, k2, d):
1101 z2 = (x-b2)/c2
1101 z2 = (x-b2)/c2
1102 h2 = 1-k2*z2
1102 h2 = 1-k2*z2
1103 h2[h2<0] = 0
1103 h2[h2<0] = 0
1104 y2 = -1/k2*numpy.log(h2)
1104 y2 = -1/k2*numpy.log(h2)
1105 val = a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1105 val = a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + d
1106 return val
1106 return val
1107
1107
1108 def triple_gaussian_skew(self,x, a1, b1, c1, a2, b2, c2, k2, a3, b3, c3, k3, d):
1108 def triple_gaussian_skew(self,x, a1, b1, c1, a2, b2, c2, k2, a3, b3, c3, k3, d):
1109 z1 = (x-b1)/c1
1109 z1 = (x-b1)/c1
1110 z2 = (x-b2)/c2
1110 z2 = (x-b2)/c2
1111 z3 = (x-b3)/c3
1111 z3 = (x-b3)/c3
1112 h2 = 1-k2*z2
1112 h2 = 1-k2*z2
1113 h2[h2<0] = 0
1113 h2[h2<0] = 0
1114 y2 = -1/k2*numpy.log(h2)
1114 y2 = -1/k2*numpy.log(h2)
1115 h3 = 1-k3*z3
1115 h3 = 1-k3*z3
1116 h3[h3<0] = 0
1116 h3[h3<0] = 0
1117 y3 = -1/k3*numpy.log(h3)
1117 y3 = -1/k3*numpy.log(h3)
1118 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + a3 * numpy.exp(-y3**2/2)/(1-k3*z3) + d
1118 val = a1 * numpy.exp(-z1**2/2) + a2 * numpy.exp(-y2**2/2)/(1-k2*z2) + a3 * numpy.exp(-y3**2/2)/(1-k3*z3) + d
1119 return val
1119 return val
1120
1120
1121 def Double_Gauss_Skew_fit_weight_bound_no_inputs(self,spc,freq):
1121 def Double_Gauss_Skew_fit_weight_bound_no_inputs(self,spc,freq):
1122
1122
1123 from scipy.optimize import least_squares
1123 from scipy.optimize import least_squares
1124
1124
1125 freq_max = numpy.max(numpy.abs(freq))
1125 freq_max = numpy.max(numpy.abs(freq))
1126 spc_max = numpy.max(spc)
1126 spc_max = numpy.max(spc)
1127
1127
1128 from scipy.signal import medfilt
1128 from scipy.signal import medfilt
1129 Nincoh = 20
1129 Nincoh = 20
1130 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1130 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1131
1131
1132 # define a least squares function to optimize
1132 # define a least squares function to optimize
1133 def lsq_func(params):
1133 def lsq_func(params):
1134 return (spc-self.double_gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7]))/spcm
1134 return (spc-self.double_gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7]))/spcm
1135
1135
1136 # fit
1136 # fit
1137 bounds=([0,-numpy.inf,0,0,-400,0,0,0],[numpy.inf,-340,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1137 bounds=([0,-numpy.inf,0,0,-400,0,0,0],[numpy.inf,-340,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1138
1138
1139 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,1,spc_max]
1139 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,1,spc_max]
1140 x0_value = numpy.array([spc_max,-400,30,spc_max/4,-200,150,1,1.0e7])
1140 x0_value = numpy.array([spc_max,-400,30,spc_max/4,-200,150,1,1.0e7])
1141 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1141 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1142 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1142 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1143 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]; K2f = popt.x[6]
1143 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]; K2f = popt.x[6]
1144 Df = popt.x[7]
1144 Df = popt.x[7]
1145
1145
1146 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1146 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1147 doppler = freq[numpy.argmax(aux)]
1147 doppler = freq[numpy.argmax(aux)]
1148
1148
1149 return A1f, B1f, C1f, A2f, B2f, C2f, K2f, Df, doppler
1149 return A1f, B1f, C1f, A2f, B2f, C2f, K2f, Df, doppler
1150
1150
1151 def Double_Gauss_Double_Skew_fit_weight_bound_no_inputs(self,spc,freq,Nincoh,hei):
1151 def Double_Gauss_Double_Skew_fit_weight_bound_no_inputs(self,spc,freq,Nincoh,hei):
1152
1152
1153 from scipy.optimize import least_squares
1153 from scipy.optimize import least_squares
1154
1154
1155 freq_max = numpy.max(numpy.abs(freq))
1155 freq_max = numpy.max(numpy.abs(freq))
1156 spc_max = numpy.max(spc)
1156 spc_max = numpy.max(spc)
1157
1157
1158 #from scipy.signal import medfilt
1158 #from scipy.signal import medfilt
1159 #Nincoh = 20
1159 #Nincoh = 20
1160 #Nincoh = 80
1160 #Nincoh = 80
1161 Nincoh = Nincoh
1161 Nincoh = Nincoh
1162 #spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1162 #spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1163 spcm = spc/numpy.sqrt(Nincoh)
1163 spcm = spc/numpy.sqrt(Nincoh)
1164
1164
1165 # define a least squares function to optimize
1165 # define a least squares function to optimize
1166 def lsq_func(params):
1166 def lsq_func(params):
1167 return (spc-self.double_gaussian_double_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]))/spcm
1167 return (spc-self.double_gaussian_double_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]))/spcm
1168
1168
1169 # fit
1169 # fit
1170 bounds=([0,-numpy.inf,0,-5,0,-400,0,0,0],[numpy.inf,-200,numpy.inf,5,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1170 bounds=([0,-numpy.inf,0,-5,0,-400,0,0,0],[numpy.inf,-200,numpy.inf,5,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1171
1171
1172 params_scale = [spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1172 params_scale = [spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1173
1173
1174 dop1_x0 = freq[numpy.argmax(spc)]
1174 dop1_x0 = freq[numpy.argmax(spc)]
1175 if dop1_x0 < 0:
1175 if dop1_x0 < 0:
1176 dop2_x0 = dop1_x0 + 100
1176 dop2_x0 = dop1_x0 + 100
1177 if dop1_x0 > 0:
1177 if dop1_x0 > 0:
1178 dop2_x0 = dop1_x0 - 100
1178 dop2_x0 = dop1_x0 - 100
1179
1179
1180 x0_value = numpy.array([spc_max,dop1_x0,30,-.1,spc_max/4, dop2_x0,150,1,1.0e7])
1180 x0_value = numpy.array([spc_max,dop1_x0,30,-.1,spc_max/4, dop2_x0,150,1,1.0e7])
1181 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1181 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1182 J = popt.jac
1182 J = popt.jac
1183
1183
1184 try:
1184 try:
1185 cov = numpy.linalg.inv(J.T.dot(J))
1185 cov = numpy.linalg.inv(J.T.dot(J))
1186 error = numpy.sqrt(numpy.diagonal(cov))
1186 error = numpy.sqrt(numpy.diagonal(cov))
1187 except:
1187 except:
1188 error = numpy.ones((9))*numpy.NAN
1188 error = numpy.ones((9))*numpy.NAN
1189
1189
1190 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1190 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1191 A2f = popt.x[4]; B2f = popt.x[5]; C2f = popt.x[6]; K2f = popt.x[7]
1191 A2f = popt.x[4]; B2f = popt.x[5]; C2f = popt.x[6]; K2f = popt.x[7]
1192 Df = popt.x[8]
1192 Df = popt.x[8]
1193 aux1 = self.gaussian_skew(freq, A1f, B1f, C1f, K1f, Df)
1193 aux1 = self.gaussian_skew(freq, A1f, B1f, C1f, K1f, Df)
1194 doppler1 = freq[numpy.argmax(aux1)]
1194 doppler1 = freq[numpy.argmax(aux1)]
1195
1195
1196 aux2 = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1196 aux2 = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1197 doppler2 = freq[numpy.argmax(aux2)]
1197 doppler2 = freq[numpy.argmax(aux2)]
1198 #print("error",error)
1198 #print("error",error)
1199 #exit(1)
1199 #exit(1)
1200
1200
1201
1201
1202 return A1f, B1f, C1f, K1f, A2f, B2f, C2f, K2f, Df, doppler1, doppler2, error
1202 return A1f, B1f, C1f, K1f, A2f, B2f, C2f, K2f, Df, doppler1, doppler2, error
1203
1203
1204 def Double_Gauss_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1204 def Double_Gauss_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1205
1205
1206 from scipy.optimize import least_squares
1206 from scipy.optimize import least_squares
1207
1207
1208 freq_max = numpy.max(numpy.abs(freq))
1208 freq_max = numpy.max(numpy.abs(freq))
1209 spc_max = numpy.max(spc)
1209 spc_max = numpy.max(spc)
1210
1210
1211 from scipy.signal import medfilt
1211 from scipy.signal import medfilt
1212 Nincoh = 20
1212 Nincoh = 20
1213 Nincoh = 80
1213 Nincoh = 80
1214 Nincoh = Nincoh
1214 Nincoh = Nincoh
1215 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1215 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1216
1216
1217 # define a least squares function to optimize
1217 # define a least squares function to optimize
1218 def lsq_func(params):
1218 def lsq_func(params):
1219 return (spc-self.double_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))/spcm
1219 return (spc-self.double_gaussian(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))/spcm
1220
1220
1221 # fit
1221 # fit
1222 # bounds=([0,-460,0,0,-400,120,0],[numpy.inf,-340,50,numpy.inf,0,250,numpy.inf])
1222 # bounds=([0,-460,0,0,-400,120,0],[numpy.inf,-340,50,numpy.inf,0,250,numpy.inf])
1223 # bounds=([0,-numpy.inf,0,0,-numpy.inf,0,-numpy.inf,0],[numpy.inf,-200,numpy.inf,numpy.inf,0,numpy.inf,0,numpy.inf])
1223 # bounds=([0,-numpy.inf,0,0,-numpy.inf,0,-numpy.inf,0],[numpy.inf,-200,numpy.inf,numpy.inf,0,numpy.inf,0,numpy.inf])
1224 #print(a1,b1,c1,a2,b2,c2,k2,d)
1224 #print(a1,b1,c1,a2,b2,c2,k2,d)
1225
1225
1226 dop1_x0 = freq[numpy.argmax(spcm)]
1226 dop1_x0 = freq[numpy.argmax(spcm)]
1227
1227
1228 bounds=([0,-numpy.inf,0,0,dop1_x0-50,0,0],[numpy.inf,-300,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf])
1228 bounds=([0,-numpy.inf,0,0,dop1_x0-50,0,0],[numpy.inf,-300,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf])
1229 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1229 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,spc_max]
1230 x0_value = numpy.array([spc_max,-400.5,30,spc_max/4,dop1_x0,150,1.0e7])
1230 x0_value = numpy.array([spc_max,-400.5,30,spc_max/4,dop1_x0,150,1.0e7])
1231 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1231 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1232 J = popt.jac
1232 J = popt.jac
1233
1233
1234 try:
1234 try:
1235 cov = numpy.linalg.inv(J.T.dot(J))
1235 cov = numpy.linalg.inv(J.T.dot(J))
1236 error = numpy.sqrt(numpy.diagonal(cov))
1236 error = numpy.sqrt(numpy.diagonal(cov))
1237 except:
1237 except:
1238 error = numpy.ones((7))*numpy.NAN
1238 error = numpy.ones((7))*numpy.NAN
1239
1239
1240 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1240 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1241 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1241 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]
1242 Df = popt.x[6]
1242 Df = popt.x[6]
1243 return A1f, B1f, C1f, A2f, B2f, C2f, Df, error
1243 return A1f, B1f, C1f, A2f, B2f, C2f, Df, error
1244
1244
1245 def Double_Gauss_Double_Skew_fit_weight_bound_with_inputs(self, spc, freq, a1, b1, c1, a2, b2, c2, k2, d):
1245 def Double_Gauss_Double_Skew_fit_weight_bound_with_inputs(self, spc, freq, a1, b1, c1, a2, b2, c2, k2, d):
1246
1246
1247 from scipy.optimize import least_squares
1247 from scipy.optimize import least_squares
1248
1248
1249 freq_max = numpy.max(numpy.abs(freq))
1249 freq_max = numpy.max(numpy.abs(freq))
1250 spc_max = numpy.max(spc)
1250 spc_max = numpy.max(spc)
1251
1251
1252 from scipy.signal import medfilt
1252 from scipy.signal import medfilt
1253 Nincoh = dataOut.nIncohInt
1253 Nincoh = dataOut.nIncohInt
1254 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1254 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1255
1255
1256 # define a least squares function to optimize
1256 # define a least squares function to optimize
1257 def lsq_func(params):
1257 def lsq_func(params):
1258 return (spc-self.double_gaussian_double_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]))/spcm
1258 return (spc-self.double_gaussian_double_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8]))/spcm
1259
1259
1260
1260
1261 bounds=([0,-numpy.inf,0,-numpy.inf,0,-400,0,0,0],[numpy.inf,-340,numpy.inf,0,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1261 bounds=([0,-numpy.inf,0,-numpy.inf,0,-400,0,0,0],[numpy.inf,-340,numpy.inf,0,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf])
1262
1262
1263 params_scale = [spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1263 params_scale = [spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1264
1264
1265 x0_value = numpy.array([a1,b1,c1,-.1,a2,b2,c2,k2,d])
1265 x0_value = numpy.array([a1,b1,c1,-.1,a2,b2,c2,k2,d])
1266
1266
1267 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1267 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1268
1268
1269 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1269 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1270 A2f = popt.x[4]; B2f = popt.x[5]; C2f = popt.x[6]; K2f = popt.x[7]
1270 A2f = popt.x[4]; B2f = popt.x[5]; C2f = popt.x[6]; K2f = popt.x[7]
1271 Df = popt.x[8]
1271 Df = popt.x[8]
1272
1272
1273 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1273 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1274 doppler = x[numpy.argmax(aux)]
1274 doppler = x[numpy.argmax(aux)]
1275
1275
1276 return A1f, B1f, C1f, K1f, A2f, B2f, C2f, K2f, Df, doppler
1276 return A1f, B1f, C1f, K1f, A2f, B2f, C2f, K2f, Df, doppler
1277
1277
1278 def Triple_Gauss_Skew_fit_weight_bound_no_inputs(self,spc,freq):
1278 def Triple_Gauss_Skew_fit_weight_bound_no_inputs(self,spc,freq):
1279
1279
1280 from scipy.optimize import least_squares
1280 from scipy.optimize import least_squares
1281
1281
1282 freq_max = numpy.max(numpy.abs(freq))
1282 freq_max = numpy.max(numpy.abs(freq))
1283 spc_max = numpy.max(spc)
1283 spc_max = numpy.max(spc)
1284
1284
1285 from scipy.signal import medfilt
1285 from scipy.signal import medfilt
1286 Nincoh = 20
1286 Nincoh = 20
1287 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1287 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1288
1288
1289 # define a least squares function to optimize
1289 # define a least squares function to optimize
1290 def lsq_func(params):
1290 def lsq_func(params):
1291 return (spc-self.triple_gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11]))/spcm
1291 return (spc-self.triple_gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4],params[5],params[6],params[7],params[8],params[9],params[10],params[11]))/spcm
1292
1292
1293 # fit
1293 # fit
1294 bounds=([0,-numpy.inf,0,0,-400,0,0,0,0,0,0,0],[numpy.inf,-340,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf])
1294 bounds=([0,-numpy.inf,0,0,-400,0,0,0,0,0,0,0],[numpy.inf,-340,numpy.inf,numpy.inf,0,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf,numpy.inf])
1295
1295
1296 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1296 params_scale = [spc_max,freq_max,freq_max,spc_max,freq_max,freq_max,1,spc_max,freq_max,freq_max,1,spc_max]
1297 x0_value = numpy.array([spc_max,-400,30,spc_max/4,-200,150,1,spc_max/4,400,150,1,1.0e7])
1297 x0_value = numpy.array([spc_max,-400,30,spc_max/4,-200,150,1,spc_max/4,400,150,1,1.0e7])
1298 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1298 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1299
1299
1300 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1300 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1301 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]; K2f = popt.x[6]
1301 A2f = popt.x[3]; B2f = popt.x[4]; C2f = popt.x[5]; K2f = popt.x[6]
1302 A3f = popt.x[7]; B3f = popt.x[8]; C3f = popt.x[9]; K3f = popt.x[10]
1302 A3f = popt.x[7]; B3f = popt.x[8]; C3f = popt.x[9]; K3f = popt.x[10]
1303 Df = popt.x[11]
1303 Df = popt.x[11]
1304
1304
1305 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1305 aux = self.gaussian_skew(freq, A2f, B2f, C2f, K2f, Df)
1306 doppler = freq[numpy.argmax(aux)]
1306 doppler = freq[numpy.argmax(aux)]
1307
1307
1308 return A1f, B1f, C1f, A2f, B2f, C2f, K2f, A3f, B3f, C3f, K3f, Df, doppler
1308 return A1f, B1f, C1f, A2f, B2f, C2f, K2f, A3f, B3f, C3f, K3f, Df, doppler
1309
1309
1310 def CEEJ_Skew_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1310 def CEEJ_Skew_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1311
1311
1312 from scipy.optimize import least_squares
1312 from scipy.optimize import least_squares
1313
1313
1314 freq_max = numpy.max(numpy.abs(freq))
1314 freq_max = numpy.max(numpy.abs(freq))
1315 spc_max = numpy.max(spc)
1315 spc_max = numpy.max(spc)
1316
1316
1317 from scipy.signal import medfilt
1317 from scipy.signal import medfilt
1318 Nincoh = 20
1318 Nincoh = 20
1319 Nincoh = 80
1319 Nincoh = 80
1320 Nincoh = Nincoh
1320 Nincoh = Nincoh
1321 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1321 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1322
1322
1323 # define a least squares function to optimize
1323 # define a least squares function to optimize
1324 def lsq_func(params):
1324 def lsq_func(params):
1325 return (spc-self.gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4]))#/spcm
1325 return (spc-self.gaussian_skew(freq,params[0],params[1],params[2],params[3],params[4]))#/spcm
1326
1326
1327
1327
1328 bounds=([0,0,0,-numpy.inf,0],[numpy.inf,numpy.inf,numpy.inf,0,numpy.inf])
1328 bounds=([0,0,0,-numpy.inf,0],[numpy.inf,numpy.inf,numpy.inf,0,numpy.inf])
1329
1329
1330 params_scale = [spc_max,freq_max,freq_max,1,spc_max]
1330 params_scale = [spc_max,freq_max,freq_max,1,spc_max]
1331
1331
1332 x0_value = numpy.array([spc_max,freq[numpy.argmax(spc)],30,-.1,numpy.mean(spc[:50])])
1332 x0_value = numpy.array([spc_max,freq[numpy.argmax(spc)],30,-.1,numpy.mean(spc[:50])])
1333
1333
1334 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1334 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1335
1335
1336 J = popt.jac
1336 J = popt.jac
1337
1337
1338 try:
1338 try:
1339 error = numpy.ones((9))*numpy.NAN
1339 error = numpy.ones((9))*numpy.NAN
1340 cov = numpy.linalg.inv(J.T.dot(J))
1340 cov = numpy.linalg.inv(J.T.dot(J))
1341 error[:4] = numpy.sqrt(numpy.diagonal(cov))[:4]
1341 error[:4] = numpy.sqrt(numpy.diagonal(cov))[:4]
1342 error[-1] = numpy.sqrt(numpy.diagonal(cov))[-1]
1342 error[-1] = numpy.sqrt(numpy.diagonal(cov))[-1]
1343 except:
1343 except:
1344 error = numpy.ones((9))*numpy.NAN
1344 error = numpy.ones((9))*numpy.NAN
1345
1345
1346 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1346 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]; K1f = popt.x[3]
1347 Df = popt.x[4]
1347 Df = popt.x[4]
1348
1348
1349 aux1 = self.gaussian_skew(freq, A1f, B1f, C1f, K1f, Df)
1349 aux1 = self.gaussian_skew(freq, A1f, B1f, C1f, K1f, Df)
1350 doppler1 = freq[numpy.argmax(aux1)]
1350 doppler1 = freq[numpy.argmax(aux1)]
1351 #print("CEEJ ERROR:",error)
1351 #print("CEEJ ERROR:",error)
1352
1352
1353 return A1f, B1f, C1f, K1f, numpy.NAN, numpy.NAN, numpy.NAN, numpy.NAN, Df, doppler1, numpy.NAN, error
1353 return A1f, B1f, C1f, K1f, numpy.NAN, numpy.NAN, numpy.NAN, numpy.NAN, Df, doppler1, numpy.NAN, error
1354
1354
1355 def CEEJ_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1355 def CEEJ_fit_weight_bound_no_inputs(self,spc,freq,Nincoh):
1356
1356
1357 from scipy.optimize import least_squares
1357 from scipy.optimize import least_squares
1358
1358
1359 freq_max = numpy.max(numpy.abs(freq))
1359 freq_max = numpy.max(numpy.abs(freq))
1360 spc_max = numpy.max(spc)
1360 spc_max = numpy.max(spc)
1361
1361
1362 from scipy.signal import medfilt
1362 from scipy.signal import medfilt
1363 Nincoh = 20
1363 Nincoh = 20
1364 Nincoh = 80
1364 Nincoh = 80
1365 Nincoh = Nincoh
1365 Nincoh = Nincoh
1366 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1366 spcm = medfilt(spc,11)/numpy.sqrt(Nincoh)
1367
1367
1368 # define a least squares function to optimize
1368 # define a least squares function to optimize
1369 def lsq_func(params):
1369 def lsq_func(params):
1370 return (spc-self.gaussian(freq,params[0],params[1],params[2],params[3]))#/spcm
1370 return (spc-self.gaussian(freq,params[0],params[1],params[2],params[3]))#/spcm
1371
1371
1372
1372
1373 bounds=([0,0,0,0],[numpy.inf,numpy.inf,numpy.inf,numpy.inf])
1373 bounds=([0,0,0,0],[numpy.inf,numpy.inf,numpy.inf,numpy.inf])
1374
1374
1375 params_scale = [spc_max,freq_max,freq_max,spc_max]
1375 params_scale = [spc_max,freq_max,freq_max,spc_max]
1376
1376
1377 x0_value = numpy.array([spc_max,freq[numpy.argmax(spcm)],30,numpy.mean(spc[:50])])
1377 x0_value = numpy.array([spc_max,freq[numpy.argmax(spcm)],30,numpy.mean(spc[:50])])
1378
1378
1379 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1379 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1380
1380
1381 J = popt.jac
1381 J = popt.jac
1382
1382
1383 try:
1383 try:
1384 error = numpy.ones((4))*numpy.NAN
1384 error = numpy.ones((4))*numpy.NAN
1385 cov = numpy.linalg.inv(J.T.dot(J))
1385 cov = numpy.linalg.inv(J.T.dot(J))
1386 error = numpy.sqrt(numpy.diagonal(cov))
1386 error = numpy.sqrt(numpy.diagonal(cov))
1387 except:
1387 except:
1388 error = numpy.ones((4))*numpy.NAN
1388 error = numpy.ones((4))*numpy.NAN
1389
1389
1390 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1390 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1391 Df = popt.x[3]
1391 Df = popt.x[3]
1392
1392
1393 return A1f, B1f, C1f, Df, error
1393 return A1f, B1f, C1f, Df, error
1394
1394
1395 def Simple_fit_bound(self,spc,freq,Nincoh):
1395 def Simple_fit_bound(self,spc,freq,Nincoh):
1396
1396
1397 freq_max = numpy.max(numpy.abs(freq))
1397 freq_max = numpy.max(numpy.abs(freq))
1398 spc_max = numpy.max(spc)
1398 spc_max = numpy.max(spc)
1399
1399
1400 Nincoh = Nincoh
1400 Nincoh = Nincoh
1401
1401
1402 def lsq_func(params):
1402 def lsq_func(params):
1403 return (spc-self.gaussian(freq,params[0],params[1],params[2],params[3]))
1403 return (spc-self.gaussian(freq,params[0],params[1],params[2],params[3]))
1404
1404
1405 bounds=([0,-50,0,0],[numpy.inf,+50,numpy.inf,numpy.inf])
1405 bounds=([0,-50,0,0],[numpy.inf,+50,numpy.inf,numpy.inf])
1406
1406
1407 params_scale = [spc_max,freq_max,freq_max,spc_max]
1407 params_scale = [spc_max,freq_max,freq_max,spc_max]
1408
1408
1409 x0_value = numpy.array([spc_max,-20.5,5,1.0e7])
1409 x0_value = numpy.array([spc_max,-20.5,5,1.0e7])
1410
1410
1411 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1411 popt = least_squares(lsq_func,x0=x0_value,x_scale=params_scale,bounds=bounds,verbose=0)
1412
1412
1413 J = popt.jac
1413 J = popt.jac
1414
1414
1415 try:
1415 try:
1416 cov = numpy.linalg.inv(J.T.dot(J))
1416 cov = numpy.linalg.inv(J.T.dot(J))
1417 error = numpy.sqrt(numpy.diagonal(cov))
1417 error = numpy.sqrt(numpy.diagonal(cov))
1418 except:
1418 except:
1419 error = numpy.ones((4))*numpy.NAN
1419 error = numpy.ones((4))*numpy.NAN
1420
1420
1421 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1421 A1f = popt.x[0]; B1f = popt.x[1]; C1f = popt.x[2]
1422 Df = popt.x[3]
1422 Df = popt.x[3]
1423
1423
1424 return A1f, B1f, C1f, Df, error
1424 return A1f, B1f, C1f, Df, error
1425
1425
1426 def clean_outliers(self,param):
1426 def clean_outliers(self,param):
1427
1427
1428 threshold = 700
1428 threshold = 700
1429
1429
1430 param = numpy.where(param < -threshold, numpy.nan, param)
1430 param = numpy.where(param < -threshold, numpy.nan, param)
1431 param = numpy.where(param > +threshold, numpy.nan, param)
1431 param = numpy.where(param > +threshold, numpy.nan, param)
1432
1432
1433 return param
1433 return param
1434
1434
1435 def windowing_single(self,spc,x,A,B,C,D,nFFTPoints):
1435 def windowing_single(self,spc,x,A,B,C,D,nFFTPoints):
1436 from scipy.optimize import curve_fit,fmin
1436 from scipy.optimize import curve_fit,fmin
1437
1437
1438 def R_gaussian(x, a, b, c):
1438 def R_gaussian(x, a, b, c):
1439 N = int(numpy.shape(x)[0])
1439 N = int(numpy.shape(x)[0])
1440 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
1440 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
1441 return val
1441 return val
1442
1442
1443 def T(x,N):
1443 def T(x,N):
1444 T = 1-abs(x)/N
1444 T = 1-abs(x)/N
1445 return T
1445 return T
1446
1446
1447 def R_T_spc_fun(x, a, b, c, d, nFFTPoints):
1447 def R_T_spc_fun(x, a, b, c, d, nFFTPoints):
1448
1448
1449 N = int(numpy.shape(x)[0])
1449 N = int(numpy.shape(x)[0])
1450
1450
1451 x_max = x[-1]
1451 x_max = x[-1]
1452
1452
1453 x_pos = x[int(nFFTPoints/2):]
1453 x_pos = x[int(nFFTPoints/2):]
1454 x_neg = x[:int(nFFTPoints/2)]
1454 x_neg = x[:int(nFFTPoints/2)]
1455
1455
1456 R_T_neg_1 = R_gaussian(x, a, b, c)[:int(nFFTPoints/2)]*T(x_neg,-x[0])
1456 R_T_neg_1 = R_gaussian(x, a, b, c)[:int(nFFTPoints/2)]*T(x_neg,-x[0])
1457 R_T_pos_1 = R_gaussian(x, a, b, c)[int(nFFTPoints/2):]*T(x_pos,x[-1])
1457 R_T_pos_1 = R_gaussian(x, a, b, c)[int(nFFTPoints/2):]*T(x_pos,x[-1])
1458 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
1458 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
1459 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
1459 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
1460 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
1460 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
1461 max_val_1 = numpy.max(R_T_spc_1)
1461 max_val_1 = numpy.max(R_T_spc_1)
1462 R_T_spc_1 = R_T_spc_1*a/max_val_1
1462 R_T_spc_1 = R_T_spc_1*a/max_val_1
1463
1463
1464 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
1464 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
1465 R_T_d_neg = R_T_d[:int(nFFTPoints/2)]*T(x_neg,-x[0])
1465 R_T_d_neg = R_T_d[:int(nFFTPoints/2)]*T(x_neg,-x[0])
1466 R_T_d_pos = R_T_d[int(nFFTPoints/2):]*T(x_pos,x[-1])
1466 R_T_d_pos = R_T_d[int(nFFTPoints/2):]*T(x_pos,x[-1])
1467 R_T_d_sum = R_T_d_pos + R_T_d_neg
1467 R_T_d_sum = R_T_d_pos + R_T_d_neg
1468 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
1468 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
1469 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
1469 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
1470
1470
1471 R_T_final = R_T_spc_1 + R_T_spc_3
1471 R_T_final = R_T_spc_1 + R_T_spc_3
1472
1472
1473 return R_T_final
1473 return R_T_final
1474
1474
1475 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
1475 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
1476
1476
1477 from scipy.stats import norm
1477 from scipy.stats import norm
1478 mean,std=norm.fit(spc)
1478 mean,std=norm.fit(spc)
1479
1479
1480 # estimate starting values from the data
1480 # estimate starting values from the data
1481 a = A
1481 a = A
1482 b = B
1482 b = B
1483 c = C#numpy.std(spc)
1483 c = C#numpy.std(spc)
1484 d = D
1484 d = D
1485 '''
1485 '''
1486 ippSeconds = 250*20*1.e-6/3
1486 ippSeconds = 250*20*1.e-6/3
1487
1487
1488 x_t = ippSeconds * (numpy.arange(1600) -1600 / 2.)
1488 x_t = ippSeconds * (numpy.arange(1600) -1600 / 2.)
1489
1489
1490 x_t = numpy.linspace(x_t[0],x_t[-1],3200)
1490 x_t = numpy.linspace(x_t[0],x_t[-1],3200)
1491
1491
1492 x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
1492 x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
1493 x_freq = numpy.fft.fftshift(x_freq)
1493 x_freq = numpy.fft.fftshift(x_freq)
1494 '''
1494 '''
1495 # define a least squares function to optimize
1495 # define a least squares function to optimize
1496 def minfunc(params):
1496 def minfunc(params):
1497 return sum((y-R_T_spc_fun(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/1)#y**2)
1497 return sum((y-R_T_spc_fun(x,params[0],params[1],params[2],params[3],params[4],params[5],params[6]))**2/1)#y**2)
1498
1498
1499 # fit
1499 # fit
1500
1500
1501 popt_full = fmin(minfunc,[a,b,c,d],full_output=True)
1501 popt_full = fmin(minfunc,[a,b,c,d],full_output=True)
1502 #print("nIter", popt_full[2])
1502 #print("nIter", popt_full[2])
1503 popt = popt_full[0]
1503 popt = popt_full[0]
1504
1504
1505 #return R_T_spc_fun(x_t,popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
1505 #return R_T_spc_fun(x_t,popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
1506 return popt[0], popt[1], popt[2], popt[3]
1506 return popt[0], popt[1], popt[2], popt[3]
1507
1507
1508 def run(self, dataOut, mode = 0, Hmin1 = None, Hmax1 = None, Hmin2 = None, Hmax2 = None, Dop = 'Shift'):
1508 def run(self, dataOut, mode = 0, Hmin1 = None, Hmax1 = None, Hmin2 = None, Hmax2 = None, Dop = 'Shift'):
1509
1509
1510 pwcode = 1
1510 pwcode = 1
1511
1511
1512 if dataOut.flagDecodeData:
1512 if dataOut.flagDecodeData:
1513 pwcode = numpy.sum(dataOut.code[0]**2)
1513 pwcode = numpy.sum(dataOut.code[0]**2)
1514 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
1514 #normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
1515 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
1515 normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
1516 factor = normFactor
1516 factor = normFactor
1517 z = dataOut.data_spc / factor
1517 z = dataOut.data_spc / factor
1518 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1518 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
1519 dataOut.power = numpy.average(z, axis=1)
1519 dataOut.power = numpy.average(z, axis=1)
1520 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
1520 dataOut.powerdB = 10 * numpy.log10(dataOut.power)
1521
1521
1522 x = dataOut.getVelRange(0)
1522 x = dataOut.getVelRange(0)
1523
1523
1524 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1524 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1525 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1525 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1526 dataOut.dplr_2_u = numpy.ones((1,1,dataOut.nHeights))*numpy.NAN
1526 dataOut.dplr_2_u = numpy.ones((1,1,dataOut.nHeights))*numpy.NAN
1527
1527
1528 if mode == 6:
1528 if mode == 6:
1529 dataOut.Oblique_params = numpy.ones((1,9,dataOut.nHeights))*numpy.NAN
1529 dataOut.Oblique_params = numpy.ones((1,9,dataOut.nHeights))*numpy.NAN
1530 elif mode == 7:
1530 elif mode == 7:
1531 dataOut.Oblique_params = numpy.ones((1,13,dataOut.nHeights))*numpy.NAN
1531 dataOut.Oblique_params = numpy.ones((1,13,dataOut.nHeights))*numpy.NAN
1532 elif mode == 8:
1532 elif mode == 8:
1533 dataOut.Oblique_params = numpy.ones((1,10,dataOut.nHeights))*numpy.NAN
1533 dataOut.Oblique_params = numpy.ones((1,10,dataOut.nHeights))*numpy.NAN
1534 elif mode == 9:
1534 elif mode == 9:
1535 dataOut.Oblique_params = numpy.ones((1,11,dataOut.nHeights))*numpy.NAN
1535 dataOut.Oblique_params = numpy.ones((1,11,dataOut.nHeights))*numpy.NAN
1536 dataOut.Oblique_param_errors = numpy.ones((1,9,dataOut.nHeights))*numpy.NAN
1536 dataOut.Oblique_param_errors = numpy.ones((1,9,dataOut.nHeights))*numpy.NAN
1537 elif mode == 11:
1537 elif mode == 11:
1538 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1538 dataOut.Oblique_params = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1539 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1539 dataOut.Oblique_param_errors = numpy.ones((1,7,dataOut.nHeights))*numpy.NAN
1540 elif mode == 10: #150 km
1540 elif mode == 10: #150 km
1541 dataOut.Oblique_params = numpy.ones((1,4,dataOut.nHeights))*numpy.NAN
1541 dataOut.Oblique_params = numpy.ones((1,4,dataOut.nHeights))*numpy.NAN
1542 dataOut.Oblique_param_errors = numpy.ones((1,4,dataOut.nHeights))*numpy.NAN
1542 dataOut.Oblique_param_errors = numpy.ones((1,4,dataOut.nHeights))*numpy.NAN
1543 dataOut.snr_log10 = numpy.ones((1,dataOut.nHeights))*numpy.NAN
1543 dataOut.snr_log10 = numpy.ones((1,dataOut.nHeights))*numpy.NAN
1544
1544
1545 dataOut.VelRange = x
1545 dataOut.VelRange = x
1546
1546
1547
1547
1548
1548
1549 #l1=range(22,36) #+62
1549 #l1=range(22,36) #+62
1550 #l1=range(32,36)
1550 #l1=range(32,36)
1551 #l2=range(58,99) #+62
1551 #l2=range(58,99) #+62
1552
1552
1553 #if Hmin1 == None or Hmax1 == None or Hmin2 == None or Hmax2 == None:
1553 #if Hmin1 == None or Hmax1 == None or Hmin2 == None or Hmax2 == None:
1554
1554
1555 minHei1 = 105.
1555 minHei1 = 105.
1556 maxHei1 = 122.5
1556 maxHei1 = 122.5
1557 maxHei1 = 130.5
1557 maxHei1 = 130.5
1558
1558
1559 if mode == 10: #150 km
1559 if mode == 10: #150 km
1560 minHei1 = 100
1560 minHei1 = 100
1561 maxHei1 = 100
1561 maxHei1 = 100
1562
1562
1563 inda1 = numpy.where(dataOut.heightList >= minHei1)
1563 inda1 = numpy.where(dataOut.heightList >= minHei1)
1564 indb1 = numpy.where(dataOut.heightList <= maxHei1)
1564 indb1 = numpy.where(dataOut.heightList <= maxHei1)
1565
1565
1566 minIndex1 = inda1[0][0]
1566 minIndex1 = inda1[0][0]
1567 maxIndex1 = indb1[0][-1]
1567 maxIndex1 = indb1[0][-1]
1568
1568
1569 minHei2 = 150.
1569 minHei2 = 150.
1570 maxHei2 = 201.25
1570 maxHei2 = 201.25
1571 maxHei2 = 225.3
1571 maxHei2 = 225.3
1572
1572
1573 if mode == 10: #150 km
1573 if mode == 10: #150 km
1574 minHei2 = 110
1574 minHei2 = 110
1575 maxHei2 = 165
1575 maxHei2 = 165
1576
1576
1577 inda2 = numpy.where(dataOut.heightList >= minHei2)
1577 inda2 = numpy.where(dataOut.heightList >= minHei2)
1578 indb2 = numpy.where(dataOut.heightList <= maxHei2)
1578 indb2 = numpy.where(dataOut.heightList <= maxHei2)
1579
1579
1580 minIndex2 = inda2[0][0]
1580 minIndex2 = inda2[0][0]
1581 maxIndex2 = indb2[0][-1]
1581 maxIndex2 = indb2[0][-1]
1582
1582
1583 l1=range(minIndex1,maxIndex1)
1583 l1=range(minIndex1,maxIndex1)
1584 l2=range(minIndex2,maxIndex2)
1584 l2=range(minIndex2,maxIndex2)
1585
1585
1586 if mode == 4:
1586 if mode == 4:
1587 '''
1587 '''
1588 for ind in range(dataOut.nHeights):
1588 for ind in range(dataOut.nHeights):
1589 if(dataOut.heightList[ind]>=168 and dataOut.heightList[ind]<188):
1589 if(dataOut.heightList[ind]>=168 and dataOut.heightList[ind]<188):
1590 try:
1590 try:
1591 dataOut.Oblique_params[0,0,ind],dataOut.Oblique_params[0,1,ind],dataOut.Oblique_params[0,2,ind],dataOut.Oblique_params[0,3,ind],dataOut.Oblique_params[0,4,ind],dataOut.Oblique_params[0,5,ind],dataOut.Oblique_params[0,6,ind],dataOut.Oblique_param_errors[0,0,ind],dataOut.Oblique_param_errors[0,1,ind],dataOut.Oblique_param_errors[0,2,ind],dataOut.Oblique_param_errors[0,3,ind],dataOut.Oblique_param_errors[0,4,ind],dataOut.Oblique_param_errors[0,5,ind],dataOut.Oblique_param_errors[0,6,ind] = self.DH_mode(dataOut.data_spc[0,:,ind],dataOut.VelRange)
1591 dataOut.Oblique_params[0,0,ind],dataOut.Oblique_params[0,1,ind],dataOut.Oblique_params[0,2,ind],dataOut.Oblique_params[0,3,ind],dataOut.Oblique_params[0,4,ind],dataOut.Oblique_params[0,5,ind],dataOut.Oblique_params[0,6,ind],dataOut.Oblique_param_errors[0,0,ind],dataOut.Oblique_param_errors[0,1,ind],dataOut.Oblique_param_errors[0,2,ind],dataOut.Oblique_param_errors[0,3,ind],dataOut.Oblique_param_errors[0,4,ind],dataOut.Oblique_param_errors[0,5,ind],dataOut.Oblique_param_errors[0,6,ind] = self.DH_mode(dataOut.data_spc[0,:,ind],dataOut.VelRange)
1592 except:
1592 except:
1593 pass
1593 pass
1594 '''
1594 '''
1595 for ind in itertools.chain(l1, l2):
1595 for ind in itertools.chain(l1, l2):
1596
1596
1597 try:
1597 try:
1598 dataOut.Oblique_params[0,0,ind],dataOut.Oblique_params[0,1,ind],dataOut.Oblique_params[0,2,ind],dataOut.Oblique_params[0,3,ind],dataOut.Oblique_params[0,4,ind],dataOut.Oblique_params[0,5,ind],dataOut.Oblique_params[0,6,ind],dataOut.Oblique_param_errors[0,0,ind],dataOut.Oblique_param_errors[0,1,ind],dataOut.Oblique_param_errors[0,2,ind],dataOut.Oblique_param_errors[0,3,ind],dataOut.Oblique_param_errors[0,4,ind],dataOut.Oblique_param_errors[0,5,ind],dataOut.Oblique_param_errors[0,6,ind] = self.DH_mode(dataOut.data_spc[0,:,ind],dataOut.VelRange)
1598 dataOut.Oblique_params[0,0,ind],dataOut.Oblique_params[0,1,ind],dataOut.Oblique_params[0,2,ind],dataOut.Oblique_params[0,3,ind],dataOut.Oblique_params[0,4,ind],dataOut.Oblique_params[0,5,ind],dataOut.Oblique_params[0,6,ind],dataOut.Oblique_param_errors[0,0,ind],dataOut.Oblique_param_errors[0,1,ind],dataOut.Oblique_param_errors[0,2,ind],dataOut.Oblique_param_errors[0,3,ind],dataOut.Oblique_param_errors[0,4,ind],dataOut.Oblique_param_errors[0,5,ind],dataOut.Oblique_param_errors[0,6,ind] = self.DH_mode(dataOut.data_spc[0,:,ind],dataOut.VelRange)
1599 dataOut.dplr_2_u[0,0,ind] = dataOut.Oblique_params[0,4,ind]/numpy.sin(numpy.arccos(102/dataOut.heightList[ind]))
1599 dataOut.dplr_2_u[0,0,ind] = dataOut.Oblique_params[0,4,ind]/numpy.sin(numpy.arccos(102/dataOut.heightList[ind]))
1600 except:
1600 except:
1601 pass
1601 pass
1602
1602
1603 else:
1603 else:
1604 for hei in itertools.chain(l1, l2):
1604 for hei in itertools.chain(l1, l2):
1605 if numpy.isnan(dataOut.snl[0,hei]) or dataOut.snl[0,hei]<.0:
1605 if numpy.isnan(dataOut.snl[0,hei]) or dataOut.snl[0,hei]<.0:
1606
1606
1607 continue #Avoids the analysis when there is only noise
1607 continue #Avoids the analysis when there is only noise
1608
1608
1609 try:
1609 try:
1610 spc = dataOut.data_spc[0,:,hei]
1610 spc = dataOut.data_spc[0,:,hei]
1611
1611
1612 if mode == 6: #Skew Weighted Bounded
1612 if mode == 6: #Skew Weighted Bounded
1613 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei] = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1613 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei] = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1614 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,8,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1614 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,8,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1615
1615
1616 elif mode == 7: #Triple Skew Weighted Bounded
1616 elif mode == 7: #Triple Skew Weighted Bounded
1617 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_params[0,11,hei],dataOut.Oblique_params[0,12,hei] = self.Triple_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1617 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_params[0,11,hei],dataOut.Oblique_params[0,12,hei] = self.Triple_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1618 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,12,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1618 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,12,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1619
1619
1620 elif mode == 8: #Double Skewed Weighted Bounded with inputs
1620 elif mode == 8: #Double Skewed Weighted Bounded with inputs
1621 a1, b1, c1, a2, b2, c2, k2, d, dopp = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1621 a1, b1, c1, a2, b2, c2, k2, d, dopp = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x)
1622 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei] = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x, a1, b1, c1, a2, b2, c2, k2, d)
1622 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei] = self.Double_Gauss_Skew_fit_weight_bound_no_inputs(spc,x, a1, b1, c1, a2, b2, c2, k2, d)
1623 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,9,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1623 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,9,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1624
1624
1625 elif mode == 9: #Double Skewed Weighted Bounded no inputs
1625 elif mode == 9: #Double Skewed Weighted Bounded no inputs
1626 #if numpy.max(spc) <= 0:
1626 #if numpy.max(spc) <= 0:
1627 from scipy.signal import medfilt
1627 from scipy.signal import medfilt
1628 spcm = medfilt(spc,11)
1628 spcm = medfilt(spc,11)
1629 if x[numpy.argmax(spcm)] <= 0:
1629 if x[numpy.argmax(spcm)] <= 0:
1630 #print("EEJ", dataOut.heightList[hei], hei)
1630 #print("EEJ", dataOut.heightList[hei], hei)
1631 #if hei != 70:
1631 #if hei != 70:
1632 #continue
1632 #continue
1633 #else:
1633 #else:
1634 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_param_errors[0,:,hei] = self.Double_Gauss_Double_Skew_fit_weight_bound_no_inputs(spcm,x,dataOut.nIncohInt,dataOut.heightList[hei])
1634 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_param_errors[0,:,hei] = self.Double_Gauss_Double_Skew_fit_weight_bound_no_inputs(spcm,x,dataOut.nIncohInt,dataOut.heightList[hei])
1635 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1635 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1636 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1636 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1637 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,10,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1637 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,10,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1638
1638
1639 else:
1639 else:
1640 #print("CEEJ")
1640 #print("CEEJ")
1641 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_param_errors[0,:,hei] = self.CEEJ_Skew_fit_weight_bound_no_inputs(spcm,x,dataOut.nIncohInt)
1641 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_params[0,7,hei],dataOut.Oblique_params[0,8,hei],dataOut.Oblique_params[0,9,hei],dataOut.Oblique_params[0,10,hei],dataOut.Oblique_param_errors[0,:,hei] = self.CEEJ_Skew_fit_weight_bound_no_inputs(spcm,x,dataOut.nIncohInt)
1642 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1642 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1643 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1643 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1644 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,10,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1644 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,10,hei]/numpy.sin(numpy.arccos(100./dataOut.heightList[hei]))
1645 elif mode == 11: #Double Weighted Bounded no inputs
1645 elif mode == 11: #Double Weighted Bounded no inputs
1646 #if numpy.max(spc) <= 0:
1646 #if numpy.max(spc) <= 0:
1647 from scipy.signal import medfilt
1647 from scipy.signal import medfilt
1648 spcm = medfilt(spc,11)
1648 spcm = medfilt(spc,11)
1649
1649
1650 if x[numpy.argmax(spcm)] <= 0:
1650 if x[numpy.argmax(spcm)] <= 0:
1651 #print("EEJ")
1651 #print("EEJ")
1652 #print("EEJ",dataOut.heightList[hei])
1652 #print("EEJ",dataOut.heightList[hei])
1653 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_param_errors[0,:,hei] = self.Double_Gauss_fit_weight_bound_no_inputs(spc,x,dataOut.nIncohInt)
1653 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_param_errors[0,:,hei] = self.Double_Gauss_fit_weight_bound_no_inputs(spc,x,dataOut.nIncohInt)
1654 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1654 #if dataOut.Oblique_params[0,-2,hei] < -500 or dataOut.Oblique_params[0,-2,hei] > 500 or dataOut.Oblique_params[0,-1,hei] < -500 or dataOut.Oblique_params[0,-1,hei] > 500:
1655 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1655 # dataOut.Oblique_params[0,:,hei] *= numpy.NAN
1656 else:
1656 else:
1657 #print("CEEJ",dataOut.heightList[hei])
1657 #print("CEEJ",dataOut.heightList[hei])
1658 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_param_errors[0,:,hei] = self.CEEJ_fit_weight_bound_no_inputs(spc,x,dataOut.nIncohInt)
1658 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_param_errors[0,:,hei] = self.CEEJ_fit_weight_bound_no_inputs(spc,x,dataOut.nIncohInt)
1659
1659
1660 elif mode == 10: #150km
1660 elif mode == 10: #150km
1661 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_param_errors[0,:,hei] = self.Simple_fit_bound(spc,x,dataOut.nIncohInt)
1661 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_param_errors[0,:,hei] = self.Simple_fit_bound(spc,x,dataOut.nIncohInt)
1662 snr = (dataOut.power[0,hei]*factor - dataOut.Oblique_params[0,3,hei])/dataOut.Oblique_params[0,3,hei]
1662 snr = (dataOut.power[0,hei]*factor - dataOut.Oblique_params[0,3,hei])/dataOut.Oblique_params[0,3,hei]
1663 dataOut.snr_log10[0,hei] = numpy.log10(snr)
1663 dataOut.snr_log10[0,hei] = numpy.log10(snr)
1664
1664
1665 else:
1665 else:
1666 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
1666 spc_fit, A1, B1, C1, D1 = self.Gauss_fit_2(spc,x,'first')
1667
1667
1668 spc_diff = spc - spc_fit
1668 spc_diff = spc - spc_fit
1669 spc_diff[spc_diff < 0] = 0
1669 spc_diff[spc_diff < 0] = 0
1670
1670
1671 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
1671 spc_fit_diff, A2, B2, C2, D2 = self.Gauss_fit_2(spc_diff,x,'second')
1672
1672
1673 D = (D1+D2)
1673 D = (D1+D2)
1674
1674
1675 if mode == 0: #Double Fit
1675 if mode == 0: #Double Fit
1676 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_param_errors[0,0,hei],dataOut.Oblique_param_errors[0,1,hei],dataOut.Oblique_param_errors[0,2,hei],dataOut.Oblique_param_errors[0,3,hei],dataOut.Oblique_param_errors[0,4,hei],dataOut.Oblique_param_errors[0,5,hei],dataOut.Oblique_param_errors[0,6,hei] = self.Double_Gauss_fit_2(spc,x,A1,B1,C1,A2,B2,C2,D)
1676 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei],dataOut.Oblique_param_errors[0,0,hei],dataOut.Oblique_param_errors[0,1,hei],dataOut.Oblique_param_errors[0,2,hei],dataOut.Oblique_param_errors[0,3,hei],dataOut.Oblique_param_errors[0,4,hei],dataOut.Oblique_param_errors[0,5,hei],dataOut.Oblique_param_errors[0,6,hei] = self.Double_Gauss_fit_2(spc,x,A1,B1,C1,A2,B2,C2,D)
1677 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
1677 #spc_double_fit,dataOut.Oblique_params = self.Double_Gauss_fit(spc,x,A1,B1,C1,A2,B2,C2,D)
1678
1678
1679 elif mode == 1: #Double Fit Windowed
1679 elif mode == 1: #Double Fit Windowed
1680 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei] = self.windowing_double(spc,dataOut.getFreqRange(0),A1,B1,C1,A2,B2,C2,D)
1680 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei] = self.windowing_double(spc,dataOut.getFreqRange(0),A1,B1,C1,A2,B2,C2,D)
1681
1681
1682 elif mode == 2: #Double Fit Weight
1682 elif mode == 2: #Double Fit Weight
1683 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei] = self.Double_Gauss_fit_weight(spc,x,A1,B1,C1,A2,B2,C2,D)
1683 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei] = self.Double_Gauss_fit_weight(spc,x,A1,B1,C1,A2,B2,C2,D)
1684
1684
1685 elif mode == 3: #Simple Fit
1685 elif mode == 3: #Simple Fit
1686 dataOut.Oblique_params[0,0,hei] = A1
1686 dataOut.Oblique_params[0,0,hei] = A1
1687 dataOut.Oblique_params[0,1,hei] = B1
1687 dataOut.Oblique_params[0,1,hei] = B1
1688 dataOut.Oblique_params[0,2,hei] = C1
1688 dataOut.Oblique_params[0,2,hei] = C1
1689 dataOut.Oblique_params[0,3,hei] = A2
1689 dataOut.Oblique_params[0,3,hei] = A2
1690 dataOut.Oblique_params[0,4,hei] = B2
1690 dataOut.Oblique_params[0,4,hei] = B2
1691 dataOut.Oblique_params[0,5,hei] = C2
1691 dataOut.Oblique_params[0,5,hei] = C2
1692 dataOut.Oblique_params[0,6,hei] = D
1692 dataOut.Oblique_params[0,6,hei] = D
1693
1693
1694 elif mode == 5: #Triple Fit Weight
1694 elif mode == 5: #Triple Fit Weight
1695 if hei in l1:
1695 if hei in l1:
1696 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei] = self.duo_Marco(spc,x,A1,B1,C1,A2,B2,C2,D)
1696 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei] = self.duo_Marco(spc,x,A1,B1,C1,A2,B2,C2,D)
1697 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,4,hei]/numpy.sin(numpy.arccos(102/dataOut.heightList[hei]))
1697 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,4,hei]/numpy.sin(numpy.arccos(102/dataOut.heightList[hei]))
1698 #print(dataOut.Oblique_params[0,0,hei])
1698 #print(dataOut.Oblique_params[0,0,hei])
1699 #print(dataOut.dplr_2_u[0,0,hei])
1699 #print(dataOut.dplr_2_u[0,0,hei])
1700 else:
1700 else:
1701 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei] = self.Double_Gauss_fit_weight(spc,x,A1,B1,C1,A2,B2,C2,D)
1701 dataOut.Oblique_params[0,0,hei],dataOut.Oblique_params[0,1,hei],dataOut.Oblique_params[0,2,hei],dataOut.Oblique_params[0,3,hei],dataOut.Oblique_params[0,4,hei],dataOut.Oblique_params[0,5,hei],dataOut.Oblique_params[0,6,hei] = self.Double_Gauss_fit_weight(spc,x,A1,B1,C1,A2,B2,C2,D)
1702 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,4,hei]/numpy.sin(numpy.arccos(102/dataOut.heightList[hei]))
1702 dataOut.dplr_2_u[0,0,hei] = dataOut.Oblique_params[0,4,hei]/numpy.sin(numpy.arccos(102/dataOut.heightList[hei]))
1703
1703
1704
1704
1705 except:
1705 except:
1706 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
1706 ###dataOut.Oblique_params[0,:,hei] = dataOut.Oblique_params[0,:,hei]*numpy.NAN
1707 pass
1707 pass
1708
1708
1709 #exit(1)
1709 #exit(1)
1710 dataOut.paramInterval = dataOut.nProfiles*dataOut.nCohInt*dataOut.ippSeconds
1710 dataOut.paramInterval = dataOut.nProfiles*dataOut.nCohInt*dataOut.ippSeconds
1711 dataOut.lat=-11.95
1711 dataOut.lat=-11.95
1712 dataOut.lon=-76.87
1712 dataOut.lon=-76.87
1713 '''
1713 '''
1714 dataOut.Oblique_params = numpy.where(dataOut.Oblique_params<-700, numpy.nan, dop_t1)
1714 dataOut.Oblique_params = numpy.where(dataOut.Oblique_params<-700, numpy.nan, dop_t1)
1715 dataOut.Oblique_params = numpy.where(dataOut.Oblique_params<+700, numpy.nan, dop_t1)
1715 dataOut.Oblique_params = numpy.where(dataOut.Oblique_params<+700, numpy.nan, dop_t1)
1716 AquΓ­ debo exceptuar las amplitudes
1716 AquΓ­ debo exceptuar las amplitudes
1717 '''
1717 '''
1718 if mode == 9: #Double Skew Gaussian
1718 if mode == 9: #Double Skew Gaussian
1719 #dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,-2,:] #Pos[Max_value]
1719 #dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,-2,:] #Pos[Max_value]
1720 #dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:] #Shift
1720 #dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:] #Shift
1721 dataOut.Spec_W_T1 = dataOut.Oblique_params[:,2,:]
1721 dataOut.Spec_W_T1 = dataOut.Oblique_params[:,2,:]
1722 #dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,-1,:] #Pos[Max_value]
1722 #dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,-1,:] #Pos[Max_value]
1723 #dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,5,:] #Shift
1723 #dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,5,:] #Shift
1724 dataOut.Spec_W_T2 = dataOut.Oblique_params[:,6,:]
1724 dataOut.Spec_W_T2 = dataOut.Oblique_params[:,6,:]
1725 if Dop == 'Shift':
1725 if Dop == 'Shift':
1726 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:] #Shift
1726 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:] #Shift
1727 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,5,:] #Shift
1727 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,5,:] #Shift
1728 elif Dop == 'Max':
1728 elif Dop == 'Max':
1729 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,-2,:] #Pos[Max_value]
1729 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,-2,:] #Pos[Max_value]
1730 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,-1,:] #Pos[Max_value]
1730 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,-1,:] #Pos[Max_value]
1731
1731
1732 dataOut.Err_Dop_EEJ_T1 = dataOut.Oblique_param_errors[:,1,:] #En realidad este es el error?
1732 dataOut.Err_Dop_EEJ_T1 = dataOut.Oblique_param_errors[:,1,:] #En realidad este es el error?
1733 dataOut.Err_Spec_W_T1 = dataOut.Oblique_param_errors[:,2,:]
1733 dataOut.Err_Spec_W_T1 = dataOut.Oblique_param_errors[:,2,:]
1734 dataOut.Err_Dop_EEJ_T2 = dataOut.Oblique_param_errors[:,5,:] #En realidad este es el error?
1734 dataOut.Err_Dop_EEJ_T2 = dataOut.Oblique_param_errors[:,5,:] #En realidad este es el error?
1735 dataOut.Err_Spec_W_T2 = dataOut.Oblique_param_errors[:,6,:]
1735 dataOut.Err_Spec_W_T2 = dataOut.Oblique_param_errors[:,6,:]
1736
1736
1737 elif mode == 11: #Double Gaussian
1737 elif mode == 11: #Double Gaussian
1738 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:]
1738 dataOut.Dop_EEJ_T1 = dataOut.Oblique_params[:,1,:]
1739 dataOut.Spec_W_T1 = dataOut.Oblique_params[:,2,:]
1739 dataOut.Spec_W_T1 = dataOut.Oblique_params[:,2,:]
1740 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,4,:]
1740 dataOut.Dop_EEJ_T2 = dataOut.Oblique_params[:,4,:]
1741 dataOut.Spec_W_T2 = dataOut.Oblique_params[:,5,:]
1741 dataOut.Spec_W_T2 = dataOut.Oblique_params[:,5,:]
1742
1742
1743 dataOut.Err_Dop_EEJ_T1 = dataOut.Oblique_param_errors[:,1,:]
1743 dataOut.Err_Dop_EEJ_T1 = dataOut.Oblique_param_errors[:,1,:]
1744 dataOut.Err_Spec_W_T1 = dataOut.Oblique_param_errors[:,2,:]
1744 dataOut.Err_Spec_W_T1 = dataOut.Oblique_param_errors[:,2,:]
1745 dataOut.Err_Dop_EEJ_T2 = dataOut.Oblique_param_errors[:,4,:]
1745 dataOut.Err_Dop_EEJ_T2 = dataOut.Oblique_param_errors[:,4,:]
1746 dataOut.Err_Spec_W_T2 = dataOut.Oblique_param_errors[:,5,:]
1746 dataOut.Err_Spec_W_T2 = dataOut.Oblique_param_errors[:,5,:]
1747
1747
1748 #print("Before: ", dataOut.Dop_EEJ_T2)
1748 #print("Before: ", dataOut.Dop_EEJ_T2)
1749 dataOut.Spec_W_T1 = self.clean_outliers(dataOut.Spec_W_T1)
1749 dataOut.Spec_W_T1 = self.clean_outliers(dataOut.Spec_W_T1)
1750 dataOut.Spec_W_T2 = self.clean_outliers(dataOut.Spec_W_T2)
1750 dataOut.Spec_W_T2 = self.clean_outliers(dataOut.Spec_W_T2)
1751 dataOut.Dop_EEJ_T1 = self.clean_outliers(dataOut.Dop_EEJ_T1)
1751 dataOut.Dop_EEJ_T1 = self.clean_outliers(dataOut.Dop_EEJ_T1)
1752 dataOut.Dop_EEJ_T2 = self.clean_outliers(dataOut.Dop_EEJ_T2)
1752 dataOut.Dop_EEJ_T2 = self.clean_outliers(dataOut.Dop_EEJ_T2)
1753 #print("After: ", dataOut.Dop_EEJ_T2)
1753 #print("After: ", dataOut.Dop_EEJ_T2)
1754 dataOut.Err_Spec_W_T1 = self.clean_outliers(dataOut.Err_Spec_W_T1)
1754 dataOut.Err_Spec_W_T1 = self.clean_outliers(dataOut.Err_Spec_W_T1)
1755 dataOut.Err_Spec_W_T2 = self.clean_outliers(dataOut.Err_Spec_W_T2)
1755 dataOut.Err_Spec_W_T2 = self.clean_outliers(dataOut.Err_Spec_W_T2)
1756 dataOut.Err_Dop_EEJ_T1 = self.clean_outliers(dataOut.Err_Dop_EEJ_T1)
1756 dataOut.Err_Dop_EEJ_T1 = self.clean_outliers(dataOut.Err_Dop_EEJ_T1)
1757 dataOut.Err_Dop_EEJ_T2 = self.clean_outliers(dataOut.Err_Dop_EEJ_T2)
1757 dataOut.Err_Dop_EEJ_T2 = self.clean_outliers(dataOut.Err_Dop_EEJ_T2)
1758 #print("Before data_snr: ", dataOut.data_snr)
1758 #print("Before data_snr: ", dataOut.data_snr)
1759 #dataOut.data_snr = numpy.where(numpy.isnan(dataOut.Dop_EEJ_T1), numpy.nan, dataOut.data_snr)
1759 #dataOut.data_snr = numpy.where(numpy.isnan(dataOut.Dop_EEJ_T1), numpy.nan, dataOut.data_snr)
1760 dataOut.snl = numpy.where(numpy.isnan(dataOut.Dop_EEJ_T1), numpy.nan, dataOut.snl)
1760 dataOut.snl = numpy.where(numpy.isnan(dataOut.Dop_EEJ_T1), numpy.nan, dataOut.snl)
1761
1761
1762 #print("After data_snr: ", dataOut.data_snr)
1762 #print("After data_snr: ", dataOut.data_snr)
1763 dataOut.mode = mode
1763 dataOut.mode = mode
1764 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.Dop_EEJ_T1)) #Si todos los valores son NaN no se prosigue
1764 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.Dop_EEJ_T1)) #Si todos los valores son NaN no se prosigue
1765 ###dataOut.flagNoData = False #Descomentar solo para ploteo sino mantener comentado (para guardado)
1765 ###dataOut.flagNoData = False #Descomentar solo para ploteo sino mantener comentado (para guardado)
1766
1766
1767 return dataOut
1767 return dataOut
1768
1768
1769 class Gaussian_Windowed(Operation):
1769 class Gaussian_Windowed(Operation):
1770 '''
1770 '''
1771 Written by R. Flores
1771 Written by R. Flores
1772 '''
1772 '''
1773 def __init__(self):
1773 def __init__(self):
1774 Operation.__init__(self)
1774 Operation.__init__(self)
1775
1775
1776 def windowing_single(self,spc,x,A,B,C,D,nFFTPoints):
1776 def windowing_single(self,spc,x,A,B,C,D,nFFTPoints):
1777 from scipy.optimize import curve_fit,fmin
1777 from scipy.optimize import curve_fit,fmin
1778
1778
1779 def gaussian(x, a, b, c, d):
1779 def gaussian(x, a, b, c, d):
1780 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
1780 val = a * numpy.exp(-(x - b)**2 / (2*c**2)) + d
1781 return val
1781 return val
1782
1782
1783 def R_gaussian(x, a, b, c):
1783 def R_gaussian(x, a, b, c):
1784 N = int(numpy.shape(x)[0])
1784 N = int(numpy.shape(x)[0])
1785 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
1785 val = a * numpy.exp(-((x)*c*2*2*numpy.pi)**2 / (2))* numpy.exp(1.j*b*x*4*numpy.pi)
1786 return val
1786 return val
1787
1787
1788 def T(x,N):
1788 def T(x,N):
1789 T = 1-abs(x)/N
1789 T = 1-abs(x)/N
1790 return T
1790 return T
1791
1791
1792 def R_T_spc_fun(x, a, b, c, d, nFFTPoints):
1792 def R_T_spc_fun(x, a, b, c, d, nFFTPoints):
1793
1793
1794 N = int(numpy.shape(x)[0])
1794 N = int(numpy.shape(x)[0])
1795
1795
1796 x_max = x[-1]
1796 x_max = x[-1]
1797
1797
1798 x_pos = x[nFFTPoints:]
1798 x_pos = x[nFFTPoints:]
1799 x_neg = x[:nFFTPoints]
1799 x_neg = x[:nFFTPoints]
1800 #print([int(nFFTPoints/2))
1800 #print([int(nFFTPoints/2))
1801 #print("x: ", x)
1801 #print("x: ", x)
1802 #print("x_neg: ", x_neg)
1802 #print("x_neg: ", x_neg)
1803 #print("x_pos: ", x_pos)
1803 #print("x_pos: ", x_pos)
1804
1804
1805
1805
1806 R_T_neg_1 = R_gaussian(x, a, b, c)[:nFFTPoints]*T(x_neg,-x[0])
1806 R_T_neg_1 = R_gaussian(x, a, b, c)[:nFFTPoints]*T(x_neg,-x[0])
1807 R_T_pos_1 = R_gaussian(x, a, b, c)[nFFTPoints:]*T(x_pos,x[-1])
1807 R_T_pos_1 = R_gaussian(x, a, b, c)[nFFTPoints:]*T(x_pos,x[-1])
1808 #print(T(x_pos,x[-1]),x_pos,x[-1])
1808 #print(T(x_pos,x[-1]),x_pos,x[-1])
1809 #print(R_T_neg_1.shape,R_T_pos_1.shape)
1809 #print(R_T_neg_1.shape,R_T_pos_1.shape)
1810 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
1810 R_T_sum_1 = R_T_pos_1 + R_T_neg_1
1811 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
1811 R_T_spc_1 = numpy.fft.fft(R_T_sum_1).real
1812 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
1812 R_T_spc_1 = numpy.fft.fftshift(R_T_spc_1)
1813 max_val_1 = numpy.max(R_T_spc_1)
1813 max_val_1 = numpy.max(R_T_spc_1)
1814 R_T_spc_1 = R_T_spc_1*a/max_val_1
1814 R_T_spc_1 = R_T_spc_1*a/max_val_1
1815
1815
1816 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
1816 R_T_d = d*numpy.fft.fftshift(signal.unit_impulse(N))
1817 R_T_d_neg = R_T_d[:nFFTPoints]*T(x_neg,-x[0])
1817 R_T_d_neg = R_T_d[:nFFTPoints]*T(x_neg,-x[0])
1818 R_T_d_pos = R_T_d[nFFTPoints:]*T(x_pos,x[-1])
1818 R_T_d_pos = R_T_d[nFFTPoints:]*T(x_pos,x[-1])
1819 R_T_d_sum = R_T_d_pos + R_T_d_neg
1819 R_T_d_sum = R_T_d_pos + R_T_d_neg
1820 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
1820 R_T_spc_3 = numpy.fft.fft(R_T_d_sum).real
1821 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
1821 R_T_spc_3 = numpy.fft.fftshift(R_T_spc_3)
1822
1822
1823 R_T_final = R_T_spc_1 + R_T_spc_3
1823 R_T_final = R_T_spc_1 + R_T_spc_3
1824
1824
1825 return R_T_final
1825 return R_T_final
1826
1826
1827 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
1827 y = spc#gaussian(x, a, meanY, sigmaY) + a*0.1*numpy.random.normal(0, 1, size=len(x))
1828
1828
1829 from scipy.stats import norm
1829 from scipy.stats import norm
1830 mean,std=norm.fit(spc)
1830 mean,std=norm.fit(spc)
1831
1831
1832 # estimate starting values from the data
1832 # estimate starting values from the data
1833 a = A
1833 a = A
1834 b = B
1834 b = B
1835 c = C#numpy.std(spc)
1835 c = C#numpy.std(spc)
1836 d = D
1836 d = D
1837 #'''
1837 #'''
1838 #ippSeconds = 250*20*1.e-6/3
1838 #ippSeconds = 250*20*1.e-6/3
1839
1839
1840 #x_t = ippSeconds * (numpy.arange(nFFTPoints) - nFFTPoints / 2.)
1840 #x_t = ippSeconds * (numpy.arange(nFFTPoints) - nFFTPoints / 2.)
1841
1841
1842 #x_t = numpy.linspace(x_t[0],x_t[-1],3200)
1842 #x_t = numpy.linspace(x_t[0],x_t[-1],3200)
1843 #print("x_t: ", x_t)
1843 #print("x_t: ", x_t)
1844 #print("nFFTPoints: ", nFFTPoints)
1844 #print("nFFTPoints: ", nFFTPoints)
1845 x_vel = numpy.linspace(x[0],x[-1],int(2*nFFTPoints))
1845 x_vel = numpy.linspace(x[0],x[-1],int(2*nFFTPoints))
1846 #print("x_vel: ", x_vel)
1846 #print("x_vel: ", x_vel)
1847 #x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
1847 #x_freq = numpy.fft.fftfreq(1600,d=ippSeconds)
1848 #x_freq = numpy.fft.fftshift(x_freq)
1848 #x_freq = numpy.fft.fftshift(x_freq)
1849 #'''
1849 #'''
1850 # define a least squares function to optimize
1850 # define a least squares function to optimize
1851 def minfunc(params):
1851 def minfunc(params):
1852 #print("y.shape: ", numpy.shape(y))
1852 #print("y.shape: ", numpy.shape(y))
1853 return sum((y-R_T_spc_fun(x_vel,params[0],params[1],params[2],params[3],nFFTPoints))**2/1)#y**2)
1853 return sum((y-R_T_spc_fun(x_vel,params[0],params[1],params[2],params[3],nFFTPoints))**2/1)#y**2)
1854
1854
1855 # fit
1855 # fit
1856
1856
1857 popt_full = fmin(minfunc,[a,b,c,d], disp=False)
1857 popt_full = fmin(minfunc,[a,b,c,d], disp=False)
1858 #print("nIter", popt_full[2])
1858 #print("nIter", popt_full[2])
1859 popt = popt_full#[0]
1859 popt = popt_full#[0]
1860
1860
1861 fun = gaussian(x, popt[0], popt[1], popt[2], popt[3])
1861 fun = gaussian(x, popt[0], popt[1], popt[2], popt[3])
1862
1862
1863 #return R_T_spc_fun(x_t,popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
1863 #return R_T_spc_fun(x_t,popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]), popt[0], popt[1], popt[2], popt[3], popt[4], popt[5], popt[6]
1864 return fun, popt[0], popt[1], popt[2], popt[3]
1864 return fun, popt[0], popt[1], popt[2], popt[3]
1865
1865
1866 def run(self, dataOut):
1866 def run(self, dataOut):
1867
1867
1868 from scipy.signal import medfilt
1868 from scipy.signal import medfilt
1869 import matplotlib.pyplot as plt
1869 import matplotlib.pyplot as plt
1870 dataOut.moments = numpy.ones((dataOut.nChannels,4,dataOut.nHeights))*numpy.NAN
1870 dataOut.moments = numpy.ones((dataOut.nChannels,4,dataOut.nHeights))*numpy.NAN
1871 dataOut.VelRange = dataOut.getVelRange(0)
1871 dataOut.VelRange = dataOut.getVelRange(0)
1872 for nChannel in range(dataOut.nChannels):
1872 for nChannel in range(dataOut.nChannels):
1873 for hei in range(dataOut.heightList.shape[0]):
1873 for hei in range(dataOut.heightList.shape[0]):
1874 #print("ipp: ", dataOut.ippSeconds)
1874 #print("ipp: ", dataOut.ippSeconds)
1875 spc = numpy.copy(dataOut.data_spc[nChannel,:,hei])
1875 spc = numpy.copy(dataOut.data_spc[nChannel,:,hei])
1876
1876
1877 #print(VelRange)
1877 #print(VelRange)
1878 #print(dataOut.getFreqRange(64))
1878 #print(dataOut.getFreqRange(64))
1879 spcm = medfilt(spc,11)
1879 spcm = medfilt(spc,11)
1880 spc_max = numpy.max(spcm)
1880 spc_max = numpy.max(spcm)
1881 dop1_x0 = dataOut.VelRange[numpy.argmax(spcm)]
1881 dop1_x0 = dataOut.VelRange[numpy.argmax(spcm)]
1882 D = numpy.min(spcm)
1882 D = numpy.min(spcm)
1883
1883
1884 fun, A, B, C, D = self.windowing_single(spc,dataOut.VelRange,spc_max,dop1_x0,abs(dop1_x0),D,dataOut.nFFTPoints)
1884 fun, A, B, C, D = self.windowing_single(spc,dataOut.VelRange,spc_max,dop1_x0,abs(dop1_x0),D,dataOut.nFFTPoints)
1885 dataOut.moments[nChannel,0,hei] = A
1885 dataOut.moments[nChannel,0,hei] = A
1886 dataOut.moments[nChannel,1,hei] = B
1886 dataOut.moments[nChannel,1,hei] = B
1887 dataOut.moments[nChannel,2,hei] = C
1887 dataOut.moments[nChannel,2,hei] = C
1888 dataOut.moments[nChannel,3,hei] = D
1888 dataOut.moments[nChannel,3,hei] = D
1889 '''
1889 '''
1890 plt.figure()
1890 plt.figure()
1891 plt.plot(VelRange,spc,marker='*',linestyle='')
1891 plt.plot(VelRange,spc,marker='*',linestyle='')
1892 plt.plot(VelRange,fun)
1892 plt.plot(VelRange,fun)
1893 plt.title(dataOut.heightList[hei])
1893 plt.title(dataOut.heightList[hei])
1894 plt.show()
1894 plt.show()
1895 '''
1895 '''
1896
1896
1897 return dataOut
1897 return dataOut
1898
1898
1899 class PrecipitationProc(Operation):
1899 class PrecipitationProc(Operation):
1900
1900
1901 '''
1901 '''
1902 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
1902 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
1903
1903
1904 Input:
1904 Input:
1905 self.dataOut.data_pre : SelfSpectra
1905 self.dataOut.data_pre : SelfSpectra
1906
1906
1907 Output:
1907 Output:
1908
1908
1909 self.dataOut.data_output : Reflectivity factor, rainfall Rate
1909 self.dataOut.data_output : Reflectivity factor, rainfall Rate
1910
1910
1911
1911
1912 Parameters affected:
1912 Parameters affected:
1913 '''
1913 '''
1914
1914
1915 def __init__(self):
1915 def __init__(self):
1916 Operation.__init__(self)
1916 Operation.__init__(self)
1917 self.i=0
1917 self.i=0
1918
1918
1919 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
1919 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
1920 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30,
1920 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30,
1921 channel=None):
1921 channel=None):
1922
1922
1923 # print ('Entering PrecepitationProc ... ')
1923 # print ('Entering PrecepitationProc ... ')
1924
1924
1925 if radar == "MIRA35C" :
1925 if radar == "MIRA35C" :
1926
1926
1927 self.spc = dataOut.data_pre[0].copy()
1927 self.spc = dataOut.data_pre[0].copy()
1928 self.Num_Hei = self.spc.shape[2]
1928 self.Num_Hei = self.spc.shape[2]
1929 self.Num_Bin = self.spc.shape[1]
1929 self.Num_Bin = self.spc.shape[1]
1930 self.Num_Chn = self.spc.shape[0]
1930 self.Num_Chn = self.spc.shape[0]
1931 Ze = self.dBZeMODE2(dataOut)
1931 Ze = self.dBZeMODE2(dataOut)
1932
1932
1933 else:
1933 else:
1934
1934
1935 self.spc = dataOut.data_pre[0].copy()
1935 self.spc = dataOut.data_pre[0].copy()
1936
1936
1937 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
1937 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
1938 self.spc[:,:,0:7]= numpy.NaN
1938 self.spc[:,:,0:7]= numpy.NaN
1939
1939
1940 self.Num_Hei = self.spc.shape[2]
1940 self.Num_Hei = self.spc.shape[2]
1941 self.Num_Bin = self.spc.shape[1]
1941 self.Num_Bin = self.spc.shape[1]
1942 self.Num_Chn = self.spc.shape[0]
1942 self.Num_Chn = self.spc.shape[0]
1943
1943
1944 VelRange = dataOut.spc_range[2]
1944 VelRange = dataOut.spc_range[2]
1945
1945
1946 ''' Se obtiene la constante del RADAR '''
1946 ''' Se obtiene la constante del RADAR '''
1947
1947
1948 self.Pt = Pt
1948 self.Pt = Pt
1949 self.Gt = Gt
1949 self.Gt = Gt
1950 self.Gr = Gr
1950 self.Gr = Gr
1951 self.Lambda = Lambda
1951 self.Lambda = Lambda
1952 self.aL = aL
1952 self.aL = aL
1953 self.tauW = tauW
1953 self.tauW = tauW
1954 self.ThetaT = ThetaT
1954 self.ThetaT = ThetaT
1955 self.ThetaR = ThetaR
1955 self.ThetaR = ThetaR
1956 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
1956 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
1957 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
1957 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
1958 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
1958 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
1959
1959
1960 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1960 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
1961 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
1961 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
1962 RadarConstant = 10e-26 * Numerator / Denominator #
1962 RadarConstant = 10e-26 * Numerator / Denominator #
1963 ExpConstant = 10**(40/10) #Constante Experimental
1963 ExpConstant = 10**(40/10) #Constante Experimental
1964
1964
1965 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
1965 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
1966 for i in range(self.Num_Chn):
1966 for i in range(self.Num_Chn):
1967 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
1967 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
1968 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
1968 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
1969
1969
1970 if channel is None:
1970 if channel is None:
1971 SPCmean = numpy.mean(SignalPower, 0)
1971 SPCmean = numpy.mean(SignalPower, 0)
1972 else:
1972 else:
1973 SPCmean = SignalPower[channel]
1973 SPCmean = SignalPower[channel]
1974 Pr = SPCmean[:,:]/dataOut.normFactor
1974 Pr = SPCmean[:,:]/dataOut.normFactor
1975
1975
1976 # Declaring auxiliary variables
1976 # Declaring auxiliary variables
1977 Range = dataOut.heightList*1000. #Range in m
1977 Range = dataOut.heightList*1000. #Range in m
1978 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
1978 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
1979 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
1979 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
1980 zMtrx = rMtrx+Altitude
1980 zMtrx = rMtrx+Altitude
1981 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
1981 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
1982 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
1982 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
1983
1983
1984 # height dependence to air density Foote and Du Toit (1969)
1984 # height dependence to air density Foote and Du Toit (1969)
1985 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
1985 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
1986 VMtrx = VelMtrx / delv_z #Normalized velocity
1986 VMtrx = VelMtrx / delv_z #Normalized velocity
1987 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
1987 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
1988 # Diameter is related to the fall speed of falling drops
1988 # Diameter is related to the fall speed of falling drops
1989 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
1989 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
1990 # Only valid for D>= 0.16 mm
1990 # Only valid for D>= 0.16 mm
1991 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
1991 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
1992
1992
1993 #Calculate Radar Reflectivity ETAn
1993 #Calculate Radar Reflectivity ETAn
1994 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
1994 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
1995 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
1995 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
1996 # Radar Cross Section
1996 # Radar Cross Section
1997 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
1997 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
1998 # Drop Size Distribution
1998 # Drop Size Distribution
1999 DSD = ETAn / sigmaD
1999 DSD = ETAn / sigmaD
2000 # Equivalente Reflectivy
2000 # Equivalente Reflectivy
2001 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
2001 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
2002 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
2002 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
2003 # RainFall Rate
2003 # RainFall Rate
2004 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
2004 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
2005
2005
2006 # Censoring the data
2006 # Censoring the data
2007 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
2007 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
2008 SNRth = 10**(SNRdBlimit/10) #-30dB
2008 SNRth = 10**(SNRdBlimit/10) #-30dB
2009 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
2009 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
2010 W = numpy.nanmean(dataOut.data_dop,0)
2010 W = numpy.nanmean(dataOut.data_dop,0)
2011 W[novalid] = numpy.NaN
2011 W[novalid] = numpy.NaN
2012 Ze_org[novalid] = numpy.NaN
2012 Ze_org[novalid] = numpy.NaN
2013 RR[novalid] = numpy.NaN
2013 RR[novalid] = numpy.NaN
2014
2014
2015 dataOut.data_output = RR[8]
2015 dataOut.data_output = RR[8]
2016 dataOut.data_param = numpy.ones([3,self.Num_Hei])
2016 dataOut.data_param = numpy.ones([3,self.Num_Hei])
2017 dataOut.channelList = [0,1,2]
2017 dataOut.channelList = [0,1,2]
2018
2018
2019 dataOut.data_param[0]=10*numpy.log10(Ze_org)
2019 dataOut.data_param[0]=10*numpy.log10(Ze_org)
2020 dataOut.data_param[1]=-W
2020 dataOut.data_param[1]=-W
2021 dataOut.data_param[2]=RR
2021 dataOut.data_param[2]=RR
2022
2022
2023 # print ('Leaving PrecepitationProc ... ')
2023 # print ('Leaving PrecepitationProc ... ')
2024 return dataOut
2024 return dataOut
2025
2025
2026 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
2026 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
2027
2027
2028 NPW = dataOut.NPW
2028 NPW = dataOut.NPW
2029 COFA = dataOut.COFA
2029 COFA = dataOut.COFA
2030
2030
2031 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
2031 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
2032 RadarConst = dataOut.RadarConst
2032 RadarConst = dataOut.RadarConst
2033 #frequency = 34.85*10**9
2033 #frequency = 34.85*10**9
2034
2034
2035 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
2035 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
2036 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
2036 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
2037
2037
2038 ETA = numpy.sum(SNR,1)
2038 ETA = numpy.sum(SNR,1)
2039
2039
2040 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
2040 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
2041
2041
2042 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
2042 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
2043
2043
2044 for r in range(self.Num_Hei):
2044 for r in range(self.Num_Hei):
2045
2045
2046 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
2046 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
2047 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
2047 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
2048
2048
2049 return Ze
2049 return Ze
2050
2050
2051 # def GetRadarConstant(self):
2051 # def GetRadarConstant(self):
2052 #
2052 #
2053 # """
2053 # """
2054 # Constants:
2054 # Constants:
2055 #
2055 #
2056 # Pt: Transmission Power dB 5kW 5000
2056 # Pt: Transmission Power dB 5kW 5000
2057 # Gt: Transmission Gain dB 24.7 dB 295.1209
2057 # Gt: Transmission Gain dB 24.7 dB 295.1209
2058 # Gr: Reception Gain dB 18.5 dB 70.7945
2058 # Gr: Reception Gain dB 18.5 dB 70.7945
2059 # Lambda: Wavelenght m 0.6741 m 0.6741
2059 # Lambda: Wavelenght m 0.6741 m 0.6741
2060 # aL: Attenuation loses dB 4dB 2.5118
2060 # aL: Attenuation loses dB 4dB 2.5118
2061 # tauW: Width of transmission pulse s 4us 4e-6
2061 # tauW: Width of transmission pulse s 4us 4e-6
2062 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
2062 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
2063 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
2063 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
2064 #
2064 #
2065 # """
2065 # """
2066 #
2066 #
2067 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
2067 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
2068 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
2068 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
2069 # RadarConstant = Numerator / Denominator
2069 # RadarConstant = Numerator / Denominator
2070 #
2070 #
2071 # return RadarConstant
2071 # return RadarConstant
2072
2072
2073
2073
2074 class FullSpectralAnalysis(Operation):
2074 class FullSpectralAnalysis(Operation):
2075
2075
2076 """
2076 """
2077 Function that implements Full Spectral Analysis technique.
2077 Function that implements Full Spectral Analysis technique.
2078
2078
2079 Input:
2079 Input:
2080 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
2080 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
2081 self.dataOut.groupList : Pairlist of channels
2081 self.dataOut.groupList : Pairlist of channels
2082 self.dataOut.ChanDist : Physical distance between receivers
2082 self.dataOut.ChanDist : Physical distance between receivers
2083
2083
2084
2084
2085 Output:
2085 Output:
2086
2086
2087 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
2087 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
2088
2088
2089
2089
2090 Parameters affected: Winds, height range, SNR
2090 Parameters affected: Winds, height range, SNR
2091
2091
2092 """
2092 """
2093 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
2093 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
2094 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
2094 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
2095
2095
2096 spc = dataOut.data_pre[0].copy()
2096 spc = dataOut.data_pre[0].copy()
2097 cspc = dataOut.data_pre[1]
2097 cspc = dataOut.data_pre[1]
2098 nHeights = spc.shape[2]
2098 nHeights = spc.shape[2]
2099
2099
2100 # first_height = 0.75 #km (ref: data header 20170822)
2100 # first_height = 0.75 #km (ref: data header 20170822)
2101 # resolution_height = 0.075 #km
2101 # resolution_height = 0.075 #km
2102 '''
2102 '''
2103 finding height range. check this when radar parameters are changed!
2103 finding height range. check this when radar parameters are changed!
2104 '''
2104 '''
2105 if maxheight is not None:
2105 if maxheight is not None:
2106 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
2106 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
2107 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
2107 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
2108 else:
2108 else:
2109 range_max = nHeights
2109 range_max = nHeights
2110 if minheight is not None:
2110 if minheight is not None:
2111 # range_min = int((minheight - first_height) / resolution_height) # theoretical
2111 # range_min = int((minheight - first_height) / resolution_height) # theoretical
2112 range_min = int(13.26 * minheight - 5) # empirical, works better
2112 range_min = int(13.26 * minheight - 5) # empirical, works better
2113 if range_min < 0:
2113 if range_min < 0:
2114 range_min = 0
2114 range_min = 0
2115 else:
2115 else:
2116 range_min = 0
2116 range_min = 0
2117
2117
2118 pairsList = dataOut.groupList
2118 pairsList = dataOut.groupList
2119 if dataOut.ChanDist is not None :
2119 if dataOut.ChanDist is not None :
2120 ChanDist = dataOut.ChanDist
2120 ChanDist = dataOut.ChanDist
2121 else:
2121 else:
2122 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
2122 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
2123
2123
2124 # 4 variables: zonal, meridional, vertical, and average SNR
2124 # 4 variables: zonal, meridional, vertical, and average SNR
2125 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
2125 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
2126 velocityX = numpy.zeros([nHeights]) * numpy.NaN
2126 velocityX = numpy.zeros([nHeights]) * numpy.NaN
2127 velocityY = numpy.zeros([nHeights]) * numpy.NaN
2127 velocityY = numpy.zeros([nHeights]) * numpy.NaN
2128 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
2128 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
2129
2129
2130 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
2130 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
2131
2131
2132 '''***********************************************WIND ESTIMATION**************************************'''
2132 '''***********************************************WIND ESTIMATION**************************************'''
2133 for Height in range(nHeights):
2133 for Height in range(nHeights):
2134
2134
2135 if Height >= range_min and Height < range_max:
2135 if Height >= range_min and Height < range_max:
2136 # error_code will be useful in future analysis
2136 # error_code will be useful in future analysis
2137 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
2137 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
2138 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
2138 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
2139
2139
2140 if abs(Vzon) < 100. and abs(Vmer) < 100.:
2140 if abs(Vzon) < 100. and abs(Vmer) < 100.:
2141 velocityX[Height] = Vzon
2141 velocityX[Height] = Vzon
2142 velocityY[Height] = -Vmer
2142 velocityY[Height] = -Vmer
2143 velocityZ[Height] = Vver
2143 velocityZ[Height] = Vver
2144
2144
2145 # Censoring data with SNR threshold
2145 # Censoring data with SNR threshold
2146 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
2146 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
2147
2147
2148 data_param[0] = velocityX
2148 data_param[0] = velocityX
2149 data_param[1] = velocityY
2149 data_param[1] = velocityY
2150 data_param[2] = velocityZ
2150 data_param[2] = velocityZ
2151 data_param[3] = dbSNR
2151 data_param[3] = dbSNR
2152 dataOut.data_param = data_param
2152 dataOut.data_param = data_param
2153 return dataOut
2153 return dataOut
2154
2154
2155 def moving_average(self,x, N=2):
2155 def moving_average(self,x, N=2):
2156 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
2156 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
2157 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
2157 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
2158
2158
2159 def gaus(self,xSamples,Amp,Mu,Sigma):
2159 def gaus(self,xSamples,Amp,Mu,Sigma):
2160 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
2160 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
2161
2161
2162 def Moments(self, ySamples, xSamples):
2162 def Moments(self, ySamples, xSamples):
2163 Power = numpy.nanmean(ySamples) # Power, 0th Moment
2163 Power = numpy.nanmean(ySamples) # Power, 0th Moment
2164 yNorm = ySamples / numpy.nansum(ySamples)
2164 yNorm = ySamples / numpy.nansum(ySamples)
2165 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
2165 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
2166 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
2166 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
2167 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
2167 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
2168 return numpy.array([Power,RadVel,StdDev])
2168 return numpy.array([Power,RadVel,StdDev])
2169
2169
2170 def StopWindEstimation(self, error_code):
2170 def StopWindEstimation(self, error_code):
2171 Vzon = numpy.NaN
2171 Vzon = numpy.NaN
2172 Vmer = numpy.NaN
2172 Vmer = numpy.NaN
2173 Vver = numpy.NaN
2173 Vver = numpy.NaN
2174 return Vzon, Vmer, Vver, error_code
2174 return Vzon, Vmer, Vver, error_code
2175
2175
2176 def AntiAliasing(self, interval, maxstep):
2176 def AntiAliasing(self, interval, maxstep):
2177 """
2177 """
2178 function to prevent errors from aliased values when computing phaseslope
2178 function to prevent errors from aliased values when computing phaseslope
2179 """
2179 """
2180 antialiased = numpy.zeros(len(interval))
2180 antialiased = numpy.zeros(len(interval))
2181 copyinterval = interval.copy()
2181 copyinterval = interval.copy()
2182
2182
2183 antialiased[0] = copyinterval[0]
2183 antialiased[0] = copyinterval[0]
2184
2184
2185 for i in range(1,len(antialiased)):
2185 for i in range(1,len(antialiased)):
2186 step = interval[i] - interval[i-1]
2186 step = interval[i] - interval[i-1]
2187 if step > maxstep:
2187 if step > maxstep:
2188 copyinterval -= 2*numpy.pi
2188 copyinterval -= 2*numpy.pi
2189 antialiased[i] = copyinterval[i]
2189 antialiased[i] = copyinterval[i]
2190 elif step < maxstep*(-1):
2190 elif step < maxstep*(-1):
2191 copyinterval += 2*numpy.pi
2191 copyinterval += 2*numpy.pi
2192 antialiased[i] = copyinterval[i]
2192 antialiased[i] = copyinterval[i]
2193 else:
2193 else:
2194 antialiased[i] = copyinterval[i].copy()
2194 antialiased[i] = copyinterval[i].copy()
2195
2195
2196 return antialiased
2196 return antialiased
2197
2197
2198 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
2198 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
2199 """
2199 """
2200 Function that Calculates Zonal, Meridional and Vertical wind velocities.
2200 Function that Calculates Zonal, Meridional and Vertical wind velocities.
2201 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
2201 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
2202
2202
2203 Input:
2203 Input:
2204 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
2204 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
2205 pairsList : Pairlist of channels
2205 pairsList : Pairlist of channels
2206 ChanDist : array of xi_ij and eta_ij
2206 ChanDist : array of xi_ij and eta_ij
2207 Height : height at which data is processed
2207 Height : height at which data is processed
2208 noise : noise in [channels] format for specific height
2208 noise : noise in [channels] format for specific height
2209 Abbsisarange : range of the frequencies or velocities
2209 Abbsisarange : range of the frequencies or velocities
2210 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
2210 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
2211
2211
2212 Output:
2212 Output:
2213 Vzon, Vmer, Vver : wind velocities
2213 Vzon, Vmer, Vver : wind velocities
2214 error_code : int that states where code is terminated
2214 error_code : int that states where code is terminated
2215
2215
2216 0 : no error detected
2216 0 : no error detected
2217 1 : Gaussian of mean spc exceeds widthlimit
2217 1 : Gaussian of mean spc exceeds widthlimit
2218 2 : no Gaussian of mean spc found
2218 2 : no Gaussian of mean spc found
2219 3 : SNR to low or velocity to high -> prec. e.g.
2219 3 : SNR to low or velocity to high -> prec. e.g.
2220 4 : at least one Gaussian of cspc exceeds widthlimit
2220 4 : at least one Gaussian of cspc exceeds widthlimit
2221 5 : zero out of three cspc Gaussian fits converged
2221 5 : zero out of three cspc Gaussian fits converged
2222 6 : phase slope fit could not be found
2222 6 : phase slope fit could not be found
2223 7 : arrays used to fit phase have different length
2223 7 : arrays used to fit phase have different length
2224 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
2224 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
2225
2225
2226 """
2226 """
2227
2227
2228 error_code = 0
2228 error_code = 0
2229
2229
2230 nChan = spc.shape[0]
2230 nChan = spc.shape[0]
2231 nProf = spc.shape[1]
2231 nProf = spc.shape[1]
2232 nPair = cspc.shape[0]
2232 nPair = cspc.shape[0]
2233
2233
2234 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
2234 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
2235 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
2235 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
2236 phase = numpy.zeros([nPair, nProf]) # phase between channels
2236 phase = numpy.zeros([nPair, nProf]) # phase between channels
2237 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
2237 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
2238 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
2238 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
2239 xFrec = AbbsisaRange[0][:-1] # frequency range
2239 xFrec = AbbsisaRange[0][:-1] # frequency range
2240 xVel = AbbsisaRange[2][:-1] # velocity range
2240 xVel = AbbsisaRange[2][:-1] # velocity range
2241 xSamples = xFrec # the frequency range is taken
2241 xSamples = xFrec # the frequency range is taken
2242 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
2242 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
2243
2243
2244 # only consider velocities with in NegativeLimit and PositiveLimit
2244 # only consider velocities with in NegativeLimit and PositiveLimit
2245 if (NegativeLimit is None):
2245 if (NegativeLimit is None):
2246 NegativeLimit = numpy.min(xVel)
2246 NegativeLimit = numpy.min(xVel)
2247 if (PositiveLimit is None):
2247 if (PositiveLimit is None):
2248 PositiveLimit = numpy.max(xVel)
2248 PositiveLimit = numpy.max(xVel)
2249 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
2249 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
2250 xSamples_zoom = xSamples[xvalid]
2250 xSamples_zoom = xSamples[xvalid]
2251
2251
2252 '''Getting Eij and Nij'''
2252 '''Getting Eij and Nij'''
2253 Xi01, Xi02, Xi12 = ChanDist[:,0]
2253 Xi01, Xi02, Xi12 = ChanDist[:,0]
2254 Eta01, Eta02, Eta12 = ChanDist[:,1]
2254 Eta01, Eta02, Eta12 = ChanDist[:,1]
2255
2255
2256 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
2256 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
2257 widthlimit = 10
2257 widthlimit = 10
2258 '''************************* SPC is normalized ********************************'''
2258 '''************************* SPC is normalized ********************************'''
2259 spc_norm = spc.copy()
2259 spc_norm = spc.copy()
2260 # For each channel
2260 # For each channel
2261 for i in range(nChan):
2261 for i in range(nChan):
2262 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
2262 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
2263 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
2263 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
2264
2264
2265 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
2265 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
2266
2266
2267 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
2267 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
2268 you only fit the curve and don't need the absolute value of height for calculation,
2268 you only fit the curve and don't need the absolute value of height for calculation,
2269 only for estimation of width. for normalization of cross spectra, you need initial,
2269 only for estimation of width. for normalization of cross spectra, you need initial,
2270 unnormalized self-spectra With noise.
2270 unnormalized self-spectra With noise.
2271
2271
2272 Technically, you don't even need to normalize the self-spectra, as you only need the
2272 Technically, you don't even need to normalize the self-spectra, as you only need the
2273 width of the peak. However, it was left this way. Note that the normalization has a flaw:
2273 width of the peak. However, it was left this way. Note that the normalization has a flaw:
2274 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
2274 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
2275 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
2275 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
2276 """
2276 """
2277 # initial conditions
2277 # initial conditions
2278 popt = [1e-10,0,1e-10]
2278 popt = [1e-10,0,1e-10]
2279 # Spectra average
2279 # Spectra average
2280 SPCMean = numpy.average(SPC_Samples,0)
2280 SPCMean = numpy.average(SPC_Samples,0)
2281 # Moments in frequency
2281 # Moments in frequency
2282 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
2282 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
2283
2283
2284 # Gauss Fit SPC in frequency domain
2284 # Gauss Fit SPC in frequency domain
2285 if dbSNR > SNRlimit: # only if SNR > SNRth
2285 if dbSNR > SNRlimit: # only if SNR > SNRth
2286 try:
2286 try:
2287 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
2287 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
2288 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
2288 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
2289 return self.StopWindEstimation(error_code = 1)
2289 return self.StopWindEstimation(error_code = 1)
2290 FitGauss = self.gaus(xSamples_zoom,*popt)
2290 FitGauss = self.gaus(xSamples_zoom,*popt)
2291 except :#RuntimeError:
2291 except :#RuntimeError:
2292 return self.StopWindEstimation(error_code = 2)
2292 return self.StopWindEstimation(error_code = 2)
2293 else:
2293 else:
2294 return self.StopWindEstimation(error_code = 3)
2294 return self.StopWindEstimation(error_code = 3)
2295
2295
2296 '''***************************** CSPC Normalization *************************
2296 '''***************************** CSPC Normalization *************************
2297 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
2297 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
2298 influence the norm which is not desired. First, a range is identified where the
2298 influence the norm which is not desired. First, a range is identified where the
2299 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
2299 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
2300 around it gets cut off and values replaced by mean determined by the boundary
2300 around it gets cut off and values replaced by mean determined by the boundary
2301 data -> sum_noise (spc is not normalized here, thats why the noise is important)
2301 data -> sum_noise (spc is not normalized here, thats why the noise is important)
2302
2302
2303 The sums are then added and multiplied by range/datapoints, because you need
2303 The sums are then added and multiplied by range/datapoints, because you need
2304 an integral and not a sum for normalization.
2304 an integral and not a sum for normalization.
2305
2305
2306 A norm is found according to Briggs 92.
2306 A norm is found according to Briggs 92.
2307 '''
2307 '''
2308 # for each pair
2308 # for each pair
2309 for i in range(nPair):
2309 for i in range(nPair):
2310 cspc_norm = cspc[i,:].copy()
2310 cspc_norm = cspc[i,:].copy()
2311 chan_index0 = pairsList[i][0]
2311 chan_index0 = pairsList[i][0]
2312 chan_index1 = pairsList[i][1]
2312 chan_index1 = pairsList[i][1]
2313 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
2313 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
2314 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
2314 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
2315
2315
2316 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
2316 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
2317 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
2317 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
2318 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
2318 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
2319
2319
2320 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
2320 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
2321 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
2321 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
2322
2322
2323 '''*******************************FIT GAUSS CSPC************************************'''
2323 '''*******************************FIT GAUSS CSPC************************************'''
2324 try:
2324 try:
2325 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
2325 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
2326 if popt01[2] > widthlimit: # CONDITION
2326 if popt01[2] > widthlimit: # CONDITION
2327 return self.StopWindEstimation(error_code = 4)
2327 return self.StopWindEstimation(error_code = 4)
2328 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
2328 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
2329 if popt02[2] > widthlimit: # CONDITION
2329 if popt02[2] > widthlimit: # CONDITION
2330 return self.StopWindEstimation(error_code = 4)
2330 return self.StopWindEstimation(error_code = 4)
2331 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
2331 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
2332 if popt12[2] > widthlimit: # CONDITION
2332 if popt12[2] > widthlimit: # CONDITION
2333 return self.StopWindEstimation(error_code = 4)
2333 return self.StopWindEstimation(error_code = 4)
2334
2334
2335 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
2335 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
2336 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
2336 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
2337 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
2337 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
2338 except:
2338 except:
2339 return self.StopWindEstimation(error_code = 5)
2339 return self.StopWindEstimation(error_code = 5)
2340
2340
2341
2341
2342 '''************* Getting Fij ***************'''
2342 '''************* Getting Fij ***************'''
2343 # x-axis point of the gaussian where the center is located from GaussFit of spectra
2343 # x-axis point of the gaussian where the center is located from GaussFit of spectra
2344 GaussCenter = popt[1]
2344 GaussCenter = popt[1]
2345 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
2345 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
2346 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
2346 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
2347
2347
2348 # Point where e^-1 is located in the gaussian
2348 # Point where e^-1 is located in the gaussian
2349 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
2349 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
2350 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
2350 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
2351 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
2351 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
2352 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
2352 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
2353
2353
2354 '''********** Taking frequency ranges from mean SPCs **********'''
2354 '''********** Taking frequency ranges from mean SPCs **********'''
2355 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
2355 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
2356 Range = numpy.empty(2)
2356 Range = numpy.empty(2)
2357 Range[0] = GaussCenter - GauWidth
2357 Range[0] = GaussCenter - GauWidth
2358 Range[1] = GaussCenter + GauWidth
2358 Range[1] = GaussCenter + GauWidth
2359 # Point in x-axis where the bandwidth is located (min:max)
2359 # Point in x-axis where the bandwidth is located (min:max)
2360 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
2360 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
2361 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
2361 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
2362 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
2362 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
2363 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
2363 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
2364 Range = numpy.array([ PointRangeMin, PointRangeMax ])
2364 Range = numpy.array([ PointRangeMin, PointRangeMax ])
2365 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
2365 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
2366
2366
2367 '''************************** Getting Phase Slope ***************************'''
2367 '''************************** Getting Phase Slope ***************************'''
2368 for i in range(nPair):
2368 for i in range(nPair):
2369 if len(FrecRange) > 5:
2369 if len(FrecRange) > 5:
2370 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
2370 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
2371 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
2371 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
2372 if len(FrecRange) == len(PhaseRange):
2372 if len(FrecRange) == len(PhaseRange):
2373 try:
2373 try:
2374 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
2374 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
2375 PhaseSlope[i] = slope
2375 PhaseSlope[i] = slope
2376 PhaseInter[i] = intercept
2376 PhaseInter[i] = intercept
2377 except:
2377 except:
2378 return self.StopWindEstimation(error_code = 6)
2378 return self.StopWindEstimation(error_code = 6)
2379 else:
2379 else:
2380 return self.StopWindEstimation(error_code = 7)
2380 return self.StopWindEstimation(error_code = 7)
2381 else:
2381 else:
2382 return self.StopWindEstimation(error_code = 8)
2382 return self.StopWindEstimation(error_code = 8)
2383
2383
2384 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
2384 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
2385
2385
2386 '''Getting constant C'''
2386 '''Getting constant C'''
2387 cC=(Fij*numpy.pi)**2
2387 cC=(Fij*numpy.pi)**2
2388
2388
2389 '''****** Getting constants F and G ******'''
2389 '''****** Getting constants F and G ******'''
2390 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
2390 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
2391 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
2391 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
2392 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
2392 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
2393 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
2393 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
2394 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
2394 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
2395 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
2395 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
2396 MijResults = numpy.array([MijResult1, MijResult2])
2396 MijResults = numpy.array([MijResult1, MijResult2])
2397 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
2397 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
2398
2398
2399 '''****** Getting constants A, B and H ******'''
2399 '''****** Getting constants A, B and H ******'''
2400 W01 = numpy.nanmax( FitGauss01 )
2400 W01 = numpy.nanmax( FitGauss01 )
2401 W02 = numpy.nanmax( FitGauss02 )
2401 W02 = numpy.nanmax( FitGauss02 )
2402 W12 = numpy.nanmax( FitGauss12 )
2402 W12 = numpy.nanmax( FitGauss12 )
2403
2403
2404 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
2404 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
2405 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
2405 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
2406 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
2406 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
2407 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
2407 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
2408
2408
2409 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
2409 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
2410 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
2410 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
2411
2411
2412 VxVy = numpy.array([[cA,cH],[cH,cB]])
2412 VxVy = numpy.array([[cA,cH],[cH,cB]])
2413 VxVyResults = numpy.array([-cF,-cG])
2413 VxVyResults = numpy.array([-cF,-cG])
2414 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
2414 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
2415 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
2415 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
2416 error_code = 0
2416 error_code = 0
2417
2417
2418 return Vzon, Vmer, Vver, error_code
2418 return Vzon, Vmer, Vver, error_code
2419
2419
2420 class SpectralMoments(Operation):
2420 class SpectralMoments(Operation):
2421
2421
2422 '''
2422 '''
2423 Function SpectralMoments()
2423 Function SpectralMoments()
2424
2424
2425 Calculates moments (power, mean, standard deviation) and SNR of the signal
2425 Calculates moments (power, mean, standard deviation) and SNR of the signal
2426
2426
2427 Type of dataIn: Spectra
2427 Type of dataIn: Spectra
2428
2428
2429 Configuration Parameters:
2429 Configuration Parameters:
2430
2430
2431 dirCosx : Cosine director in X axis
2431 dirCosx : Cosine director in X axis
2432 dirCosy : Cosine director in Y axis
2432 dirCosy : Cosine director in Y axis
2433
2433
2434 elevation :
2434 elevation :
2435 azimuth :
2435 azimuth :
2436
2436
2437 Input:
2437 Input:
2438 channelList : simple channel list to select e.g. [2,3,7]
2438 channelList : simple channel list to select e.g. [2,3,7]
2439 self.dataOut.data_pre : Spectral data
2439 self.dataOut.data_pre : Spectral data
2440 self.dataOut.abscissaList : List of frequencies
2440 self.dataOut.abscissaList : List of frequencies
2441 self.dataOut.noise : Noise level per channel
2441 self.dataOut.noise : Noise level per channel
2442
2442
2443 Affected:
2443 Affected:
2444 self.dataOut.moments : Parameters per channel
2444 self.dataOut.moments : Parameters per channel
2445 self.dataOut.data_snr : SNR per channel
2445 self.dataOut.data_snr : SNR per channel
2446
2446
2447 '''
2447 '''
2448
2448
2449 def run(self, dataOut, proc_type=0):
2449 def run(self, dataOut, proc_type=0):
2450
2450
2451 absc = dataOut.abscissaList[:-1]
2451 absc = dataOut.abscissaList[:-1]
2452 nChannel = dataOut.data_pre[0].shape[0]
2452 nChannel = dataOut.data_pre[0].shape[0]
2453 nHei = dataOut.data_pre[0].shape[2]
2453 nHei = dataOut.data_pre[0].shape[2]
2454 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
2454 data_param = numpy.zeros((nChannel, 4 + proc_type*3, nHei))
2455
2455
2456 if proc_type == 1:
2456 if proc_type == 1:
2457 fwindow = numpy.zeros(absc.size) + 1
2457 fwindow = numpy.zeros(absc.size) + 1
2458 b=64
2458 b=64
2459 #b=16
2459 #b=16
2460 fwindow[0:absc.size//2 - b] = 0
2460 fwindow[0:absc.size//2 - b] = 0
2461 fwindow[absc.size//2 + b:] = 0
2461 fwindow[absc.size//2 + b:] = 0
2462 type1 = 1 # moments calculation & gaussean fitting
2462 type1 = 1 # moments calculation & gaussean fitting
2463 nProfiles = dataOut.nProfiles
2463 nProfiles = dataOut.nProfiles
2464 nCohInt = dataOut.nCohInt
2464 nCohInt = dataOut.nCohInt
2465 nIncohInt = dataOut.nIncohInt
2465 nIncohInt = dataOut.nIncohInt
2466 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
2466 M = numpy.power(numpy.array(1/(nProfiles * nCohInt) ,dtype='float32'),2)
2467 N = numpy.array(M / nIncohInt,dtype='float32')
2467 N = numpy.array(M / nIncohInt,dtype='float32')
2468 data = dataOut.data_pre[0] * N
2468 data = dataOut.data_pre[0] * N
2469 #noise = dataOut.noise * N
2469 #noise = dataOut.noise * N
2470 noise = numpy.zeros(nChannel)
2470 noise = numpy.zeros(nChannel)
2471 for ind in range(nChannel):
2471 for ind in range(nChannel):
2472 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
2472 noise[ind] = self.__NoiseByChannel(nProfiles, nIncohInt, data[ind,:,:])
2473 smooth=3
2473 smooth=3
2474 else:
2474 else:
2475 data = dataOut.data_pre[0]
2475 data = dataOut.data_pre[0]
2476 noise = dataOut.noise
2476 noise = dataOut.noise
2477 fwindow = None
2477 fwindow = None
2478 type1 = 0
2478 type1 = 0
2479 nIncohInt = None
2479 nIncohInt = None
2480 smooth=None
2480 smooth=None
2481
2481
2482 for ind in range(nChannel):
2482 for ind in range(nChannel):
2483 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, id_ch=ind)
2483 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind], nicoh=nIncohInt, smooth=smooth, type1=type1, fwindow=fwindow, id_ch=ind)
2484
2484
2485 if proc_type == 1:
2485 if proc_type == 1:
2486 dataOut.moments = data_param[:,1:,:]
2486 dataOut.moments = data_param[:,1:,:]
2487 dataOut.data_dop = data_param[:,2]
2487 dataOut.data_dop = data_param[:,2]
2488 dataOut.data_width = data_param[:,1]
2488 dataOut.data_width = data_param[:,1]
2489 dataOut.data_snr = data_param[:,0]
2489 dataOut.data_snr = data_param[:,0]
2490 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
2490 dataOut.data_pow = data_param[:,6] # to compare with type0 proccessing
2491 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
2491 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, data_param[:,3], data_param[:,4],data_param[:,5]),axis=2)
2492 else:
2492 else:
2493 dataOut.moments = data_param[:,1:,:]
2493 dataOut.moments = data_param[:,1:,:]
2494 dataOut.data_snr = data_param[:,0]
2494 dataOut.data_snr = data_param[:,0]
2495 dataOut.data_pow = data_param[:,1]
2495 dataOut.data_pow = data_param[:,1]
2496 dataOut.data_dop = data_param[:,2]
2496 dataOut.data_dop = data_param[:,2]
2497 dataOut.data_width = data_param[:,3]
2497 dataOut.data_width = data_param[:,3]
2498 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
2498 dataOut.spcpar=numpy.stack((dataOut.data_dop,dataOut.data_width,dataOut.data_snr, dataOut.data_pow),axis=2)
2499
2499
2500 return dataOut
2500 return dataOut
2501
2501
2502 def __calculateMoments(self, oldspec, oldfreq, n0, normFactor = 1,
2502 def __calculateMoments(self, oldspec, oldfreq, n0, normFactor = 1,
2503 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None,id_ch=0):
2503 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None,id_ch=0):
2504
2504
2505 def __GAUSSWINFIT1(A, flagPDER=0):
2505 def __GAUSSWINFIT1(A, flagPDER=0):
2506 nonlocal truex, xvalid
2506 nonlocal truex, xvalid
2507 nparams = 4
2507 nparams = 4
2508 M=truex.size
2508 M=truex.size
2509 mm=numpy.arange(M,dtype='f4')
2509 mm=numpy.arange(M,dtype='f4')
2510 delta = numpy.zeros(M,dtype='f4')
2510 delta = numpy.zeros(M,dtype='f4')
2511 delta[0] = 1.0
2511 delta[0] = 1.0
2512 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
2512 Ts = numpy.array([1.0/(2*truex[0])],dtype='f4')[0]
2513 jj = -1j
2513 jj = -1j
2514 #if self.winauto is None: self.winauto = (1.0 - mm/M)
2514 #if self.winauto is None: self.winauto = (1.0 - mm/M)
2515 winauto = (1.0 - mm/M)
2515 winauto = (1.0 - mm/M)
2516 winauto = winauto/winauto.max() # Normalized to 1
2516 winauto = winauto/winauto.max() # Normalized to 1
2517 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
2517 #ON_ERROR,2 # IDL sentence: Return to caller if an error occurs
2518 A[0] = numpy.abs(A[0])
2518 A[0] = numpy.abs(A[0])
2519 A[2] = numpy.abs(A[2])
2519 A[2] = numpy.abs(A[2])
2520 A[3] = numpy.abs(A[3])
2520 A[3] = numpy.abs(A[3])
2521 pi=numpy.array([numpy.pi],dtype='f4')[0]
2521 pi=numpy.array([numpy.pi],dtype='f4')[0]
2522 if A[2] != 0:
2522 if A[2] != 0:
2523 Z = numpy.exp(-2*numpy.power((pi*A[2]*mm*Ts),2,dtype='f4')+jj*2*pi*A[1]*mm*Ts, dtype='c8') # Get Z
2523 Z = numpy.exp(-2*numpy.power((pi*A[2]*mm*Ts),2,dtype='f4')+jj*2*pi*A[1]*mm*Ts, dtype='c8') # Get Z
2524 else:
2524 else:
2525 Z = mm*0.0
2525 Z = mm*0.0
2526 A[0] = 0.0
2526 A[0] = 0.0
2527 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
2527 junkF = numpy.roll(2*fft(winauto*(A[0]*Z+A[3]*delta)).real - \
2528 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
2528 winauto[0]*(A[0]+A[3]), M//2) # *M scale for fft not needed in python
2529 F = junkF[xvalid]
2529 F = junkF[xvalid]
2530 if flagPDER == 0: #NEED PARTIAL?
2530 if flagPDER == 0: #NEED PARTIAL?
2531 return F
2531 return F
2532 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
2532 PDER = numpy.zeros((M,nparams)) #YES, MAKE ARRAY.
2533 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
2533 PDER[:,0] = numpy.shift(2*(fft(winauto*Z)*M) - winauto[0], M/2)
2534 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
2534 PDER[:,1] = numpy.shift(2*(fft(winauto*jj*2*numpy.pi*mm*Ts*A[0]*Z)*M), M/2)
2535 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
2535 PDER[:,2] = numpy.shift(2*(fft(winauto*(-4*numpy.power(numpy.pi*mm*Ts,2)*A[2]*A[0]*Z))*M), M/2)
2536 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
2536 PDER[:,3] = numpy.shift(2*(fft(winauto*delta)*M) - winauto[0], M/2)
2537 PDER = PDER[xvalid,:]
2537 PDER = PDER[xvalid,:]
2538 return F, PDER
2538 return F, PDER
2539
2539
2540 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
2540 def __curvefit_koki(y, a, Weights, FlagNoDerivative=1,
2541 itmax=20, tol=None):
2541 itmax=20, tol=None):
2542 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
2542 #ON_ERROR,2 IDL SENTENCE: RETURN TO THE CALLER IF ERROR
2543 if tol == None:
2543 if tol == None:
2544 tol = numpy.array([1.e-3],dtype='f4')[0]
2544 tol = numpy.array([1.e-3],dtype='f4')[0]
2545 typ=a.dtype
2545 typ=a.dtype
2546 double = 1 if typ == numpy.float64 else 0
2546 double = 1 if typ == numpy.float64 else 0
2547 if typ != numpy.float32:
2547 if typ != numpy.float32:
2548 a=a.astype(numpy.float32) #Make params floating
2548 a=a.astype(numpy.float32) #Make params floating
2549 # if we will be estimating partial derivates then compute machine precision
2549 # if we will be estimating partial derivates then compute machine precision
2550 if FlagNoDerivative == 1:
2550 if FlagNoDerivative == 1:
2551 res=numpy.MachAr(float_conv=numpy.float32)
2551 res=numpy.MachAr(float_conv=numpy.float32)
2552 eps=numpy.sqrt(res.eps)
2552 eps=numpy.sqrt(res.eps)
2553
2553
2554 nterms = a.size # Number of parameters
2554 nterms = a.size # Number of parameters
2555 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
2555 nfree=numpy.array([numpy.size(y) - nterms],dtype='f4')[0] # Degrees of freedom
2556 if nfree <= 0: print('Curvefit - not enough data points.')
2556 if nfree <= 0: print('Curvefit - not enough data points.')
2557 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
2557 flambda= numpy.array([0.001],dtype='f4')[0] # Initial lambda
2558 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
2558 #diag=numpy.arange(nterms)*(nterms+1) # Subscripta of diagonal elements
2559 # Use diag method in python
2559 # Use diag method in python
2560 converge=1
2560 converge=1
2561
2561
2562 #Define the partial derivative array
2562 #Define the partial derivative array
2563 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
2563 PDER = numpy.zeros((nterms,numpy.size(y)),dtype='f8') if double == 1 else numpy.zeros((nterms,numpy.size(y)),dtype='f4')
2564
2564
2565 for Niter in range(itmax): #Iteration loop
2565 for Niter in range(itmax): #Iteration loop
2566
2566
2567 if FlagNoDerivative == 1:
2567 if FlagNoDerivative == 1:
2568 #Evaluate function and estimate partial derivatives
2568 #Evaluate function and estimate partial derivatives
2569 yfit = __GAUSSWINFIT1(a)
2569 yfit = __GAUSSWINFIT1(a)
2570 for term in range(nterms):
2570 for term in range(nterms):
2571 p=a.copy() # Copy current parameters
2571 p=a.copy() # Copy current parameters
2572 #Increment size for forward difference derivative
2572 #Increment size for forward difference derivative
2573 inc = eps * abs(p[term])
2573 inc = eps * abs(p[term])
2574 if inc == 0: inc = eps
2574 if inc == 0: inc = eps
2575 p[term] = p[term] + inc
2575 p[term] = p[term] + inc
2576 yfit1 = __GAUSSWINFIT1(p)
2576 yfit1 = __GAUSSWINFIT1(p)
2577 PDER[term,:] = (yfit1-yfit)/inc
2577 PDER[term,:] = (yfit1-yfit)/inc
2578 else:
2578 else:
2579 #The user's procedure will return partial derivatives
2579 #The user's procedure will return partial derivatives
2580 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
2580 yfit,PDER=__GAUSSWINFIT1(a, flagPDER=1)
2581
2581
2582 beta = numpy.dot(PDER,(y-yfit)*Weights)
2582 beta = numpy.dot(PDER,(y-yfit)*Weights)
2583 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
2583 alpha = numpy.dot(PDER * numpy.tile(Weights,(nterms,1)), numpy.transpose(PDER))
2584 # save current values of return parameters
2584 # save current values of return parameters
2585 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
2585 sigma1 = numpy.sqrt( 1.0 / numpy.diag(alpha) ) # Current sigma.
2586 sigma = sigma1
2586 sigma = sigma1
2587
2587
2588 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
2588 chisq1 = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # Current chi squared.
2589 chisq = chisq1
2589 chisq = chisq1
2590 yfit1 = yfit
2590 yfit1 = yfit
2591 elev7=numpy.array([1.0e7],dtype='f4')[0]
2591 elev7=numpy.array([1.0e7],dtype='f4')[0]
2592 compara =numpy.sum(abs(y))/elev7/nfree
2592 compara =numpy.sum(abs(y))/elev7/nfree
2593 done_early = chisq1 < compara
2593 done_early = chisq1 < compara
2594
2594
2595 if done_early:
2595 if done_early:
2596 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2596 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2597 if done_early: Niter -= 1
2597 if done_early: Niter -= 1
2598 #save_tp(chisq,Niter,yfit)
2598 #save_tp(chisq,Niter,yfit)
2599 return yfit, a, converge, sigma, chisq # return result
2599 return yfit, a, converge, sigma, chisq # return result
2600 #c = numpy.dot(c, c) # this operator implemented at the next lines
2600 #c = numpy.dot(c, c) # this operator implemented at the next lines
2601 c_tmp = numpy.sqrt(numpy.diag(alpha))
2601 c_tmp = numpy.sqrt(numpy.diag(alpha))
2602 siz=len(c_tmp)
2602 siz=len(c_tmp)
2603 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
2603 c=numpy.dot(c_tmp.reshape(siz,1),c_tmp.reshape(1,siz))
2604 lambdaCount = 0
2604 lambdaCount = 0
2605 while True:
2605 while True:
2606 lambdaCount += 1
2606 lambdaCount += 1
2607 # Normalize alpha to have unit diagonal.
2607 # Normalize alpha to have unit diagonal.
2608 array = alpha / c
2608 array = alpha / c
2609 # Augment the diagonal.
2609 # Augment the diagonal.
2610 one=numpy.array([1.],dtype='f4')[0]
2610 one=numpy.array([1.],dtype='f4')[0]
2611 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
2611 numpy.fill_diagonal(array,numpy.diag(array)*(one+flambda))
2612 # Invert modified curvature matrix to find new parameters.
2612 # Invert modified curvature matrix to find new parameters.
2613 try:
2613 try:
2614 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
2614 array = (1.0/array) if array.size == 1 else numpy.linalg.inv(array)
2615 except Exception as e:
2615 except Exception as e:
2616 print(e)
2616 print(e)
2617 array[:]=numpy.NaN
2617 array[:]=numpy.NaN
2618
2618
2619 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
2619 b = a + numpy.dot(numpy.transpose(beta),array/c) # New params
2620 yfit = __GAUSSWINFIT1(b) # Evaluate function
2620 yfit = __GAUSSWINFIT1(b) # Evaluate function
2621 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
2621 chisq = numpy.sum(Weights*numpy.power(y-yfit,2,dtype='f4'),dtype='f4')/nfree # New chisq
2622 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
2622 sigma = numpy.sqrt(numpy.diag(array)/numpy.diag(alpha)) # New sigma
2623 if (numpy.isfinite(chisq) == 0) or \
2623 if (numpy.isfinite(chisq) == 0) or \
2624 (lambdaCount > 30 and chisq >= chisq1):
2624 (lambdaCount > 30 and chisq >= chisq1):
2625 # Reject changes made this iteration, use old values.
2625 # Reject changes made this iteration, use old values.
2626 yfit = yfit1
2626 yfit = yfit1
2627 sigma = sigma1
2627 sigma = sigma1
2628 chisq = chisq1
2628 chisq = chisq1
2629 converge = 0
2629 converge = 0
2630 #print('Failed to converge.')
2630 #print('Failed to converge.')
2631 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2631 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2632 if done_early: Niter -= 1
2632 if done_early: Niter -= 1
2633 #save_tp(chisq,Niter,yfit)
2633 #save_tp(chisq,Niter,yfit)
2634 return yfit, a, converge, sigma, chisq, chi2 # return result
2634 return yfit, a, converge, sigma, chisq, chi2 # return result
2635 ten=numpy.array([10.0],dtype='f4')[0]
2635 ten=numpy.array([10.0],dtype='f4')[0]
2636 flambda *= ten # Assume fit got worse
2636 flambda *= ten # Assume fit got worse
2637 if chisq <= chisq1:
2637 if chisq <= chisq1:
2638 break
2638 break
2639 hundred=numpy.array([100.0],dtype='f4')[0]
2639 hundred=numpy.array([100.0],dtype='f4')[0]
2640 flambda /= hundred
2640 flambda /= hundred
2641
2641
2642 a=b # Save new parameter estimate.
2642 a=b # Save new parameter estimate.
2643 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
2643 if ((chisq1-chisq)/chisq1) <= tol: # Finished?
2644 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2644 chi2 = chisq # Return chi-squared (chi2 obsolete-still works)
2645 if done_early: Niter -= 1
2645 if done_early: Niter -= 1
2646 #save_tp(chisq,Niter,yfit)
2646 #save_tp(chisq,Niter,yfit)
2647 return yfit, a, converge, sigma, chisq, chi2 # return result
2647 return yfit, a, converge, sigma, chisq, chi2 # return result
2648 converge = 0
2648 converge = 0
2649 chi2 = chisq
2649 chi2 = chisq
2650 #print('Failed to converge.')
2650 #print('Failed to converge.')
2651 #save_tp(chisq,Niter,yfit)
2651 #save_tp(chisq,Niter,yfit)
2652 return yfit, a, converge, sigma, chisq, chi2
2652 return yfit, a, converge, sigma, chisq, chi2
2653
2653
2654 if (nicoh is None): nicoh = 1
2654 if (nicoh is None): nicoh = 1
2655 if (graph is None): graph = 0
2655 if (graph is None): graph = 0
2656 if (smooth is None): smooth = 0
2656 if (smooth is None): smooth = 0
2657 elif (self.smooth < 3): smooth = 0
2657 elif (self.smooth < 3): smooth = 0
2658
2658
2659 if (type1 is None): type1 = 0
2659 if (type1 is None): type1 = 0
2660 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2660 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
2661 if (snrth is None): snrth = -20.0
2661 if (snrth is None): snrth = -20.0
2662 if (dc is None): dc = 0
2662 if (dc is None): dc = 0
2663 if (aliasing is None): aliasing = 0
2663 if (aliasing is None): aliasing = 0
2664 if (oldfd is None): oldfd = 0
2664 if (oldfd is None): oldfd = 0
2665 if (wwauto is None): wwauto = 0
2665 if (wwauto is None): wwauto = 0
2666
2666
2667 if (n0 < 1.e-20): n0 = 1.e-20
2667 if (n0 < 1.e-20): n0 = 1.e-20
2668
2668
2669 xvalid = numpy.where(fwindow == 1)[0]
2669 xvalid = numpy.where(fwindow == 1)[0]
2670 freq = oldfreq
2670 freq = oldfreq
2671 truex = oldfreq
2671 truex = oldfreq
2672 vec_power = numpy.zeros(oldspec.shape[1])
2672 vec_power = numpy.zeros(oldspec.shape[1])
2673 vec_fd = numpy.zeros(oldspec.shape[1])
2673 vec_fd = numpy.zeros(oldspec.shape[1])
2674 vec_w = numpy.zeros(oldspec.shape[1])
2674 vec_w = numpy.zeros(oldspec.shape[1])
2675 vec_snr = numpy.zeros(oldspec.shape[1])
2675 vec_snr = numpy.zeros(oldspec.shape[1])
2676 vec_n1 = numpy.empty(oldspec.shape[1])
2676 vec_n1 = numpy.empty(oldspec.shape[1])
2677 vec_fp = numpy.empty(oldspec.shape[1])
2677 vec_fp = numpy.empty(oldspec.shape[1])
2678 vec_sigma_fd = numpy.empty(oldspec.shape[1])
2678 vec_sigma_fd = numpy.empty(oldspec.shape[1])
2679
2679
2680 norm = 1
2680 norm = 1
2681
2681
2682 for ind in range(oldspec.shape[1]):
2682 for ind in range(oldspec.shape[1]):
2683
2683
2684 spec = oldspec[:,ind]
2684 spec = oldspec[:,ind]
2685 if (smooth == 0):
2685 if (smooth == 0):
2686 spec2 = spec
2686 spec2 = spec
2687 else:
2687 else:
2688 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2688 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
2689
2689
2690 aux = spec2*fwindow
2690 aux = spec2*fwindow
2691 max_spec = aux.max()
2691 max_spec = aux.max()
2692 m = aux.tolist().index(max_spec)
2692 m = aux.tolist().index(max_spec)
2693
2693
2694 if hasattr(normFactor, "ndim"):
2694 if hasattr(normFactor, "ndim"):
2695 if normFactor.ndim >= 1:
2695 if normFactor.ndim >= 1:
2696 norm = normFactor[ind]
2696 norm = normFactor[ind]
2697
2697
2698 if m > 2 and m < oldfreq.size - 3:
2698 if m > 2 and m < oldfreq.size - 3:
2699 newindex = m + numpy.array([-2,-1,0,1,2])
2699 newindex = m + numpy.array([-2,-1,0,1,2])
2700 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
2700 newfreq = numpy.arange(20)/20.0*(numpy.max(freq[newindex])-numpy.min(freq[newindex]))+numpy.min(freq[newindex])
2701 #peakspec = SPLINE(,)
2701 #peakspec = SPLINE(,)
2702 tck = interpolate.splrep(freq[newindex], spec2[newindex])
2702 tck = interpolate.splrep(freq[newindex], spec2[newindex])
2703 peakspec = interpolate.splev(newfreq, tck)
2703 peakspec = interpolate.splev(newfreq, tck)
2704 # max_spec = MAX(peakspec,)
2704 # max_spec = MAX(peakspec,)
2705 max_spec = numpy.max(peakspec)
2705 max_spec = numpy.max(peakspec)
2706 mnew = numpy.argmax(peakspec)
2706 mnew = numpy.argmax(peakspec)
2707 #fp = newfreq(mnew)
2707 #fp = newfreq(mnew)
2708 fp = newfreq[mnew]
2708 fp = newfreq[mnew]
2709 else:
2709 else:
2710 fp = freq[m]
2710 fp = freq[m]
2711
2711
2712 if type1==0:
2712 if type1==0:
2713
2713
2714 # Moments Estimation
2714 # Moments Estimation
2715 bb = spec2[numpy.arange(m,spec2.size)]
2715 bb = spec2[numpy.arange(m,spec2.size)]
2716 bb = (bb<n0).nonzero()
2716 bb = (bb<n0).nonzero()
2717 bb = bb[0]
2717 bb = bb[0]
2718
2718
2719 ss = spec2[numpy.arange(0,m + 1)]
2719 ss = spec2[numpy.arange(0,m + 1)]
2720 ss = (ss<n0).nonzero()
2720 ss = (ss<n0).nonzero()
2721 ss = ss[0]
2721 ss = ss[0]
2722
2722
2723 if (bb.size == 0):
2723 if (bb.size == 0):
2724 bb0 = spec.size - 1 - m
2724 bb0 = spec.size - 1 - m
2725 else:
2725 else:
2726 bb0 = bb[0] - 1
2726 bb0 = bb[0] - 1
2727 if (bb0 < 0):
2727 if (bb0 < 0):
2728 bb0 = 0
2728 bb0 = 0
2729
2729
2730 if (ss.size == 0):
2730 if (ss.size == 0):
2731 ss1 = 1
2731 ss1 = 1
2732 else:
2732 else:
2733 ss1 = max(ss) + 1
2733 ss1 = max(ss) + 1
2734
2734
2735 if (ss1 > m):
2735 if (ss1 > m):
2736 ss1 = m
2736 ss1 = m
2737
2737
2738 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
2738 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
2739
2739
2740 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
2740 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
2741 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
2741 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
2742 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
2742 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
2743 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
2743 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
2744 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
2744 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
2745 spec2 /=(norm) #compensation for sats remove
2745 spec2 /=(norm) #compensation for sats remove
2746 snr = (spec2.mean()-n0)/n0
2746 snr = (spec2.mean()-n0)/n0
2747 if (snr < 1.e-20): snr = 1.e-20
2747 if (snr < 1.e-20): snr = 1.e-20
2748
2748
2749 vec_power[ind] = total_power
2749 vec_power[ind] = total_power
2750 vec_fd[ind] = fd
2750 vec_fd[ind] = fd
2751 vec_w[ind] = w
2751 vec_w[ind] = w
2752 vec_snr[ind] = snr
2752 vec_snr[ind] = snr
2753 else:
2753 else:
2754 # Noise by heights
2754 # Noise by heights
2755 n1, stdv = self.__get_noise2(spec, nicoh)
2755 n1, stdv = self.__get_noise2(spec, nicoh)
2756 # Moments Estimation
2756 # Moments Estimation
2757 bb = spec2[numpy.arange(m,spec2.size)]
2757 bb = spec2[numpy.arange(m,spec2.size)]
2758 bb = (bb<n1).nonzero()
2758 bb = (bb<n1).nonzero()
2759 bb = bb[0]
2759 bb = bb[0]
2760
2760
2761 ss = spec2[numpy.arange(0,m + 1)]
2761 ss = spec2[numpy.arange(0,m + 1)]
2762 ss = (ss<n1).nonzero()
2762 ss = (ss<n1).nonzero()
2763 ss = ss[0]
2763 ss = ss[0]
2764
2764
2765 if (bb.size == 0):
2765 if (bb.size == 0):
2766 bb0 = spec.size - 1 - m
2766 bb0 = spec.size - 1 - m
2767 else:
2767 else:
2768 bb0 = bb[0] - 1
2768 bb0 = bb[0] - 1
2769 if (bb0 < 0):
2769 if (bb0 < 0):
2770 bb0 = 0
2770 bb0 = 0
2771
2771
2772 if (ss.size == 0):
2772 if (ss.size == 0):
2773 ss1 = 1
2773 ss1 = 1
2774 else:
2774 else:
2775 ss1 = max(ss) + 1
2775 ss1 = max(ss) + 1
2776
2776
2777 if (ss1 > m):
2777 if (ss1 > m):
2778 ss1 = m
2778 ss1 = m
2779
2779
2780 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
2780 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
2781 power = ((spec[valid] - n1)*fwindow[valid]).sum()
2781 power = ((spec[valid] - n1)*fwindow[valid]).sum()
2782 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
2782 fd = ((spec[valid]- n1)*freq[valid]*fwindow[valid]).sum()/power
2783 try:
2783 try:
2784 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2784 w = numpy.sqrt(((spec[valid] - n1)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
2785 except:
2785 except:
2786 w = float("NaN")
2786 w = float("NaN")
2787 snr = power/(n0*fwindow.sum())
2787 snr = power/(n0*fwindow.sum())
2788 if snr < 1.e-20: snr = 1.e-20
2788 if snr < 1.e-20: snr = 1.e-20
2789
2789
2790 # Here start gaussean adjustment
2790 # Here start gaussean adjustment
2791
2791
2792 if snr > numpy.power(10,0.1*snrth):
2792 if snr > numpy.power(10,0.1*snrth):
2793
2793
2794 a = numpy.zeros(4,dtype='f4')
2794 a = numpy.zeros(4,dtype='f4')
2795 a[0] = snr * n0
2795 a[0] = snr * n0
2796 a[1] = fd
2796 a[1] = fd
2797 a[2] = w
2797 a[2] = w
2798 a[3] = n0
2798 a[3] = n0
2799
2799
2800 np = spec.size
2800 np = spec.size
2801 aold = a.copy()
2801 aold = a.copy()
2802 spec2 = spec.copy()
2802 spec2 = spec.copy()
2803 oldxvalid = xvalid.copy()
2803 oldxvalid = xvalid.copy()
2804
2804
2805 for i in range(2):
2805 for i in range(2):
2806
2806
2807 ww = 1.0/(numpy.power(spec2,2)/nicoh)
2807 ww = 1.0/(numpy.power(spec2,2)/nicoh)
2808 ww[np//2] = 0.0
2808 ww[np//2] = 0.0
2809
2809
2810 a = aold.copy()
2810 a = aold.copy()
2811 xvalid = oldxvalid.copy()
2811 xvalid = oldxvalid.copy()
2812 #self.show_var(xvalid)
2812 #self.show_var(xvalid)
2813
2813
2814 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
2814 gaussfn = __curvefit_koki(spec[xvalid], a, ww[xvalid])
2815 a = gaussfn[1]
2815 a = gaussfn[1]
2816 converge = gaussfn[2]
2816 converge = gaussfn[2]
2817
2817
2818 xvalid = numpy.arange(np)
2818 xvalid = numpy.arange(np)
2819 spec2 = __GAUSSWINFIT1(a)
2819 spec2 = __GAUSSWINFIT1(a)
2820
2820
2821 xvalid = oldxvalid.copy()
2821 xvalid = oldxvalid.copy()
2822 power = a[0] * np
2822 power = a[0] * np
2823 fd = a[1]
2823 fd = a[1]
2824 sigma_fd = gaussfn[3][1]
2824 sigma_fd = gaussfn[3][1]
2825 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
2825 snr = max(power/ (max(a[3],n0) * len(oldxvalid)) * converge, 1e-20)
2826 w = numpy.abs(a[2])
2826 w = numpy.abs(a[2])
2827 n1 = max(a[3], n0)
2827 n1 = max(a[3], n0)
2828
2828
2829 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
2829 #gauss_adj=[fd,w,snr,n1,fp,sigma_fd]
2830 else:
2830 else:
2831 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
2831 sigma_fd=numpy.nan # to avoid UnboundLocalError: local variable 'sigma_fd' referenced before assignment
2832
2832
2833 vec_fd[ind] = fd
2833 vec_fd[ind] = fd
2834 vec_w[ind] = w
2834 vec_w[ind] = w
2835 vec_snr[ind] = snr
2835 vec_snr[ind] = snr
2836 vec_n1[ind] = n1
2836 vec_n1[ind] = n1
2837 vec_fp[ind] = fp
2837 vec_fp[ind] = fp
2838 vec_sigma_fd[ind] = sigma_fd
2838 vec_sigma_fd[ind] = sigma_fd
2839 vec_power[ind] = power # to compare with type 0 proccessing
2839 vec_power[ind] = power # to compare with type 0 proccessing
2840
2840
2841 if type1==1:
2841 if type1==1:
2842 return numpy.vstack((vec_snr, vec_w, vec_fd, vec_n1, vec_fp, vec_sigma_fd, vec_power)) # snr and fd exchanged to compare doppler of both types
2842 return numpy.vstack((vec_snr, vec_w, vec_fd, vec_n1, vec_fp, vec_sigma_fd, vec_power)) # snr and fd exchanged to compare doppler of both types
2843 else:
2843 else:
2844 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2844 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
2845
2845
2846 def __get_noise2(self,POWER, fft_avg, TALK=0):
2846 def __get_noise2(self,POWER, fft_avg, TALK=0):
2847 '''
2847 '''
2848 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
2848 Rutina para cΓ‘lculo de ruido por alturas(n1). Similar a IDL
2849 '''
2849 '''
2850 SPECT_PTS = len(POWER)
2850 SPECT_PTS = len(POWER)
2851 fft_avg = fft_avg*1.0
2851 fft_avg = fft_avg*1.0
2852 NOMIT = 0
2852 NOMIT = 0
2853 NN = SPECT_PTS - NOMIT
2853 NN = SPECT_PTS - NOMIT
2854 N = NN//2
2854 N = NN//2
2855 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
2855 ARR = numpy.concatenate((POWER[0:N+1],POWER[N+NOMIT+1:SPECT_PTS]))
2856 ARR = numpy.sort(ARR)
2856 ARR = numpy.sort(ARR)
2857 NUMS_MIN = (SPECT_PTS+7)//8
2857 NUMS_MIN = (SPECT_PTS+7)//8
2858 RTEST = (1.0+1.0/fft_avg)
2858 RTEST = (1.0+1.0/fft_avg)
2859 SUM = 0.0
2859 SUM = 0.0
2860 SUMSQ = 0.0
2860 SUMSQ = 0.0
2861 J = 0
2861 J = 0
2862 for I in range(NN):
2862 for I in range(NN):
2863 J = J + 1
2863 J = J + 1
2864 SUM = SUM + ARR[I]
2864 SUM = SUM + ARR[I]
2865 SUMSQ = SUMSQ + ARR[I]*ARR[I]
2865 SUMSQ = SUMSQ + ARR[I]*ARR[I]
2866 AVE = SUM*1.0/J
2866 AVE = SUM*1.0/J
2867 if J > NUMS_MIN:
2867 if J > NUMS_MIN:
2868 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
2868 if (SUMSQ*J <= RTEST*SUM*SUM): RNOISE = AVE
2869 else:
2869 else:
2870 if J == NUMS_MIN: RNOISE = AVE
2870 if J == NUMS_MIN: RNOISE = AVE
2871 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
2871 if TALK == 1: print('Noise Power (2):%4.4f' %RNOISE)
2872 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
2872 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
2873 return RNOISE, stdv
2873 return RNOISE, stdv
2874
2874
2875 def __get_noise1(self, power, fft_avg, TALK=0):
2875 def __get_noise1(self, power, fft_avg, TALK=0):
2876 '''
2876 '''
2877 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
2877 Rutina para cΓ‘lculo de ruido por alturas(n0). Similar a IDL
2878 '''
2878 '''
2879 num_pts = numpy.size(power)
2879 num_pts = numpy.size(power)
2880 #print('num_pts',num_pts)
2880 #print('num_pts',num_pts)
2881 #print('power',power.shape)
2881 #print('power',power.shape)
2882 #print(power[256:267,0:2])
2882 #print(power[256:267,0:2])
2883 fft_avg = fft_avg*1.0
2883 fft_avg = fft_avg*1.0
2884
2884
2885 ind = numpy.argsort(power, axis=None, kind='stable')
2885 ind = numpy.argsort(power, axis=None, kind='stable')
2886 #ind = numpy.argsort(numpy.reshape(power,-1))
2886 #ind = numpy.argsort(numpy.reshape(power,-1))
2887 #print(ind.shape)
2887 #print(ind.shape)
2888 #print(ind[0:11])
2888 #print(ind[0:11])
2889 #print(numpy.reshape(power,-1)[ind[0:11]])
2889 #print(numpy.reshape(power,-1)[ind[0:11]])
2890 ARR = numpy.reshape(power,-1)[ind]
2890 ARR = numpy.reshape(power,-1)[ind]
2891 #print('ARR',len(ARR))
2891 #print('ARR',len(ARR))
2892 #print('ARR',ARR.shape)
2892 #print('ARR',ARR.shape)
2893 NUMS_MIN = num_pts//10
2893 NUMS_MIN = num_pts//10
2894 RTEST = (1.0+1.0/fft_avg)
2894 RTEST = (1.0+1.0/fft_avg)
2895 SUM = 0.0
2895 SUM = 0.0
2896 SUMSQ = 0.0
2896 SUMSQ = 0.0
2897 J = 0
2897 J = 0
2898 cont = 1
2898 cont = 1
2899 while cont == 1 and J < num_pts:
2899 while cont == 1 and J < num_pts:
2900
2900
2901 SUM = SUM + ARR[J]
2901 SUM = SUM + ARR[J]
2902 SUMSQ = SUMSQ + ARR[J]*ARR[J]
2902 SUMSQ = SUMSQ + ARR[J]*ARR[J]
2903 J = J + 1
2903 J = J + 1
2904
2904
2905 if J > NUMS_MIN:
2905 if J > NUMS_MIN:
2906 if (SUMSQ*J <= RTEST*SUM*SUM):
2906 if (SUMSQ*J <= RTEST*SUM*SUM):
2907 LNOISE = SUM*1.0/J
2907 LNOISE = SUM*1.0/J
2908 else:
2908 else:
2909 J = J - 1
2909 J = J - 1
2910 SUM = SUM - ARR[J]
2910 SUM = SUM - ARR[J]
2911 SUMSQ = SUMSQ - ARR[J]*ARR[J]
2911 SUMSQ = SUMSQ - ARR[J]*ARR[J]
2912 cont = 0
2912 cont = 0
2913 else:
2913 else:
2914 if J == NUMS_MIN: LNOISE = SUM*1.0/J
2914 if J == NUMS_MIN: LNOISE = SUM*1.0/J
2915 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
2915 if TALK == 1: print('Noise Power (1):%8.8f' %LNOISE)
2916 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
2916 stdv = numpy.sqrt(SUMSQ/J - numpy.power(SUM/J,2))
2917 return LNOISE, stdv
2917 return LNOISE, stdv
2918
2918
2919 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
2919 def __NoiseByChannel(self, num_prof, num_incoh, spectra,talk=0):
2920
2920
2921 val_frq = numpy.arange(num_prof-2)+1
2921 val_frq = numpy.arange(num_prof-2)+1
2922 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
2922 val_frq[(num_prof-2)//2:] = val_frq[(num_prof-2)//2:] + 1
2923 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
2923 junkspc = numpy.sum(spectra[val_frq,:], axis=1)
2924 junkid = numpy.argsort(junkspc)
2924 junkid = numpy.argsort(junkspc)
2925 noisezone = val_frq[junkid[0:num_prof//2]]
2925 noisezone = val_frq[junkid[0:num_prof//2]]
2926 specnoise = spectra[noisezone,:]
2926 specnoise = spectra[noisezone,:]
2927 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
2927 noise, stdvnoise = self.__get_noise1(specnoise,num_incoh)
2928
2928
2929 if talk:
2929 if talk:
2930 print('noise =', noise)
2930 print('noise =', noise)
2931 return noise
2931 return noise
2932 #------------------ Get SA Parameters --------------------------
2932 #------------------ Get SA Parameters --------------------------
2933
2933
2934 def GetSAParameters(self):
2934 def GetSAParameters(self):
2935 #SA en frecuencia
2935 #SA en frecuencia
2936 pairslist = self.dataOut.groupList
2936 pairslist = self.dataOut.groupList
2937 num_pairs = len(pairslist)
2937 num_pairs = len(pairslist)
2938
2938
2939 vel = self.dataOut.abscissaList
2939 vel = self.dataOut.abscissaList
2940 spectra = self.dataOut.data_pre
2940 spectra = self.dataOut.data_pre
2941 cspectra = self.dataIn.data_cspc
2941 cspectra = self.dataIn.data_cspc
2942 delta_v = vel[1] - vel[0]
2942 delta_v = vel[1] - vel[0]
2943
2943
2944 #Calculating the power spectrum
2944 #Calculating the power spectrum
2945 spc_pow = numpy.sum(spectra, 3)*delta_v
2945 spc_pow = numpy.sum(spectra, 3)*delta_v
2946 #Normalizing Spectra
2946 #Normalizing Spectra
2947 norm_spectra = spectra/spc_pow
2947 norm_spectra = spectra/spc_pow
2948 #Calculating the norm_spectra at peak
2948 #Calculating the norm_spectra at peak
2949 max_spectra = numpy.max(norm_spectra, 3)
2949 max_spectra = numpy.max(norm_spectra, 3)
2950
2950
2951 #Normalizing Cross Spectra
2951 #Normalizing Cross Spectra
2952 norm_cspectra = numpy.zeros(cspectra.shape)
2952 norm_cspectra = numpy.zeros(cspectra.shape)
2953
2953
2954 for i in range(num_chan):
2954 for i in range(num_chan):
2955 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
2955 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
2956
2956
2957 max_cspectra = numpy.max(norm_cspectra,2)
2957 max_cspectra = numpy.max(norm_cspectra,2)
2958 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
2958 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
2959
2959
2960 for i in range(num_pairs):
2960 for i in range(num_pairs):
2961 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
2961 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
2962 #------------------- Get Lags ----------------------------------
2962 #------------------- Get Lags ----------------------------------
2963
2963
2964 class JULIADriftsEstimation(Operation):
2964 class JULIADriftsEstimation(Operation):
2965
2965
2966 def __init__(self):
2966 def __init__(self):
2967 Operation.__init__(self)
2967 Operation.__init__(self)
2968
2968
2969 def newtotal(self, data):
2969 def newtotal(self, data):
2970 return numpy.nansum(data)
2970 return numpy.nansum(data)
2971
2971
2972 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
2972 def data_filter(self, parm, snrth=-20, swth=20, wErrth=500):
2973
2973
2974 Sz0 = parm.shape # Sz0: h,p
2974 Sz0 = parm.shape # Sz0: h,p
2975 drift = parm[:,0]
2975 drift = parm[:,0]
2976 sw = 2*parm[:,1]
2976 sw = 2*parm[:,1]
2977 snr = 10*numpy.log10(parm[:,2])
2977 snr = 10*numpy.log10(parm[:,2])
2978 Sz = drift.shape # Sz: h
2978 Sz = drift.shape # Sz: h
2979 mask = numpy.ones((Sz[0]))
2979 mask = numpy.ones((Sz[0]))
2980 th=0
2980 th=0
2981 valid=numpy.where(numpy.isfinite(snr))
2981 valid=numpy.where(numpy.isfinite(snr))
2982 cvalid = len(valid[0])
2982 cvalid = len(valid[0])
2983 if cvalid >= 1:
2983 if cvalid >= 1:
2984 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
2984 # CΓ‘lculo del ruido promedio de snr para el i-Γ©simo grupo de alturas
2985 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
2985 nbins = int(numpy.max(snr)-numpy.min(snr))+1 # bin size = 1, similar to IDL
2986 h = numpy.histogram(snr,bins=nbins)
2986 h = numpy.histogram(snr,bins=nbins)
2987 hist = h[0]
2987 hist = h[0]
2988 values = numpy.round_(h[1])
2988 values = numpy.round_(h[1])
2989 moda = values[numpy.where(hist == numpy.max(hist))]
2989 moda = values[numpy.where(hist == numpy.max(hist))]
2990 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
2990 indNoise = numpy.where(numpy.abs(snr - numpy.min(moda)) < 3)[0]
2991
2991
2992 noise = snr[indNoise]
2992 noise = snr[indNoise]
2993 noise_mean = numpy.sum(noise)/len(noise)
2993 noise_mean = numpy.sum(noise)/len(noise)
2994 # CΓ‘lculo de media de snr
2994 # CΓ‘lculo de media de snr
2995 med = numpy.median(snr)
2995 med = numpy.median(snr)
2996 # Establece el umbral de snr
2996 # Establece el umbral de snr
2997 if noise_mean > med + 3:
2997 if noise_mean > med + 3:
2998 th = med
2998 th = med
2999 else:
2999 else:
3000 th = noise_mean + 3
3000 th = noise_mean + 3
3001 # Establece mΓ‘scara
3001 # Establece mΓ‘scara
3002 novalid = numpy.where(snr <= th)[0]
3002 novalid = numpy.where(snr <= th)[0]
3003 mask[novalid] = numpy.nan
3003 mask[novalid] = numpy.nan
3004 # Elimina datos que no sobrepasen el umbral: PARAMETRO
3004 # Elimina datos que no sobrepasen el umbral: PARAMETRO
3005 novalid = numpy.where(snr <= snrth)
3005 novalid = numpy.where(snr <= snrth)
3006 cnovalid = len(novalid[0])
3006 cnovalid = len(novalid[0])
3007 if cnovalid > 0:
3007 if cnovalid > 0:
3008 mask[novalid] = numpy.nan
3008 mask[novalid] = numpy.nan
3009 novalid = numpy.where(numpy.isnan(snr))
3009 novalid = numpy.where(numpy.isnan(snr))
3010 cnovalid = len(novalid[0])
3010 cnovalid = len(novalid[0])
3011 if cnovalid > 0:
3011 if cnovalid > 0:
3012 mask[novalid] = numpy.nan
3012 mask[novalid] = numpy.nan
3013 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
3013 new_parm = numpy.zeros((Sz0[0],Sz0[1]))
3014 for h in range(Sz0[0]):
3014 for h in range(Sz0[0]):
3015 for p in range(Sz0[1]):
3015 for p in range(Sz0[1]):
3016 if numpy.isnan(mask[h]):
3016 if numpy.isnan(mask[h]):
3017 new_parm[h,p]=numpy.nan
3017 new_parm[h,p]=numpy.nan
3018 else:
3018 else:
3019 new_parm[h,p]=parm[h,p]
3019 new_parm[h,p]=parm[h,p]
3020
3020
3021 return new_parm, th
3021 return new_parm, th
3022
3022
3023 def run(self, dataOut, zenith, zenithCorrection,heights=None, statistics=0, otype=0):
3023 def run(self, dataOut, zenith, zenithCorrection,heights=None, statistics=0, otype=0):
3024
3024
3025 dataOut.lat=-11.95
3025 dataOut.lat=-11.95
3026 dataOut.lon=-76.87
3026 dataOut.lon=-76.87
3027 nCh=dataOut.spcpar.shape[0]
3027 nCh=dataOut.spcpar.shape[0]
3028 nHei=dataOut.spcpar.shape[1]
3028 nHei=dataOut.spcpar.shape[1]
3029 nParam=dataOut.spcpar.shape[2]
3029 nParam=dataOut.spcpar.shape[2]
3030 # SelecciΓ³n de alturas
3030 # SelecciΓ³n de alturas
3031
3031
3032 if not heights:
3032 if not heights:
3033 parm = numpy.zeros((nCh,nHei,nParam))
3033 parm = numpy.zeros((nCh,nHei,nParam))
3034 parm[:] = dataOut.spcpar[:]
3034 parm[:] = dataOut.spcpar[:]
3035 else:
3035 else:
3036 hei=dataOut.heightList
3036 hei=dataOut.heightList
3037 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
3037 hvalid=numpy.where([hei >= heights[0]][0] & [hei <= heights[1]][0])[0]
3038 nhvalid=len(hvalid)
3038 nhvalid=len(hvalid)
3039 dataOut.heightList = hei[hvalid]
3039 dataOut.heightList = hei[hvalid]
3040 parm = numpy.zeros((nCh,nhvalid,nParam))
3040 parm = numpy.zeros((nCh,nhvalid,nParam))
3041 parm[:] = dataOut.spcpar[:,hvalid,:]
3041 parm[:] = dataOut.spcpar[:,hvalid,:]
3042
3042
3043
3043
3044 # Primer filtrado: Umbral de SNR
3044 # Primer filtrado: Umbral de SNR
3045 for i in range(nCh):
3045 for i in range(nCh):
3046 parm[i,:,:] = self.data_filter(parm[i,:,:])[0]
3046 parm[i,:,:] = self.data_filter(parm[i,:,:])[0]
3047
3047
3048 zenith = numpy.array(zenith)
3048 zenith = numpy.array(zenith)
3049 zenith -= zenithCorrection
3049 zenith -= zenithCorrection
3050 zenith *= numpy.pi/180
3050 zenith *= numpy.pi/180
3051 alpha = zenith[0]
3051 alpha = zenith[0]
3052 beta = zenith[1]
3052 beta = zenith[1]
3053 dopplerCH0 = parm[0,:,0]
3053 dopplerCH0 = parm[0,:,0]
3054 dopplerCH1 = parm[1,:,0]
3054 dopplerCH1 = parm[1,:,0]
3055 swCH0 = parm[0,:,1]
3055 swCH0 = parm[0,:,1]
3056 swCH1 = parm[1,:,1]
3056 swCH1 = parm[1,:,1]
3057 snrCH0 = 10*numpy.log10(parm[0,:,2])
3057 snrCH0 = 10*numpy.log10(parm[0,:,2])
3058 snrCH1 = 10*numpy.log10(parm[1,:,2])
3058 snrCH1 = 10*numpy.log10(parm[1,:,2])
3059 noiseCH0 = parm[0,:,3]
3059 noiseCH0 = parm[0,:,3]
3060 noiseCH1 = parm[1,:,3]
3060 noiseCH1 = parm[1,:,3]
3061 wErrCH0 = parm[0,:,5]
3061 wErrCH0 = parm[0,:,5]
3062 wErrCH1 = parm[1,:,5]
3062 wErrCH1 = parm[1,:,5]
3063
3063
3064 # Vertical and zonal calculation according to geometry
3064 # Vertical and zonal calculation according to geometry
3065 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
3065 sinB_A = numpy.sin(beta)*numpy.cos(alpha) - numpy.sin(alpha)* numpy.cos(beta)
3066 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
3066 drift = -(dopplerCH0 * numpy.sin(beta) - dopplerCH1 * numpy.sin(alpha))/ sinB_A
3067 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
3067 zonal = (dopplerCH0 * numpy.cos(beta) - dopplerCH1 * numpy.cos(alpha))/ sinB_A
3068 snr = (snrCH0 + snrCH1)/2
3068 snr = (snrCH0 + snrCH1)/2
3069 noise = (noiseCH0 + noiseCH1)/2
3069 noise = (noiseCH0 + noiseCH1)/2
3070 sw = (swCH0 + swCH1)/2
3070 sw = (swCH0 + swCH1)/2
3071 w_w_err= numpy.sqrt(numpy.power(wErrCH0 * numpy.sin(beta)/numpy.abs(sinB_A),2) + numpy.power(wErrCH1 * numpy.sin(alpha)/numpy.abs(sinB_A),2))
3071 w_w_err= numpy.sqrt(numpy.power(wErrCH0 * numpy.sin(beta)/numpy.abs(sinB_A),2) + numpy.power(wErrCH1 * numpy.sin(alpha)/numpy.abs(sinB_A),2))
3072 w_e_err= numpy.sqrt(numpy.power(wErrCH0 * numpy.cos(beta)/numpy.abs(-1*sinB_A),2) + numpy.power(wErrCH1 * numpy.cos(alpha)/numpy.abs(-1*sinB_A),2))
3072 w_e_err= numpy.sqrt(numpy.power(wErrCH0 * numpy.cos(beta)/numpy.abs(-1*sinB_A),2) + numpy.power(wErrCH1 * numpy.cos(alpha)/numpy.abs(-1*sinB_A),2))
3073
3073
3074 # for statistics150km
3074 # for statistics150km
3075 if statistics:
3075 if statistics:
3076 print('Implemented offline.')
3076 print('Implemented offline.')
3077
3077
3078 if otype == 0:
3078 if otype == 0:
3079 winds = numpy.vstack((snr, drift, zonal, noise, sw, w_w_err, w_e_err)) # to process statistics drifts
3079 winds = numpy.vstack((snr, drift, zonal, noise, sw, w_w_err, w_e_err)) # to process statistics drifts
3080 elif otype == 3:
3080 elif otype == 3:
3081 winds = numpy.vstack((snr, drift, zonal)) # to generic plot: 3 RTI's
3081 winds = numpy.vstack((snr, drift, zonal)) # to generic plot: 3 RTI's
3082 elif otype == 4:
3082 elif otype == 4:
3083 winds = numpy.vstack((snrCH0, drift, snrCH1, zonal)) # to generic plot: 4 RTI's
3083 winds = numpy.vstack((snrCH0, drift, snrCH1, zonal)) # to generic plot: 4 RTI's
3084
3084
3085 snr1 = numpy.vstack((snrCH0, snrCH1))
3085 snr1 = numpy.vstack((snrCH0, snrCH1))
3086 dataOut.data_output = winds
3086 dataOut.data_output = winds
3087 dataOut.data_snr = snr1
3087 dataOut.data_snr = snr1
3088
3088
3089 dataOut.utctimeInit = dataOut.utctime
3089 dataOut.utctimeInit = dataOut.utctime
3090 dataOut.outputInterval = dataOut.timeInterval
3090 dataOut.outputInterval = dataOut.timeInterval
3091 try:
3091 try:
3092 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.data_output[0])) # NAN vectors are not written MADRIGAL CASE
3092 dataOut.flagNoData = numpy.all(numpy.isnan(dataOut.data_output[0])) # NAN vectors are not written MADRIGAL CASE
3093 except:
3093 except:
3094 print("Check there is no Data")
3094 print("Check there is no Data")
3095
3095
3096 return dataOut
3096 return dataOut
3097
3097
3098 class SALags(Operation):
3098 class SALags(Operation):
3099 '''
3099 '''
3100 Function GetMoments()
3100 Function GetMoments()
3101
3101
3102 Input:
3102 Input:
3103 self.dataOut.data_pre
3103 self.dataOut.data_pre
3104 self.dataOut.abscissaList
3104 self.dataOut.abscissaList
3105 self.dataOut.noise
3105 self.dataOut.noise
3106 self.dataOut.normFactor
3106 self.dataOut.normFactor
3107 self.dataOut.data_snr
3107 self.dataOut.data_snr
3108 self.dataOut.groupList
3108 self.dataOut.groupList
3109 self.dataOut.nChannels
3109 self.dataOut.nChannels
3110
3110
3111 Affected:
3111 Affected:
3112 self.dataOut.data_param
3112 self.dataOut.data_param
3113
3113
3114 '''
3114 '''
3115 def run(self, dataOut):
3115 def run(self, dataOut):
3116 data_acf = dataOut.data_pre[0]
3116 data_acf = dataOut.data_pre[0]
3117 data_ccf = dataOut.data_pre[1]
3117 data_ccf = dataOut.data_pre[1]
3118 normFactor_acf = dataOut.normFactor[0]
3118 normFactor_acf = dataOut.normFactor[0]
3119 normFactor_ccf = dataOut.normFactor[1]
3119 normFactor_ccf = dataOut.normFactor[1]
3120 pairs_acf = dataOut.groupList[0]
3120 pairs_acf = dataOut.groupList[0]
3121 pairs_ccf = dataOut.groupList[1]
3121 pairs_ccf = dataOut.groupList[1]
3122
3122
3123 nHeights = dataOut.nHeights
3123 nHeights = dataOut.nHeights
3124 absc = dataOut.abscissaList
3124 absc = dataOut.abscissaList
3125 noise = dataOut.noise
3125 noise = dataOut.noise
3126 SNR = dataOut.data_snr
3126 SNR = dataOut.data_snr
3127 nChannels = dataOut.nChannels
3127 nChannels = dataOut.nChannels
3128 for l in range(len(pairs_acf)):
3128 for l in range(len(pairs_acf)):
3129 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
3129 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
3130
3130
3131 for l in range(len(pairs_ccf)):
3131 for l in range(len(pairs_ccf)):
3132 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
3132 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
3133
3133
3134 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
3134 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
3135 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
3135 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
3136 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
3136 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
3137 return
3137 return
3138
3138
3139 def __calculateTaus(self, data_acf, data_ccf, lagRange):
3139 def __calculateTaus(self, data_acf, data_ccf, lagRange):
3140
3140
3141 lag0 = data_acf.shape[1]/2
3141 lag0 = data_acf.shape[1]/2
3142 #Funcion de Autocorrelacion
3142 #Funcion de Autocorrelacion
3143 mean_acf = stats.nanmean(data_acf, axis = 0)
3143 mean_acf = stats.nanmean(data_acf, axis = 0)
3144
3144
3145 #Obtencion Indice de TauCross
3145 #Obtencion Indice de TauCross
3146 ind_ccf = data_ccf.argmax(axis = 1)
3146 ind_ccf = data_ccf.argmax(axis = 1)
3147 #Obtencion Indice de TauAuto
3147 #Obtencion Indice de TauAuto
3148 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
3148 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
3149 ccf_lag0 = data_ccf[:,lag0,:]
3149 ccf_lag0 = data_ccf[:,lag0,:]
3150
3150
3151 for i in range(ccf_lag0.shape[0]):
3151 for i in range(ccf_lag0.shape[0]):
3152 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
3152 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
3153
3153
3154 #Obtencion de TauCross y TauAuto
3154 #Obtencion de TauCross y TauAuto
3155 tau_ccf = lagRange[ind_ccf]
3155 tau_ccf = lagRange[ind_ccf]
3156 tau_acf = lagRange[ind_acf]
3156 tau_acf = lagRange[ind_acf]
3157
3157
3158 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
3158 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
3159
3159
3160 tau_ccf[Nan1,Nan2] = numpy.nan
3160 tau_ccf[Nan1,Nan2] = numpy.nan
3161 tau_acf[Nan1,Nan2] = numpy.nan
3161 tau_acf[Nan1,Nan2] = numpy.nan
3162 tau = numpy.vstack((tau_ccf,tau_acf))
3162 tau = numpy.vstack((tau_ccf,tau_acf))
3163
3163
3164 return tau
3164 return tau
3165
3165
3166 def __calculateLag1Phase(self, data, lagTRange):
3166 def __calculateLag1Phase(self, data, lagTRange):
3167 data1 = stats.nanmean(data, axis = 0)
3167 data1 = stats.nanmean(data, axis = 0)
3168 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
3168 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
3169
3169
3170 phase = numpy.angle(data1[lag1,:])
3170 phase = numpy.angle(data1[lag1,:])
3171
3171
3172 return phase
3172 return phase
3173
3173
3174 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
3174 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
3175 z = (x - a1) / a2
3175 z = (x - a1) / a2
3176 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
3176 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
3177 return y
3177 return y
3178
3178
3179
3180 class SpectralFitting(Operation):
3179 class SpectralFitting(Operation):
3181 '''
3180 '''
3182 Function GetMoments()
3181 Function GetMoments()
3183
3182
3184 Input:
3183 Input:
3185 Output:
3184 Output:
3186 Variables modified:
3185 Variables modified:
3187 '''
3186 '''
3188 isConfig = False
3187 isConfig = False
3189 __dataReady = False
3188 __dataReady = False
3190 bloques = None
3189 bloques = None
3191 bloque0 = None
3190 bloque0 = None
3192 index = 0
3193 fint = 0
3194 buffer = 0
3195 buffer2 = 0
3196 buffer3 = 0
3197
3191
3198 def __init__(self):
3192 def __init__(self):
3199 Operation.__init__(self)
3193 Operation.__init__(self)
3200 self.i=0
3194 self.i=0
3201 self.isConfig = False
3195 self.isConfig = False
3202
3196
3203
3197 def setup(self,nChan,nProf,nHei,nBlocks):
3204 def setup(self,dataOut,groupList,path,file,filec):
3205 self.__dataReady = False
3198 self.__dataReady = False
3206 # new
3199 self.bloques = numpy.zeros([2, nProf, nHei,nBlocks], dtype= complex)
3207 self.nChannels = dataOut.nChannels
3200 self.bloque0 = numpy.zeros([nChan, nProf, nHei, nBlocks])
3208 self.channels = dataOut.channelList
3209 self.nHeights = dataOut.heightList.size
3210 self.heights = dataOut.heightList
3211 self.nProf = dataOut.nProfiles
3212 self.nIncohInt = dataOut.nIncohInt
3213 self.absc = dataOut.abscissaList[:-1]
3214
3215
3216 #To be inserted as a parameter
3217 try:
3218 self.groupArray = numpy.array(groupList)#groupArray = numpy.array([[0,1],[2,3]])
3219 except:
3220 print("Please insert groupList. Example (0,1),(2,3) format multilist")
3221 dataOut.groupList = self.groupArray
3222 self.crosspairs = dataOut.groupList
3223 self.nPairs = len(self.crosspairs)
3224 self.nGroups = self.groupArray.shape[0]
3225
3226 #List of possible combinations
3227
3228 self.listComb = itertools.combinations(numpy.arange(self.groupArray.shape[1]),2)
3229 self.indCross = numpy.zeros(len(list(self.listComb)), dtype = 'int')
3230
3231 #Parameters Array
3232 dataOut.data_param = None
3233 dataOut.data_paramC = None
3234 dataOut.clean_num_aver = None
3235 dataOut.coh_num_aver = None
3236 dataOut.tmp_spectra_i = None
3237 dataOut.tmp_cspectra_i = None
3238 dataOut.tmp_spectra_c = None
3239 dataOut.tmp_cspectra_c = None
3240 dataOut.index = None
3241
3242 if path != None:
3243 sys.path.append(path)
3244 self.library = importlib.import_module(file)
3245 if filec != None:
3246 self.weightf = importlib.import_module(filec)
3247
3248 #Set constants
3249 self.constants = self.library.setConstants(dataOut)
3250 dataOut.constants = self.constants
3251 self.M = dataOut.normFactor
3252 self.N = dataOut.nFFTPoints
3253 self.ippSeconds = dataOut.ippSeconds
3254 self.K = dataOut.nIncohInt
3255 self.pairsArray = numpy.array(dataOut.pairsList)
3256 self.snrth = 20
3257
3258 def __calculateMoments(self,oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
3201 def __calculateMoments(self,oldspec, oldfreq, n0, nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
3259
3202
3260 if (nicoh is None): nicoh = 1
3203 if (nicoh is None): nicoh = 1
3261 if (graph is None): graph = 0
3204 if (graph is None): graph = 0
3262 if (smooth is None): smooth = 0
3205 if (smooth is None): smooth = 0
3263 elif (self.smooth < 3): smooth = 0
3206 elif (self.smooth < 3): smooth = 0
3264
3207
3265 if (type1 is None): type1 = 0
3208 if (type1 is None): type1 = 0
3266 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
3209 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
3267 if (snrth is None): snrth = -3
3210 if (snrth is None): snrth = -3
3268 if (dc is None): dc = 0
3211 if (dc is None): dc = 0
3269 if (aliasing is None): aliasing = 0
3212 if (aliasing is None): aliasing = 0
3270 if (oldfd is None): oldfd = 0
3213 if (oldfd is None): oldfd = 0
3271 if (wwauto is None): wwauto = 0
3214 if (wwauto is None): wwauto = 0
3272
3215
3273 if (n0 < 1.e-20): n0 = 1.e-20
3216 if (n0 < 1.e-20): n0 = 1.e-20
3274
3217
3275 freq = oldfreq
3218 freq = oldfreq
3276 vec_power = numpy.zeros(oldspec.shape[1])
3219 vec_power = numpy.zeros(oldspec.shape[1])
3277 vec_fd = numpy.zeros(oldspec.shape[1])
3220 vec_fd = numpy.zeros(oldspec.shape[1])
3278 vec_w = numpy.zeros(oldspec.shape[1])
3221 vec_w = numpy.zeros(oldspec.shape[1])
3279 vec_snr = numpy.zeros(oldspec.shape[1])
3222 vec_snr = numpy.zeros(oldspec.shape[1])
3280
3223
3281 oldspec = numpy.ma.masked_invalid(oldspec)
3224 oldspec = numpy.ma.masked_invalid(oldspec)
3282
3225
3283 for ind in range(oldspec.shape[1]):
3226 for ind in range(oldspec.shape[1]):
3284
3227
3285 spec = oldspec[:,ind]
3228 spec = oldspec[:,ind]
3286 aux = spec*fwindow
3229 aux = spec*fwindow
3287 max_spec = aux.max()
3230 max_spec = aux.max()
3288 m = list(aux).index(max_spec)
3231 m = list(aux).index(max_spec)
3289
3232
3290 #Smooth
3233 #Smooth
3291 if (smooth == 0): spec2 = spec
3234 if (smooth == 0): spec2 = spec
3292 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
3235 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
3293
3236
3294 # Calculo de Momentos
3237 # Calculo de Momentos
3295 bb = spec2[list(range(m,spec2.size))]
3238 bb = spec2[list(range(m,spec2.size))]
3296 bb = (bb<n0).nonzero()
3239 bb = (bb<n0).nonzero()
3297 bb = bb[0]
3240 bb = bb[0]
3298
3241
3299 ss = spec2[list(range(0,m + 1))]
3242 ss = spec2[list(range(0,m + 1))]
3300 ss = (ss<n0).nonzero()
3243 ss = (ss<n0).nonzero()
3301 ss = ss[0]
3244 ss = ss[0]
3302
3245
3303 if (bb.size == 0):
3246 if (bb.size == 0):
3304 bb0 = spec.size - 1 - m
3247 bb0 = spec.size - 1 - m
3305 else:
3248 else:
3306 bb0 = bb[0] - 1
3249 bb0 = bb[0] - 1
3307 if (bb0 < 0):
3250 if (bb0 < 0):
3308 bb0 = 0
3251 bb0 = 0
3309
3252
3310 if (ss.size == 0): ss1 = 1
3253 if (ss.size == 0): ss1 = 1
3311 else: ss1 = max(ss) + 1
3254 else: ss1 = max(ss) + 1
3312
3255
3313 if (ss1 > m): ss1 = m
3256 if (ss1 > m): ss1 = m
3314
3257
3315 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
3258 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
3316 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
3259 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
3317 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
3260 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
3318 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
3261 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
3319 snr = (spec2.mean()-n0)/n0
3262 snr = (spec2.mean()-n0)/n0
3320
3263
3321 if (snr < 1.e-20) :
3264 # if (snr < 1.e-20) :
3322 snr = 1.e-20
3265 # snr = 1.e-20
3323
3266
3324 vec_power[ind] = power
3267 vec_power[ind] = power
3325 vec_fd[ind] = fd
3268 vec_fd[ind] = fd
3326 vec_w[ind] = w
3269 vec_w[ind] = w
3327 vec_snr[ind] = snr
3270 vec_snr[ind] = snr
3328
3271
3329 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
3272 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
3330 return moments
3273 return moments
3331
3274
3275 #def __DiffCoherent(self,snrth, spectra, cspectra, nProf, heights,nChan, nHei, nPairs, channels, noise, crosspairs):
3332 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
3276 def __DiffCoherent(self, spectra, cspectra, dataOut, noise, snrth, coh_th, hei_th):
3333
3277
3278 #import matplotlib.pyplot as plt
3334 nProf = dataOut.nProfiles
3279 nProf = dataOut.nProfiles
3335 heights = dataOut.heightList
3280 heights = dataOut.heightList
3336 nHei = len(heights)
3281 nHei = len(heights)
3337 channels = dataOut.channelList
3282 channels = dataOut.channelList
3338 nChan = len(channels)
3283 nChan = len(channels)
3339 crosspairs = dataOut.groupList
3284 crosspairs = dataOut.groupList
3340 nPairs = len(crosspairs)
3285 nPairs = len(crosspairs)
3341 #Separar espectros incoherentes de coherentes snr > 20 dB'
3286 #Separar espectros incoherentes de coherentes snr > 20 dB'
3342 snr_th = 10**(snrth/10.0)
3287 snr_th = 10**(snrth/10.0)
3343 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
3288 my_incoh_spectra = numpy.zeros([nChan, nProf,nHei], dtype='float')
3344 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
3289 my_incoh_cspectra = numpy.zeros([nPairs,nProf, nHei], dtype='complex')
3345 my_incoh_aver = numpy.zeros([nChan, nHei])
3290 my_incoh_aver = numpy.zeros([nChan, nHei])
3346 my_coh_aver = numpy.zeros([nChan, nHei])
3291 my_coh_aver = numpy.zeros([nChan, nHei])
3347
3292
3348 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
3293 coh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
3349 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
3294 coh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
3350 coh_aver = numpy.zeros([nChan, nHei])
3295 coh_aver = numpy.zeros([nChan, nHei])
3351
3296
3352 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
3297 incoh_spectra = numpy.zeros([nChan, nProf, nHei], dtype='float')
3353 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
3298 incoh_cspectra = numpy.zeros([nPairs, nProf, nHei], dtype='complex')
3354 incoh_aver = numpy.zeros([nChan, nHei])
3299 incoh_aver = numpy.zeros([nChan, nHei])
3355 power = numpy.sum(spectra, axis=1)
3300 power = numpy.sum(spectra, axis=1)
3356
3301
3357 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
3302 if coh_th == None : coh_th = numpy.array([0.75,0.65,0.15]) # 0.65
3358 if hei_th == None : hei_th = numpy.array([60,300,650])
3303 if hei_th == None : hei_th = numpy.array([60,300,650])
3359 for ic in range(nPairs):
3304 for ic in range(nPairs):
3360 pair = crosspairs[ic]
3305 pair = crosspairs[ic]
3361 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
3306 #si el SNR es mayor que el SNR threshold los datos se toman coherentes
3362 s_n0 = power[pair[0],:]/noise[pair[0]]
3307 s_n0 = power[pair[0],:]/noise[pair[0]]
3363 s_n1 = power[pair[1],:]/noise[pair[1]]
3308 s_n1 = power[pair[1],:]/noise[pair[1]]
3364 valid1 =(s_n0>=snr_th).nonzero()
3309 valid1 =(s_n0>=snr_th).nonzero()
3365 valid2 = (s_n1>=snr_th).nonzero()
3310 valid2 = (s_n1>=snr_th).nonzero()
3311
3366 valid1 = numpy.array(valid1[0])
3312 valid1 = numpy.array(valid1[0])
3367 valid2 = numpy.array(valid2[0])
3313 valid2 = numpy.array(valid2[0])
3368 valid = valid1
3314 valid = valid1
3369 for iv in range(len(valid2)):
3315 for iv in range(len(valid2)):
3316
3370 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3317 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3371 if len(indv[0]) == 0 :
3318 if len(indv[0]) == 0 :
3372 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
3319 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
3373 if len(valid)>0:
3320 if len(valid)>0:
3374 my_coh_aver[pair[0],valid]=1
3321 my_coh_aver[pair[0],valid]=1
3375 my_coh_aver[pair[1],valid]=1
3322 my_coh_aver[pair[1],valid]=1
3376 # si la coherencia es mayor a la coherencia threshold los datos se toman
3323 # si la coherencia es mayor a la coherencia threshold los datos se toman
3324
3377 coh = numpy.squeeze(numpy.nansum(cspectra[ic,:,:], axis=0)/numpy.sqrt(numpy.nansum(spectra[pair[0],:,:], axis=0)*numpy.nansum(spectra[pair[1],:,:], axis=0)))
3325 coh = numpy.squeeze(numpy.nansum(cspectra[ic,:,:], axis=0)/numpy.sqrt(numpy.nansum(spectra[pair[0],:,:], axis=0)*numpy.nansum(spectra[pair[1],:,:], axis=0)))
3326
3378 for ih in range(len(hei_th)):
3327 for ih in range(len(hei_th)):
3379 hvalid = (heights>hei_th[ih]).nonzero()
3328 hvalid = (heights>hei_th[ih]).nonzero()
3380 hvalid = hvalid[0]
3329 hvalid = hvalid[0]
3381 if len(hvalid)>0:
3330 if len(hvalid)>0:
3382 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
3331 valid = (numpy.absolute(coh[hvalid])>coh_th[ih]).nonzero()
3383 valid = valid[0]
3332 valid = valid[0]
3333
3384 if len(valid)>0:
3334 if len(valid)>0:
3385 my_coh_aver[pair[0],hvalid[valid]] =1
3335 my_coh_aver[pair[0],hvalid[valid]] =1
3386 my_coh_aver[pair[1],hvalid[valid]] =1
3336 my_coh_aver[pair[1],hvalid[valid]] =1
3387
3337
3388 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
3338 coh_echoes = (my_coh_aver[pair[0],:] == 1).nonzero()
3389 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
3339 incoh_echoes = (my_coh_aver[pair[0],:] != 1).nonzero()
3390 incoh_echoes = incoh_echoes[0]
3340 incoh_echoes = incoh_echoes[0]
3391 if len(incoh_echoes) > 0:
3341 if len(incoh_echoes) > 0:
3392 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
3342 my_incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
3393 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
3343 my_incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
3394 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
3344 my_incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
3395 my_incoh_aver[pair[0],incoh_echoes] = 1
3345 my_incoh_aver[pair[0],incoh_echoes] = 1
3396 my_incoh_aver[pair[1],incoh_echoes] = 1
3346 my_incoh_aver[pair[1],incoh_echoes] = 1
3397
3347
3398
3348
3399 for ic in range(nPairs):
3349 for ic in range(nPairs):
3400 pair = crosspairs[ic]
3350 pair = crosspairs[ic]
3401
3351
3402 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
3352 valid1 =(my_coh_aver[pair[0],:]==1 ).nonzero()
3403 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
3353 valid2 = (my_coh_aver[pair[1],:]==1).nonzero()
3404 valid1 = numpy.array(valid1[0])
3354 valid1 = numpy.array(valid1[0])
3405 valid2 = numpy.array(valid2[0])
3355 valid2 = numpy.array(valid2[0])
3406 valid = valid1
3356 valid = valid1
3407
3357
3408 for iv in range(len(valid2)):
3358 for iv in range(len(valid2)):
3409
3359
3410 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3360 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3411 if len(indv[0]) == 0 :
3361 if len(indv[0]) == 0 :
3412 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
3362 valid = numpy.concatenate((valid,valid2[iv]), axis=None)
3413 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
3363 valid1 =(my_coh_aver[pair[0],:] !=1 ).nonzero()
3414 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
3364 valid2 = (my_coh_aver[pair[1],:] !=1).nonzero()
3415 valid1 = numpy.array(valid1[0])
3365 valid1 = numpy.array(valid1[0])
3416 valid2 = numpy.array(valid2[0])
3366 valid2 = numpy.array(valid2[0])
3417 incoh_echoes = valid1
3367 incoh_echoes = valid1
3368
3418 for iv in range(len(valid2)):
3369 for iv in range(len(valid2)):
3419
3370
3420 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3371 indv = numpy.array((valid1 == valid2[iv]).nonzero())
3421 if len(indv[0]) == 0 :
3372 if len(indv[0]) == 0 :
3422 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
3373 incoh_echoes = numpy.concatenate(( incoh_echoes,valid2[iv]), axis=None)
3423
3374
3424 if len(valid)>0:
3375 if len(valid)>0:
3425 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
3376 coh_spectra[pair[0],:,valid] = spectra[pair[0],:,valid]
3426 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
3377 coh_spectra[pair[1],:,valid] = spectra[pair[1],:,valid]
3427 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
3378 coh_cspectra[ic,:,valid] = cspectra[ic,:,valid]
3428 coh_aver[pair[0],valid]=1
3379 coh_aver[pair[0],valid]=1
3429 coh_aver[pair[1],valid]=1
3380 coh_aver[pair[1],valid]=1
3430 if len(incoh_echoes)>0:
3381 if len(incoh_echoes)>0:
3431 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
3382 incoh_spectra[pair[0],:,incoh_echoes] = spectra[pair[0],:,incoh_echoes]
3432 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
3383 incoh_spectra[pair[1],:,incoh_echoes] = spectra[pair[1],:,incoh_echoes]
3433 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
3384 incoh_cspectra[ic,:,incoh_echoes] = cspectra[ic,:,incoh_echoes]
3434 incoh_aver[pair[0],incoh_echoes]=1
3385 incoh_aver[pair[0],incoh_echoes]=1
3435 incoh_aver[pair[1],incoh_echoes]=1
3386 incoh_aver[pair[1],incoh_echoes]=1
3387
3436 return my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver
3388 return my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver
3437
3389
3438
3439 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
3390 def __CleanCoherent(self,snrth, spectra, cspectra, coh_aver,dataOut, noise,clean_coh_echoes,index):
3440
3391
3392 #import matplotlib.pyplot as plt
3441 nProf = dataOut.nProfiles
3393 nProf = dataOut.nProfiles
3442 heights = dataOut.heightList
3394 heights = dataOut.heightList
3443 nHei = len(heights)
3395 nHei = len(heights)
3444 channels = dataOut.channelList
3396 channels = dataOut.channelList
3445 nChan = len(channels)
3397 nChan = len(channels)
3446 crosspairs = dataOut.groupList
3398 crosspairs = dataOut.groupList
3447 nPairs = len(crosspairs)
3399 nPairs = len(crosspairs)
3448
3400
3449 absc = dataOut.abscissaList[:-1]
3401 absc = dataOut.abscissaList[:-1]
3450 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
3402 data_param = numpy.zeros((nChan, 4, spectra.shape[2]))
3403
3451 clean_coh_spectra = spectra.copy()
3404 clean_coh_spectra = spectra.copy()
3452 clean_coh_cspectra = cspectra.copy()
3405 clean_coh_cspectra = cspectra.copy()
3453 clean_coh_aver = coh_aver.copy()
3406 clean_coh_aver = coh_aver.copy()
3454
3407
3455 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
3408 spwd_th=[10,6] #spwd_th[0] --> For satellites ; spwd_th[1] --> For special events like SUN.
3456 coh_th = 0.75
3409 coh_th = 0.75
3457
3410
3458 rtime0 = [6,18] # periodo sin ESF
3411 rtime0 = [6,18] # periodo sin ESF
3459 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
3412 rtime1 = [10.5,13.5] # periodo con alta coherencia y alto ancho espectral (esperado): SOL.
3460
3413
3461 time = index*5./60 # en base a 5 min de proceso
3414 time = index*5./60 # en base a 5 min de proceso
3462 if clean_coh_echoes == 1 :
3415 if clean_coh_echoes == 1 :
3463 for ind in range(nChan):
3416 for ind in range(nChan):
3464 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
3417 data_param[ind,:,:] = self.__calculateMoments( spectra[ind,:,:] , absc , noise[ind] )
3418
3465 spwd = data_param[:,3]
3419 spwd = data_param[:,3]
3420
3466 # SPECB_JULIA,header=anal_header,jspectra=spectra,vel=velocities,hei=heights, num_aver=1, mode_fit=0,smoothing=smoothing,jvelr=velr,jspwd=spwd,jsnr=snr,jnoise=noise,jstdvnoise=stdvnoise
3421 # SPECB_JULIA,header=anal_header,jspectra=spectra,vel=velocities,hei=heights, num_aver=1, mode_fit=0,smoothing=smoothing,jvelr=velr,jspwd=spwd,jsnr=snr,jnoise=noise,jstdvnoise=stdvnoise
3467 # para obtener spwd
3422 # para obtener spwd
3468 for ic in range(nPairs):
3423 for ic in range(nPairs):
3469 pair = crosspairs[ic]
3424 pair = crosspairs[ic]
3470 coh = numpy.squeeze(numpy.sum(cspectra[ic,:,:], axis=1)/numpy.sqrt(numpy.sum(spectra[pair[0],:,:], axis=1)*numpy.sum(spectra[pair[1],:,:], axis=1)))
3425 coh = numpy.squeeze(numpy.sum(cspectra[ic,:,:], axis=1)/numpy.sqrt(numpy.sum(spectra[pair[0],:,:], axis=1)*numpy.sum(spectra[pair[1],:,:], axis=1)))
3471 for ih in range(nHei) :
3426 for ih in range(nHei) :
3472 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
3427 # Considering heights higher than 200km in order to avoid removing phenomena like EEJ.
3473 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
3428 if heights[ih] >= 200 and coh_aver[pair[0],ih] == 1 and coh_aver[pair[1],ih] == 1 :
3474 # Checking coherence
3429 # Checking coherence
3475 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
3430 if (numpy.abs(coh[ih]) <= coh_th) or (time >= rtime0[0] and time <= rtime0[1]) :
3476 # Checking spectral widths
3431 # Checking spectral widths
3477 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
3432 if (spwd[pair[0],ih] > spwd_th[0]) or (spwd[pair[1],ih] > spwd_th[0]) :
3478 # satelite
3433 # satelite
3479 clean_coh_spectra[pair,ih,:] = 0.0
3434 clean_coh_spectra[pair,ih,:] = 0.0
3480 clean_coh_cspectra[ic,ih,:] = 0.0
3435 clean_coh_cspectra[ic,ih,:] = 0.0
3481 clean_coh_aver[pair,ih] = 0
3436 clean_coh_aver[pair,ih] = 0
3482 else :
3437 else :
3483 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
3438 if ((spwd[pair[0],ih] < spwd_th[1]) or (spwd[pair[1],ih] < spwd_th[1])) :
3484 # Especial event like sun.
3439 # Especial event like sun.
3485 clean_coh_spectra[pair,ih,:] = 0.0
3440 clean_coh_spectra[pair,ih,:] = 0.0
3486 clean_coh_cspectra[ic,ih,:] = 0.0
3441 clean_coh_cspectra[ic,ih,:] = 0.0
3487 clean_coh_aver[pair,ih] = 0
3442 clean_coh_aver[pair,ih] = 0
3488
3443
3489 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
3444 return clean_coh_spectra, clean_coh_cspectra, clean_coh_aver
3490
3445
3491 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
3446 def CleanRayleigh(self,dataOut,spectra,cspectra,save_drifts):
3492
3447
3493 rfunc = cspectra.copy()
3448 rfunc = cspectra.copy()
3494 n_funct = len(rfunc[0,:,0,0])
3449 n_funct = len(rfunc[0,:,0,0])
3495 val_spc = spectra*0.0
3450 val_spc = spectra*0.0
3496 val_cspc = cspectra*0.0
3451 val_cspc = cspectra*0.0
3497 in_sat_spectra = spectra.copy()
3452 in_sat_spectra = spectra.copy()
3498 in_sat_cspectra = cspectra.copy()
3453 in_sat_cspectra = cspectra.copy()
3499
3454
3500 min_hei = 200
3455 min_hei = 200
3501 nProf = dataOut.nProfiles
3456 nProf = dataOut.nProfiles
3502 heights = dataOut.heightList
3457 heights = dataOut.heightList
3503 nHei = len(heights)
3458 nHei = len(heights)
3504 channels = dataOut.channelList
3459 channels = dataOut.channelList
3505 nChan = len(channels)
3460 nChan = len(channels)
3506 crosspairs = dataOut.groupList
3461 crosspairs = dataOut.groupList
3507 nPairs = len(crosspairs)
3462 nPairs = len(crosspairs)
3508 hval=(heights >= min_hei).nonzero()
3463 hval=(heights >= min_hei).nonzero()
3509 ih=hval[0]
3464 ih=hval[0]
3465
3466
3510 for ih in range(hval[0][0],nHei):
3467 for ih in range(hval[0][0],nHei):
3511 for ifreq in range(nProf):
3468 for ifreq in range(nProf):
3512 for ii in range(n_funct):
3469 for ii in range(n_funct):
3513
3470
3514 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
3471 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih]))
3472
3515 val = (numpy.isfinite(func2clean)==True).nonzero()
3473 val = (numpy.isfinite(func2clean)==True).nonzero()
3516 if len(val)>0:
3474 if len(val)>0:
3517 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
3475 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
3518 if min_val <= -40 : min_val = -40
3476 if min_val <= -40 : min_val = -40
3519 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
3477 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
3520 if max_val >= 200 : max_val = 200
3478 if max_val >= 200 : max_val = 200
3479
3521 step = 1
3480 step = 1
3522 #Getting bins and the histogram
3481 #Getting bins and the histogram
3523 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
3482 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
3524 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
3483 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
3525 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
3484 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
3526 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
3485 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
3527 parg = [numpy.amax(y_dist),mean,sigma]
3486 parg = [numpy.amax(y_dist),mean,sigma]
3528 try :
3487 try :
3529 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
3488 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
3530 mode = gauss_fit[1]
3489 mode = gauss_fit[1]
3531 stdv = gauss_fit[2]
3490 stdv = gauss_fit[2]
3532 except:
3491 except:
3533 mode = mean
3492 mode = mean
3534 stdv = sigma
3493 stdv = sigma
3535
3494
3536 #Removing echoes greater than mode + 3*stdv
3495 #Removing echoes greater than mode + 3*stdv
3537 factor_stdv = 2.5
3496 factor_stdv = 2.5
3538 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
3497 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
3539
3498
3540 if len(noval[0]) > 0:
3499 if len(noval[0]) > 0:
3541 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
3500 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
3542 cross_pairs = crosspairs[ii]
3501 cross_pairs = crosspairs[ii]
3543 #Getting coherent echoes which are removed.
3502 #Getting coherent echoes which are removed.
3544 if len(novall[0]) > 0:
3503 if len(novall[0]) > 0:
3545 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
3504 val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
3546 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
3505 val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
3547 val_cspc[novall[0],ii,ifreq,ih] = 1
3506 val_cspc[novall[0],ii,ifreq,ih] = 1
3548 #Removing coherent from ISR data
3507 #Removing coherent from ISR data
3549 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
3508 spectra[noval,cross_pairs[0],ifreq,ih] = numpy.nan
3550 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
3509 spectra[noval,cross_pairs[1],ifreq,ih] = numpy.nan
3551 cspectra[noval,ii,ifreq,ih] = numpy.nan
3510 cspectra[noval,ii,ifreq,ih] = numpy.nan
3552
3511 #
3512 #no sale es para savedrifts >2
3513 ''' channels = dataOut.channelList
3514 cross_pairs = dataOut.groupList
3515
3516 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
3517 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
3518 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
3519
3520 #Getting coherent echoes which are removed.
3521 if len(novall) > 0:
3522 #val_spc[novall,ii,ifreq,ih] = 1
3523 val_spc[ii,ifreq,ih,novall] = 1
3524 if len(vcross) > 0:
3525 val_cspc[vcross,ifreq,ih,novall] = 1
3526
3527 #Removing coherent from ISR data.
3528 spectra[ii,ifreq,ih,noval] = numpy.nan
3529 if len(vcross) > 0:
3530 cspectra[vcross,ifreq,ih,noval] = numpy.nan
3531 '''
3553 #Getting average of the spectra and cross-spectra from incoherent echoes.
3532 #Getting average of the spectra and cross-spectra from incoherent echoes.
3533
3554 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
3534 out_spectra = numpy.zeros([nChan,nProf,nHei], dtype=float) #+numpy.nan
3555 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
3535 out_cspectra = numpy.zeros([nPairs,nProf,nHei], dtype=complex) #+numpy.nan
3556 for ih in range(nHei):
3536 for ih in range(nHei):
3557 for ifreq in range(nProf):
3537 for ifreq in range(nProf):
3558 for ich in range(nChan):
3538 for ich in range(nChan):
3559 tmp = spectra[:,ich,ifreq,ih]
3539 tmp = spectra[:,ich,ifreq,ih]
3560 valid = (numpy.isfinite(tmp[:])==True).nonzero()
3540 valid = (numpy.isfinite(tmp[:])==True).nonzero()
3561 if len(valid[0]) >0 :
3541 if len(valid[0]) >0 :
3562 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3542 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3543
3563 for icr in range(nPairs):
3544 for icr in range(nPairs):
3564 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
3545 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
3565 valid = (numpy.isfinite(tmp)==True).nonzero()
3546 valid = (numpy.isfinite(tmp)==True).nonzero()
3566 if len(valid[0]) > 0:
3547 if len(valid[0]) > 0:
3567 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3548 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3568 #Removing fake coherent echoes (at least 4 points around the point)
3549 #Removing fake coherent echoes (at least 4 points around the point)
3569 val_spectra = numpy.sum(val_spc,0)
3550 val_spectra = numpy.sum(val_spc,0)
3570 val_cspectra = numpy.sum(val_cspc,0)
3551 val_cspectra = numpy.sum(val_cspc,0)
3571
3552
3572 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
3553 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
3573 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
3554 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
3574
3555
3575 for i in range(nChan):
3556 for i in range(nChan):
3576 for j in range(nProf):
3557 for j in range(nProf):
3577 for k in range(nHei):
3558 for k in range(nHei):
3578 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
3559 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
3579 val_spc[:,i,j,k] = 0.0
3560 val_spc[:,i,j,k] = 0.0
3580 for i in range(nPairs):
3561 for i in range(nPairs):
3581 for j in range(nProf):
3562 for j in range(nProf):
3582 for k in range(nHei):
3563 for k in range(nHei):
3583 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
3564 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
3584 val_cspc[:,i,j,k] = 0.0
3565 val_cspc[:,i,j,k] = 0.0
3566 # val_spc = numpy.reshape(val_spc, (len(spectra[:,0,0,0]),nProf*nHei*nChan))
3567 # if numpy.isfinite(val_spectra)==str(True):
3568 # noval = (val_spectra<1).nonzero()
3569 # if len(noval) > 0:
3570 # val_spc[:,noval] = 0.0
3571 # val_spc = numpy.reshape(val_spc, (149,nChan,nProf,nHei))
3572
3573 #val_cspc = numpy.reshape(val_spc, (149,nChan*nHei*nProf))
3574 #if numpy.isfinite(val_cspectra)==str(True):
3575 # noval = (val_cspectra<1).nonzero()
3576 # if len(noval) > 0:
3577 # val_cspc[:,noval] = 0.0
3578 # val_cspc = numpy.reshape(val_cspc, (149,nChan,nProf,nHei))
3585
3579
3586 tmp_sat_spectra = spectra.copy()
3580 tmp_sat_spectra = spectra.copy()
3587 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
3581 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
3588 tmp_sat_cspectra = cspectra.copy()
3582 tmp_sat_cspectra = cspectra.copy()
3589 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
3583 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
3584
3590 val = (val_spc > 0).nonzero()
3585 val = (val_spc > 0).nonzero()
3591 if len(val[0]) > 0:
3586 if len(val[0]) > 0:
3592 tmp_sat_spectra[val] = in_sat_spectra[val]
3587 tmp_sat_spectra[val] = in_sat_spectra[val]
3593
3588
3594 val = (val_cspc > 0).nonzero()
3589 val = (val_cspc > 0).nonzero()
3595 if len(val[0]) > 0:
3590 if len(val[0]) > 0:
3596 tmp_sat_cspectra[val] = in_sat_cspectra[val]
3591 tmp_sat_cspectra[val] = in_sat_cspectra[val]
3597
3592
3598 #Getting average of the spectra and cross-spectra from incoherent echoes.
3593 #Getting average of the spectra and cross-spectra from incoherent echoes.
3599 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
3594 sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
3600 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
3595 sat_cspectra = numpy.zeros((nPairs,nProf,nHei), dtype=complex)
3601 for ih in range(nHei):
3596 for ih in range(nHei):
3602 for ifreq in range(nProf):
3597 for ifreq in range(nProf):
3603 for ich in range(nChan):
3598 for ich in range(nChan):
3604 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
3599 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
3605 valid = (numpy.isfinite(tmp)).nonzero()
3600 valid = (numpy.isfinite(tmp)).nonzero()
3606 if len(valid[0]) > 0:
3601 if len(valid[0]) > 0:
3607 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3602 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3608
3603
3609 for icr in range(nPairs):
3604 for icr in range(nPairs):
3610 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
3605 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
3611 valid = (numpy.isfinite(tmp)).nonzero()
3606 valid = (numpy.isfinite(tmp)).nonzero()
3612 if len(valid[0]) > 0:
3607 if len(valid[0]) > 0:
3613 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3608 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
3609
3614 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
3610 return out_spectra, out_cspectra,sat_spectra,sat_cspectra
3615
3616 def REM_ISOLATED_POINTS(self,array,rth):
3611 def REM_ISOLATED_POINTS(self,array,rth):
3617 if rth == None : rth = 4
3612 if rth == None : rth = 4
3618 num_prof = len(array[0,:,0])
3613 num_prof = len(array[0,:,0])
3619 num_hei = len(array[0,0,:])
3614 num_hei = len(array[0,0,:])
3620 n2d = len(array[:,0,0])
3615 n2d = len(array[:,0,0])
3621
3616
3622 for ii in range(n2d) :
3617 for ii in range(n2d) :
3623 tmp = array[ii,:,:]
3618 tmp = array[ii,:,:]
3624 tmp = numpy.reshape(tmp,num_prof*num_hei)
3619 tmp = numpy.reshape(tmp,num_prof*num_hei)
3625 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
3620 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
3626 indxs2 = (tmp > 0).nonzero()
3621 indxs2 = (tmp > 0).nonzero()
3627 indxs1 = (indxs1[0])
3622 indxs1 = (indxs1[0])
3628 indxs2 = indxs2[0]
3623 indxs2 = indxs2[0]
3629 indxs = None
3624 indxs = None
3625
3630 for iv in range(len(indxs2)):
3626 for iv in range(len(indxs2)):
3631 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
3627 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
3632 if len(indv[0]) > 0 :
3628 if len(indv[0]) > 0 :
3633 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
3629 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
3630
3634 indxs = indxs[1:]
3631 indxs = indxs[1:]
3635 if len(indxs) < 4 :
3632 if len(indxs) < 4 :
3636 array[ii,:,:] = 0.
3633 array[ii,:,:] = 0.
3637 return
3634 return
3638
3635
3639 xpos = numpy.mod(indxs ,num_hei)
3636 xpos = numpy.mod(indxs ,num_prof)
3640 ypos = (indxs / num_hei)
3637 ypos = (indxs / num_prof)
3641 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
3638 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
3642 xpos = xpos[sx]
3639 xpos = xpos[sx]
3643 ypos = ypos[sx]
3640 ypos = ypos[sx]
3644 # *********************************** Cleaning isolated points **********************************
3641
3642 # *********************************** Cleaning isolated points **********************************
3645 ic = 0
3643 ic = 0
3646 while True :
3644 while True :
3647 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
3645 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
3646
3648 no_coh1 = (numpy.isfinite(r)==True).nonzero()
3647 no_coh1 = (numpy.isfinite(r)==True).nonzero()
3649 no_coh2 = (r <= rth).nonzero()
3648 no_coh2 = (r <= rth).nonzero()
3650 no_coh1 = numpy.array(no_coh1[0])
3649 no_coh1 = numpy.array(no_coh1[0])
3651 no_coh2 = numpy.array(no_coh2[0])
3650 no_coh2 = numpy.array(no_coh2[0])
3652 no_coh = None
3651 no_coh = None
3653 for iv in range(len(no_coh2)):
3652 for iv in range(len(no_coh2)):
3654 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
3653 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
3655 if len(indv[0]) > 0 :
3654 if len(indv[0]) > 0 :
3656 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
3655 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
3657 no_coh = no_coh[1:]
3656 no_coh = no_coh[1:]
3658 if len(no_coh) < 4 :
3657 if len(no_coh) < 4 :
3659 xpos[ic] = numpy.nan
3658 xpos[ic] = numpy.nan
3660 ypos[ic] = numpy.nan
3659 ypos[ic] = numpy.nan
3661
3660
3662 ic = ic + 1
3661 ic = ic + 1
3663 if (ic == len(indxs)) :
3662 if (ic == len(indxs)) :
3664 break
3663 break
3665 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
3664 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
3666 if len(indxs[0]) < 4 :
3665 if len(indxs[0]) < 4 :
3667 array[ii,:,:] = 0.
3666 array[ii,:,:] = 0.
3668 return
3667 return
3669
3668
3670 xpos = xpos[indxs[0]]
3669 xpos = xpos[indxs[0]]
3671 ypos = ypos[indxs[0]]
3670 ypos = ypos[indxs[0]]
3672 for i in range(0,len(ypos)):
3671 for i in range(0,len(ypos)):
3673 ypos[i]=int(ypos[i])
3672 ypos[i]=int(ypos[i])
3674 junk = tmp
3673 junk = tmp
3675 tmp = junk*0.0
3674 tmp = junk*0.0
3676
3675
3677 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
3676 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
3678 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
3677 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
3678
3679 return array
3679 return array
3680
3681 def moments(self,doppler,yarray,npoints):
3680 def moments(self,doppler,yarray,npoints):
3682 ytemp = yarray
3681 ytemp = yarray
3683 val = (ytemp > 0).nonzero()
3682 val = (ytemp > 0).nonzero()
3684 val = val[0]
3683 val = val[0]
3685 if len(val) == 0 : val = range(npoints-1)
3684 if len(val) == 0 : val = range(npoints-1)
3686
3685
3687 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
3686 ynew = 0.5*(ytemp[val[0]]+ytemp[val[len(val)-1]])
3688 ytemp[len(ytemp):] = [ynew]
3687 ytemp[len(ytemp):] = [ynew]
3689
3688
3690 index = 0
3689 index = 0
3691 index = numpy.argmax(ytemp)
3690 index = numpy.argmax(ytemp)
3692 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
3691 ytemp = numpy.roll(ytemp,int(npoints/2)-1-index)
3693 ytemp = ytemp[0:npoints-1]
3692 ytemp = ytemp[0:npoints-1]
3694
3693
3695 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
3694 fmom = numpy.sum(doppler*ytemp)/numpy.sum(ytemp)+(index-(npoints/2-1))*numpy.abs(doppler[1]-doppler[0])
3696 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
3695 smom = numpy.sum(doppler*doppler*ytemp)/numpy.sum(ytemp)
3697 return [fmom,numpy.sqrt(smom)]
3696 return [fmom,numpy.sqrt(smom)]
3698
3697 # **********************************************************************************************
3698 index = 0
3699 fint = 0
3700 buffer = 0
3701 buffer2 = 0
3702 buffer3 = 0
3699 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None, filec=None,coh_th=None, hei_th=None,taver=None,proc=None,nhei=None,nprofs=None,ipp=None,channelList=None):
3703 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None, filec=None,coh_th=None, hei_th=None,taver=None,proc=None,nhei=None,nprofs=None,ipp=None,channelList=None):
3700 if not self.isConfig:
3704 if not numpy.any(proc):
3701 self.setup(dataOut = dataOut,groupList=groupList,path=path,file=file,filec=filec)
3705
3702 self.isConfig = True
3706 nChannels = dataOut.nChannels
3703
3707 nHeights= dataOut.heightList.size
3704 if not numpy.any(proc):
3708 nProf = dataOut.nProfiles
3705 if numpy.any(taver):
3709 if numpy.any(taver): taver=int(taver)
3706 taver = int(taver)
3710 else : taver = 5
3707 else :
3711 tini=time.localtime(dataOut.utctime)
3708 taver = 5
3712 if (tini.tm_min % taver) == 0 and (tini.tm_sec < 5 and self.fint==0):
3709 tini = time.localtime(dataOut.utctime)
3713
3710 if (tini.tm_min % taver) == 0 and (tini.tm_sec < 5 and self.fint==0):
3714 self.index = 0
3711 self.index = 0
3715 jspc = self.buffer
3712 jspc = self.buffer
3716 jcspc = self.buffer2
3713 jcspc = self.buffer2
3717 jnoise = self.buffer3
3714 jnoise = self.buffer3
3718 self.buffer = dataOut.data_spc
3715 self.buffer = dataOut.data_spc
3716 self.buffer2 = dataOut.data_cspc
3719 self.buffer2 = dataOut.data_cspc
3717 self.buffer3 = dataOut.noise
3720 self.buffer3 = dataOut.noise
3718 self.fint = 1
3721 self.fint = 1
3719 if numpy.any(jspc) :
3722 if numpy.any(jspc) :
3720 jspc = numpy.reshape(jspc ,(int(len(jspc) / self.nChannels) , self.nChannels ,self.nProf,self.nHeights ))
3723 jspc= numpy.reshape(jspc,(int(len(jspc)/nChannels),nChannels,nProf,nHeights))
3721 jcspc = numpy.reshape(jcspc ,(int(len(jcspc) /int(self.nChannels/2)),int(self.nChannels/2),self.nProf,self.nHeights ))
3724 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/int(nChannels/2)),int(nChannels/2),nProf,nHeights))
3722 jnoise = numpy.reshape(jnoise,(int(len(jnoise)/ self.nChannels) , self.nChannels))
3725 jnoise= numpy.reshape(jnoise,(int(len(jnoise)/nChannels),nChannels))
3723 else:
3726 else:
3724 dataOut.flagNoData = True
3727 dataOut.flagNoData = True
3725 return dataOut
3728 return dataOut
3726 else :
3729 else :
3727 if (tini.tm_min % taver) == 0 :
3730 if (tini.tm_min % taver) == 0 : self.fint = 1
3728 self.fint = 1
3731 else : self.fint = 0
3729 else :
3730 self.fint = 0
3731
3732 self.index += 1
3732 self.index += 1
3733 if numpy.any(self.buffer):
3733 if numpy.any(self.buffer):
3734 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
3734 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
3735 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
3735 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
3736 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
3736 self.buffer3 = numpy.concatenate((self.buffer3,dataOut.noise), axis=0)
3737 else:
3737 else:
3738 self.buffer = dataOut.data_spc
3738 self.buffer = dataOut.data_spc
3739 self.buffer2 = dataOut.data_cspc
3739 self.buffer2 = dataOut.data_cspc
3740 self.buffer3 = dataOut.noise
3740 self.buffer3 = dataOut.noise
3741 dataOut.flagNoData = True
3741 dataOut.flagNoData = True
3742 return dataOut
3742 return dataOut
3743 if path != None:
3744 sys.path.append(path)
3745 self.library = importlib.import_module(file)
3746 if filec != None:
3747 self.weightf = importlib.import_module(filec)
3748 #self.weightf = importlib.import_module('weightfit')
3749
3750 #To be inserted as a parameter
3751 groupArray = numpy.array(groupList)
3752 #groupArray = numpy.array([[0,1],[2,3]])
3753 dataOut.groupList = groupArray
3754
3755 nGroups = groupArray.shape[0]
3756 nChannels = dataOut.nChannels
3757 nHeights = dataOut.heightList.size
3743
3758
3744 jnoise = jnoise/self.N# creo que falta dividirlo entre N
3759 #Parameters Array
3745 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
3760 dataOut.data_param = None
3746 index = tini.tm_hour*12+tini.tm_min/taver
3761 dataOut.data_paramC = None
3747 dataOut.index = index
3762 dataOut.clean_num_aver = None
3748 jspc = jspc/self.N/self.N
3763 dataOut.coh_num_aver = None
3749 jcspc = jcspc/self.N/self.N
3764 dataOut.tmp_spectra_i = None
3750
3765 dataOut.tmp_cspectra_i = None
3766 dataOut.tmp_spectra_c = None
3767 dataOut.tmp_cspectra_c = None
3768 dataOut.sat_spectra = None
3769 dataOut.sat_cspectra = None
3770 dataOut.index = None
3771
3772 #Set constants
3773 constants = self.library.setConstants(dataOut)
3774 dataOut.constants = constants
3775 M = dataOut.normFactor
3776 N = dataOut.nFFTPoints
3777
3778 ippSeconds = dataOut.ippSeconds
3779 K = dataOut.nIncohInt
3780 pairsArray = numpy.array(dataOut.pairsList)
3781
3782 snrth= 15
3783 spectra = dataOut.data_spc
3784 cspectra = dataOut.data_cspc
3785 nProf = dataOut.nProfiles
3786 heights = dataOut.heightList
3787 nHei = len(heights)
3788 channels = dataOut.channelList
3789 nChan = len(channels)
3790 nIncohInt = dataOut.nIncohInt
3791 crosspairs = dataOut.groupList
3792 noise = dataOut.noise
3793 jnoise = jnoise/N
3794 noise = numpy.nansum(jnoise,axis=0)#/len(jnoise)
3795 #print("NOISE-> ", 10*numpy.log10(noise))
3796 power = numpy.sum(spectra, axis=1)
3797 nPairs = len(crosspairs)
3798 absc = dataOut.abscissaList[:-1]
3799 #print('para escribir h5 ',dataOut.paramInterval)
3800 if not self.isConfig:
3801 self.isConfig = True
3802
3803 index = tini.tm_hour*12+tini.tm_min/taver
3804 dataOut.index= index
3805 jspc = jspc/N/N
3806 jcspc = jcspc/N/N
3751 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
3807 tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.CleanRayleigh(dataOut,jspc,jcspc,2)
3752 jspectra = tmp_spectra * len(jspc[:,0,0,0])
3808 jspectra = tmp_spectra*len(jspc[:,0,0,0])
3753 jcspectra = tmp_cspectra * len(jspc[:,0,0,0])
3809 jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
3754
3810 my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver = self.__DiffCoherent(jspectra, jcspectra, dataOut, noise, snrth,coh_th, hei_th)
3755 my_incoh_spectra ,my_incoh_cspectra,my_incoh_aver,my_coh_aver, incoh_spectra, coh_spectra, incoh_cspectra, coh_cspectra, incoh_aver, coh_aver = self.__DiffCoherent(jspectra, jcspectra, dataOut, noise, self.snrth,coh_th, hei_th)
3811 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
3756 clean_coh_spectra, clean_coh_cspectra, clean_coh_aver = self.__CleanCoherent(self.snrth, coh_spectra, coh_cspectra, coh_aver, dataOut, noise,1,index)
3812 dataOut.data_spc = incoh_spectra
3757
3813 dataOut.data_cspc = incoh_cspectra
3758 dataOut.data_spc = incoh_spectra
3814 dataOut.sat_spectra = sat_spectra
3759 dataOut.data_cspc = incoh_cspectra
3815 dataOut.sat_cspectra = sat_cspectra
3760 clean_num_aver = incoh_aver * len(jspc[:,0,0,0])
3816 # dataOut.data_spc = tmp_spectra
3761 coh_num_aver = clean_coh_aver* len(jspc[:,0,0,0])
3817 # dataOut.data_cspc = tmp_cspectra
3762 dataOut.clean_num_aver = clean_num_aver
3818
3763 dataOut.coh_num_aver = coh_num_aver
3819 clean_num_aver = incoh_aver*len(jspc[:,0,0,0])
3764
3820 coh_num_aver = clean_coh_aver*len(jspc[:,0,0,0])
3821 # clean_num_aver = (numpy.zeros([nChan, nHei])+1)*len(jspc[:,0,0,0])
3822 # coh_num_aver = numpy.zeros([nChan, nHei])*0*len(jspc[:,0,0,0])
3823 dataOut.clean_num_aver = clean_num_aver
3824 dataOut.coh_num_aver = coh_num_aver
3825 dataOut.tmp_spectra_i = incoh_spectra
3826 dataOut.tmp_cspectra_i = incoh_cspectra
3827 dataOut.tmp_spectra_c = clean_coh_spectra
3828 dataOut.tmp_cspectra_c = clean_coh_cspectra
3829 #List of possible combinations
3830 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
3831 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
3832
3833 if getSNR:
3834 listChannels = groupArray.reshape((groupArray.size))
3835 listChannels.sort()
3836 norm = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter #* jspc.shape[0]
3837 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise[listChannels], norm=norm)
3765 else:
3838 else:
3839 if numpy.any(taver): taver=int(taver)
3840 else : taver = 5
3841 tini=time.localtime(dataOut.utctime)
3842 index = tini.tm_hour*12+tini.tm_min/taver
3766 clean_num_aver = dataOut.clean_num_aver
3843 clean_num_aver = dataOut.clean_num_aver
3767 coh_num_aver = dataOut.coh_num_aver
3844 coh_num_aver = dataOut.coh_num_aver
3768 dataOut.data_spc = dataOut.tmp_spectra_i
3845 dataOut.data_spc = dataOut.tmp_spectra_i
3769 dataOut.data_cspc = dataOut.tmp_cspectra_i
3846 dataOut.data_cspc = dataOut.tmp_cspectra_i
3770 clean_coh_spectra = dataOut.tmp_spectra_c
3847 clean_coh_spectra = dataOut.tmp_spectra_c
3771 clean_coh_cspectra = dataOut.tmp_cspectra_c
3848 clean_coh_cspectra = dataOut.tmp_cspectra_c
3772 jspectra = dataOut.data_spc+clean_coh_spectra
3849 jspectra = dataOut.data_spc+clean_coh_spectra
3773 nHeights = len(dataOut.heightList) # nhei
3850 nHeights = len(dataOut.heightList) # nhei
3774 nProf = int(dataOut.nProfiles)
3851 nProf = int(dataOut.nProfiles)
3775 dataOut.nProfiles = nProf
3852 dataOut.nProfiles = nProf
3776 dataOut.data_param = None
3853 dataOut.data_param = None
3777 dataOut.data_paramC = None
3854 dataOut.data_paramC = None
3778 dataOut.code = numpy.array([[-1.,-1.,1.],[1.,1.,-1.]])
3855 dataOut.code = numpy.array([[-1.,-1.,1.],[1.,1.,-1.]])
3856 #dataOut.paramInterval = 2.0
3779 #M=600
3857 #M=600
3780 #N=200
3858 #N=200
3781 dataOut.flagDecodeData=True
3859 dataOut.flagDecodeData=True
3782 M = int(dataOut.normFactor)
3860 M = int(dataOut.normFactor)
3783 N = int(dataOut.nFFTPoints)
3861 N = int(dataOut.nFFTPoints)
3784 dataOut.nFFTPoints = N
3862 dataOut.nFFTPoints = N
3785 dataOut.nIncohInt= int(dataOut.nIncohInt)
3863 dataOut.nIncohInt= int(dataOut.nIncohInt)
3786 dataOut.nProfiles = int(dataOut.nProfiles)
3864 dataOut.nProfiles = int(dataOut.nProfiles)
3787 dataOut.nCohInt = int(dataOut.nCohInt)
3865 dataOut.nCohInt = int(dataOut.nCohInt)
3866 #print('sale',dataOut.nProfiles,dataOut.nHeights)
3788 #dataOut.nFFTPoints=nprofs
3867 #dataOut.nFFTPoints=nprofs
3789 #dataOut.normFactor = nprofs
3868 #dataOut.normFactor = nprofs
3790 dataOut.channelList = channelList
3869 dataOut.channelList = channelList
3870 nChan = len(channelList)
3791 #dataOut.ippFactor=1
3871 #dataOut.ippFactor=1
3792 #ipp = ipp/150*1.e-3
3872 #ipp = ipp/150*1.e-3
3793 vmax = (300000000/49920000.0/2) / (dataOut.ippSeconds)
3873 vmax = (300000000/49920000.0/2) / (dataOut.ippSeconds)
3794 #dataOut.ippSeconds=ipp
3874 #dataOut.ippSeconds=ipp
3795 absc = vmax*( numpy.arange(nProf,dtype='float')-nProf/2.)/nProf
3875 absc = vmax*( numpy.arange(nProf,dtype='float')-nProf/2.)/nProf
3876 #print('sale 2',dataOut.ippSeconds,M,N)
3877 # print('Empieza procesamiento offline')
3796 if path != None:
3878 if path != None:
3797 sys.path.append(path)
3879 sys.path.append(path)
3798 self.library = importlib.import_module(file)
3880 self.library = importlib.import_module(file)
3799 constants = self.library.setConstants(dataOut)
3881 constants = self.library.setConstants(dataOut)
3800 constants['M'] = M
3882 constants['M'] = M
3801 dataOut.constants = constants
3883 dataOut.constants = constants
3802
3884 if filec != None:
3803 #List of possible combinations
3885 self.weightf = importlib.import_module(filec)
3804 listComb = itertools.combinations(numpy.arange(self.groupArray.shape[1]),2)
3886
3887 groupArray = numpy.array(groupList)
3888 dataOut.groupList = groupArray
3889 nGroups = groupArray.shape[0]
3890 #List of possible combinations
3891 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
3805 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
3892 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
3806 if dataOut.data_paramC is None:
3893 if dataOut.data_paramC is None:
3807 dataOut.data_paramC = numpy.zeros((self.nGroups*4, self.nHeights ,2))*numpy.nan
3894 dataOut.data_paramC = numpy.zeros((nGroups*4, nHeights,2))*numpy.nan
3808 for i in range(self.nGroups):
3895 dataOut.data_snr1_i = numpy.zeros((nGroups*2, nHeights))*numpy.nan
3809 coord = self.groupArray[i,:]
3896 # dataOut.smooth_i = numpy.zeros((nGroups*2, nHeights))*numpy.nan
3897 for i in range(nGroups):
3898 coord = groupArray[i,:]
3810 #Input data array
3899 #Input data array
3811 data = dataOut.data_spc[coord,:,:]/(self.M*self.N)
3900 data = dataOut.data_spc[coord,:,:]/(M*N)
3812 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
3901 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
3813
3902
3814 #Cross Spectra data array for Covariance Matrixes
3903 #Cross Spectra data array for Covariance Matrixes
3815 ind = 0
3904 ind = 0
3816 for pairs in listComb:
3905 for pairs in listComb:
3817 pairsSel = numpy.array([coord[x],coord[y]])
3906 pairsSel = numpy.array([coord[x],coord[y]])
3818 indCross[ind] = int(numpy.where(numpy.all(self.pairsArray == pairsSel, axis = 1))[0][0])
3907 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
3819 ind += 1
3908 ind += 1
3820 dataCross = dataOut.data_cspc[indCross,:,:]/(self.M*self.N)
3909 dataCross = dataOut.data_cspc[indCross,:,:]/(M*N)
3821 dataCross = dataCross**2
3910 dataCross = dataCross**2
3822 nhei = self.nHeights
3911 nhei = nHeights
3823 poweri = numpy.sum(dataOut.data_spc[:,1:self.nProf-0,:],axis=1)/clean_num_aver[:,:]
3912 poweri = numpy.sum(dataOut.data_spc[:,1:nProf-0,:],axis=1)/clean_num_aver[:,:]
3824
3825 if i == 0 : my_noises = numpy.zeros(4,dtype=float)
3913 if i == 0 : my_noises = numpy.zeros(4,dtype=float)
3826 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(self.nProf-1)
3914 n0i = numpy.nanmin(poweri[0+i*2,0:nhei-0])/(nProf-1)
3827 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(self.nProf-1)
3915 n1i = numpy.nanmin(poweri[1+i*2,0:nhei-0])/(nProf-1)
3828 n0 = n0i
3916 n0 = n0i
3829 n1= n1i
3917 n1= n1i
3830 my_noises[2*i+0] = n0
3918 my_noises[2*i+0] = n0
3831 my_noises[2*i+1] = n1
3919 my_noises[2*i+1] = n1
3832 snrth = -15.0 # -4 -16 -25
3920 snrth = -13.0 # -4 -16 -25
3833 snrth = 10**(snrth/10.0)
3921 snrth = 10**(snrth/10.0)
3834 jvelr = numpy.zeros(self.nHeights, dtype = 'float')
3922 jvelr = numpy.zeros(nHeights, dtype = 'float')
3923 #snr0 = numpy.zeros(nHeights, dtype = 'float')
3924 #snr1 = numpy.zeros(nHeights, dtype = 'float')
3835 hvalid = [0]
3925 hvalid = [0]
3836 coh2 = abs(dataOut.data_cspc[i,1:self.nProf,:])**2/(dataOut.data_spc[0+i*2,1:self.nProf-0,:]*dataOut.data_spc[1+i*2,1:self.nProf-0,:])
3926
3837
3927 coh2 = abs(dataOut.data_cspc[i,1:nProf,:])**2/(dataOut.data_spc[0+i*2,1:nProf-0,:]*dataOut.data_spc[1+i*2,1:nProf-0,:])
3838 for h in range(self.nHeights):
3928
3929 for h in range(nHeights):
3839 smooth = clean_num_aver[i+1,h]
3930 smooth = clean_num_aver[i+1,h]
3840 signalpn0 = (dataOut.data_spc[i*2,1:(self.nProf-0),h])/smooth
3931 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
3841 signalpn1 = (dataOut.data_spc[i*2+1,1:(self.nProf-0),h])/smooth
3932 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
3842 signal0 = signalpn0-n0
3933 signal0 = signalpn0-n0
3843 signal1 = signalpn1-n1
3934 signal1 = signalpn1-n1
3844 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
3935 snr0 = numpy.sum(signal0/n0)/(nProf-1)
3845 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
3936 snr1 = numpy.sum(signal1/n1)/(nProf-1)
3937 #jmax0 = MAX(signal0,maxp0)
3938 #jmax1 = MAX(signal1,maxp1)
3846 gamma = coh2[:,h]
3939 gamma = coh2[:,h]
3940
3847 indxs = (numpy.isfinite(list(gamma))==True).nonzero()
3941 indxs = (numpy.isfinite(list(gamma))==True).nonzero()
3942
3848 if len(indxs) >0:
3943 if len(indxs) >0:
3849 if numpy.nanmean(gamma) > 0.07:
3944 if numpy.nanmean(gamma) > 0.07:
3850 maxp0 = numpy.argmax(signal0*gamma)
3945 maxp0 = numpy.argmax(signal0*gamma)
3851 maxp1 = numpy.argmax(signal1*gamma)
3946 maxp1 = numpy.argmax(signal1*gamma)
3852 #print('usa gamma',numpy.nanmean(gamma))
3947 #print('usa gamma',numpy.nanmean(gamma))
3853 else:
3948 else:
3854 maxp0 = numpy.argmax(signal0)
3949 maxp0 = numpy.argmax(signal0)
3855 maxp1 = numpy.argmax(signal1)
3950 maxp1 = numpy.argmax(signal1)
3856 jvelr[h] = (self.absc[maxp0]+self.absc[maxp1])/2.
3951 jvelr[h] = (absc[maxp0]+absc[maxp1])/2.
3857 else: jvelr[h] = self.absc[0]
3952 else: jvelr[h] = absc[0]
3858 if snr0 > 0.1 and snr1 > 0.1: hvalid = numpy.concatenate((hvalid,h), axis=None)
3953 if snr0 > 0.1 and snr1 > 0.1: hvalid = numpy.concatenate((hvalid,h), axis=None)
3859 #print(maxp0,absc[maxp0],snr0,jvelr[h])
3954 #print(maxp0,absc[maxp0],snr0,jvelr[h])
3860
3955
3861 if len(hvalid)> 1: fd0 = numpy.median(jvelr[hvalid[1:]])*-1
3956 if len(hvalid)> 1: fd0 = numpy.median(jvelr[hvalid[1:]])*-1
3862 else: fd0 = numpy.nan
3957 else: fd0 = numpy.nan
3863 for h in range(self.nHeights):
3958 #print(fd0)
3959 for h in range(nHeights):
3864 d = data[:,h]
3960 d = data[:,h]
3865 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
3961 smooth = clean_num_aver[i+1,h] #dataOut.data_spc[:,1:nProf-0,:]
3866 signalpn0 = (dataOut.data_spc[i*2,1:(self.nProf-0),h])/smooth
3962 signalpn0 = (dataOut.data_spc[i*2,1:(nProf-0),h])/smooth
3867 signalpn1 = (dataOut.data_spc[i*2+1,1:(self.nProf-0),h])/smooth
3963 signalpn1 = (dataOut.data_spc[i*2+1,1:(nProf-0),h])/smooth
3868 signal0 = signalpn0-n0
3964 signal0 = signalpn0-n0
3869 signal1 = signalpn1-n1
3965 signal1 = signalpn1-n1
3870 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
3966 snr0 = numpy.sum(signal0/n0)/(nProf-1)
3871 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
3967 snr1 = numpy.sum(signal1/n1)/(nProf-1)
3968
3872 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
3969 if snr0 > snrth and snr1 > snrth and clean_num_aver[i+1,h] > 0 :
3873 #Covariance Matrix
3970 #Covariance Matrix
3874 D = numpy.diag(d**2)
3971 D = numpy.diag(d**2)
3875 ind = 0
3972 ind = 0
3876 for pairs in listComb:
3973 for pairs in listComb:
3877 #Coordinates in Covariance Matrix
3974 #Coordinates in Covariance Matrix
3878 x = pairs[0]
3975 x = pairs[0]
3879 y = pairs[1]
3976 y = pairs[1]
3880 #Channel Index
3977 #Channel Index
3881 S12 = dataCross[ind,:,h]
3978 S12 = dataCross[ind,:,h]
3882 D12 = numpy.diag(S12)
3979 D12 = numpy.diag(S12)
3883 #Completing Covariance Matrix with Cross Spectras
3980 #Completing Covariance Matrix with Cross Spectras
3884 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
3981 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
3885 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
3982 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
3886 ind += 1
3983 ind += 1
3887 diagD = numpy.zeros(256)
3984 diagD = numpy.zeros(256)
3888
3985
3986 #Dinv=numpy.linalg.inv(D)
3987 #L=numpy.linalg.cholesky(Dinv)
3889 try:
3988 try:
3890 Dinv=numpy.linalg.inv(D)
3989 Dinv=numpy.linalg.inv(D)
3891 L=numpy.linalg.cholesky(Dinv)
3990 L=numpy.linalg.cholesky(Dinv)
3892 except:
3991 except:
3893 Dinv = D*numpy.nan
3992 Dinv = D*numpy.nan
3894 L= D*numpy.nan
3993 L= D*numpy.nan
3895 LT=L.T
3994 LT=L.T
3896
3995
3897 dp = numpy.dot(LT,d)
3996 dp = numpy.dot(LT,d)
3898 #Initial values
3997
3998 #Initial values
3899 data_spc = dataOut.data_spc[coord,:,h]
3999 data_spc = dataOut.data_spc[coord,:,h]
3900 w = data_spc/data_spc
4000 w = data_spc/data_spc
3901 if filec != None:
4001 if filec != None:
3902 w = self.weightf.weightfit(w,tini.tm_year,tini.tm_yday,index,h,i)
4002 w = self.weightf.weightfit(w,tini.tm_year,tini.tm_yday,index,h,i)
3903 if (h>6)and(error1[3]<25):
4003
4004 if (h>6) and (error1[3]<25):
3904 p0 = dataOut.data_param[i,:,h-1].copy()
4005 p0 = dataOut.data_param[i,:,h-1].copy()
4006 #print('usa anterior')
3905 else:
4007 else:
3906 p0 = numpy.array(self.library.initialValuesFunction(data_spc*w, self.constants))# sin el i(data_spc, constants, i)
4008 p0 = numpy.array(self.library.initialValuesFunction(data_spc*w, constants))# sin el i(data_spc, constants, i)
3907 p0[3] = fd0
4009 p0[3] = fd0
3908
3909 if filec != None:
4010 if filec != None:
3910 p0 = self.weightf.Vrfit(p0,tini.tm_year,tini.tm_yday,index,h,i)
4011 p0 = self.weightf.Vrfit(p0,tini.tm_year,tini.tm_yday,index,h,i)
3911
4012
4013 #if index == 175 and i==1 and h>=27 and h<=35: p0[3]=30
4014 #if h >= 6 and i==1 and h<= 10: print(p0)
3912 try:
4015 try:
3913 #Least Squares
4016 #Least Squares
3914 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,self.constants),full_output=True)
4017 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
3915 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
4018 #minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
3916 #Chi square error
4019 #Chi square error
3917 error0 = numpy.sum(infodict['fvec']**2)/(2*self.N)
4020 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
3918 #Error with Jacobian
4021 #Error with Jacobian
3919 error1 = self.library.errorFunction(minp,self.constants,LT)
4022 error1 = self.library.errorFunction(minp,constants,LT)
4023 #if h >= 0 and h<= 10 and i ==0: print(p0,minp,error1)
4024 #if i>=0 and h>=0: print(index,h,minp[3])
4025 # print self.__residFunction(p0,dp,LT, constants)
4026 # print infodict['fvec']
4027 # print self.__residFunction(minp,dp,LT,constants)
3920
4028
3921 except:
4029 except:
3922 minp = p0*numpy.nan
4030 minp = p0*numpy.nan
3923 error0 = numpy.nan
4031 error0 = numpy.nan
3924 error1 = p0*numpy.nan
4032 error1 = p0*numpy.nan
4033 # s_sq = (self.__residFunction(minp,dp,LT,constants)).sum()/(len(dp)-len(p0))
4034 # covp = covp*s_sq
4035 # error = []
4036 # for ip in range(len(minp)):
4037 # try:
4038 # error.append(numpy.absolute(covp[ip][ip])**0.5)
4039 # except:
4040 # error.append( 0.00 )
4041 #if i==1 and h==11 and index == 139: print(p0, minp,data_spc)
3925 else :
4042 else :
3926 data_spc = dataOut.data_spc[coord,:,h]
4043 data_spc = dataOut.data_spc[coord,:,h]
3927 p0 = numpy.array(self.library.initialValuesFunction(data_spc, self.constants))
4044 p0 = numpy.array(self.library.initialValuesFunction(data_spc, constants))
3928 minp = p0*numpy.nan
4045 minp = p0*numpy.nan
3929 error0 = numpy.nan
4046 error0 = numpy.nan
3930 error1 = p0*numpy.nan
4047 error1 = p0*numpy.nan
4048
3931 if dataOut.data_param is None:
4049 if dataOut.data_param is None:
3932 dataOut.data_param = numpy.zeros((self.nGroups, p0.size, self.nHeights ))*numpy.nan
4050 dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
3933 dataOut.data_error = numpy.zeros((self.nGroups, p0.size + 1, self.nHeights ))*numpy.nan
4051 dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
4052
3934 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
4053 dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
3935 dataOut.data_param[i,:,h] = minp
4054 dataOut.data_param[i,:,h] = minp
3936
4055 dataOut.data_snr1_i[i*2,h] = numpy.sum(signalpn0/(nProf-1))/n0
3937 for ht in range(self.nHeights-1) :
4056 dataOut.data_snr1_i[i*2+1,h] = numpy.sum(signalpn1/(nProf-1))/n1
4057 #dataOut.smooth_i[i*2,h] = clean_num_aver[i+1,h]
4058 #print(fd0,dataOut.data_param[i,3,h])
4059 #print(fd0,dataOut.data_param[i,3,:])
4060 for ht in range(nHeights-1) :
3938 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
4061 smooth = coh_num_aver[i+1,ht] #datc[0,ht,0,beam]
3939 dataOut.data_paramC[4*i,ht,1] = smooth
4062 dataOut.data_paramC[4*i,ht,1] = smooth
3940 signalpn0 = (clean_coh_spectra[i*2 ,1:(self.nProf-0),ht])/smooth #coh_spectra
4063 signalpn0 = (clean_coh_spectra[i*2 ,1:(nProf-0),ht])/smooth #coh_spectra
3941 signalpn1 = (clean_coh_spectra[i*2+1,1:(self.nProf-0),ht])/smooth
4064 signalpn1 = (clean_coh_spectra[i*2+1,1:(nProf-0),ht])/smooth
4065
3942 val0 = (signalpn0 > 0).nonzero()
4066 val0 = (signalpn0 > 0).nonzero()
3943 val0 = val0[0]
4067 val0 = val0[0]
3944 if len(val0) == 0 : val0_npoints = self.nProf
4068
4069 if len(val0) == 0 : val0_npoints = nProf
3945 else : val0_npoints = len(val0)
4070 else : val0_npoints = len(val0)
3946
4071
3947 val1 = (signalpn1 > 0).nonzero()
4072 val1 = (signalpn1 > 0).nonzero()
3948 val1 = val1[0]
4073 val1 = val1[0]
3949 if len(val1) == 0 : val1_npoints = self.nProf
4074 if len(val1) == 0 : val1_npoints = nProf
3950 else : val1_npoints = len(val1)
4075 else : val1_npoints = len(val1)
3951
4076
3952 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
4077 dataOut.data_paramC[0+4*i,ht,0] = numpy.sum((signalpn0/val0_npoints))/n0
3953 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
4078 dataOut.data_paramC[1+4*i,ht,0] = numpy.sum((signalpn1/val1_npoints))/n1
3954
4079
3955 signal0 = (signalpn0-n0)
4080 signal0 = (signalpn0-n0)
3956 vali = (signal0 < 0).nonzero()
4081 vali = (signal0 < 0).nonzero()
3957 vali = vali[0]
4082 vali = vali[0]
3958 if len(vali) > 0 : signal0[vali] = 0
4083 if len(vali) > 0 : signal0[vali] = 0
3959 signal1 = (signalpn1-n1)
4084 signal1 = (signalpn1-n1)
3960 vali = (signal1 < 0).nonzero()
4085 vali = (signal1 < 0).nonzero()
3961 vali = vali[0]
4086 vali = vali[0]
3962 if len(vali) > 0 : signal1[vali] = 0
4087 if len(vali) > 0 : signal1[vali] = 0
3963 snr0 = numpy.sum(signal0/n0)/(self.nProf-1)
4088 snr0 = numpy.sum(signal0/n0)/(nProf-1)
3964 snr1 = numpy.sum(signal1/n1)/(self.nProf-1)
4089 snr1 = numpy.sum(signal1/n1)/(nProf-1)
3965 doppler = self.absc[1:]
4090 doppler = absc[1:]
3966 if snr0 >= snrth and snr1 >= snrth and smooth :
4091 if snr0 >= snrth and snr1 >= snrth and smooth :
3967 signalpn0_n0 = signalpn0
4092 signalpn0_n0 = signalpn0
3968 signalpn0_n0[val0] = signalpn0[val0] - n0
4093 signalpn0_n0[val0] = signalpn0[val0] - n0
3969 mom0 = self.moments(doppler,signalpn0-n0,self.nProf)
4094 mom0 = self.moments(doppler,signalpn0-n0,nProf)
4095
3970 signalpn1_n1 = signalpn1
4096 signalpn1_n1 = signalpn1
3971 signalpn1_n1[val1] = signalpn1[val1] - n1
4097 signalpn1_n1[val1] = signalpn1[val1] - n1
3972 mom1 = self.moments(doppler,signalpn1_n1,self.nProf)
4098 mom1 = self.moments(doppler,signalpn1_n1,nProf)
3973 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
4099 dataOut.data_paramC[2+4*i,ht,0] = (mom0[0]+mom1[0])/2.
3974 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
4100 dataOut.data_paramC[3+4*i,ht,0] = (mom0[1]+mom1[1])/2.
4101 #dataOut.data_snr1_c[i*2,ht] = numpy.sum(signalpn0/(nProf-1))/n0
4102 #dataOut.data_snr1_c[i*2+1,ht] = numpy.sum(signalpn1/(nProf-1))/n1
3975 dataOut.data_spc = jspectra
4103 dataOut.data_spc = jspectra
3976 dataOut.spc_noise = my_noises*self.nProf*self.M
4104 dataOut.spc_noise = my_noises*nProf*M
3977 if numpy.any(proc): dataOut.spc_noise = my_noises*self.nProf*self.M
4105
3978 if getSNR:
4106 if numpy.any(proc): dataOut.spc_noise = my_noises*nProf*M
3979 listChannels = self.groupArray.reshape((self.groupArray.size))
4107 if 0:
4108 listChannels = groupArray.reshape((groupArray.size))
3980 listChannels.sort()
4109 listChannels.sort()
3981 # TEST
4110 norm = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * dataOut.windowOfFilter
3982 noise_C = numpy.zeros(self.nChannels)
4111 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], my_noises[listChannels], norm=norm)
3983 noise_C = dataOut.getNoise()
4112 #print(dataOut.data_snr1_i)
3984 #print("noise_C",noise_C)
4113 # Adding coherent echoes from possible satellites.
3985 dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:],noise_C/(600.0*1.15))# PRUEBA *nProf*M
4114 #sat_spectra = numpy.zeros((nChan,nProf,nHei), dtype=float)
3986 #dataOut.data_snr = self.__getSNR(dataOut.data_spc[listChannels,:,:], noise_C[listChannels])# PRUEBA *nProf*M
4115 #sat_spectra = sat_spectra[*,*,anal_header.channels]
3987 dataOut.flagNoData = False
4116 isat_spectra = numpy.zeros([2,int(nChan/2),nProf,nhei], dtype=float)
4117
4118 sat_fits = numpy.zeros([4,nhei], dtype=float)
4119 noises = my_noises/nProf
4120 #nchan2 = int(nChan/2)
4121 for beam in range(int(nChan/2)-0) :
4122 n0 = noises[2*beam]
4123 n1 = noises[2*beam+1]
4124 isat_spectra[0:2,beam,:,:] = dataOut.sat_spectra[2*beam +0:2*beam+2 ,:,:]
4125
4126 for ht in range(nhei-1) :
4127 signalpn0 = isat_spectra[0,beam,:,ht]
4128 signalpn0 = numpy.reshape(signalpn0,nProf)
4129 signalpn1 = isat_spectra[1,beam,:,ht]
4130 signalpn1 = numpy.reshape(signalpn1,nProf)
4131
4132 cval0 = len((signalpn0 > 0).nonzero()[0])
4133 if cval0 == 0 : val0_npoints = nProf
4134 else: val0_npoints = cval0
4135
4136 cval1 = len((signalpn1 > 0).nonzero()[0])
4137 if cval1 == 0 : val1_npoints = nProf
4138 else: val1_npoints = cval1
4139
4140 sat_fits[0+2*beam,ht] = numpy.sum(signalpn0/(val0_npoints*nProf))/n0
4141 sat_fits[1+2*beam,ht] = numpy.sum(signalpn1/(val1_npoints*nProf))/n1
4142
4143 dataOut.sat_fits = sat_fits
3988 return dataOut
4144 return dataOut
3989
4145
3990 def __residFunction(self, p, dp, LT, constants):
4146 def __residFunction(self, p, dp, LT, constants):
3991
4147
3992 fm = self.library.modelFunction(p, constants)
4148 fm = self.library.modelFunction(p, constants)
3993 fmp=numpy.dot(LT,fm)
4149 fmp=numpy.dot(LT,fm)
3994 return dp-fmp
4150 return dp-fmp
3995
4151
3996 def __getSNR(self, z, noise):
4152 def __getSNR(self, z, noise, norm=1):
3997
4153
4154 # normFactor = dataOut.nProfiles * dataOut.nIncohInt * dataOut.nCohInt * pwcode * dataOut.windowOfFilter
3998 avg = numpy.average(z, axis=1)
4155 avg = numpy.average(z, axis=1)
4156 #noise /= norm
3999 SNR = (avg.T-noise)/noise
4157 SNR = (avg.T-noise)/noise
4158 # SNR = avg.T/noise
4159 # print("Noise: ", 10*numpy.log10(noise))
4160 # print("SNR: ", SNR)
4161 # print("SNR: ", 10*numpy.log10(SNR))
4000 SNR = SNR.T
4162 SNR = SNR.T
4001 return SNR
4163 return SNR
4002
4164
4003 def __chisq(self, p, chindex, hindex):
4165 def __chisq(self, p, chindex, hindex):
4004 #similar to Resid but calculates CHI**2
4166 #similar to Resid but calculates CHI**2
4005 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
4167 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
4006 dp=numpy.dot(LT,d)
4168 dp=numpy.dot(LT,d)
4007 fmp=numpy.dot(LT,fm)
4169 fmp=numpy.dot(LT,fm)
4008 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
4170 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
4009 return chisq
4171 return chisq
4010
4011 class WindProfiler(Operation):
4172 class WindProfiler(Operation):
4012
4173
4013 __isConfig = False
4174 __isConfig = False
4014
4175
4015 __initime = None
4176 __initime = None
4016 __lastdatatime = None
4177 __lastdatatime = None
4017 __integrationtime = None
4178 __integrationtime = None
4018
4179
4019 __buffer = None
4180 __buffer = None
4020
4181
4021 __dataReady = False
4182 __dataReady = False
4022
4183
4023 __firstdata = None
4184 __firstdata = None
4024
4185
4025 n = None
4186 n = None
4026
4187
4027 def __init__(self):
4188 def __init__(self):
4028 Operation.__init__(self)
4189 Operation.__init__(self)
4029
4190
4030 def __calculateCosDir(self, elev, azim):
4191 def __calculateCosDir(self, elev, azim):
4031 zen = (90 - elev)*numpy.pi/180
4192 zen = (90 - elev)*numpy.pi/180
4032 azim = azim*numpy.pi/180
4193 azim = azim*numpy.pi/180
4033 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
4194 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
4034 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
4195 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
4035
4196
4036 signX = numpy.sign(numpy.cos(azim))
4197 signX = numpy.sign(numpy.cos(azim))
4037 signY = numpy.sign(numpy.sin(azim))
4198 signY = numpy.sign(numpy.sin(azim))
4038
4199
4039 cosDirX = numpy.copysign(cosDirX, signX)
4200 cosDirX = numpy.copysign(cosDirX, signX)
4040 cosDirY = numpy.copysign(cosDirY, signY)
4201 cosDirY = numpy.copysign(cosDirY, signY)
4041 return cosDirX, cosDirY
4202 return cosDirX, cosDirY
4042
4203
4043 def __calculateAngles(self, theta_x, theta_y, azimuth):
4204 def __calculateAngles(self, theta_x, theta_y, azimuth):
4044
4205
4045 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
4206 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
4046 zenith_arr = numpy.arccos(dir_cosw)
4207 zenith_arr = numpy.arccos(dir_cosw)
4047 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
4208 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
4048
4209
4049 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
4210 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
4050 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
4211 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
4051
4212
4052 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
4213 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
4053
4214
4054 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
4215 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
4055
4216
4056 if horOnly:
4217 if horOnly:
4057 A = numpy.c_[dir_cosu,dir_cosv]
4218 A = numpy.c_[dir_cosu,dir_cosv]
4058 else:
4219 else:
4059 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
4220 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
4060 A = numpy.asmatrix(A)
4221 A = numpy.asmatrix(A)
4061 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
4222 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
4062
4223
4063 return A1
4224 return A1
4064
4225
4065 def __correctValues(self, heiRang, phi, velRadial, SNR):
4226 def __correctValues(self, heiRang, phi, velRadial, SNR):
4066 listPhi = phi.tolist()
4227 listPhi = phi.tolist()
4067 maxid = listPhi.index(max(listPhi))
4228 maxid = listPhi.index(max(listPhi))
4068 minid = listPhi.index(min(listPhi))
4229 minid = listPhi.index(min(listPhi))
4069
4230
4070 rango = list(range(len(phi)))
4231 rango = list(range(len(phi)))
4071
4232
4072 heiRang1 = heiRang*math.cos(phi[maxid])
4233 heiRang1 = heiRang*math.cos(phi[maxid])
4073 heiRangAux = heiRang*math.cos(phi[minid])
4234 heiRangAux = heiRang*math.cos(phi[minid])
4074 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4235 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4075 heiRang1 = numpy.delete(heiRang1,indOut)
4236 heiRang1 = numpy.delete(heiRang1,indOut)
4076
4237
4077 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4238 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4078 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4239 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4079
4240
4080 for i in rango:
4241 for i in rango:
4081 x = heiRang*math.cos(phi[i])
4242 x = heiRang*math.cos(phi[i])
4082 y1 = velRadial[i,:]
4243 y1 = velRadial[i,:]
4083 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
4244 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
4084
4245
4085 x1 = heiRang1
4246 x1 = heiRang1
4086 y11 = f1(x1)
4247 y11 = f1(x1)
4087
4248
4088 y2 = SNR[i,:]
4249 y2 = SNR[i,:]
4089 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
4250 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
4090 y21 = f2(x1)
4251 y21 = f2(x1)
4091
4252
4092 velRadial1[i,:] = y11
4253 velRadial1[i,:] = y11
4093 SNR1[i,:] = y21
4254 SNR1[i,:] = y21
4094
4255
4095 return heiRang1, velRadial1, SNR1
4256 return heiRang1, velRadial1, SNR1
4096
4257
4097 def __calculateVelUVW(self, A, velRadial):
4258 def __calculateVelUVW(self, A, velRadial):
4098
4259
4099 #Operacion Matricial
4260 #Operacion Matricial
4100 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
4261 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
4101 velUVW[:,:] = numpy.dot(A,velRadial)
4262 velUVW[:,:] = numpy.dot(A,velRadial)
4102
4263
4103
4264
4104 return velUVW
4265 return velUVW
4105
4266
4106 def techniqueDBS(self, kwargs):
4267 def techniqueDBS(self, kwargs):
4107 """
4268 """
4108 Function that implements Doppler Beam Swinging (DBS) technique.
4269 Function that implements Doppler Beam Swinging (DBS) technique.
4109
4270
4110 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
4271 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
4111 Direction correction (if necessary), Ranges and SNR
4272 Direction correction (if necessary), Ranges and SNR
4112
4273
4113 Output: Winds estimation (Zonal, Meridional and Vertical)
4274 Output: Winds estimation (Zonal, Meridional and Vertical)
4114
4275
4115 Parameters affected: Winds, height range, SNR
4276 Parameters affected: Winds, height range, SNR
4116 """
4277 """
4117 velRadial0 = kwargs['velRadial']
4278 velRadial0 = kwargs['velRadial']
4118 heiRang = kwargs['heightList']
4279 heiRang = kwargs['heightList']
4119 SNR0 = kwargs['SNR']
4280 SNR0 = kwargs['SNR']
4120
4281
4121 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
4282 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
4122 theta_x = numpy.array(kwargs['dirCosx'])
4283 theta_x = numpy.array(kwargs['dirCosx'])
4123 theta_y = numpy.array(kwargs['dirCosy'])
4284 theta_y = numpy.array(kwargs['dirCosy'])
4124 else:
4285 else:
4125 elev = numpy.array(kwargs['elevation'])
4286 elev = numpy.array(kwargs['elevation'])
4126 azim = numpy.array(kwargs['azimuth'])
4287 azim = numpy.array(kwargs['azimuth'])
4127 theta_x, theta_y = self.__calculateCosDir(elev, azim)
4288 theta_x, theta_y = self.__calculateCosDir(elev, azim)
4128 azimuth = kwargs['correctAzimuth']
4289 azimuth = kwargs['correctAzimuth']
4129 if 'horizontalOnly' in kwargs:
4290 if 'horizontalOnly' in kwargs:
4130 horizontalOnly = kwargs['horizontalOnly']
4291 horizontalOnly = kwargs['horizontalOnly']
4131 else: horizontalOnly = False
4292 else: horizontalOnly = False
4132 if 'correctFactor' in kwargs:
4293 if 'correctFactor' in kwargs:
4133 correctFactor = kwargs['correctFactor']
4294 correctFactor = kwargs['correctFactor']
4134 else: correctFactor = 1
4295 else: correctFactor = 1
4135 if 'channelList' in kwargs:
4296 if 'channelList' in kwargs:
4136 channelList = kwargs['channelList']
4297 channelList = kwargs['channelList']
4137 if len(channelList) == 2:
4298 if len(channelList) == 2:
4138 horizontalOnly = True
4299 horizontalOnly = True
4139 arrayChannel = numpy.array(channelList)
4300 arrayChannel = numpy.array(channelList)
4140 param = param[arrayChannel,:,:]
4301 param = param[arrayChannel,:,:]
4141 theta_x = theta_x[arrayChannel]
4302 theta_x = theta_x[arrayChannel]
4142 theta_y = theta_y[arrayChannel]
4303 theta_y = theta_y[arrayChannel]
4143
4304
4144 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4305 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4145 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
4306 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
4146 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
4307 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
4147
4308
4148 #Calculo de Componentes de la velocidad con DBS
4309 #Calculo de Componentes de la velocidad con DBS
4149 winds = self.__calculateVelUVW(A,velRadial1)
4310 winds = self.__calculateVelUVW(A,velRadial1)
4150
4311
4151 return winds, heiRang1, SNR1
4312 return winds, heiRang1, SNR1
4152
4313
4153 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
4314 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
4154
4315
4155 nPairs = len(pairs_ccf)
4316 nPairs = len(pairs_ccf)
4156 posx = numpy.asarray(posx)
4317 posx = numpy.asarray(posx)
4157 posy = numpy.asarray(posy)
4318 posy = numpy.asarray(posy)
4158
4319
4159 #Rotacion Inversa para alinear con el azimuth
4320 #Rotacion Inversa para alinear con el azimuth
4160 if azimuth!= None:
4321 if azimuth!= None:
4161 azimuth = azimuth*math.pi/180
4322 azimuth = azimuth*math.pi/180
4162 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
4323 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
4163 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
4324 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
4164 else:
4325 else:
4165 posx1 = posx
4326 posx1 = posx
4166 posy1 = posy
4327 posy1 = posy
4167
4328
4168 #Calculo de Distancias
4329 #Calculo de Distancias
4169 distx = numpy.zeros(nPairs)
4330 distx = numpy.zeros(nPairs)
4170 disty = numpy.zeros(nPairs)
4331 disty = numpy.zeros(nPairs)
4171 dist = numpy.zeros(nPairs)
4332 dist = numpy.zeros(nPairs)
4172 ang = numpy.zeros(nPairs)
4333 ang = numpy.zeros(nPairs)
4173
4334
4174 for i in range(nPairs):
4335 for i in range(nPairs):
4175 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
4336 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
4176 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
4337 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
4177 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
4338 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
4178 ang[i] = numpy.arctan2(disty[i],distx[i])
4339 ang[i] = numpy.arctan2(disty[i],distx[i])
4179
4340
4180 return distx, disty, dist, ang
4341 return distx, disty, dist, ang
4181 #Calculo de Matrices
4342 #Calculo de Matrices
4182
4343
4183
4344
4184 def __calculateVelVer(self, phase, lagTRange, _lambda):
4345 def __calculateVelVer(self, phase, lagTRange, _lambda):
4185
4346
4186 Ts = lagTRange[1] - lagTRange[0]
4347 Ts = lagTRange[1] - lagTRange[0]
4187 velW = -_lambda*phase/(4*math.pi*Ts)
4348 velW = -_lambda*phase/(4*math.pi*Ts)
4188
4349
4189 return velW
4350 return velW
4190
4351
4191 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
4352 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
4192 nPairs = tau1.shape[0]
4353 nPairs = tau1.shape[0]
4193 nHeights = tau1.shape[1]
4354 nHeights = tau1.shape[1]
4194 vel = numpy.zeros((nPairs,3,nHeights))
4355 vel = numpy.zeros((nPairs,3,nHeights))
4195 dist1 = numpy.reshape(dist, (dist.size,1))
4356 dist1 = numpy.reshape(dist, (dist.size,1))
4196
4357
4197 angCos = numpy.cos(ang)
4358 angCos = numpy.cos(ang)
4198 angSin = numpy.sin(ang)
4359 angSin = numpy.sin(ang)
4199
4360
4200 vel0 = dist1*tau1/(2*tau2**2)
4361 vel0 = dist1*tau1/(2*tau2**2)
4201 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
4362 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
4202 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
4363 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
4203
4364
4204 ind = numpy.where(numpy.isinf(vel))
4365 ind = numpy.where(numpy.isinf(vel))
4205 vel[ind] = numpy.nan
4366 vel[ind] = numpy.nan
4206
4367
4207 return vel
4368 return vel
4208
4369
4209 def techniqueSA(self, kwargs):
4370 def techniqueSA(self, kwargs):
4210
4371
4211 """
4372 """
4212 Function that implements Spaced Antenna (SA) technique.
4373 Function that implements Spaced Antenna (SA) technique.
4213
4374
4214 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
4375 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
4215 Direction correction (if necessary), Ranges and SNR
4376 Direction correction (if necessary), Ranges and SNR
4216
4377
4217 Output: Winds estimation (Zonal, Meridional and Vertical)
4378 Output: Winds estimation (Zonal, Meridional and Vertical)
4218
4379
4219 Parameters affected: Winds
4380 Parameters affected: Winds
4220 """
4381 """
4221 position_x = kwargs['positionX']
4382 position_x = kwargs['positionX']
4222 position_y = kwargs['positionY']
4383 position_y = kwargs['positionY']
4223 azimuth = kwargs['azimuth']
4384 azimuth = kwargs['azimuth']
4224
4385
4225 if 'correctFactor' in kwargs:
4386 if 'correctFactor' in kwargs:
4226 correctFactor = kwargs['correctFactor']
4387 correctFactor = kwargs['correctFactor']
4227 else:
4388 else:
4228 correctFactor = 1
4389 correctFactor = 1
4229
4390
4230 groupList = kwargs['groupList']
4391 groupList = kwargs['groupList']
4231 pairs_ccf = groupList[1]
4392 pairs_ccf = groupList[1]
4232 tau = kwargs['tau']
4393 tau = kwargs['tau']
4233 _lambda = kwargs['_lambda']
4394 _lambda = kwargs['_lambda']
4234
4395
4235 #Cross Correlation pairs obtained
4396 #Cross Correlation pairs obtained
4236
4397
4237 indtau = tau.shape[0]/2
4398 indtau = tau.shape[0]/2
4238 tau1 = tau[:indtau,:]
4399 tau1 = tau[:indtau,:]
4239 tau2 = tau[indtau:-1,:]
4400 tau2 = tau[indtau:-1,:]
4240 phase1 = tau[-1,:]
4401 phase1 = tau[-1,:]
4241
4402
4242 #---------------------------------------------------------------------
4403 #---------------------------------------------------------------------
4243 #Metodo Directo
4404 #Metodo Directo
4244 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
4405 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
4245 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
4406 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
4246 winds = stats.nanmean(winds, axis=0)
4407 winds = stats.nanmean(winds, axis=0)
4247 #---------------------------------------------------------------------
4408 #---------------------------------------------------------------------
4248 #Metodo General
4409 #Metodo General
4249
4410
4250 #---------------------------------------------------------------------
4411 #---------------------------------------------------------------------
4251 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
4412 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
4252 winds = correctFactor*winds
4413 winds = correctFactor*winds
4253 return winds
4414 return winds
4254
4415
4255 def __checkTime(self, currentTime, paramInterval, outputInterval):
4416 def __checkTime(self, currentTime, paramInterval, outputInterval):
4256
4417
4257 dataTime = currentTime + paramInterval
4418 dataTime = currentTime + paramInterval
4258 deltaTime = dataTime - self.__initime
4419 deltaTime = dataTime - self.__initime
4259
4420
4260 if deltaTime >= outputInterval or deltaTime < 0:
4421 if deltaTime >= outputInterval or deltaTime < 0:
4261 self.__dataReady = True
4422 self.__dataReady = True
4262 return
4423 return
4263
4424
4264 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
4425 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
4265 '''
4426 '''
4266 Function that implements winds estimation technique with detected meteors.
4427 Function that implements winds estimation technique with detected meteors.
4267
4428
4268 Input: Detected meteors, Minimum meteor quantity to wind estimation
4429 Input: Detected meteors, Minimum meteor quantity to wind estimation
4269
4430
4270 Output: Winds estimation (Zonal and Meridional)
4431 Output: Winds estimation (Zonal and Meridional)
4271
4432
4272 Parameters affected: Winds
4433 Parameters affected: Winds
4273 '''
4434 '''
4274 #Settings
4435 #Settings
4275 nInt = (heightMax - heightMin)/2
4436 nInt = (heightMax - heightMin)/2
4276 nInt = int(nInt)
4437 nInt = int(nInt)
4277 winds = numpy.zeros((2,nInt))*numpy.nan
4438 winds = numpy.zeros((2,nInt))*numpy.nan
4278
4439
4279 #Filter errors
4440 #Filter errors
4280 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
4441 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
4281 finalMeteor = arrayMeteor[error,:]
4442 finalMeteor = arrayMeteor[error,:]
4282
4443
4283 #Meteor Histogram
4444 #Meteor Histogram
4284 finalHeights = finalMeteor[:,2]
4445 finalHeights = finalMeteor[:,2]
4285 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
4446 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
4286 nMeteorsPerI = hist[0]
4447 nMeteorsPerI = hist[0]
4287 heightPerI = hist[1]
4448 heightPerI = hist[1]
4288
4449
4289 #Sort of meteors
4450 #Sort of meteors
4290 indSort = finalHeights.argsort()
4451 indSort = finalHeights.argsort()
4291 finalMeteor2 = finalMeteor[indSort,:]
4452 finalMeteor2 = finalMeteor[indSort,:]
4292
4453
4293 # Calculating winds
4454 # Calculating winds
4294 ind1 = 0
4455 ind1 = 0
4295 ind2 = 0
4456 ind2 = 0
4296
4457
4297 for i in range(nInt):
4458 for i in range(nInt):
4298 nMet = nMeteorsPerI[i]
4459 nMet = nMeteorsPerI[i]
4299 ind1 = ind2
4460 ind1 = ind2
4300 ind2 = ind1 + nMet
4461 ind2 = ind1 + nMet
4301
4462
4302 meteorAux = finalMeteor2[ind1:ind2,:]
4463 meteorAux = finalMeteor2[ind1:ind2,:]
4303
4464
4304 if meteorAux.shape[0] >= meteorThresh:
4465 if meteorAux.shape[0] >= meteorThresh:
4305 vel = meteorAux[:, 6]
4466 vel = meteorAux[:, 6]
4306 zen = meteorAux[:, 4]*numpy.pi/180
4467 zen = meteorAux[:, 4]*numpy.pi/180
4307 azim = meteorAux[:, 3]*numpy.pi/180
4468 azim = meteorAux[:, 3]*numpy.pi/180
4308
4469
4309 n = numpy.cos(zen)
4470 n = numpy.cos(zen)
4310 l = numpy.sin(zen)*numpy.sin(azim)
4471 l = numpy.sin(zen)*numpy.sin(azim)
4311 m = numpy.sin(zen)*numpy.cos(azim)
4472 m = numpy.sin(zen)*numpy.cos(azim)
4312
4473
4313 A = numpy.vstack((l, m)).transpose()
4474 A = numpy.vstack((l, m)).transpose()
4314 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
4475 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
4315 windsAux = numpy.dot(A1, vel)
4476 windsAux = numpy.dot(A1, vel)
4316
4477
4317 winds[0,i] = windsAux[0]
4478 winds[0,i] = windsAux[0]
4318 winds[1,i] = windsAux[1]
4479 winds[1,i] = windsAux[1]
4319
4480
4320 return winds, heightPerI[:-1]
4481 return winds, heightPerI[:-1]
4321
4482
4322 def techniqueNSM_SA(self, **kwargs):
4483 def techniqueNSM_SA(self, **kwargs):
4323 metArray = kwargs['metArray']
4484 metArray = kwargs['metArray']
4324 heightList = kwargs['heightList']
4485 heightList = kwargs['heightList']
4325 timeList = kwargs['timeList']
4486 timeList = kwargs['timeList']
4326
4487
4327 rx_location = kwargs['rx_location']
4488 rx_location = kwargs['rx_location']
4328 groupList = kwargs['groupList']
4489 groupList = kwargs['groupList']
4329 azimuth = kwargs['azimuth']
4490 azimuth = kwargs['azimuth']
4330 dfactor = kwargs['dfactor']
4491 dfactor = kwargs['dfactor']
4331 k = kwargs['k']
4492 k = kwargs['k']
4332
4493
4333 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
4494 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
4334 d = dist*dfactor
4495 d = dist*dfactor
4335 #Phase calculation
4496 #Phase calculation
4336 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
4497 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
4337
4498
4338 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
4499 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
4339
4500
4340 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4501 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4341 azimuth1 = azimuth1*numpy.pi/180
4502 azimuth1 = azimuth1*numpy.pi/180
4342
4503
4343 for i in range(heightList.size):
4504 for i in range(heightList.size):
4344 h = heightList[i]
4505 h = heightList[i]
4345 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
4506 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
4346 metHeight = metArray1[indH,:]
4507 metHeight = metArray1[indH,:]
4347 if metHeight.shape[0] >= 2:
4508 if metHeight.shape[0] >= 2:
4348 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
4509 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
4349 iazim = metHeight[:,1].astype(int)
4510 iazim = metHeight[:,1].astype(int)
4350 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
4511 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
4351 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
4512 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
4352 A = numpy.asmatrix(A)
4513 A = numpy.asmatrix(A)
4353 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
4514 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
4354 velHor = numpy.dot(A1,velAux)
4515 velHor = numpy.dot(A1,velAux)
4355
4516
4356 velEst[i,:] = numpy.squeeze(velHor)
4517 velEst[i,:] = numpy.squeeze(velHor)
4357 return velEst
4518 return velEst
4358
4519
4359 def __getPhaseSlope(self, metArray, heightList, timeList):
4520 def __getPhaseSlope(self, metArray, heightList, timeList):
4360 meteorList = []
4521 meteorList = []
4361 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
4522 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
4362 #Putting back together the meteor matrix
4523 #Putting back together the meteor matrix
4363 utctime = metArray[:,0]
4524 utctime = metArray[:,0]
4364 uniqueTime = numpy.unique(utctime)
4525 uniqueTime = numpy.unique(utctime)
4365
4526
4366 phaseDerThresh = 0.5
4527 phaseDerThresh = 0.5
4367 ippSeconds = timeList[1] - timeList[0]
4528 ippSeconds = timeList[1] - timeList[0]
4368 sec = numpy.where(timeList>1)[0][0]
4529 sec = numpy.where(timeList>1)[0][0]
4369 nPairs = metArray.shape[1] - 6
4530 nPairs = metArray.shape[1] - 6
4370 nHeights = len(heightList)
4531 nHeights = len(heightList)
4371
4532
4372 for t in uniqueTime:
4533 for t in uniqueTime:
4373 metArray1 = metArray[utctime==t,:]
4534 metArray1 = metArray[utctime==t,:]
4374 tmet = metArray1[:,1].astype(int)
4535 tmet = metArray1[:,1].astype(int)
4375 hmet = metArray1[:,2].astype(int)
4536 hmet = metArray1[:,2].astype(int)
4376
4537
4377 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
4538 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
4378 metPhase[:,:] = numpy.nan
4539 metPhase[:,:] = numpy.nan
4379 metPhase[:,hmet,tmet] = metArray1[:,6:].T
4540 metPhase[:,hmet,tmet] = metArray1[:,6:].T
4380
4541
4381 #Delete short trails
4542 #Delete short trails
4382 metBool = ~numpy.isnan(metPhase[0,:,:])
4543 metBool = ~numpy.isnan(metPhase[0,:,:])
4383 heightVect = numpy.sum(metBool, axis = 1)
4544 heightVect = numpy.sum(metBool, axis = 1)
4384 metBool[heightVect<sec,:] = False
4545 metBool[heightVect<sec,:] = False
4385 metPhase[:,heightVect<sec,:] = numpy.nan
4546 metPhase[:,heightVect<sec,:] = numpy.nan
4386
4547
4387 #Derivative
4548 #Derivative
4388 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
4549 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
4389 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
4550 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
4390 metPhase[phDerAux] = numpy.nan
4551 metPhase[phDerAux] = numpy.nan
4391
4552
4392 #--------------------------METEOR DETECTION -----------------------------------------
4553 #--------------------------METEOR DETECTION -----------------------------------------
4393 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
4554 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
4394
4555
4395 for p in numpy.arange(nPairs):
4556 for p in numpy.arange(nPairs):
4396 phase = metPhase[p,:,:]
4557 phase = metPhase[p,:,:]
4397 phDer = metDer[p,:,:]
4558 phDer = metDer[p,:,:]
4398
4559
4399 for h in indMet:
4560 for h in indMet:
4400 height = heightList[h]
4561 height = heightList[h]
4401 phase1 = phase[h,:] #82
4562 phase1 = phase[h,:] #82
4402 phDer1 = phDer[h,:]
4563 phDer1 = phDer[h,:]
4403
4564
4404 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
4565 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
4405
4566
4406 indValid = numpy.where(~numpy.isnan(phase1))[0]
4567 indValid = numpy.where(~numpy.isnan(phase1))[0]
4407 initMet = indValid[0]
4568 initMet = indValid[0]
4408 endMet = 0
4569 endMet = 0
4409
4570
4410 for i in range(len(indValid)-1):
4571 for i in range(len(indValid)-1):
4411
4572
4412 #Time difference
4573 #Time difference
4413 inow = indValid[i]
4574 inow = indValid[i]
4414 inext = indValid[i+1]
4575 inext = indValid[i+1]
4415 idiff = inext - inow
4576 idiff = inext - inow
4416 #Phase difference
4577 #Phase difference
4417 phDiff = numpy.abs(phase1[inext] - phase1[inow])
4578 phDiff = numpy.abs(phase1[inext] - phase1[inow])
4418
4579
4419 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
4580 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
4420 sizeTrail = inow - initMet + 1
4581 sizeTrail = inow - initMet + 1
4421 if sizeTrail>3*sec: #Too short meteors
4582 if sizeTrail>3*sec: #Too short meteors
4422 x = numpy.arange(initMet,inow+1)*ippSeconds
4583 x = numpy.arange(initMet,inow+1)*ippSeconds
4423 y = phase1[initMet:inow+1]
4584 y = phase1[initMet:inow+1]
4424 ynnan = ~numpy.isnan(y)
4585 ynnan = ~numpy.isnan(y)
4425 x = x[ynnan]
4586 x = x[ynnan]
4426 y = y[ynnan]
4587 y = y[ynnan]
4427 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
4588 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
4428 ylin = x*slope + intercept
4589 ylin = x*slope + intercept
4429 rsq = r_value**2
4590 rsq = r_value**2
4430 if rsq > 0.5:
4591 if rsq > 0.5:
4431 vel = slope#*height*1000/(k*d)
4592 vel = slope#*height*1000/(k*d)
4432 estAux = numpy.array([utctime,p,height, vel, rsq])
4593 estAux = numpy.array([utctime,p,height, vel, rsq])
4433 meteorList.append(estAux)
4594 meteorList.append(estAux)
4434 initMet = inext
4595 initMet = inext
4435 metArray2 = numpy.array(meteorList)
4596 metArray2 = numpy.array(meteorList)
4436
4597
4437 return metArray2
4598 return metArray2
4438
4599
4439 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
4600 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
4440
4601
4441 azimuth1 = numpy.zeros(len(pairslist))
4602 azimuth1 = numpy.zeros(len(pairslist))
4442 dist = numpy.zeros(len(pairslist))
4603 dist = numpy.zeros(len(pairslist))
4443
4604
4444 for i in range(len(rx_location)):
4605 for i in range(len(rx_location)):
4445 ch0 = pairslist[i][0]
4606 ch0 = pairslist[i][0]
4446 ch1 = pairslist[i][1]
4607 ch1 = pairslist[i][1]
4447
4608
4448 diffX = rx_location[ch0][0] - rx_location[ch1][0]
4609 diffX = rx_location[ch0][0] - rx_location[ch1][0]
4449 diffY = rx_location[ch0][1] - rx_location[ch1][1]
4610 diffY = rx_location[ch0][1] - rx_location[ch1][1]
4450 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
4611 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
4451 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
4612 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
4452
4613
4453 azimuth1 -= azimuth0
4614 azimuth1 -= azimuth0
4454 return azimuth1, dist
4615 return azimuth1, dist
4455
4616
4456 def techniqueNSM_DBS(self, **kwargs):
4617 def techniqueNSM_DBS(self, **kwargs):
4457 metArray = kwargs['metArray']
4618 metArray = kwargs['metArray']
4458 heightList = kwargs['heightList']
4619 heightList = kwargs['heightList']
4459 timeList = kwargs['timeList']
4620 timeList = kwargs['timeList']
4460 azimuth = kwargs['azimuth']
4621 azimuth = kwargs['azimuth']
4461 theta_x = numpy.array(kwargs['theta_x'])
4622 theta_x = numpy.array(kwargs['theta_x'])
4462 theta_y = numpy.array(kwargs['theta_y'])
4623 theta_y = numpy.array(kwargs['theta_y'])
4463
4624
4464 utctime = metArray[:,0]
4625 utctime = metArray[:,0]
4465 cmet = metArray[:,1].astype(int)
4626 cmet = metArray[:,1].astype(int)
4466 hmet = metArray[:,3].astype(int)
4627 hmet = metArray[:,3].astype(int)
4467 SNRmet = metArray[:,4]
4628 SNRmet = metArray[:,4]
4468 vmet = metArray[:,5]
4629 vmet = metArray[:,5]
4469 spcmet = metArray[:,6]
4630 spcmet = metArray[:,6]
4470
4631
4471 nChan = numpy.max(cmet) + 1
4632 nChan = numpy.max(cmet) + 1
4472 nHeights = len(heightList)
4633 nHeights = len(heightList)
4473
4634
4474 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4635 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
4475 hmet = heightList[hmet]
4636 hmet = heightList[hmet]
4476 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
4637 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
4477
4638
4478 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4639 velEst = numpy.zeros((heightList.size,2))*numpy.nan
4479
4640
4480 for i in range(nHeights - 1):
4641 for i in range(nHeights - 1):
4481 hmin = heightList[i]
4642 hmin = heightList[i]
4482 hmax = heightList[i + 1]
4643 hmax = heightList[i + 1]
4483
4644
4484 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
4645 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
4485 indthisH = numpy.where(thisH)
4646 indthisH = numpy.where(thisH)
4486
4647
4487 if numpy.size(indthisH) > 3:
4648 if numpy.size(indthisH) > 3:
4488
4649
4489 vel_aux = vmet[thisH]
4650 vel_aux = vmet[thisH]
4490 chan_aux = cmet[thisH]
4651 chan_aux = cmet[thisH]
4491 cosu_aux = dir_cosu[chan_aux]
4652 cosu_aux = dir_cosu[chan_aux]
4492 cosv_aux = dir_cosv[chan_aux]
4653 cosv_aux = dir_cosv[chan_aux]
4493 cosw_aux = dir_cosw[chan_aux]
4654 cosw_aux = dir_cosw[chan_aux]
4494
4655
4495 nch = numpy.size(numpy.unique(chan_aux))
4656 nch = numpy.size(numpy.unique(chan_aux))
4496 if nch > 1:
4657 if nch > 1:
4497 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
4658 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
4498 velEst[i,:] = numpy.dot(A,vel_aux)
4659 velEst[i,:] = numpy.dot(A,vel_aux)
4499
4660
4500 return velEst
4661 return velEst
4501
4662
4502 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
4663 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
4503
4664
4504 param = dataOut.moments
4665 param = dataOut.moments
4505 if numpy.any(dataOut.abscissaList):
4666 if numpy.any(dataOut.abscissaList):
4506 absc = dataOut.abscissaList[:-1]
4667 absc = dataOut.abscissaList[:-1]
4507 # noise = dataOut.noise
4668 # noise = dataOut.noise
4508 heightList = dataOut.heightList
4669 heightList = dataOut.heightList
4509 SNR = dataOut.data_snr
4670 SNR = dataOut.data_snr
4510
4671
4511 if technique == 'DBS':
4672 if technique == 'DBS':
4512
4673
4513 kwargs['velRadial'] = param[:,1,:] #Radial velocity
4674 kwargs['velRadial'] = param[:,1,:] #Radial velocity
4514 kwargs['heightList'] = heightList
4675 kwargs['heightList'] = heightList
4515 kwargs['SNR'] = SNR
4676 kwargs['SNR'] = SNR
4516
4677
4517 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
4678 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
4518 dataOut.utctimeInit = dataOut.utctime
4679 dataOut.utctimeInit = dataOut.utctime
4519 dataOut.outputInterval = dataOut.paramInterval
4680 dataOut.outputInterval = dataOut.paramInterval
4520
4681
4521 elif technique == 'SA':
4682 elif technique == 'SA':
4522
4683
4523 #Parameters
4684 #Parameters
4524 kwargs['groupList'] = dataOut.groupList
4685 kwargs['groupList'] = dataOut.groupList
4525 kwargs['tau'] = dataOut.data_param
4686 kwargs['tau'] = dataOut.data_param
4526 kwargs['_lambda'] = dataOut.C/dataOut.frequency
4687 kwargs['_lambda'] = dataOut.C/dataOut.frequency
4527 dataOut.data_output = self.techniqueSA(kwargs)
4688 dataOut.data_output = self.techniqueSA(kwargs)
4528 dataOut.utctimeInit = dataOut.utctime
4689 dataOut.utctimeInit = dataOut.utctime
4529 dataOut.outputInterval = dataOut.timeInterval
4690 dataOut.outputInterval = dataOut.timeInterval
4530
4691
4531 elif technique == 'Meteors':
4692 elif technique == 'Meteors':
4532 dataOut.flagNoData = True
4693 dataOut.flagNoData = True
4533 self.__dataReady = False
4694 self.__dataReady = False
4534
4695
4535 if 'nHours' in kwargs:
4696 if 'nHours' in kwargs:
4536 nHours = kwargs['nHours']
4697 nHours = kwargs['nHours']
4537 else:
4698 else:
4538 nHours = 1
4699 nHours = 1
4539
4700
4540 if 'meteorsPerBin' in kwargs:
4701 if 'meteorsPerBin' in kwargs:
4541 meteorThresh = kwargs['meteorsPerBin']
4702 meteorThresh = kwargs['meteorsPerBin']
4542 else:
4703 else:
4543 meteorThresh = 6
4704 meteorThresh = 6
4544
4705
4545 if 'hmin' in kwargs:
4706 if 'hmin' in kwargs:
4546 hmin = kwargs['hmin']
4707 hmin = kwargs['hmin']
4547 else: hmin = 70
4708 else: hmin = 70
4548 if 'hmax' in kwargs:
4709 if 'hmax' in kwargs:
4549 hmax = kwargs['hmax']
4710 hmax = kwargs['hmax']
4550 else: hmax = 110
4711 else: hmax = 110
4551
4712
4552 dataOut.outputInterval = nHours*3600
4713 dataOut.outputInterval = nHours*3600
4553
4714
4554 if self.__isConfig == False:
4715 if self.__isConfig == False:
4555 #Get Initial LTC time
4716 #Get Initial LTC time
4556 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4717 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4557 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4718 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4558
4719
4559 self.__isConfig = True
4720 self.__isConfig = True
4560
4721
4561 if self.__buffer is None:
4722 if self.__buffer is None:
4562 self.__buffer = dataOut.data_param
4723 self.__buffer = dataOut.data_param
4563 self.__firstdata = copy.copy(dataOut)
4724 self.__firstdata = copy.copy(dataOut)
4564
4725
4565 else:
4726 else:
4566 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4727 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4567
4728
4568 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4729 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4569
4730
4570 if self.__dataReady:
4731 if self.__dataReady:
4571 dataOut.utctimeInit = self.__initime
4732 dataOut.utctimeInit = self.__initime
4572
4733
4573 self.__initime += dataOut.outputInterval #to erase time offset
4734 self.__initime += dataOut.outputInterval #to erase time offset
4574
4735
4575 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
4736 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
4576 dataOut.flagNoData = False
4737 dataOut.flagNoData = False
4577 self.__buffer = None
4738 self.__buffer = None
4578
4739
4579 elif technique == 'Meteors1':
4740 elif technique == 'Meteors1':
4580 dataOut.flagNoData = True
4741 dataOut.flagNoData = True
4581 self.__dataReady = False
4742 self.__dataReady = False
4582
4743
4583 if 'nMins' in kwargs:
4744 if 'nMins' in kwargs:
4584 nMins = kwargs['nMins']
4745 nMins = kwargs['nMins']
4585 else: nMins = 20
4746 else: nMins = 20
4586 if 'rx_location' in kwargs:
4747 if 'rx_location' in kwargs:
4587 rx_location = kwargs['rx_location']
4748 rx_location = kwargs['rx_location']
4588 else: rx_location = [(0,1),(1,1),(1,0)]
4749 else: rx_location = [(0,1),(1,1),(1,0)]
4589 if 'azimuth' in kwargs:
4750 if 'azimuth' in kwargs:
4590 azimuth = kwargs['azimuth']
4751 azimuth = kwargs['azimuth']
4591 else: azimuth = 51.06
4752 else: azimuth = 51.06
4592 if 'dfactor' in kwargs:
4753 if 'dfactor' in kwargs:
4593 dfactor = kwargs['dfactor']
4754 dfactor = kwargs['dfactor']
4594 if 'mode' in kwargs:
4755 if 'mode' in kwargs:
4595 mode = kwargs['mode']
4756 mode = kwargs['mode']
4596 if 'theta_x' in kwargs:
4757 if 'theta_x' in kwargs:
4597 theta_x = kwargs['theta_x']
4758 theta_x = kwargs['theta_x']
4598 if 'theta_y' in kwargs:
4759 if 'theta_y' in kwargs:
4599 theta_y = kwargs['theta_y']
4760 theta_y = kwargs['theta_y']
4600 else: mode = 'SA'
4761 else: mode = 'SA'
4601
4762
4602 #Borrar luego esto
4763 #Borrar luego esto
4603 if dataOut.groupList is None:
4764 if dataOut.groupList is None:
4604 dataOut.groupList = [(0,1),(0,2),(1,2)]
4765 dataOut.groupList = [(0,1),(0,2),(1,2)]
4605 groupList = dataOut.groupList
4766 groupList = dataOut.groupList
4606 C = 3e8
4767 C = 3e8
4607 freq = 50e6
4768 freq = 50e6
4608 lamb = C/freq
4769 lamb = C/freq
4609 k = 2*numpy.pi/lamb
4770 k = 2*numpy.pi/lamb
4610
4771
4611 timeList = dataOut.abscissaList
4772 timeList = dataOut.abscissaList
4612 heightList = dataOut.heightList
4773 heightList = dataOut.heightList
4613
4774
4614 if self.__isConfig == False:
4775 if self.__isConfig == False:
4615 dataOut.outputInterval = nMins*60
4776 dataOut.outputInterval = nMins*60
4616 #Get Initial LTC time
4777 #Get Initial LTC time
4617 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4778 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
4618 minuteAux = initime.minute
4779 minuteAux = initime.minute
4619 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
4780 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
4620 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4781 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
4621
4782
4622 self.__isConfig = True
4783 self.__isConfig = True
4623
4784
4624 if self.__buffer is None:
4785 if self.__buffer is None:
4625 self.__buffer = dataOut.data_param
4786 self.__buffer = dataOut.data_param
4626 self.__firstdata = copy.copy(dataOut)
4787 self.__firstdata = copy.copy(dataOut)
4627
4788
4628 else:
4789 else:
4629 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4790 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
4630
4791
4631 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4792 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
4632
4793
4633 if self.__dataReady:
4794 if self.__dataReady:
4634 dataOut.utctimeInit = self.__initime
4795 dataOut.utctimeInit = self.__initime
4635 self.__initime += dataOut.outputInterval #to erase time offset
4796 self.__initime += dataOut.outputInterval #to erase time offset
4636
4797
4637 metArray = self.__buffer
4798 metArray = self.__buffer
4638 if mode == 'SA':
4799 if mode == 'SA':
4639 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
4800 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
4640 elif mode == 'DBS':
4801 elif mode == 'DBS':
4641 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
4802 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
4642 dataOut.data_output = dataOut.data_output.T
4803 dataOut.data_output = dataOut.data_output.T
4643 dataOut.flagNoData = False
4804 dataOut.flagNoData = False
4644 self.__buffer = None
4805 self.__buffer = None
4645
4806
4646 return dataOut
4807 return dataOut
4647
4808
4648 class EWDriftsEstimation(Operation):
4809 class EWDriftsEstimation(Operation):
4649
4810
4650 def __init__(self):
4811 def __init__(self):
4651 Operation.__init__(self)
4812 Operation.__init__(self)
4652
4813
4653 def __correctValues(self, heiRang, phi, velRadial, SNR):
4814 def __correctValues(self, heiRang, phi, velRadial, SNR):
4654 listPhi = phi.tolist()
4815 listPhi = phi.tolist()
4655 maxid = listPhi.index(max(listPhi))
4816 maxid = listPhi.index(max(listPhi))
4656 minid = listPhi.index(min(listPhi))
4817 minid = listPhi.index(min(listPhi))
4657
4818
4658 rango = list(range(len(phi)))
4819 rango = list(range(len(phi)))
4659 heiRang1 = heiRang*math.cos(phi[maxid])
4820 heiRang1 = heiRang*math.cos(phi[maxid])
4660 heiRangAux = heiRang*math.cos(phi[minid])
4821 heiRangAux = heiRang*math.cos(phi[minid])
4661 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4822 indOut = (heiRang1 < heiRangAux[0]).nonzero()
4662 heiRang1 = numpy.delete(heiRang1,indOut)
4823 heiRang1 = numpy.delete(heiRang1,indOut)
4663
4824
4664 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4825 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
4665 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4826 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
4666
4827
4667 for i in rango:
4828 for i in rango:
4668 x = heiRang*math.cos(phi[i])
4829 x = heiRang*math.cos(phi[i])
4669 y1 = velRadial[i,:]
4830 y1 = velRadial[i,:]
4670 vali= (numpy.isfinite(y1)==True).nonzero()
4831 vali= (numpy.isfinite(y1)==True).nonzero()
4671 y1=y1[vali]
4832 y1=y1[vali]
4672 x = x[vali]
4833 x = x[vali]
4673 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
4834 f1 = interpolate.interp1d(x,y1,kind = 'cubic',bounds_error=False)
4835
4674 x1 = heiRang1
4836 x1 = heiRang1
4675 y11 = f1(x1)
4837 y11 = f1(x1)
4676 y2 = SNR[i,:]
4838 y2 = SNR[i,:]
4677 x = heiRang*math.cos(phi[i])
4839 x = heiRang*math.cos(phi[i])
4678 vali= (y2 != -1).nonzero()
4840 vali= (y2 != -1).nonzero()
4679 y2 = y2[vali]
4841 y2 = y2[vali]
4680 x = x[vali]
4842 x = x[vali]
4843
4681 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
4844 f2 = interpolate.interp1d(x,y2,kind = 'cubic',bounds_error=False)
4682 y21 = f2(x1)
4845 y21 = f2(x1)
4683
4846
4684 velRadial1[i,:] = y11
4847 velRadial1[i,:] = y11
4685 SNR1[i,:] = y21
4848 SNR1[i,:] = y21
4686
4849
4687 return heiRang1, velRadial1, SNR1
4850 return heiRang1, velRadial1, SNR1
4688
4851
4852
4853
4689 def run(self, dataOut, zenith, zenithCorrection,fileDrifts):
4854 def run(self, dataOut, zenith, zenithCorrection,fileDrifts):
4690
4855 dataOut.lat = -11.95
4691 dataOut.lat=-11.95
4856 dataOut.lon = -76.87
4692 dataOut.lon=-76.87
4857 dataOut.spcst = 0.00666
4858 dataOut.pl = 0.0003
4859 dataOut.cbadn = 3
4860 dataOut.inttms = 300
4861 dataOut.azw = -115.687
4862 dataOut.elw = 86.1095
4863 dataOut.aze = 130.052
4864 dataOut.ele = 87.6558
4865 dataOut.jro14 = numpy.log10(dataOut.spc_noise[0]/dataOut.normFactor)
4866 dataOut.jro15 = numpy.log10(dataOut.spc_noise[1]/dataOut.normFactor)
4867 dataOut.jro16 = numpy.log10(dataOut.spc_noise[2]/dataOut.normFactor)
4868 dataOut.nwlos = numpy.log10(dataOut.spc_noise[3]/dataOut.normFactor)
4869
4693 heiRang = dataOut.heightList
4870 heiRang = dataOut.heightList
4694 velRadial = dataOut.data_param[:,3,:]
4871 velRadial = dataOut.data_param[:,3,:]
4695 velRadialm = dataOut.data_param[:,2:4,:]*-1
4872 velRadialm = dataOut.data_param[:,2:4,:]*-1
4873
4696 rbufc=dataOut.data_paramC[:,:,0]
4874 rbufc=dataOut.data_paramC[:,:,0]
4697 ebufc=dataOut.data_paramC[:,:,1]
4875 ebufc=dataOut.data_paramC[:,:,1]
4698 SNR = dataOut.data_snr
4876 SNR = dataOut.data_snr1_i
4877 rbufi = dataOut.data_snr1_i
4699 velRerr = dataOut.data_error[:,4,:]
4878 velRerr = dataOut.data_error[:,4,:]
4879 range1 = dataOut.heightList
4880 nhei = len(range1)
4881
4882 sat_fits = dataOut.sat_fits
4883
4700 channels = dataOut.channelList
4884 channels = dataOut.channelList
4701 nChan = len(channels)
4885 nChan = len(channels)
4702 my_nbeams = nChan/2
4886 my_nbeams = nChan/2
4703 if my_nbeams == 2:
4887 if my_nbeams == 2:
4704 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
4888 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]],[velRadialm[1,:]],[velRadialm[1,:]]))
4705 else :
4889 else :
4706 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]]))
4890 moments=numpy.vstack(([velRadialm[0,:]],[velRadialm[0,:]]))
4707 dataOut.moments=moments
4891 dataOut.moments=moments
4892 #Incoherent
4893 smooth_w = dataOut.clean_num_aver[0,:]
4894 chisq_w = dataOut.data_error[0,0,:]
4895 p_w0 = rbufi[0,:]
4896 p_w1 = rbufi[1,:]
4708 # Coherent
4897 # Coherent
4709 smooth_wC = ebufc[0,:]
4898 smooth_wC = ebufc[0,:]
4710 p_w0C = rbufc[0,:]
4899 p_w0C = rbufc[0,:]
4711 p_w1C = rbufc[1,:]
4900 p_w1C = rbufc[1,:]
4712 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
4901 w_wC = rbufc[2,:]*-1 #*radial_sign(radial EQ 1)
4713 t_wC = rbufc[3,:]
4902 t_wC = rbufc[3,:]
4903 val = (numpy.isfinite(p_w0)==False).nonzero()
4904 p_w0[val]=0
4905 val = (numpy.isfinite(p_w1)==False).nonzero()
4906 p_w1[val]=0
4907 val = (numpy.isfinite(p_w0C)==False).nonzero()
4908 p_w0C[val]=0
4909 val = (numpy.isfinite(p_w1C)==False).nonzero()
4910 p_w1C[val]=0
4911 val = (numpy.isfinite(smooth_w)==False).nonzero()
4912 smooth_w[val]=0
4913 val = (numpy.isfinite(smooth_wC)==False).nonzero()
4914 smooth_wC[val]=0
4915
4916 #p_w0 = (p_w0*smooth_w+p_w0C*smooth_wC)/(smooth_w+smooth_wC)
4917 #p_w1 = (p_w1*smooth_w+p_w1C*smooth_wC)/(smooth_w+smooth_wC)
4918
4919 if len(sat_fits) >0 :
4920 p_w0C = p_w0C + sat_fits[0,:]
4921 p_w1C = p_w1C + sat_fits[1,:]
4922
4714 if my_nbeams == 1:
4923 if my_nbeams == 1:
4715 w = velRadial[0,:]
4924 w = velRadial[0,:]
4716 winds = velRadial.copy()
4925 winds = velRadial.copy()
4717 w_err = velRerr[0,:]
4926 w_err = velRerr[0,:]
4718 snr1 = 10*numpy.log10(SNR[0])
4927 u = w*numpy.nan
4928 u_err = w_err*numpy.nan
4929 p_e0 = p_w0*numpy.nan
4930 p_e1 = p_w1*numpy.nan
4931 #snr1 = 10*numpy.log10(SNR[0])
4719 if my_nbeams == 2:
4932 if my_nbeams == 2:
4933
4720 zenith = numpy.array(zenith)
4934 zenith = numpy.array(zenith)
4721 zenith -= zenithCorrection
4935 zenith -= zenithCorrection
4722 zenith *= numpy.pi/180
4936 zenith *= numpy.pi/180
4723 if zenithCorrection != 0 :
4937 if zenithCorrection != 0 :
4724 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
4938 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
4725 else :
4939 else :
4726 heiRang1 = heiRang
4940 heiRang1 = heiRang
4727 velRadial1 = velRadial
4941 velRadial1 = velRadial
4728 SNR1 = SNR
4942 SNR1 = SNR
4729
4943
4730 alp = zenith[0]
4944 alp = zenith[0]
4731 bet = zenith[1]
4945 bet = zenith[1]
4732
4946
4733 w_w = velRadial1[0,:]
4947 w_w = velRadial1[0,:]
4734 w_e = velRadial1[1,:]
4948 w_e = velRadial1[1,:]
4735 w_w_err = velRerr[0,:]
4949 w_w_err = velRerr[0,:]
4736 w_e_err = velRerr[1,:]
4950 w_e_err = velRerr[1,:]
4737
4951 smooth_e = dataOut.clean_num_aver[2,:]
4738 val = (numpy.isfinite(w_w)==False).nonzero()
4952 chisq_e = dataOut.data_error[1,0,:]
4739 val = val[0]
4953 p_e0 = rbufi[2,:]
4740 bad = val
4954 p_e1 = rbufi[3,:]
4741 if len(bad) > 0 :
4955
4742 w_w[bad] = w_wC[bad]
4956 tini=time.localtime(dataOut.utctime)
4743 w_w_err[bad]= numpy.nan
4957 #print(tini[3],tini[4])
4958 #val = (numpy.isfinite(w_w)==False).nonzero()
4959 #val = val[0]
4960 #bad = val
4961 #if len(bad) > 0 :
4962 # w_w[bad] = w_wC[bad]
4963 # w_w_err[bad]= numpy.nan
4964 if tini[3] >= 6 and tini[3] < 18 :
4965 w_wtmp = numpy.where(numpy.isfinite(w_wC)==True,w_wC,w_w)
4966 w_w_errtmp = numpy.where(numpy.isfinite(w_wC)==True,numpy.nan,w_w_err)
4967 else:
4968 w_wtmp = numpy.where(numpy.isfinite(w_wC)==True,w_wC,w_w)
4969 w_wtmp = numpy.where(range1 > 200,w_w,w_wtmp)
4970 w_w_errtmp = numpy.where(numpy.isfinite(w_wC)==True,numpy.nan,w_w_err)
4971 w_w_errtmp = numpy.where(range1 > 200,w_w_err,w_w_errtmp)
4972 w_w = w_wtmp
4973 w_w_err = w_w_errtmp
4974
4975 #if my_nbeams == 2:
4744 smooth_eC=ebufc[4,:]
4976 smooth_eC=ebufc[4,:]
4745 p_e0C = rbufc[4,:]
4977 p_e0C = rbufc[4,:]
4746 p_e1C = rbufc[5,:]
4978 p_e1C = rbufc[5,:]
4747 w_eC = rbufc[6,:]*-1
4979 w_eC = rbufc[6,:]*-1
4748 t_eC = rbufc[7,:]
4980 t_eC = rbufc[7,:]
4749 val = (numpy.isfinite(w_e)==False).nonzero()
4981
4750 val = val[0]
4982 val = (numpy.isfinite(p_e0)==False).nonzero()
4751 bad = val
4983 p_e0[val]=0
4752 if len(bad) > 0 :
4984 val = (numpy.isfinite(p_e1)==False).nonzero()
4753 w_e[bad] = w_eC[bad]
4985 p_e1[val]=0
4754 w_e_err[bad]= numpy.nan
4986 val = (numpy.isfinite(p_e0C)==False).nonzero()
4755
4987 p_e0C[val]=0
4988 val = (numpy.isfinite(p_e1C)==False).nonzero()
4989 p_e1C[val]=0
4990 val = (numpy.isfinite(smooth_e)==False).nonzero()
4991 smooth_e[val]=0
4992 val = (numpy.isfinite(smooth_eC)==False).nonzero()
4993 smooth_eC[val]=0
4994 #p_e0 = (p_e0*smooth_e+p_e0C*smooth_eC)/(smooth_e+smooth_eC)
4995 #p_e1 = (p_e1*smooth_e+p_e1C*smooth_eC)/(smooth_e+smooth_eC)
4996
4997 if len(sat_fits) >0 :
4998 p_e0C = p_e0C + sat_fits[2,:]
4999 p_e1C = p_e1C + sat_fits[3,:]
5000
5001 #val = (numpy.isfinite(w_e)==False).nonzero()
5002 #val = val[0]
5003 #bad = val
5004 #if len(bad) > 0 :
5005 # w_e[bad] = w_eC[bad]
5006 # w_e_err[bad]= numpy.nan
5007 if tini[3] >= 6 and tini[3] < 18 :
5008 w_etmp = numpy.where(numpy.isfinite(w_eC)==True,w_eC,w_e)
5009 w_e_errtmp = numpy.where(numpy.isfinite(w_eC)==True,numpy.nan,w_e_err)
5010 else:
5011 w_etmp = numpy.where(numpy.isfinite(w_eC)==True,w_eC,w_e)
5012 w_etmp = numpy.where(range1 > 200,w_e,w_etmp)
5013 w_e_errtmp = numpy.where(numpy.isfinite(w_eC)==True,numpy.nan,w_e_err)
5014 w_e_errtmp = numpy.where(range1 > 200,w_e_err,w_e_errtmp)
5015 w_e = w_etmp
5016 w_e_err = w_e_errtmp
5017
4756 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
5018 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
4757 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
5019 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
4758
5020
4759 w_err = numpy.sqrt((w_w_err*numpy.sin(bet))**2.+(w_e_err*numpy.sin(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
5021 w_err = numpy.sqrt((w_w_err*numpy.sin(bet))**2.+(w_e_err*numpy.sin(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
4760 u_err = numpy.sqrt((w_w_err*numpy.cos(bet))**2.+(w_e_err*numpy.cos(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
5022 u_err = numpy.sqrt((w_w_err*numpy.cos(bet))**2.+(w_e_err*numpy.cos(alp))**2.)/ numpy.absolute(numpy.cos(alp)*numpy.sin(bet)-numpy.cos(bet)*numpy.sin(alp))
4761
5023
4762 winds = numpy.vstack((w,u))
5024 winds = numpy.vstack((w,u))
4763
5025 #winds = numpy.vstack((w,u,w_err,u_err))
4764 dataOut.heightList = heiRang1
5026 dataOut.heightList = heiRang1
4765 snr1 = 10*numpy.log10(SNR1[0])
5027 #snr1 = 10*numpy.log10(SNR1[0])
4766 dataOut.data_output = winds
5028 dataOut.data_output = winds
4767 #snr1 = 10*numpy.log10(SNR1[0])# estaba comentado
5029 range1 = dataOut.heightList
4768 dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
5030 nhei = len(range1)
4769 #print("data_snr1",dataOut.data_snr1)
5031 #print('alt ',range1*numpy.sin(86.1*numpy.pi/180))
5032 #print(numpy.min([dataOut.eldir7,dataOut.eldir8]))
5033 galt = range1*numpy.sin(numpy.min([dataOut.elw,dataOut.ele])*numpy.pi/180.)
5034 dataOut.params = numpy.vstack((range1,galt,w,w_err,u,u_err,w_w,w_w_err,w_e,w_e_err,numpy.log10(p_w0),numpy.log10(p_w0C),numpy.log10(p_w1),numpy.log10(p_w1C),numpy.log10(p_e0),numpy.log10(p_e0C),numpy.log10(p_e1),numpy.log10(p_e1C),chisq_w,chisq_e))
5035 #snr1 = 10*numpy.log10(SNR1[0])
5036 #print(min(snr1), max(snr1))
5037 snr1 = numpy.vstack((p_w0,p_w1,p_e0,p_e1))
5038 snr1db = 10*numpy.log10(snr1[0])
5039 #dataOut.data_snr1 = numpy.reshape(snr1,(1,snr1.shape[0]))
5040 dataOut.data_snr1 = numpy.reshape(snr1db,(1,snr1db.shape[0]))
4770 dataOut.utctimeInit = dataOut.utctime
5041 dataOut.utctimeInit = dataOut.utctime
4771 dataOut.outputInterval = dataOut.timeInterval
5042 dataOut.outputInterval = dataOut.timeInterval
4772
5043
4773 hei_aver0 = 218
5044 hei_aver0 = 218
4774 jrange = 450 #900 para HA drifts
5045 jrange = 450 #900 para HA drifts
4775 deltah = 15.0 #dataOut.spacing(0) 25 HAD
5046 deltah = 15.0 #dataOut.spacing(0) 25 HAD
4776 h0 = 0.0 #dataOut.first_height(0)
5047 h0 = 0.0 #dataOut.first_height(0)
4777 heights = dataOut.heightList
4778 nhei = len(heights)
4779
5048
4780 range1 = numpy.arange(nhei) * deltah + h0
5049 range1 = numpy.arange(nhei) * deltah + h0
4781 jhei = (range1 >= hei_aver0).nonzero()
5050 jhei = (range1 >= hei_aver0).nonzero()
4782 if len(jhei[0]) > 0 :
5051 if len(jhei[0]) > 0 :
4783 h0_index = jhei[0][0] # Initial height for getting averages 218km
5052 h0_index = jhei[0][0] # Initial height for getting averages 218km
4784
5053
4785 mynhei = 7
5054 mynhei = 7
4786 nhei_avg = int(jrange/deltah)
5055 nhei_avg = int(jrange/deltah)
4787 h_avgs = int(nhei_avg/mynhei)
5056 h_avgs = int(nhei_avg/mynhei)
4788 nhei_avg = h_avgs*(mynhei-1)+mynhei
5057 nhei_avg = h_avgs*(mynhei-1)+mynhei
4789
5058
4790 navgs = numpy.zeros(mynhei,dtype='float')
5059 navgs = numpy.zeros(mynhei,dtype='float')
4791 delta_h = numpy.zeros(mynhei,dtype='float')
5060 delta_h = numpy.zeros(mynhei,dtype='float')
4792 range_aver = numpy.zeros(mynhei,dtype='float')
5061 range_aver = numpy.zeros(mynhei,dtype='float')
4793 for ih in range( mynhei-1 ):
5062 for ih in range( mynhei-1 ):
4794 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
5063 range_aver[ih] = numpy.sum(range1[h0_index+h_avgs*ih:h0_index+h_avgs*(ih+1)-0])/h_avgs
4795 navgs[ih] = h_avgs
5064 navgs[ih] = h_avgs
4796 delta_h[ih] = deltah*h_avgs
5065 delta_h[ih] = deltah*h_avgs
4797
5066
4798 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
5067 range_aver[mynhei-1] = numpy.sum(range1[h0_index:h0_index+6*h_avgs-0])/(6*h_avgs)
4799 navgs[mynhei-1] = 6*h_avgs
5068 navgs[mynhei-1] = 6*h_avgs
4800 delta_h[mynhei-1] = deltah*6*h_avgs
5069 delta_h[mynhei-1] = deltah*6*h_avgs
4801
5070
4802 wA = w[h0_index:h0_index+nhei_avg-0]
5071 wA = w[h0_index:h0_index+nhei_avg-0]
4803 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
5072 wA_err = w_err[h0_index:h0_index+nhei_avg-0]
4804 for i in range(5) :
5073 for i in range(5) :
4805 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
5074 vals = wA[i*h_avgs:(i+1)*h_avgs-0]
4806 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
5075 errs = wA_err[i*h_avgs:(i+1)*h_avgs-0]
4807 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
5076 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4808 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
5077 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4809 wA[6*h_avgs+i] = avg
5078 wA[6*h_avgs+i] = avg
4810 wA_err[6*h_avgs+i] = sigma
5079 wA_err[6*h_avgs+i] = sigma
4811
5080
4812
5081
4813 vals = wA[0:6*h_avgs-0]
5082 vals = wA[0:6*h_avgs-0]
4814 errs=wA_err[0:6*h_avgs-0]
5083 errs=wA_err[0:6*h_avgs-0]
4815 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
5084 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2)
4816 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
5085 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4817 wA[nhei_avg-1] = avg
5086 wA[nhei_avg-1] = avg
4818 wA_err[nhei_avg-1] = sigma
5087 wA_err[nhei_avg-1] = sigma
4819
5088
4820 wA = wA[6*h_avgs:nhei_avg-0]
5089 wA = wA[6*h_avgs:nhei_avg-0]
4821 wA_err=wA_err[6*h_avgs:nhei_avg-0]
5090 wA_err=wA_err[6*h_avgs:nhei_avg-0]
4822 if my_nbeams == 2 :
5091 if my_nbeams == 2 :
4823 uA = u[h0_index:h0_index+nhei_avg]
5092 uA = u[h0_index:h0_index+nhei_avg]
4824 uA_err=u_err[h0_index:h0_index+nhei_avg]
5093 uA_err=u_err[h0_index:h0_index+nhei_avg]
4825
5094
4826 for i in range(5) :
5095 for i in range(5) :
4827 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
5096 vals = uA[i*h_avgs:(i+1)*h_avgs-0]
4828 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
5097 errs=uA_err[i*h_avgs:(i+1)*h_avgs-0]
4829 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
5098 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4830 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
5099 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4831 uA[6*h_avgs+i] = avg
5100 uA[6*h_avgs+i] = avg
4832 uA_err[6*h_avgs+i]=sigma
5101 uA_err[6*h_avgs+i]=sigma
4833
5102
4834 vals = uA[0:6*h_avgs-0]
5103 vals = uA[0:6*h_avgs-0]
4835 errs = uA_err[0:6*h_avgs-0]
5104 errs = uA_err[0:6*h_avgs-0]
4836 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
5105 avg = numpy.nansum(vals/errs**2.)/numpy.nansum(1./errs**2.)
4837 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
5106 sigma = numpy.sqrt(1./numpy.nansum(1./errs**2.))
4838 uA[nhei_avg-1] = avg
5107 uA[nhei_avg-1] = avg
4839 uA_err[nhei_avg-1] = sigma
5108 uA_err[nhei_avg-1] = sigma
4840 uA = uA[6*h_avgs:nhei_avg-0]
5109 uA = uA[6*h_avgs:nhei_avg-0]
4841 uA_err = uA_err[6*h_avgs:nhei_avg-0]
5110 uA_err = uA_err[6*h_avgs:nhei_avg-0]
4842 dataOut.drifts_avg = numpy.vstack((wA,uA))
5111 dataOut.drifts_avg = numpy.vstack((wA,uA))
5112
4843 if my_nbeams == 1: dataOut.drifts_avg = wA
5113 if my_nbeams == 1: dataOut.drifts_avg = wA
5114 #deltahavg= wA*0.0+deltah
5115 dataOut.range = range1
5116 galtavg = range_aver*numpy.sin(numpy.min([dataOut.elw,dataOut.ele])*numpy.pi/180.)
5117 dataOut.params_avg = numpy.vstack((wA,wA_err,uA,uA_err,range_aver,galtavg,delta_h))
5118
5119 #print('comparando dim de avg ',wA.shape,deltahavg.shape,range_aver.shape)
4844 tini=time.localtime(dataOut.utctime)
5120 tini=time.localtime(dataOut.utctime)
4845 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
5121 datefile= str(tini[0]).zfill(4)+str(tini[1]).zfill(2)+str(tini[2]).zfill(2)
4846 nfile = fileDrifts+'/jro'+datefile+'drifts.txt'
5122 nfile = fileDrifts+'/jro'+datefile+'drifts_sch3.txt'
5123 #nfile = '/home/pcondor/Database/ewdriftsschain2019/jro'+datefile+'drifts_sch3.txt'
5124 #print(len(dataOut.drifts_avg),dataOut.drifts_avg.shape)
4847 f1 = open(nfile,'a')
5125 f1 = open(nfile,'a')
4848 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
5126 datedriftavg=str(tini[0])+' '+str(tini[1])+' '+str(tini[2])+' '+str(tini[3])+' '+str(tini[4])
4849 driftavgstr=str(dataOut.drifts_avg)
5127 driftavgstr=str(dataOut.drifts_avg)
4850 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
5128 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
4851 numpy.savetxt(f1,dataOut.drifts_avg,fmt='%10.2f')
5129 numpy.savetxt(f1,numpy.reshape(range_aver,(1,len(range_aver))) ,fmt='%10.2f')
5130 #numpy.savetxt(f1,numpy.reshape(dataOut.drifts_avg,(7,len(dataOut.drifts_avg))) ,fmt='%10.2f')
5131 numpy.savetxt(f1,dataOut.drifts_avg[:,:],fmt='%10.2f')
5132 f1.close()
5133
5134 swfile = fileDrifts+'/jro'+datefile+'drifts_sw.txt'
5135 f1 = open(swfile,'a')
5136 numpy.savetxt(f1,numpy.column_stack([tini[0],tini[1],tini[2],tini[3],tini[4]]),fmt='%4i')
5137 numpy.savetxt(f1,numpy.reshape(heiRang,(1,len(heiRang))),fmt='%10.2f')
5138 numpy.savetxt(f1,dataOut.data_param[:,0,:],fmt='%10.2f')
4852 f1.close()
5139 f1.close()
5140 dataOut.heightListtmp = dataOut.heightList
5141 '''
5142 one = {'range':'range','gdlatr': 'lat', 'gdlonr': 'lon', 'inttms': 'paramInterval'} #reader gdlatr-->lat only 1D
5143
5144 two = {
5145 'gdalt': 'heightList', #<----- nmonics
5146 'VIPN': ('params', 0),
5147 'dvipn': ('params', 1),
5148 'vipe': ('params', 2),
5149 'dvipe': ('params', 3),
5150 'PACWL': ('params', 4),
5151 'pbcwl': ('params', 5),
5152 'pccel': ('params', 6),
5153 'pdcel': ('params', 7)
5154 } #writer
5155
5156 #f=open('/home/roberto/moder_test.txt','r')
5157 #file_contents=f.read()
5158
5159 ind = ['gdalt']
5160
5161 meta = {
5162 'kinst': 10, #instrument code
5163 'kindat': 1910, #type of data
5164 'catalog': {
5165 'principleInvestigator': 'Danny ScipiΓ³n',
5166 'expPurpose': 'Drifts'#,
5167 # 'sciRemarks': file_contents
5168 },
5169 'header': {
5170 'analyst': 'D. Hysell'
5171 }
5172 }
5173 print('empieza h5 madrigal')
5174 try:
5175 h5mad=MADWriter(dataOut, fileDrifts, one, ind, two, meta, format='hdf5')
5176 except:
5177 print("Error in MADWriter")
5178 print(h5mad)
5179 '''
5180 return dataOut
5181 class setHeightDrifts(Operation):
4853
5182
5183 def __init__(self):
5184 Operation.__init__(self)
5185 def run(self, dataOut):
5186 #print('h inicial ',dataOut.heightList,dataOut.heightListtmp)
5187 dataOut.heightList = dataOut.heightListtmp
5188 #print('regresa H ',dataOut.heightList)
4854 return dataOut
5189 return dataOut
5190 class setHeightDriftsavg(Operation):
5191
5192 def __init__(self):
5193 Operation.__init__(self)
5194 def run(self, dataOut):
5195 #print('h inicial ',dataOut.heightList)
5196 dataOut.heightList = dataOut.params_avg[4]
5197 #print('cambia H ',dataOut.params_avg[4],dataOut.heightList)
5198 return dataOut
5199
5200
4855
5201
4856 #--------------- Non Specular Meteor ----------------
5202 #--------------- Non Specular Meteor ----------------
4857
5203
4858 class NonSpecularMeteorDetection(Operation):
5204 class NonSpecularMeteorDetection(Operation):
4859
5205
4860 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
5206 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
4861 data_acf = dataOut.data_pre[0]
5207 data_acf = dataOut.data_pre[0]
4862 data_ccf = dataOut.data_pre[1]
5208 data_ccf = dataOut.data_pre[1]
4863 pairsList = dataOut.groupList[1]
5209 pairsList = dataOut.groupList[1]
4864
5210
4865 lamb = dataOut.C/dataOut.frequency
5211 lamb = dataOut.C/dataOut.frequency
4866 tSamp = dataOut.ippSeconds*dataOut.nCohInt
5212 tSamp = dataOut.ippSeconds*dataOut.nCohInt
4867 paramInterval = dataOut.paramInterval
5213 paramInterval = dataOut.paramInterval
4868
5214
4869 nChannels = data_acf.shape[0]
5215 nChannels = data_acf.shape[0]
4870 nLags = data_acf.shape[1]
5216 nLags = data_acf.shape[1]
4871 nProfiles = data_acf.shape[2]
5217 nProfiles = data_acf.shape[2]
4872 nHeights = dataOut.nHeights
5218 nHeights = dataOut.nHeights
4873 nCohInt = dataOut.nCohInt
5219 nCohInt = dataOut.nCohInt
4874 sec = numpy.round(nProfiles/dataOut.paramInterval)
5220 sec = numpy.round(nProfiles/dataOut.paramInterval)
4875 heightList = dataOut.heightList
5221 heightList = dataOut.heightList
4876 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
5222 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
4877 utctime = dataOut.utctime
5223 utctime = dataOut.utctime
4878
5224
4879 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
5225 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
4880
5226
4881 #------------------------ SNR --------------------------------------
5227 #------------------------ SNR --------------------------------------
4882 power = data_acf[:,0,:,:].real
5228 power = data_acf[:,0,:,:].real
4883 noise = numpy.zeros(nChannels)
5229 noise = numpy.zeros(nChannels)
4884 SNR = numpy.zeros(power.shape)
5230 SNR = numpy.zeros(power.shape)
4885 for i in range(nChannels):
5231 for i in range(nChannels):
4886 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
5232 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
4887 SNR[i] = (power[i]-noise[i])/noise[i]
5233 SNR[i] = (power[i]-noise[i])/noise[i]
4888 SNRm = numpy.nanmean(SNR, axis = 0)
5234 SNRm = numpy.nanmean(SNR, axis = 0)
4889 SNRdB = 10*numpy.log10(SNR)
5235 SNRdB = 10*numpy.log10(SNR)
4890
5236
4891 if mode == 'SA':
5237 if mode == 'SA':
4892 dataOut.groupList = dataOut.groupList[1]
5238 dataOut.groupList = dataOut.groupList[1]
4893 nPairs = data_ccf.shape[0]
5239 nPairs = data_ccf.shape[0]
4894 #---------------------- Coherence and Phase --------------------------
5240 #---------------------- Coherence and Phase --------------------------
4895 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
5241 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
4896 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
5242 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
4897
5243
4898 for p in range(nPairs):
5244 for p in range(nPairs):
4899 ch0 = pairsList[p][0]
5245 ch0 = pairsList[p][0]
4900 ch1 = pairsList[p][1]
5246 ch1 = pairsList[p][1]
4901 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
5247 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
4902 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
5248 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
4903 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
5249 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
4904 coh = numpy.nanmax(coh1, axis = 0)
5250 coh = numpy.nanmax(coh1, axis = 0)
4905 #---------------------- Radial Velocity ----------------------------
5251 #---------------------- Radial Velocity ----------------------------
4906 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
5252 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
4907 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
5253 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
4908
5254
4909 if allData:
5255 if allData:
4910 boolMetFin = ~numpy.isnan(SNRm)
5256 boolMetFin = ~numpy.isnan(SNRm)
4911 else:
5257 else:
4912 #------------------------ Meteor mask ---------------------------------
5258 #------------------------ Meteor mask ---------------------------------
4913
5259
4914 #Coherence mask
5260 #Coherence mask
4915 boolMet1 = coh > 0.75
5261 boolMet1 = coh > 0.75
4916 struc = numpy.ones((30,1))
5262 struc = numpy.ones((30,1))
4917 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
5263 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
4918
5264
4919 #Derivative mask
5265 #Derivative mask
4920 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
5266 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
4921 boolMet2 = derPhase < 0.2
5267 boolMet2 = derPhase < 0.2
4922 boolMet2 = ndimage.median_filter(boolMet2,size=5)
5268 boolMet2 = ndimage.median_filter(boolMet2,size=5)
4923 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
5269 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
4924 boolMetFin = boolMet1&boolMet2
5270 boolMetFin = boolMet1&boolMet2
4925 #Creating data_param
5271 #Creating data_param
4926 coordMet = numpy.where(boolMetFin)
5272 coordMet = numpy.where(boolMetFin)
4927
5273
4928 tmet = coordMet[0]
5274 tmet = coordMet[0]
4929 hmet = coordMet[1]
5275 hmet = coordMet[1]
4930
5276
4931 data_param = numpy.zeros((tmet.size, 6 + nPairs))
5277 data_param = numpy.zeros((tmet.size, 6 + nPairs))
4932 data_param[:,0] = utctime
5278 data_param[:,0] = utctime
4933 data_param[:,1] = tmet
5279 data_param[:,1] = tmet
4934 data_param[:,2] = hmet
5280 data_param[:,2] = hmet
4935 data_param[:,3] = SNRm[tmet,hmet]
5281 data_param[:,3] = SNRm[tmet,hmet]
4936 data_param[:,4] = velRad[tmet,hmet]
5282 data_param[:,4] = velRad[tmet,hmet]
4937 data_param[:,5] = coh[tmet,hmet]
5283 data_param[:,5] = coh[tmet,hmet]
4938 data_param[:,6:] = phase[:,tmet,hmet].T
5284 data_param[:,6:] = phase[:,tmet,hmet].T
4939
5285
4940 elif mode == 'DBS':
5286 elif mode == 'DBS':
4941 dataOut.groupList = numpy.arange(nChannels)
5287 dataOut.groupList = numpy.arange(nChannels)
4942
5288
4943 #Radial Velocities
5289 #Radial Velocities
4944 phase = numpy.angle(data_acf[:,1,:,:])
5290 phase = numpy.angle(data_acf[:,1,:,:])
4945 velRad = phase*lamb/(4*numpy.pi*tSamp)
5291 velRad = phase*lamb/(4*numpy.pi*tSamp)
4946
5292
4947 #Spectral width
5293 #Spectral width
4948 acf1 = data_acf[:,1,:,:]
5294 acf1 = data_acf[:,1,:,:]
4949 acf2 = data_acf[:,2,:,:]
5295 acf2 = data_acf[:,2,:,:]
4950
5296
4951 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
5297 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
4952 if allData:
5298 if allData:
4953 boolMetFin = ~numpy.isnan(SNRdB)
5299 boolMetFin = ~numpy.isnan(SNRdB)
4954 else:
5300 else:
4955 #SNR
5301 #SNR
4956 boolMet1 = (SNRdB>SNRthresh) #SNR mask
5302 boolMet1 = (SNRdB>SNRthresh) #SNR mask
4957 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
5303 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
4958
5304
4959 #Radial velocity
5305 #Radial velocity
4960 boolMet2 = numpy.abs(velRad) < 20
5306 boolMet2 = numpy.abs(velRad) < 20
4961 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
5307 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
4962
5308
4963 #Spectral Width
5309 #Spectral Width
4964 boolMet3 = spcWidth < 30
5310 boolMet3 = spcWidth < 30
4965 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
5311 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
4966 boolMetFin = boolMet1&boolMet2&boolMet3
5312 boolMetFin = boolMet1&boolMet2&boolMet3
4967
5313
4968 #Creating data_param
5314 #Creating data_param
4969 coordMet = numpy.where(boolMetFin)
5315 coordMet = numpy.where(boolMetFin)
4970
5316
4971 cmet = coordMet[0]
5317 cmet = coordMet[0]
4972 tmet = coordMet[1]
5318 tmet = coordMet[1]
4973 hmet = coordMet[2]
5319 hmet = coordMet[2]
4974
5320
4975 data_param = numpy.zeros((tmet.size, 7))
5321 data_param = numpy.zeros((tmet.size, 7))
4976 data_param[:,0] = utctime
5322 data_param[:,0] = utctime
4977 data_param[:,1] = cmet
5323 data_param[:,1] = cmet
4978 data_param[:,2] = tmet
5324 data_param[:,2] = tmet
4979 data_param[:,3] = hmet
5325 data_param[:,3] = hmet
4980 data_param[:,4] = SNR[cmet,tmet,hmet].T
5326 data_param[:,4] = SNR[cmet,tmet,hmet].T
4981 data_param[:,5] = velRad[cmet,tmet,hmet].T
5327 data_param[:,5] = velRad[cmet,tmet,hmet].T
4982 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
5328 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
4983
5329
4984 if len(data_param) == 0:
5330 if len(data_param) == 0:
4985 dataOut.flagNoData = True
5331 dataOut.flagNoData = True
4986 else:
5332 else:
4987 dataOut.data_param = data_param
5333 dataOut.data_param = data_param
4988
5334
4989 def __erase_small(self, binArray, threshX, threshY):
5335 def __erase_small(self, binArray, threshX, threshY):
4990 labarray, numfeat = ndimage.measurements.label(binArray)
5336 labarray, numfeat = ndimage.measurements.label(binArray)
4991 binArray1 = numpy.copy(binArray)
5337 binArray1 = numpy.copy(binArray)
4992
5338
4993 for i in range(1,numfeat + 1):
5339 for i in range(1,numfeat + 1):
4994 auxBin = (labarray==i)
5340 auxBin = (labarray==i)
4995 auxSize = auxBin.sum()
5341 auxSize = auxBin.sum()
4996
5342
4997 x,y = numpy.where(auxBin)
5343 x,y = numpy.where(auxBin)
4998 widthX = x.max() - x.min()
5344 widthX = x.max() - x.min()
4999 widthY = y.max() - y.min()
5345 widthY = y.max() - y.min()
5000
5346
5001 #width X: 3 seg -> 12.5*3
5347 #width X: 3 seg -> 12.5*3
5002 #width Y:
5348 #width Y:
5003
5349
5004 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
5350 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
5005 binArray1[auxBin] = False
5351 binArray1[auxBin] = False
5006
5352
5007 return binArray1
5353 return binArray1
5008
5354
5009 #--------------- Specular Meteor ----------------
5355 #--------------- Specular Meteor ----------------
5010
5356
5011 class SMDetection(Operation):
5357 class SMDetection(Operation):
5012 '''
5358 '''
5013 Function DetectMeteors()
5359 Function DetectMeteors()
5014 Project developed with paper:
5360 Project developed with paper:
5015 HOLDSWORTH ET AL. 2004
5361 HOLDSWORTH ET AL. 2004
5016
5362
5017 Input:
5363 Input:
5018 self.dataOut.data_pre
5364 self.dataOut.data_pre
5019
5365
5020 centerReceiverIndex: From the channels, which is the center receiver
5366 centerReceiverIndex: From the channels, which is the center receiver
5021
5367
5022 hei_ref: Height reference for the Beacon signal extraction
5368 hei_ref: Height reference for the Beacon signal extraction
5023 tauindex:
5369 tauindex:
5024 predefinedPhaseShifts: Predefined phase offset for the voltge signals
5370 predefinedPhaseShifts: Predefined phase offset for the voltge signals
5025
5371
5026 cohDetection: Whether to user Coherent detection or not
5372 cohDetection: Whether to user Coherent detection or not
5027 cohDet_timeStep: Coherent Detection calculation time step
5373 cohDet_timeStep: Coherent Detection calculation time step
5028 cohDet_thresh: Coherent Detection phase threshold to correct phases
5374 cohDet_thresh: Coherent Detection phase threshold to correct phases
5029
5375
5030 noise_timeStep: Noise calculation time step
5376 noise_timeStep: Noise calculation time step
5031 noise_multiple: Noise multiple to define signal threshold
5377 noise_multiple: Noise multiple to define signal threshold
5032
5378
5033 multDet_timeLimit: Multiple Detection Removal time limit in seconds
5379 multDet_timeLimit: Multiple Detection Removal time limit in seconds
5034 multDet_rangeLimit: Multiple Detection Removal range limit in km
5380 multDet_rangeLimit: Multiple Detection Removal range limit in km
5035
5381
5036 phaseThresh: Maximum phase difference between receiver to be consider a meteor
5382 phaseThresh: Maximum phase difference between receiver to be consider a meteor
5037 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
5383 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
5038
5384
5039 hmin: Minimum Height of the meteor to use it in the further wind estimations
5385 hmin: Minimum Height of the meteor to use it in the further wind estimations
5040 hmax: Maximum Height of the meteor to use it in the further wind estimations
5386 hmax: Maximum Height of the meteor to use it in the further wind estimations
5041 azimuth: Azimuth angle correction
5387 azimuth: Azimuth angle correction
5042
5388
5043 Affected:
5389 Affected:
5044 self.dataOut.data_param
5390 self.dataOut.data_param
5045
5391
5046 Rejection Criteria (Errors):
5392 Rejection Criteria (Errors):
5047 0: No error; analysis OK
5393 0: No error; analysis OK
5048 1: SNR < SNR threshold
5394 1: SNR < SNR threshold
5049 2: angle of arrival (AOA) ambiguously determined
5395 2: angle of arrival (AOA) ambiguously determined
5050 3: AOA estimate not feasible
5396 3: AOA estimate not feasible
5051 4: Large difference in AOAs obtained from different antenna baselines
5397 4: Large difference in AOAs obtained from different antenna baselines
5052 5: echo at start or end of time series
5398 5: echo at start or end of time series
5053 6: echo less than 5 examples long; too short for analysis
5399 6: echo less than 5 examples long; too short for analysis
5054 7: echo rise exceeds 0.3s
5400 7: echo rise exceeds 0.3s
5055 8: echo decay time less than twice rise time
5401 8: echo decay time less than twice rise time
5056 9: large power level before echo
5402 9: large power level before echo
5057 10: large power level after echo
5403 10: large power level after echo
5058 11: poor fit to amplitude for estimation of decay time
5404 11: poor fit to amplitude for estimation of decay time
5059 12: poor fit to CCF phase variation for estimation of radial drift velocity
5405 12: poor fit to CCF phase variation for estimation of radial drift velocity
5060 13: height unresolvable echo: not valid height within 70 to 110 km
5406 13: height unresolvable echo: not valid height within 70 to 110 km
5061 14: height ambiguous echo: more then one possible height within 70 to 110 km
5407 14: height ambiguous echo: more then one possible height within 70 to 110 km
5062 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
5408 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
5063 16: oscilatory echo, indicating event most likely not an underdense echo
5409 16: oscilatory echo, indicating event most likely not an underdense echo
5064
5410
5065 17: phase difference in meteor Reestimation
5411 17: phase difference in meteor Reestimation
5066
5412
5067 Data Storage:
5413 Data Storage:
5068 Meteors for Wind Estimation (8):
5414 Meteors for Wind Estimation (8):
5069 Utc Time | Range Height
5415 Utc Time | Range Height
5070 Azimuth Zenith errorCosDir
5416 Azimuth Zenith errorCosDir
5071 VelRad errorVelRad
5417 VelRad errorVelRad
5072 Phase0 Phase1 Phase2 Phase3
5418 Phase0 Phase1 Phase2 Phase3
5073 TypeError
5419 TypeError
5074
5420
5075 '''
5421 '''
5076
5422
5077 def run(self, dataOut, hei_ref = None, tauindex = 0,
5423 def run(self, dataOut, hei_ref = None, tauindex = 0,
5078 phaseOffsets = None,
5424 phaseOffsets = None,
5079 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
5425 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
5080 noise_timeStep = 4, noise_multiple = 4,
5426 noise_timeStep = 4, noise_multiple = 4,
5081 multDet_timeLimit = 1, multDet_rangeLimit = 3,
5427 multDet_timeLimit = 1, multDet_rangeLimit = 3,
5082 phaseThresh = 20, SNRThresh = 5,
5428 phaseThresh = 20, SNRThresh = 5,
5083 hmin = 50, hmax=150, azimuth = 0,
5429 hmin = 50, hmax=150, azimuth = 0,
5084 channelPositions = None) :
5430 channelPositions = None) :
5085
5431
5086
5432
5087 #Getting Pairslist
5433 #Getting Pairslist
5088 if channelPositions is None:
5434 if channelPositions is None:
5089 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5435 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5090 meteorOps = SMOperations()
5436 meteorOps = SMOperations()
5091 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5437 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5092 heiRang = dataOut.heightList
5438 heiRang = dataOut.heightList
5093 #Get Beacon signal - No Beacon signal anymore
5439 #Get Beacon signal - No Beacon signal anymore
5094 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
5440 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
5095 # see if the user put in pre defined phase shifts
5441 # see if the user put in pre defined phase shifts
5096 voltsPShift = dataOut.data_pre.copy()
5442 voltsPShift = dataOut.data_pre.copy()
5097
5443
5098 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
5444 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
5099
5445
5100 #Remove DC
5446 #Remove DC
5101 voltsDC = numpy.mean(voltsPShift,1)
5447 voltsDC = numpy.mean(voltsPShift,1)
5102 voltsDC = numpy.mean(voltsDC,1)
5448 voltsDC = numpy.mean(voltsDC,1)
5103 for i in range(voltsDC.shape[0]):
5449 for i in range(voltsDC.shape[0]):
5104 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
5450 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
5105
5451
5106 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
5452 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
5107
5453
5108 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
5454 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
5109 #Coherent Detection
5455 #Coherent Detection
5110 if cohDetection:
5456 if cohDetection:
5111 #use coherent detection to get the net power
5457 #use coherent detection to get the net power
5112 cohDet_thresh = cohDet_thresh*numpy.pi/180
5458 cohDet_thresh = cohDet_thresh*numpy.pi/180
5113 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
5459 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
5114
5460
5115 #Non-coherent detection!
5461 #Non-coherent detection!
5116 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
5462 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
5117 #********** END OF COH/NON-COH POWER CALCULATION**********************
5463 #********** END OF COH/NON-COH POWER CALCULATION**********************
5118
5464
5119 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
5465 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
5120 #Get noise
5466 #Get noise
5121 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
5467 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
5122 #Get signal threshold
5468 #Get signal threshold
5123 signalThresh = noise_multiple*noise
5469 signalThresh = noise_multiple*noise
5124 #Meteor echoes detection
5470 #Meteor echoes detection
5125 listMeteors = self.__findMeteors(powerNet, signalThresh)
5471 listMeteors = self.__findMeteors(powerNet, signalThresh)
5126 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
5472 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
5127
5473
5128 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
5474 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
5129 #Parameters
5475 #Parameters
5130 heiRange = dataOut.heightList
5476 heiRange = dataOut.heightList
5131 rangeInterval = heiRange[1] - heiRange[0]
5477 rangeInterval = heiRange[1] - heiRange[0]
5132 rangeLimit = multDet_rangeLimit/rangeInterval
5478 rangeLimit = multDet_rangeLimit/rangeInterval
5133 timeLimit = multDet_timeLimit/dataOut.timeInterval
5479 timeLimit = multDet_timeLimit/dataOut.timeInterval
5134 #Multiple detection removals
5480 #Multiple detection removals
5135 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
5481 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
5136 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
5482 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
5137
5483
5138 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
5484 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
5139 #Parameters
5485 #Parameters
5140 phaseThresh = phaseThresh*numpy.pi/180
5486 phaseThresh = phaseThresh*numpy.pi/180
5141 thresh = [phaseThresh, noise_multiple, SNRThresh]
5487 thresh = [phaseThresh, noise_multiple, SNRThresh]
5142 #Meteor reestimation (Errors N 1, 6, 12, 17)
5488 #Meteor reestimation (Errors N 1, 6, 12, 17)
5143 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
5489 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
5144 #Estimation of decay times (Errors N 7, 8, 11)
5490 #Estimation of decay times (Errors N 7, 8, 11)
5145 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
5491 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
5146 #******************* END OF METEOR REESTIMATION *******************
5492 #******************* END OF METEOR REESTIMATION *******************
5147
5493
5148 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
5494 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
5149 #Calculating Radial Velocity (Error N 15)
5495 #Calculating Radial Velocity (Error N 15)
5150 radialStdThresh = 10
5496 radialStdThresh = 10
5151 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
5497 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
5152
5498
5153 if len(listMeteors4) > 0:
5499 if len(listMeteors4) > 0:
5154 #Setting New Array
5500 #Setting New Array
5155 date = dataOut.utctime
5501 date = dataOut.utctime
5156 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
5502 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
5157
5503
5158 #Correcting phase offset
5504 #Correcting phase offset
5159 if phaseOffsets != None:
5505 if phaseOffsets != None:
5160 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5506 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5161 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5507 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5162
5508
5163 #Second Pairslist
5509 #Second Pairslist
5164 pairsList = []
5510 pairsList = []
5165 pairx = (0,1)
5511 pairx = (0,1)
5166 pairy = (2,3)
5512 pairy = (2,3)
5167 pairsList.append(pairx)
5513 pairsList.append(pairx)
5168 pairsList.append(pairy)
5514 pairsList.append(pairy)
5169
5515
5170 jph = numpy.array([0,0,0,0])
5516 jph = numpy.array([0,0,0,0])
5171 h = (hmin,hmax)
5517 h = (hmin,hmax)
5172 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5518 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5173 dataOut.data_param = arrayParameters
5519 dataOut.data_param = arrayParameters
5174
5520
5175 if arrayParameters is None:
5521 if arrayParameters is None:
5176 dataOut.flagNoData = True
5522 dataOut.flagNoData = True
5177 else:
5523 else:
5178 dataOut.flagNoData = True
5524 dataOut.flagNoData = True
5179
5525
5180 return
5526 return
5181
5527
5182 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
5528 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
5183
5529
5184 minIndex = min(newheis[0])
5530 minIndex = min(newheis[0])
5185 maxIndex = max(newheis[0])
5531 maxIndex = max(newheis[0])
5186
5532
5187 voltage = voltage0[:,:,minIndex:maxIndex+1]
5533 voltage = voltage0[:,:,minIndex:maxIndex+1]
5188 nLength = voltage.shape[1]/n
5534 nLength = voltage.shape[1]/n
5189 nMin = 0
5535 nMin = 0
5190 nMax = 0
5536 nMax = 0
5191 phaseOffset = numpy.zeros((len(pairslist),n))
5537 phaseOffset = numpy.zeros((len(pairslist),n))
5192
5538
5193 for i in range(n):
5539 for i in range(n):
5194 nMax += nLength
5540 nMax += nLength
5195 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
5541 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
5196 phaseCCF = numpy.mean(phaseCCF, axis = 2)
5542 phaseCCF = numpy.mean(phaseCCF, axis = 2)
5197 phaseOffset[:,i] = phaseCCF.transpose()
5543 phaseOffset[:,i] = phaseCCF.transpose()
5198 nMin = nMax
5544 nMin = nMax
5199
5545
5200 #Remove Outliers
5546 #Remove Outliers
5201 factor = 2
5547 factor = 2
5202 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
5548 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
5203 dw = numpy.std(wt,axis = 1)
5549 dw = numpy.std(wt,axis = 1)
5204 dw = dw.reshape((dw.size,1))
5550 dw = dw.reshape((dw.size,1))
5205 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
5551 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
5206 phaseOffset[ind] = numpy.nan
5552 phaseOffset[ind] = numpy.nan
5207 phaseOffset = stats.nanmean(phaseOffset, axis=1)
5553 phaseOffset = stats.nanmean(phaseOffset, axis=1)
5208
5554
5209 return phaseOffset
5555 return phaseOffset
5210
5556
5211 def __shiftPhase(self, data, phaseShift):
5557 def __shiftPhase(self, data, phaseShift):
5212 #this will shift the phase of a complex number
5558 #this will shift the phase of a complex number
5213 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
5559 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
5214 return dataShifted
5560 return dataShifted
5215
5561
5216 def __estimatePhaseDifference(self, array, pairslist):
5562 def __estimatePhaseDifference(self, array, pairslist):
5217 nChannel = array.shape[0]
5563 nChannel = array.shape[0]
5218 nHeights = array.shape[2]
5564 nHeights = array.shape[2]
5219 numPairs = len(pairslist)
5565 numPairs = len(pairslist)
5220 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
5566 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
5221
5567
5222 #Correct phases
5568 #Correct phases
5223 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
5569 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
5224 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5570 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5225
5571
5226 if indDer[0].shape[0] > 0:
5572 if indDer[0].shape[0] > 0:
5227 for i in range(indDer[0].shape[0]):
5573 for i in range(indDer[0].shape[0]):
5228 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
5574 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
5229 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
5575 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
5230
5576
5231 #Linear
5577 #Linear
5232 phaseInt = numpy.zeros((numPairs,1))
5578 phaseInt = numpy.zeros((numPairs,1))
5233 angAllCCF = phaseCCF[:,[0,1,3,4],0]
5579 angAllCCF = phaseCCF[:,[0,1,3,4],0]
5234 for j in range(numPairs):
5580 for j in range(numPairs):
5235 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
5581 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
5236 phaseInt[j] = fit[1]
5582 phaseInt[j] = fit[1]
5237 #Phase Differences
5583 #Phase Differences
5238 phaseDiff = phaseInt - phaseCCF[:,2,:]
5584 phaseDiff = phaseInt - phaseCCF[:,2,:]
5239 phaseArrival = phaseInt.reshape(phaseInt.size)
5585 phaseArrival = phaseInt.reshape(phaseInt.size)
5240
5586
5241 #Dealias
5587 #Dealias
5242 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
5588 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
5243
5589
5244 return phaseDiff, phaseArrival
5590 return phaseDiff, phaseArrival
5245
5591
5246 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
5592 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
5247 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
5593 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
5248 #find the phase shifts of each channel over 1 second intervals
5594 #find the phase shifts of each channel over 1 second intervals
5249 #only look at ranges below the beacon signal
5595 #only look at ranges below the beacon signal
5250 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5596 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5251 numBlocks = int(volts.shape[1]/numProfPerBlock)
5597 numBlocks = int(volts.shape[1]/numProfPerBlock)
5252 numHeights = volts.shape[2]
5598 numHeights = volts.shape[2]
5253 nChannel = volts.shape[0]
5599 nChannel = volts.shape[0]
5254 voltsCohDet = volts.copy()
5600 voltsCohDet = volts.copy()
5255
5601
5256 pairsarray = numpy.array(pairslist)
5602 pairsarray = numpy.array(pairslist)
5257 indSides = pairsarray[:,1]
5603 indSides = pairsarray[:,1]
5258 listBlocks = numpy.array_split(volts, numBlocks, 1)
5604 listBlocks = numpy.array_split(volts, numBlocks, 1)
5259
5605
5260 startInd = 0
5606 startInd = 0
5261 endInd = 0
5607 endInd = 0
5262
5608
5263 for i in range(numBlocks):
5609 for i in range(numBlocks):
5264 startInd = endInd
5610 startInd = endInd
5265 endInd = endInd + listBlocks[i].shape[1]
5611 endInd = endInd + listBlocks[i].shape[1]
5266
5612
5267 arrayBlock = listBlocks[i]
5613 arrayBlock = listBlocks[i]
5268
5614
5269 #Estimate the Phase Difference
5615 #Estimate the Phase Difference
5270 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
5616 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
5271 #Phase Difference RMS
5617 #Phase Difference RMS
5272 arrayPhaseRMS = numpy.abs(phaseDiff)
5618 arrayPhaseRMS = numpy.abs(phaseDiff)
5273 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
5619 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
5274 indPhase = numpy.where(phaseRMSaux==4)
5620 indPhase = numpy.where(phaseRMSaux==4)
5275 #Shifting
5621 #Shifting
5276 if indPhase[0].shape[0] > 0:
5622 if indPhase[0].shape[0] > 0:
5277 for j in range(indSides.size):
5623 for j in range(indSides.size):
5278 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
5624 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
5279 voltsCohDet[:,startInd:endInd,:] = arrayBlock
5625 voltsCohDet[:,startInd:endInd,:] = arrayBlock
5280
5626
5281 return voltsCohDet
5627 return voltsCohDet
5282
5628
5283 def __calculateCCF(self, volts, pairslist ,laglist):
5629 def __calculateCCF(self, volts, pairslist ,laglist):
5284
5630
5285 nHeights = volts.shape[2]
5631 nHeights = volts.shape[2]
5286 nPoints = volts.shape[1]
5632 nPoints = volts.shape[1]
5287 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
5633 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
5288
5634
5289 for i in range(len(pairslist)):
5635 for i in range(len(pairslist)):
5290 volts1 = volts[pairslist[i][0]]
5636 volts1 = volts[pairslist[i][0]]
5291 volts2 = volts[pairslist[i][1]]
5637 volts2 = volts[pairslist[i][1]]
5292
5638
5293 for t in range(len(laglist)):
5639 for t in range(len(laglist)):
5294 idxT = laglist[t]
5640 idxT = laglist[t]
5295 if idxT >= 0:
5641 if idxT >= 0:
5296 vStacked = numpy.vstack((volts2[idxT:,:],
5642 vStacked = numpy.vstack((volts2[idxT:,:],
5297 numpy.zeros((idxT, nHeights),dtype='complex')))
5643 numpy.zeros((idxT, nHeights),dtype='complex')))
5298 else:
5644 else:
5299 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
5645 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
5300 volts2[:(nPoints + idxT),:]))
5646 volts2[:(nPoints + idxT),:]))
5301 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
5647 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
5302
5648
5303 vStacked = None
5649 vStacked = None
5304 return voltsCCF
5650 return voltsCCF
5305
5651
5306 def __getNoise(self, power, timeSegment, timeInterval):
5652 def __getNoise(self, power, timeSegment, timeInterval):
5307 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5653 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
5308 numBlocks = int(power.shape[0]/numProfPerBlock)
5654 numBlocks = int(power.shape[0]/numProfPerBlock)
5309 numHeights = power.shape[1]
5655 numHeights = power.shape[1]
5310
5656
5311 listPower = numpy.array_split(power, numBlocks, 0)
5657 listPower = numpy.array_split(power, numBlocks, 0)
5312 noise = numpy.zeros((power.shape[0], power.shape[1]))
5658 noise = numpy.zeros((power.shape[0], power.shape[1]))
5313 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
5659 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
5314
5660
5315 startInd = 0
5661 startInd = 0
5316 endInd = 0
5662 endInd = 0
5317
5663
5318 for i in range(numBlocks): #split por canal
5664 for i in range(numBlocks): #split por canal
5319 startInd = endInd
5665 startInd = endInd
5320 endInd = endInd + listPower[i].shape[0]
5666 endInd = endInd + listPower[i].shape[0]
5321
5667
5322 arrayBlock = listPower[i]
5668 arrayBlock = listPower[i]
5323 noiseAux = numpy.mean(arrayBlock, 0)
5669 noiseAux = numpy.mean(arrayBlock, 0)
5324 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
5670 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
5325
5671
5326 noiseAux1 = numpy.mean(arrayBlock)
5672 noiseAux1 = numpy.mean(arrayBlock)
5327 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
5673 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
5328
5674
5329 return noise, noise1
5675 return noise, noise1
5330
5676
5331 def __findMeteors(self, power, thresh):
5677 def __findMeteors(self, power, thresh):
5332 nProf = power.shape[0]
5678 nProf = power.shape[0]
5333 nHeights = power.shape[1]
5679 nHeights = power.shape[1]
5334 listMeteors = []
5680 listMeteors = []
5335
5681
5336 for i in range(nHeights):
5682 for i in range(nHeights):
5337 powerAux = power[:,i]
5683 powerAux = power[:,i]
5338 threshAux = thresh[:,i]
5684 threshAux = thresh[:,i]
5339
5685
5340 indUPthresh = numpy.where(powerAux > threshAux)[0]
5686 indUPthresh = numpy.where(powerAux > threshAux)[0]
5341 indDNthresh = numpy.where(powerAux <= threshAux)[0]
5687 indDNthresh = numpy.where(powerAux <= threshAux)[0]
5342
5688
5343 j = 0
5689 j = 0
5344
5690
5345 while (j < indUPthresh.size - 2):
5691 while (j < indUPthresh.size - 2):
5346 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
5692 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
5347 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
5693 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
5348 indDNthresh = indDNthresh[indDNAux]
5694 indDNthresh = indDNthresh[indDNAux]
5349
5695
5350 if (indDNthresh.size > 0):
5696 if (indDNthresh.size > 0):
5351 indEnd = indDNthresh[0] - 1
5697 indEnd = indDNthresh[0] - 1
5352 indInit = indUPthresh[j]
5698 indInit = indUPthresh[j]
5353
5699
5354 meteor = powerAux[indInit:indEnd + 1]
5700 meteor = powerAux[indInit:indEnd + 1]
5355 indPeak = meteor.argmax() + indInit
5701 indPeak = meteor.argmax() + indInit
5356 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
5702 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
5357
5703
5358 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
5704 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
5359 j = numpy.where(indUPthresh == indEnd)[0] + 1
5705 j = numpy.where(indUPthresh == indEnd)[0] + 1
5360 else: j+=1
5706 else: j+=1
5361 else: j+=1
5707 else: j+=1
5362
5708
5363 return listMeteors
5709 return listMeteors
5364
5710
5365 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
5711 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
5366
5712
5367 arrayMeteors = numpy.asarray(listMeteors)
5713 arrayMeteors = numpy.asarray(listMeteors)
5368 listMeteors1 = []
5714 listMeteors1 = []
5369
5715
5370 while arrayMeteors.shape[0] > 0:
5716 while arrayMeteors.shape[0] > 0:
5371 FLAs = arrayMeteors[:,4]
5717 FLAs = arrayMeteors[:,4]
5372 maxFLA = FLAs.argmax()
5718 maxFLA = FLAs.argmax()
5373 listMeteors1.append(arrayMeteors[maxFLA,:])
5719 listMeteors1.append(arrayMeteors[maxFLA,:])
5374
5720
5375 MeteorInitTime = arrayMeteors[maxFLA,1]
5721 MeteorInitTime = arrayMeteors[maxFLA,1]
5376 MeteorEndTime = arrayMeteors[maxFLA,3]
5722 MeteorEndTime = arrayMeteors[maxFLA,3]
5377 MeteorHeight = arrayMeteors[maxFLA,0]
5723 MeteorHeight = arrayMeteors[maxFLA,0]
5378
5724
5379 #Check neighborhood
5725 #Check neighborhood
5380 maxHeightIndex = MeteorHeight + rangeLimit
5726 maxHeightIndex = MeteorHeight + rangeLimit
5381 minHeightIndex = MeteorHeight - rangeLimit
5727 minHeightIndex = MeteorHeight - rangeLimit
5382 minTimeIndex = MeteorInitTime - timeLimit
5728 minTimeIndex = MeteorInitTime - timeLimit
5383 maxTimeIndex = MeteorEndTime + timeLimit
5729 maxTimeIndex = MeteorEndTime + timeLimit
5384
5730
5385 #Check Heights
5731 #Check Heights
5386 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
5732 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
5387 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
5733 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
5388 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
5734 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
5389
5735
5390 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
5736 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
5391
5737
5392 return listMeteors1
5738 return listMeteors1
5393
5739
5394 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
5740 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
5395 numHeights = volts.shape[2]
5741 numHeights = volts.shape[2]
5396 nChannel = volts.shape[0]
5742 nChannel = volts.shape[0]
5397
5743
5398 thresholdPhase = thresh[0]
5744 thresholdPhase = thresh[0]
5399 thresholdNoise = thresh[1]
5745 thresholdNoise = thresh[1]
5400 thresholdDB = float(thresh[2])
5746 thresholdDB = float(thresh[2])
5401
5747
5402 thresholdDB1 = 10**(thresholdDB/10)
5748 thresholdDB1 = 10**(thresholdDB/10)
5403 pairsarray = numpy.array(pairslist)
5749 pairsarray = numpy.array(pairslist)
5404 indSides = pairsarray[:,1]
5750 indSides = pairsarray[:,1]
5405
5751
5406 pairslist1 = list(pairslist)
5752 pairslist1 = list(pairslist)
5407 pairslist1.append((0,1))
5753 pairslist1.append((0,1))
5408 pairslist1.append((3,4))
5754 pairslist1.append((3,4))
5409
5755
5410 listMeteors1 = []
5756 listMeteors1 = []
5411 listPowerSeries = []
5757 listPowerSeries = []
5412 listVoltageSeries = []
5758 listVoltageSeries = []
5413 #volts has the war data
5759 #volts has the war data
5414
5760
5415 if frequency == 30e6:
5761 if frequency == 30e6:
5416 timeLag = 45*10**-3
5762 timeLag = 45*10**-3
5417 else:
5763 else:
5418 timeLag = 15*10**-3
5764 timeLag = 15*10**-3
5419 lag = numpy.ceil(timeLag/timeInterval)
5765 lag = numpy.ceil(timeLag/timeInterval)
5420
5766
5421 for i in range(len(listMeteors)):
5767 for i in range(len(listMeteors)):
5422
5768
5423 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
5769 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
5424 meteorAux = numpy.zeros(16)
5770 meteorAux = numpy.zeros(16)
5425
5771
5426 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
5772 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
5427 mHeight = listMeteors[i][0]
5773 mHeight = listMeteors[i][0]
5428 mStart = listMeteors[i][1]
5774 mStart = listMeteors[i][1]
5429 mPeak = listMeteors[i][2]
5775 mPeak = listMeteors[i][2]
5430 mEnd = listMeteors[i][3]
5776 mEnd = listMeteors[i][3]
5431
5777
5432 #get the volt data between the start and end times of the meteor
5778 #get the volt data between the start and end times of the meteor
5433 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
5779 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
5434 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5780 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5435
5781
5436 #3.6. Phase Difference estimation
5782 #3.6. Phase Difference estimation
5437 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
5783 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
5438
5784
5439 #3.7. Phase difference removal & meteor start, peak and end times reestimated
5785 #3.7. Phase difference removal & meteor start, peak and end times reestimated
5440 #meteorVolts0.- all Channels, all Profiles
5786 #meteorVolts0.- all Channels, all Profiles
5441 meteorVolts0 = volts[:,:,mHeight]
5787 meteorVolts0 = volts[:,:,mHeight]
5442 meteorThresh = noise[:,mHeight]*thresholdNoise
5788 meteorThresh = noise[:,mHeight]*thresholdNoise
5443 meteorNoise = noise[:,mHeight]
5789 meteorNoise = noise[:,mHeight]
5444 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
5790 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
5445 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
5791 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
5446
5792
5447 #Times reestimation
5793 #Times reestimation
5448 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
5794 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
5449 if mStart1.size > 0:
5795 if mStart1.size > 0:
5450 mStart1 = mStart1[-1] + 1
5796 mStart1 = mStart1[-1] + 1
5451
5797
5452 else:
5798 else:
5453 mStart1 = mPeak
5799 mStart1 = mPeak
5454
5800
5455 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
5801 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
5456 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
5802 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
5457 if mEndDecayTime1.size == 0:
5803 if mEndDecayTime1.size == 0:
5458 mEndDecayTime1 = powerNet0.size
5804 mEndDecayTime1 = powerNet0.size
5459 else:
5805 else:
5460 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
5806 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
5461
5807
5462 #meteorVolts1.- all Channels, from start to end
5808 #meteorVolts1.- all Channels, from start to end
5463 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
5809 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
5464 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
5810 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
5465 if meteorVolts2.shape[1] == 0:
5811 if meteorVolts2.shape[1] == 0:
5466 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
5812 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
5467 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
5813 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
5468 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
5814 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
5469 ##################### END PARAMETERS REESTIMATION #########################
5815 ##################### END PARAMETERS REESTIMATION #########################
5470
5816
5471 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
5817 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
5472 if meteorVolts2.shape[1] > 0:
5818 if meteorVolts2.shape[1] > 0:
5473 #Phase Difference re-estimation
5819 #Phase Difference re-estimation
5474 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
5820 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
5475 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
5821 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
5476 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
5822 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
5477 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
5823 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
5478
5824
5479 #Phase Difference RMS
5825 #Phase Difference RMS
5480 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
5826 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
5481 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
5827 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
5482 #Data from Meteor
5828 #Data from Meteor
5483 mPeak1 = powerNet1.argmax() + mStart1
5829 mPeak1 = powerNet1.argmax() + mStart1
5484 mPeakPower1 = powerNet1.max()
5830 mPeakPower1 = powerNet1.max()
5485 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
5831 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
5486 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
5832 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
5487 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
5833 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
5488 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
5834 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
5489 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
5835 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
5490 #Vectorize
5836 #Vectorize
5491 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
5837 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
5492 meteorAux[7:11] = phaseDiffint[0:4]
5838 meteorAux[7:11] = phaseDiffint[0:4]
5493
5839
5494 #Rejection Criterions
5840 #Rejection Criterions
5495 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
5841 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
5496 meteorAux[-1] = 17
5842 meteorAux[-1] = 17
5497 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
5843 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
5498 meteorAux[-1] = 1
5844 meteorAux[-1] = 1
5499
5845
5500
5846
5501 else:
5847 else:
5502 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
5848 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
5503 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
5849 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
5504 PowerSeries = 0
5850 PowerSeries = 0
5505
5851
5506 listMeteors1.append(meteorAux)
5852 listMeteors1.append(meteorAux)
5507 listPowerSeries.append(PowerSeries)
5853 listPowerSeries.append(PowerSeries)
5508 listVoltageSeries.append(meteorVolts1)
5854 listVoltageSeries.append(meteorVolts1)
5509
5855
5510 return listMeteors1, listPowerSeries, listVoltageSeries
5856 return listMeteors1, listPowerSeries, listVoltageSeries
5511
5857
5512 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
5858 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
5513
5859
5514 threshError = 10
5860 threshError = 10
5515 #Depending if it is 30 or 50 MHz
5861 #Depending if it is 30 or 50 MHz
5516 if frequency == 30e6:
5862 if frequency == 30e6:
5517 timeLag = 45*10**-3
5863 timeLag = 45*10**-3
5518 else:
5864 else:
5519 timeLag = 15*10**-3
5865 timeLag = 15*10**-3
5520 lag = numpy.ceil(timeLag/timeInterval)
5866 lag = numpy.ceil(timeLag/timeInterval)
5521
5867
5522 listMeteors1 = []
5868 listMeteors1 = []
5523
5869
5524 for i in range(len(listMeteors)):
5870 for i in range(len(listMeteors)):
5525 meteorPower = listPower[i]
5871 meteorPower = listPower[i]
5526 meteorAux = listMeteors[i]
5872 meteorAux = listMeteors[i]
5527
5873
5528 if meteorAux[-1] == 0:
5874 if meteorAux[-1] == 0:
5529
5875
5530 try:
5876 try:
5531 indmax = meteorPower.argmax()
5877 indmax = meteorPower.argmax()
5532 indlag = indmax + lag
5878 indlag = indmax + lag
5533
5879
5534 y = meteorPower[indlag:]
5880 y = meteorPower[indlag:]
5535 x = numpy.arange(0, y.size)*timeLag
5881 x = numpy.arange(0, y.size)*timeLag
5536
5882
5537 #first guess
5883 #first guess
5538 a = y[0]
5884 a = y[0]
5539 tau = timeLag
5885 tau = timeLag
5540 #exponential fit
5886 #exponential fit
5541 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
5887 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
5542 y1 = self.__exponential_function(x, *popt)
5888 y1 = self.__exponential_function(x, *popt)
5543 #error estimation
5889 #error estimation
5544 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
5890 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
5545
5891
5546 decayTime = popt[1]
5892 decayTime = popt[1]
5547 riseTime = indmax*timeInterval
5893 riseTime = indmax*timeInterval
5548 meteorAux[11:13] = [decayTime, error]
5894 meteorAux[11:13] = [decayTime, error]
5549
5895
5550 #Table items 7, 8 and 11
5896 #Table items 7, 8 and 11
5551 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
5897 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
5552 meteorAux[-1] = 7
5898 meteorAux[-1] = 7
5553 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
5899 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
5554 meteorAux[-1] = 8
5900 meteorAux[-1] = 8
5555 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
5901 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
5556 meteorAux[-1] = 11
5902 meteorAux[-1] = 11
5557
5903
5558
5904
5559 except:
5905 except:
5560 meteorAux[-1] = 11
5906 meteorAux[-1] = 11
5561
5907
5562
5908
5563 listMeteors1.append(meteorAux)
5909 listMeteors1.append(meteorAux)
5564
5910
5565 return listMeteors1
5911 return listMeteors1
5566
5912
5567 #Exponential Function
5913 #Exponential Function
5568
5914
5569 def __exponential_function(self, x, a, tau):
5915 def __exponential_function(self, x, a, tau):
5570 y = a*numpy.exp(-x/tau)
5916 y = a*numpy.exp(-x/tau)
5571 return y
5917 return y
5572
5918
5573 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
5919 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
5574
5920
5575 pairslist1 = list(pairslist)
5921 pairslist1 = list(pairslist)
5576 pairslist1.append((0,1))
5922 pairslist1.append((0,1))
5577 pairslist1.append((3,4))
5923 pairslist1.append((3,4))
5578 numPairs = len(pairslist1)
5924 numPairs = len(pairslist1)
5579 #Time Lag
5925 #Time Lag
5580 timeLag = 45*10**-3
5926 timeLag = 45*10**-3
5581 c = 3e8
5927 c = 3e8
5582 lag = numpy.ceil(timeLag/timeInterval)
5928 lag = numpy.ceil(timeLag/timeInterval)
5583 freq = 30e6
5929 freq = 30e6
5584
5930
5585 listMeteors1 = []
5931 listMeteors1 = []
5586
5932
5587 for i in range(len(listMeteors)):
5933 for i in range(len(listMeteors)):
5588 meteorAux = listMeteors[i]
5934 meteorAux = listMeteors[i]
5589 if meteorAux[-1] == 0:
5935 if meteorAux[-1] == 0:
5590 mStart = listMeteors[i][1]
5936 mStart = listMeteors[i][1]
5591 mPeak = listMeteors[i][2]
5937 mPeak = listMeteors[i][2]
5592 mLag = mPeak - mStart + lag
5938 mLag = mPeak - mStart + lag
5593
5939
5594 #get the volt data between the start and end times of the meteor
5940 #get the volt data between the start and end times of the meteor
5595 meteorVolts = listVolts[i]
5941 meteorVolts = listVolts[i]
5596 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5942 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
5597
5943
5598 #Get CCF
5944 #Get CCF
5599 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
5945 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
5600
5946
5601 #Method 2
5947 #Method 2
5602 slopes = numpy.zeros(numPairs)
5948 slopes = numpy.zeros(numPairs)
5603 time = numpy.array([-2,-1,1,2])*timeInterval
5949 time = numpy.array([-2,-1,1,2])*timeInterval
5604 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
5950 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
5605
5951
5606 #Correct phases
5952 #Correct phases
5607 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
5953 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
5608 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5954 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
5609
5955
5610 if indDer[0].shape[0] > 0:
5956 if indDer[0].shape[0] > 0:
5611 for i in range(indDer[0].shape[0]):
5957 for i in range(indDer[0].shape[0]):
5612 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
5958 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
5613 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
5959 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
5614
5960
5615 for j in range(numPairs):
5961 for j in range(numPairs):
5616 fit = stats.linregress(time, angAllCCF[j,:])
5962 fit = stats.linregress(time, angAllCCF[j,:])
5617 slopes[j] = fit[0]
5963 slopes[j] = fit[0]
5618
5964
5619 #Remove Outlier
5965 #Remove Outlier
5620 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
5966 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
5621 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
5967 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
5622 meteorAux[-2] = radialError
5968 meteorAux[-2] = radialError
5623 meteorAux[-3] = radialVelocity
5969 meteorAux[-3] = radialVelocity
5624
5970
5625 #Setting Error
5971 #Setting Error
5626 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
5972 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
5627 if numpy.abs(radialVelocity) > 200:
5973 if numpy.abs(radialVelocity) > 200:
5628 meteorAux[-1] = 15
5974 meteorAux[-1] = 15
5629 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
5975 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
5630 elif radialError > radialStdThresh:
5976 elif radialError > radialStdThresh:
5631 meteorAux[-1] = 12
5977 meteorAux[-1] = 12
5632
5978
5633 listMeteors1.append(meteorAux)
5979 listMeteors1.append(meteorAux)
5634 return listMeteors1
5980 return listMeteors1
5635
5981
5636 def __setNewArrays(self, listMeteors, date, heiRang):
5982 def __setNewArrays(self, listMeteors, date, heiRang):
5637
5983
5638 #New arrays
5984 #New arrays
5639 arrayMeteors = numpy.array(listMeteors)
5985 arrayMeteors = numpy.array(listMeteors)
5640 arrayParameters = numpy.zeros((len(listMeteors), 13))
5986 arrayParameters = numpy.zeros((len(listMeteors), 13))
5641
5987
5642 #Date inclusion
5988 #Date inclusion
5643 arrayDate = numpy.tile(date, (len(listMeteors)))
5989 arrayDate = numpy.tile(date, (len(listMeteors)))
5644
5990
5645 #Meteor array
5991 #Meteor array
5646 #Parameters Array
5992 #Parameters Array
5647 arrayParameters[:,0] = arrayDate #Date
5993 arrayParameters[:,0] = arrayDate #Date
5648 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
5994 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
5649 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
5995 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
5650 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
5996 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
5651 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
5997 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
5652
5998
5653
5999
5654 return arrayParameters
6000 return arrayParameters
5655
6001
5656 class CorrectSMPhases(Operation):
6002 class CorrectSMPhases(Operation):
5657
6003
5658 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
6004 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
5659
6005
5660 arrayParameters = dataOut.data_param
6006 arrayParameters = dataOut.data_param
5661 pairsList = []
6007 pairsList = []
5662 pairx = (0,1)
6008 pairx = (0,1)
5663 pairy = (2,3)
6009 pairy = (2,3)
5664 pairsList.append(pairx)
6010 pairsList.append(pairx)
5665 pairsList.append(pairy)
6011 pairsList.append(pairy)
5666 jph = numpy.zeros(4)
6012 jph = numpy.zeros(4)
5667
6013
5668 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
6014 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
5669 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
6015 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
5670 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
6016 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
5671
6017
5672 meteorOps = SMOperations()
6018 meteorOps = SMOperations()
5673 if channelPositions is None:
6019 if channelPositions is None:
5674 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
6020 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
5675 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
6021 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5676
6022
5677 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
6023 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5678 h = (hmin,hmax)
6024 h = (hmin,hmax)
5679
6025
5680 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
6026 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
5681
6027
5682 dataOut.data_param = arrayParameters
6028 dataOut.data_param = arrayParameters
5683 return
6029 return
5684
6030
5685 class SMPhaseCalibration(Operation):
6031 class SMPhaseCalibration(Operation):
5686
6032
5687 __buffer = None
6033 __buffer = None
5688
6034
5689 __initime = None
6035 __initime = None
5690
6036
5691 __dataReady = False
6037 __dataReady = False
5692
6038
5693 __isConfig = False
6039 __isConfig = False
5694
6040
5695 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
6041 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
5696
6042
5697 dataTime = currentTime + paramInterval
6043 dataTime = currentTime + paramInterval
5698 deltaTime = dataTime - initTime
6044 deltaTime = dataTime - initTime
5699
6045
5700 if deltaTime >= outputInterval or deltaTime < 0:
6046 if deltaTime >= outputInterval or deltaTime < 0:
5701 return True
6047 return True
5702
6048
5703 return False
6049 return False
5704
6050
5705 def __getGammas(self, pairs, d, phases):
6051 def __getGammas(self, pairs, d, phases):
5706 gammas = numpy.zeros(2)
6052 gammas = numpy.zeros(2)
5707
6053
5708 for i in range(len(pairs)):
6054 for i in range(len(pairs)):
5709
6055
5710 pairi = pairs[i]
6056 pairi = pairs[i]
5711
6057
5712 phip3 = phases[:,pairi[0]]
6058 phip3 = phases[:,pairi[0]]
5713 d3 = d[pairi[0]]
6059 d3 = d[pairi[0]]
5714 phip2 = phases[:,pairi[1]]
6060 phip2 = phases[:,pairi[1]]
5715 d2 = d[pairi[1]]
6061 d2 = d[pairi[1]]
5716 #Calculating gamma
6062 #Calculating gamma
5717 jgamma = -phip2*d3/d2 - phip3
6063 jgamma = -phip2*d3/d2 - phip3
5718 jgamma = numpy.angle(numpy.exp(1j*jgamma))
6064 jgamma = numpy.angle(numpy.exp(1j*jgamma))
5719
6065
5720 #Revised distribution
6066 #Revised distribution
5721 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
6067 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
5722
6068
5723 #Histogram
6069 #Histogram
5724 nBins = 64
6070 nBins = 64
5725 rmin = -0.5*numpy.pi
6071 rmin = -0.5*numpy.pi
5726 rmax = 0.5*numpy.pi
6072 rmax = 0.5*numpy.pi
5727 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
6073 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
5728
6074
5729 meteorsY = phaseHisto[0]
6075 meteorsY = phaseHisto[0]
5730 phasesX = phaseHisto[1][:-1]
6076 phasesX = phaseHisto[1][:-1]
5731 width = phasesX[1] - phasesX[0]
6077 width = phasesX[1] - phasesX[0]
5732 phasesX += width/2
6078 phasesX += width/2
5733
6079
5734 #Gaussian aproximation
6080 #Gaussian aproximation
5735 bpeak = meteorsY.argmax()
6081 bpeak = meteorsY.argmax()
5736 peak = meteorsY.max()
6082 peak = meteorsY.max()
5737 jmin = bpeak - 5
6083 jmin = bpeak - 5
5738 jmax = bpeak + 5 + 1
6084 jmax = bpeak + 5 + 1
5739
6085
5740 if jmin<0:
6086 if jmin<0:
5741 jmin = 0
6087 jmin = 0
5742 jmax = 6
6088 jmax = 6
5743 elif jmax > meteorsY.size:
6089 elif jmax > meteorsY.size:
5744 jmin = meteorsY.size - 6
6090 jmin = meteorsY.size - 6
5745 jmax = meteorsY.size
6091 jmax = meteorsY.size
5746
6092
5747 x0 = numpy.array([peak,bpeak,50])
6093 x0 = numpy.array([peak,bpeak,50])
5748 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
6094 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
5749
6095
5750 #Gammas
6096 #Gammas
5751 gammas[i] = coeff[0][1]
6097 gammas[i] = coeff[0][1]
5752
6098
5753 return gammas
6099 return gammas
5754
6100
5755 def __residualFunction(self, coeffs, y, t):
6101 def __residualFunction(self, coeffs, y, t):
5756
6102
5757 return y - self.__gauss_function(t, coeffs)
6103 return y - self.__gauss_function(t, coeffs)
5758
6104
5759 def __gauss_function(self, t, coeffs):
6105 def __gauss_function(self, t, coeffs):
5760
6106
5761 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
6107 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
5762
6108
5763 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
6109 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
5764 meteorOps = SMOperations()
6110 meteorOps = SMOperations()
5765 nchan = 4
6111 nchan = 4
5766 pairx = pairsList[0] #x es 0
6112 pairx = pairsList[0] #x es 0
5767 pairy = pairsList[1] #y es 1
6113 pairy = pairsList[1] #y es 1
5768 center_xangle = 0
6114 center_xangle = 0
5769 center_yangle = 0
6115 center_yangle = 0
5770 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
6116 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
5771 ntimes = len(range_angle)
6117 ntimes = len(range_angle)
5772
6118
5773 nstepsx = 20
6119 nstepsx = 20
5774 nstepsy = 20
6120 nstepsy = 20
5775
6121
5776 for iz in range(ntimes):
6122 for iz in range(ntimes):
5777 min_xangle = -range_angle[iz]/2 + center_xangle
6123 min_xangle = -range_angle[iz]/2 + center_xangle
5778 max_xangle = range_angle[iz]/2 + center_xangle
6124 max_xangle = range_angle[iz]/2 + center_xangle
5779 min_yangle = -range_angle[iz]/2 + center_yangle
6125 min_yangle = -range_angle[iz]/2 + center_yangle
5780 max_yangle = range_angle[iz]/2 + center_yangle
6126 max_yangle = range_angle[iz]/2 + center_yangle
5781
6127
5782 inc_x = (max_xangle-min_xangle)/nstepsx
6128 inc_x = (max_xangle-min_xangle)/nstepsx
5783 inc_y = (max_yangle-min_yangle)/nstepsy
6129 inc_y = (max_yangle-min_yangle)/nstepsy
5784
6130
5785 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
6131 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
5786 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
6132 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
5787 penalty = numpy.zeros((nstepsx,nstepsy))
6133 penalty = numpy.zeros((nstepsx,nstepsy))
5788 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
6134 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
5789 jph = numpy.zeros(nchan)
6135 jph = numpy.zeros(nchan)
5790
6136
5791 # Iterations looking for the offset
6137 # Iterations looking for the offset
5792 for iy in range(int(nstepsy)):
6138 for iy in range(int(nstepsy)):
5793 for ix in range(int(nstepsx)):
6139 for ix in range(int(nstepsx)):
5794 d3 = d[pairsList[1][0]]
6140 d3 = d[pairsList[1][0]]
5795 d2 = d[pairsList[1][1]]
6141 d2 = d[pairsList[1][1]]
5796 d5 = d[pairsList[0][0]]
6142 d5 = d[pairsList[0][0]]
5797 d4 = d[pairsList[0][1]]
6143 d4 = d[pairsList[0][1]]
5798
6144
5799 alp2 = alpha_y[iy] #gamma 1
6145 alp2 = alpha_y[iy] #gamma 1
5800 alp4 = alpha_x[ix] #gamma 0
6146 alp4 = alpha_x[ix] #gamma 0
5801
6147
5802 alp3 = -alp2*d3/d2 - gammas[1]
6148 alp3 = -alp2*d3/d2 - gammas[1]
5803 alp5 = -alp4*d5/d4 - gammas[0]
6149 alp5 = -alp4*d5/d4 - gammas[0]
5804 jph[pairsList[0][1]] = alp4
6150 jph[pairsList[0][1]] = alp4
5805 jph[pairsList[0][0]] = alp5
6151 jph[pairsList[0][0]] = alp5
5806 jph[pairsList[1][0]] = alp3
6152 jph[pairsList[1][0]] = alp3
5807 jph[pairsList[1][1]] = alp2
6153 jph[pairsList[1][1]] = alp2
5808 jph_array[:,ix,iy] = jph
6154 jph_array[:,ix,iy] = jph
5809 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
6155 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
5810 error = meteorsArray1[:,-1]
6156 error = meteorsArray1[:,-1]
5811 ind1 = numpy.where(error==0)[0]
6157 ind1 = numpy.where(error==0)[0]
5812 penalty[ix,iy] = ind1.size
6158 penalty[ix,iy] = ind1.size
5813
6159
5814 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
6160 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
5815 phOffset = jph_array[:,i,j]
6161 phOffset = jph_array[:,i,j]
5816
6162
5817 center_xangle = phOffset[pairx[1]]
6163 center_xangle = phOffset[pairx[1]]
5818 center_yangle = phOffset[pairy[1]]
6164 center_yangle = phOffset[pairy[1]]
5819
6165
5820 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
6166 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
5821 phOffset = phOffset*180/numpy.pi
6167 phOffset = phOffset*180/numpy.pi
5822 return phOffset
6168 return phOffset
5823
6169
5824
6170
5825 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
6171 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
5826
6172
5827 dataOut.flagNoData = True
6173 dataOut.flagNoData = True
5828 self.__dataReady = False
6174 self.__dataReady = False
5829 dataOut.outputInterval = nHours*3600
6175 dataOut.outputInterval = nHours*3600
5830
6176
5831 if self.__isConfig == False:
6177 if self.__isConfig == False:
5832 #Get Initial LTC time
6178 #Get Initial LTC time
5833 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
6179 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
5834 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
6180 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
5835
6181
5836 self.__isConfig = True
6182 self.__isConfig = True
5837
6183
5838 if self.__buffer is None:
6184 if self.__buffer is None:
5839 self.__buffer = dataOut.data_param.copy()
6185 self.__buffer = dataOut.data_param.copy()
5840
6186
5841 else:
6187 else:
5842 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
6188 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
5843
6189
5844 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
6190 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
5845
6191
5846 if self.__dataReady:
6192 if self.__dataReady:
5847 dataOut.utctimeInit = self.__initime
6193 dataOut.utctimeInit = self.__initime
5848 self.__initime += dataOut.outputInterval #to erase time offset
6194 self.__initime += dataOut.outputInterval #to erase time offset
5849
6195
5850 freq = dataOut.frequency
6196 freq = dataOut.frequency
5851 c = dataOut.C #m/s
6197 c = dataOut.C #m/s
5852 lamb = c/freq
6198 lamb = c/freq
5853 k = 2*numpy.pi/lamb
6199 k = 2*numpy.pi/lamb
5854 azimuth = 0
6200 azimuth = 0
5855 h = (hmin, hmax)
6201 h = (hmin, hmax)
5856
6202
5857 if channelPositions is None:
6203 if channelPositions is None:
5858 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
6204 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
5859 meteorOps = SMOperations()
6205 meteorOps = SMOperations()
5860 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
6206 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
5861
6207
5862 #Checking correct order of pairs
6208 #Checking correct order of pairs
5863 pairs = []
6209 pairs = []
5864 if distances[1] > distances[0]:
6210 if distances[1] > distances[0]:
5865 pairs.append((1,0))
6211 pairs.append((1,0))
5866 else:
6212 else:
5867 pairs.append((0,1))
6213 pairs.append((0,1))
5868
6214
5869 if distances[3] > distances[2]:
6215 if distances[3] > distances[2]:
5870 pairs.append((3,2))
6216 pairs.append((3,2))
5871 else:
6217 else:
5872 pairs.append((2,3))
6218 pairs.append((2,3))
5873
6219
5874 meteorsArray = self.__buffer
6220 meteorsArray = self.__buffer
5875 error = meteorsArray[:,-1]
6221 error = meteorsArray[:,-1]
5876 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
6222 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
5877 ind1 = numpy.where(boolError)[0]
6223 ind1 = numpy.where(boolError)[0]
5878 meteorsArray = meteorsArray[ind1,:]
6224 meteorsArray = meteorsArray[ind1,:]
5879 meteorsArray[:,-1] = 0
6225 meteorsArray[:,-1] = 0
5880 phases = meteorsArray[:,8:12]
6226 phases = meteorsArray[:,8:12]
5881
6227
5882 #Calculate Gammas
6228 #Calculate Gammas
5883 gammas = self.__getGammas(pairs, distances, phases)
6229 gammas = self.__getGammas(pairs, distances, phases)
5884 #Calculate Phases
6230 #Calculate Phases
5885 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
6231 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
5886 phasesOff = phasesOff.reshape((1,phasesOff.size))
6232 phasesOff = phasesOff.reshape((1,phasesOff.size))
5887 dataOut.data_output = -phasesOff
6233 dataOut.data_output = -phasesOff
5888 dataOut.flagNoData = False
6234 dataOut.flagNoData = False
5889 self.__buffer = None
6235 self.__buffer = None
5890
6236
5891
6237
5892 return
6238 return
5893
6239
5894 class SMOperations():
6240 class SMOperations():
5895
6241
5896 def __init__(self):
6242 def __init__(self):
5897
6243
5898 return
6244 return
5899
6245
5900 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
6246 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
5901
6247
5902 arrayParameters = arrayParameters0.copy()
6248 arrayParameters = arrayParameters0.copy()
5903 hmin = h[0]
6249 hmin = h[0]
5904 hmax = h[1]
6250 hmax = h[1]
5905
6251
5906 #Calculate AOA (Error N 3, 4)
6252 #Calculate AOA (Error N 3, 4)
5907 #JONES ET AL. 1998
6253 #JONES ET AL. 1998
5908 AOAthresh = numpy.pi/8
6254 AOAthresh = numpy.pi/8
5909 error = arrayParameters[:,-1]
6255 error = arrayParameters[:,-1]
5910 phases = -arrayParameters[:,8:12] + jph
6256 phases = -arrayParameters[:,8:12] + jph
5911 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
6257 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
5912
6258
5913 #Calculate Heights (Error N 13 and 14)
6259 #Calculate Heights (Error N 13 and 14)
5914 error = arrayParameters[:,-1]
6260 error = arrayParameters[:,-1]
5915 Ranges = arrayParameters[:,1]
6261 Ranges = arrayParameters[:,1]
5916 zenith = arrayParameters[:,4]
6262 zenith = arrayParameters[:,4]
5917 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
6263 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
5918
6264
5919 #----------------------- Get Final data ------------------------------------
6265 #----------------------- Get Final data ------------------------------------
5920
6266
5921 return arrayParameters
6267 return arrayParameters
5922
6268
5923 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
6269 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
5924
6270
5925 arrayAOA = numpy.zeros((phases.shape[0],3))
6271 arrayAOA = numpy.zeros((phases.shape[0],3))
5926 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
6272 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
5927
6273
5928 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
6274 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
5929 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
6275 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
5930 arrayAOA[:,2] = cosDirError
6276 arrayAOA[:,2] = cosDirError
5931
6277
5932 azimuthAngle = arrayAOA[:,0]
6278 azimuthAngle = arrayAOA[:,0]
5933 zenithAngle = arrayAOA[:,1]
6279 zenithAngle = arrayAOA[:,1]
5934
6280
5935 #Setting Error
6281 #Setting Error
5936 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
6282 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
5937 error[indError] = 0
6283 error[indError] = 0
5938 #Number 3: AOA not fesible
6284 #Number 3: AOA not fesible
5939 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
6285 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
5940 error[indInvalid] = 3
6286 error[indInvalid] = 3
5941 #Number 4: Large difference in AOAs obtained from different antenna baselines
6287 #Number 4: Large difference in AOAs obtained from different antenna baselines
5942 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
6288 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
5943 error[indInvalid] = 4
6289 error[indInvalid] = 4
5944 return arrayAOA, error
6290 return arrayAOA, error
5945
6291
5946 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
6292 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
5947
6293
5948 #Initializing some variables
6294 #Initializing some variables
5949 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
6295 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
5950 ang_aux = ang_aux.reshape(1,ang_aux.size)
6296 ang_aux = ang_aux.reshape(1,ang_aux.size)
5951
6297
5952 cosdir = numpy.zeros((arrayPhase.shape[0],2))
6298 cosdir = numpy.zeros((arrayPhase.shape[0],2))
5953 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
6299 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
5954
6300
5955
6301
5956 for i in range(2):
6302 for i in range(2):
5957 ph0 = arrayPhase[:,pairsList[i][0]]
6303 ph0 = arrayPhase[:,pairsList[i][0]]
5958 ph1 = arrayPhase[:,pairsList[i][1]]
6304 ph1 = arrayPhase[:,pairsList[i][1]]
5959 d0 = distances[pairsList[i][0]]
6305 d0 = distances[pairsList[i][0]]
5960 d1 = distances[pairsList[i][1]]
6306 d1 = distances[pairsList[i][1]]
5961
6307
5962 ph0_aux = ph0 + ph1
6308 ph0_aux = ph0 + ph1
5963 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
6309 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
5964 #First Estimation
6310 #First Estimation
5965 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
6311 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
5966
6312
5967 #Most-Accurate Second Estimation
6313 #Most-Accurate Second Estimation
5968 phi1_aux = ph0 - ph1
6314 phi1_aux = ph0 - ph1
5969 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
6315 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
5970 #Direction Cosine 1
6316 #Direction Cosine 1
5971 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
6317 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
5972
6318
5973 #Searching the correct Direction Cosine
6319 #Searching the correct Direction Cosine
5974 cosdir0_aux = cosdir0[:,i]
6320 cosdir0_aux = cosdir0[:,i]
5975 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
6321 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
5976 #Minimum Distance
6322 #Minimum Distance
5977 cosDiff = (cosdir1 - cosdir0_aux)**2
6323 cosDiff = (cosdir1 - cosdir0_aux)**2
5978 indcos = cosDiff.argmin(axis = 1)
6324 indcos = cosDiff.argmin(axis = 1)
5979 #Saving Value obtained
6325 #Saving Value obtained
5980 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
6326 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
5981
6327
5982 return cosdir0, cosdir
6328 return cosdir0, cosdir
5983
6329
5984 def __calculateAOA(self, cosdir, azimuth):
6330 def __calculateAOA(self, cosdir, azimuth):
5985 cosdirX = cosdir[:,0]
6331 cosdirX = cosdir[:,0]
5986 cosdirY = cosdir[:,1]
6332 cosdirY = cosdir[:,1]
5987
6333
5988 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
6334 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
5989 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
6335 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
5990 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
6336 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
5991
6337
5992 return angles
6338 return angles
5993
6339
5994 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
6340 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
5995
6341
5996 Ramb = 375 #Ramb = c/(2*PRF)
6342 Ramb = 375 #Ramb = c/(2*PRF)
5997 Re = 6371 #Earth Radius
6343 Re = 6371 #Earth Radius
5998 heights = numpy.zeros(Ranges.shape)
6344 heights = numpy.zeros(Ranges.shape)
5999
6345
6000 R_aux = numpy.array([0,1,2])*Ramb
6346 R_aux = numpy.array([0,1,2])*Ramb
6001 R_aux = R_aux.reshape(1,R_aux.size)
6347 R_aux = R_aux.reshape(1,R_aux.size)
6002
6348
6003 Ranges = Ranges.reshape(Ranges.size,1)
6349 Ranges = Ranges.reshape(Ranges.size,1)
6004
6350
6005 Ri = Ranges + R_aux
6351 Ri = Ranges + R_aux
6006 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
6352 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
6007
6353
6008 #Check if there is a height between 70 and 110 km
6354 #Check if there is a height between 70 and 110 km
6009 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
6355 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
6010 ind_h = numpy.where(h_bool == 1)[0]
6356 ind_h = numpy.where(h_bool == 1)[0]
6011
6357
6012 hCorr = hi[ind_h, :]
6358 hCorr = hi[ind_h, :]
6013 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
6359 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
6014
6360
6015 hCorr = hi[ind_hCorr][:len(ind_h)]
6361 hCorr = hi[ind_hCorr][:len(ind_h)]
6016 heights[ind_h] = hCorr
6362 heights[ind_h] = hCorr
6017
6363
6018 #Setting Error
6364 #Setting Error
6019 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
6365 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
6020 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
6366 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
6021 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
6367 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
6022 error[indError] = 0
6368 error[indError] = 0
6023 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
6369 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
6024 error[indInvalid2] = 14
6370 error[indInvalid2] = 14
6025 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
6371 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
6026 error[indInvalid1] = 13
6372 error[indInvalid1] = 13
6027
6373
6028 return heights, error
6374 return heights, error
6029
6375
6030 def getPhasePairs(self, channelPositions):
6376 def getPhasePairs(self, channelPositions):
6031 chanPos = numpy.array(channelPositions)
6377 chanPos = numpy.array(channelPositions)
6032 listOper = list(itertools.combinations(list(range(5)),2))
6378 listOper = list(itertools.combinations(list(range(5)),2))
6033
6379
6034 distances = numpy.zeros(4)
6380 distances = numpy.zeros(4)
6035 axisX = []
6381 axisX = []
6036 axisY = []
6382 axisY = []
6037 distX = numpy.zeros(3)
6383 distX = numpy.zeros(3)
6038 distY = numpy.zeros(3)
6384 distY = numpy.zeros(3)
6039 ix = 0
6385 ix = 0
6040 iy = 0
6386 iy = 0
6041
6387
6042 pairX = numpy.zeros((2,2))
6388 pairX = numpy.zeros((2,2))
6043 pairY = numpy.zeros((2,2))
6389 pairY = numpy.zeros((2,2))
6044
6390
6045 for i in range(len(listOper)):
6391 for i in range(len(listOper)):
6046 pairi = listOper[i]
6392 pairi = listOper[i]
6047
6393
6048 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
6394 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
6049
6395
6050 if posDif[0] == 0:
6396 if posDif[0] == 0:
6051 axisY.append(pairi)
6397 axisY.append(pairi)
6052 distY[iy] = posDif[1]
6398 distY[iy] = posDif[1]
6053 iy += 1
6399 iy += 1
6054 elif posDif[1] == 0:
6400 elif posDif[1] == 0:
6055 axisX.append(pairi)
6401 axisX.append(pairi)
6056 distX[ix] = posDif[0]
6402 distX[ix] = posDif[0]
6057 ix += 1
6403 ix += 1
6058
6404
6059 for i in range(2):
6405 for i in range(2):
6060 if i==0:
6406 if i==0:
6061 dist0 = distX
6407 dist0 = distX
6062 axis0 = axisX
6408 axis0 = axisX
6063 else:
6409 else:
6064 dist0 = distY
6410 dist0 = distY
6065 axis0 = axisY
6411 axis0 = axisY
6066
6412
6067 side = numpy.argsort(dist0)[:-1]
6413 side = numpy.argsort(dist0)[:-1]
6068 axis0 = numpy.array(axis0)[side,:]
6414 axis0 = numpy.array(axis0)[side,:]
6069 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
6415 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
6070 axis1 = numpy.unique(numpy.reshape(axis0,4))
6416 axis1 = numpy.unique(numpy.reshape(axis0,4))
6071 side = axis1[axis1 != chanC]
6417 side = axis1[axis1 != chanC]
6072 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
6418 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
6073 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
6419 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
6074 if diff1<0:
6420 if diff1<0:
6075 chan2 = side[0]
6421 chan2 = side[0]
6076 d2 = numpy.abs(diff1)
6422 d2 = numpy.abs(diff1)
6077 chan1 = side[1]
6423 chan1 = side[1]
6078 d1 = numpy.abs(diff2)
6424 d1 = numpy.abs(diff2)
6079 else:
6425 else:
6080 chan2 = side[1]
6426 chan2 = side[1]
6081 d2 = numpy.abs(diff2)
6427 d2 = numpy.abs(diff2)
6082 chan1 = side[0]
6428 chan1 = side[0]
6083 d1 = numpy.abs(diff1)
6429 d1 = numpy.abs(diff1)
6084
6430
6085 if i==0:
6431 if i==0:
6086 chanCX = chanC
6432 chanCX = chanC
6087 chan1X = chan1
6433 chan1X = chan1
6088 chan2X = chan2
6434 chan2X = chan2
6089 distances[0:2] = numpy.array([d1,d2])
6435 distances[0:2] = numpy.array([d1,d2])
6090 else:
6436 else:
6091 chanCY = chanC
6437 chanCY = chanC
6092 chan1Y = chan1
6438 chan1Y = chan1
6093 chan2Y = chan2
6439 chan2Y = chan2
6094 distances[2:4] = numpy.array([d1,d2])
6440 distances[2:4] = numpy.array([d1,d2])
6095
6441
6096 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
6442 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
6097
6443
6098 return pairslist, distances
6444 return pairslist, distances
6099
6445
6100 class IGRFModel(Operation):
6446 class IGRFModel(Operation):
6101 """Operation to calculate Geomagnetic parameters.
6447 """Operation to calculate Geomagnetic parameters.
6102
6448
6103 Parameters:
6449 Parameters:
6104 -----------
6450 -----------
6105 None
6451 None
6106
6452
6107 Example
6453 Example
6108 --------
6454 --------
6109
6455
6110 op = proc_unit.addOperation(name='IGRFModel', optype='other')
6456 op = proc_unit.addOperation(name='IGRFModel', optype='other')
6111
6457
6112 """
6458 """
6113
6459
6114 def __init__(self, **kwargs):
6460 def __init__(self, **kwargs):
6115
6461
6116 Operation.__init__(self, **kwargs)
6462 Operation.__init__(self, **kwargs)
6117
6463
6118 self.aux=1
6464 self.aux=1
6119
6465
6120 def run(self,dataOut):
6466 def run(self,dataOut):
6121
6467
6122 try:
6468 try:
6123 from schainpy.model.proc import mkfact_short_2020
6469 from schainpy.model.proc import mkfact_short_2020
6124 except:
6470 except:
6125 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
6471 log.warning('You should install "mkfact_short_2020" module to process IGRF Model')
6126
6472
6127 if self.aux==1:
6473 if self.aux==1:
6128
6474
6129 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
6475 #dataOut.TimeBlockSeconds_First_Time=time.mktime(time.strptime(dataOut.TimeBlockDate))
6130 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
6476 #### we do not use dataOut.datatime.ctime() because it's the time of the second (next) block
6131 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
6477 dataOut.TimeBlockSeconds_First_Time=dataOut.TimeBlockSeconds
6132 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
6478 dataOut.bd_time=time.gmtime(dataOut.TimeBlockSeconds_First_Time)
6133 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
6479 dataOut.year=dataOut.bd_time.tm_year+(dataOut.bd_time.tm_yday-1)/364.0
6134 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
6480 dataOut.ut=dataOut.bd_time.tm_hour+dataOut.bd_time.tm_min/60.0+dataOut.bd_time.tm_sec/3600.0
6135
6481
6136 self.aux=0
6482 self.aux=0
6137
6483
6138 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
6484 dataOut.h=numpy.arange(0.0,15.0*dataOut.MAXNRANGENDT,15.0,dtype='float32')
6139 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6485 dataOut.bfm=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6140 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
6486 dataOut.bfm=numpy.array(dataOut.bfm,order='F')
6141 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6487 dataOut.thb=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6142 dataOut.thb=numpy.array(dataOut.thb,order='F')
6488 dataOut.thb=numpy.array(dataOut.thb,order='F')
6143 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6489 dataOut.bki=numpy.zeros(dataOut.MAXNRANGENDT,dtype='float32')
6144 dataOut.bki=numpy.array(dataOut.bki,order='F')
6490 dataOut.bki=numpy.array(dataOut.bki,order='F')
6145
6491
6146 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
6492 mkfact_short_2020.mkfact(dataOut.year,dataOut.h,dataOut.bfm,dataOut.thb,dataOut.bki,dataOut.MAXNRANGENDT)
6147
6493
6148 return dataOut
6494 return dataOut
6149
6495
6150 class MergeProc(ProcessingUnit):
6496 class MergeProc(ProcessingUnit):
6151
6497
6152 def __init__(self):
6498 def __init__(self):
6153 ProcessingUnit.__init__(self)
6499 ProcessingUnit.__init__(self)
6154
6500
6155 def run(self, attr_data, attr_data_2 = None, attr_data_3 = None, attr_data_4 = None, attr_data_5 = None, mode=0):
6501 def run(self, attr_data, attr_data_2 = None, attr_data_3 = None, attr_data_4 = None, attr_data_5 = None, mode=0):
6156
6502
6157 self.dataOut = getattr(self, self.inputs[0])
6503 self.dataOut = getattr(self, self.inputs[0])
6158 data_inputs = [getattr(self, attr) for attr in self.inputs]
6504 data_inputs = [getattr(self, attr) for attr in self.inputs]
6159 #print(self.inputs)
6505 #print(self.inputs)
6160 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
6506 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
6161 #exit(1)
6507 #exit(1)
6162 if mode==0:
6508 if mode==0:
6163 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
6509 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
6164 setattr(self.dataOut, attr_data, data)
6510 setattr(self.dataOut, attr_data, data)
6165
6511
6166 if mode==1: #Hybrid
6512 if mode==1: #Hybrid
6167 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
6513 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
6168 #setattr(self.dataOut, attr_data, data)
6514 #setattr(self.dataOut, attr_data, data)
6169 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
6515 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
6170 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
6516 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
6171 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
6517 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
6172 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
6518 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
6173 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
6519 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
6174 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
6520 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
6175 '''
6521 '''
6176 print(self.dataOut.dataLag_spc_LP.shape)
6522 print(self.dataOut.dataLag_spc_LP.shape)
6177 print(self.dataOut.dataLag_cspc_LP.shape)
6523 print(self.dataOut.dataLag_cspc_LP.shape)
6178 exit(1)
6524 exit(1)
6179 '''
6525 '''
6180
6526
6181 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
6527 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
6182 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
6528 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
6183 '''
6529 '''
6184 print("Merge")
6530 print("Merge")
6185 print(numpy.shape(self.dataOut.dataLag_spc))
6531 print(numpy.shape(self.dataOut.dataLag_spc))
6186 print(numpy.shape(self.dataOut.dataLag_spc_LP))
6532 print(numpy.shape(self.dataOut.dataLag_spc_LP))
6187 print(numpy.shape(self.dataOut.dataLag_cspc))
6533 print(numpy.shape(self.dataOut.dataLag_cspc))
6188 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
6534 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
6189 exit(1)
6535 exit(1)
6190 '''
6536 '''
6191 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
6537 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
6192 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
6538 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
6193 #exit(1)
6539 #exit(1)
6194 #print(self.dataOut.NDP)
6540 #print(self.dataOut.NDP)
6195 #print(self.dataOut.nNoiseProfiles)
6541 #print(self.dataOut.nNoiseProfiles)
6196
6542
6197 #self.dataOut.nIncohInt_LP = 128
6543 #self.dataOut.nIncohInt_LP = 128
6198 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
6544 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
6199 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
6545 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
6200 self.dataOut.NLAG = 16
6546 self.dataOut.NLAG = 16
6201 self.dataOut.NRANGE = 200
6547 self.dataOut.NRANGE = 200
6202 self.dataOut.NSCAN = 128
6548 self.dataOut.NSCAN = 128
6203 #print(numpy.shape(self.dataOut.data_spc))
6549 #print(numpy.shape(self.dataOut.data_spc))
6204
6550
6205 #exit(1)
6551 #exit(1)
6206
6552
6207 if mode==2: #HAE 2022
6553 if mode==2: #HAE 2022
6208 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
6554 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
6209 setattr(self.dataOut, attr_data, data)
6555 setattr(self.dataOut, attr_data, data)
6210
6556
6211 self.dataOut.nIncohInt *= 2
6557 self.dataOut.nIncohInt *= 2
6212 #meta = self.dataOut.getFreqRange(1)/1000.
6558 #meta = self.dataOut.getFreqRange(1)/1000.
6213 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
6559 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
6214
6560
6215 #exit(1)
6561 #exit(1)
6216
6562
6217 if mode==4: #Hybrid LP-SSheightProfiles
6563 if mode==4: #Hybrid LP-SSheightProfiles
6218 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
6564 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
6219 #setattr(self.dataOut, attr_data, data)
6565 #setattr(self.dataOut, attr_data, data)
6220 setattr(self.dataOut, 'dataLag_spc', getattr(data_inputs[0], attr_data)) #DP
6566 setattr(self.dataOut, 'dataLag_spc', getattr(data_inputs[0], attr_data)) #DP
6221 setattr(self.dataOut, 'dataLag_cspc', getattr(data_inputs[0], attr_data_2)) #DP
6567 setattr(self.dataOut, 'dataLag_cspc', getattr(data_inputs[0], attr_data_2)) #DP
6222 setattr(self.dataOut, 'dataLag_spc_LP', getattr(data_inputs[1], attr_data_3)) #LP
6568 setattr(self.dataOut, 'dataLag_spc_LP', getattr(data_inputs[1], attr_data_3)) #LP
6223 #setattr(self.dataOut, 'dataLag_cspc_LP', getattr(data_inputs[1], attr_data_4)) #LP
6569 #setattr(self.dataOut, 'dataLag_cspc_LP', getattr(data_inputs[1], attr_data_4)) #LP
6224 #setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
6570 #setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
6225 setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
6571 setattr(self.dataOut, 'data_acf', getattr(data_inputs[1], attr_data_5)) #LP
6226 #print("Merge data_acf: ",self.dataOut.data_acf.shape)
6572 #print("Merge data_acf: ",self.dataOut.data_acf.shape)
6227 #exit(1)
6573 #exit(1)
6228 #print(self.dataOut.data_spc_LP.shape)
6574 #print(self.dataOut.data_spc_LP.shape)
6229 #print("Exit")
6575 #print("Exit")
6230 #exit(1)
6576 #exit(1)
6231 #setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
6577 #setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
6232 #setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
6578 #setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
6233 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
6579 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
6234 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
6580 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
6235 '''
6581 '''
6236 print(self.dataOut.dataLag_spc_LP.shape)
6582 print(self.dataOut.dataLag_spc_LP.shape)
6237 print(self.dataOut.dataLag_cspc_LP.shape)
6583 print(self.dataOut.dataLag_cspc_LP.shape)
6238 exit(1)
6584 exit(1)
6239 '''
6585 '''
6240 '''
6586 '''
6241 print(self.dataOut.dataLag_spc_LP[0,:,100])
6587 print(self.dataOut.dataLag_spc_LP[0,:,100])
6242 print(self.dataOut.dataLag_spc_LP[1,:,100])
6588 print(self.dataOut.dataLag_spc_LP[1,:,100])
6243 exit(1)
6589 exit(1)
6244 '''
6590 '''
6245 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
6591 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
6246 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
6592 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
6247 '''
6593 '''
6248 print("Merge")
6594 print("Merge")
6249 print(numpy.shape(self.dataOut.dataLag_spc))
6595 print(numpy.shape(self.dataOut.dataLag_spc))
6250 print(numpy.shape(self.dataOut.dataLag_spc_LP))
6596 print(numpy.shape(self.dataOut.dataLag_spc_LP))
6251 print(numpy.shape(self.dataOut.dataLag_cspc))
6597 print(numpy.shape(self.dataOut.dataLag_cspc))
6252 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
6598 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
6253 exit(1)
6599 exit(1)
6254 '''
6600 '''
6255 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
6601 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
6256 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
6602 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
6257 #exit(1)
6603 #exit(1)
6258 #print(self.dataOut.NDP)
6604 #print(self.dataOut.NDP)
6259 #print(self.dataOut.nNoiseProfiles)
6605 #print(self.dataOut.nNoiseProfiles)
6260
6606
6261 #self.dataOut.nIncohInt_LP = 128
6607 #self.dataOut.nIncohInt_LP = 128
6262 #self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
6608 #self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
6263 self.dataOut.nProfiles_LP = 16#28#self.dataOut.nIncohInt_LP
6609 self.dataOut.nProfiles_LP = 16#28#self.dataOut.nIncohInt_LP
6264 self.dataOut.nProfiles_LP = self.dataOut.data_acf.shape[1]#28#self.dataOut.nIncohInt_LP
6610 self.dataOut.nProfiles_LP = self.dataOut.data_acf.shape[1]#28#self.dataOut.nIncohInt_LP
6265 self.dataOut.NSCAN = 128
6611 self.dataOut.NSCAN = 128
6266 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt*self.dataOut.NSCAN
6612 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt*self.dataOut.NSCAN
6267 #print("sahpi",self.dataOut.nIncohInt_LP)
6613 #print("sahpi",self.dataOut.nIncohInt_LP)
6268 #exit(1)
6614 #exit(1)
6269 self.dataOut.NLAG = 16
6615 self.dataOut.NLAG = 16
6270 self.dataOut.NRANGE = self.dataOut.data_acf.shape[-1]
6616 self.dataOut.NRANGE = self.dataOut.data_acf.shape[-1]
6271
6617
6272 #print(numpy.shape(self.dataOut.data_spc))
6618 #print(numpy.shape(self.dataOut.data_spc))
6273
6619
6274 #exit(1)
6620 #exit(1)
6275 if mode==5:
6621 if mode==5:
6276 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
6622 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
6277 setattr(self.dataOut, attr_data, data)
6623 setattr(self.dataOut, attr_data, data)
6278 data = numpy.concatenate([getattr(data, attr_data_2) for data in data_inputs])
6624 data = numpy.concatenate([getattr(data, attr_data_2) for data in data_inputs])
6279 setattr(self.dataOut, attr_data_2, data)
6625 setattr(self.dataOut, attr_data_2, data)
6280 #data = numpy.concatenate([getattr(data, attr_data_3) for data in data_inputs])
6626 #data = numpy.concatenate([getattr(data, attr_data_3) for data in data_inputs])
6281 #setattr(self.dataOut, attr_data_3, data)
6627 #setattr(self.dataOut, attr_data_3, data)
6282 #print(self.dataOut.moments.shape,self.dataOut.data_snr.shape,self.dataOut.heightList.shape)
6628 #print(self.dataOut.moments.shape,self.dataOut.data_snr.shape,self.dataOut.heightList.shape)
6283
6629
6284
6630
6285 class addTxPower(Operation):
6631 class addTxPower(Operation):
6286 '''
6632 '''
6287 Transmited power level integrated in the dataOut ->AMISR
6633 Transmited power level integrated in the dataOut ->AMISR
6288 resolution 1 min
6634 resolution 1 min
6289 The power files have the pattern power_YYYYMMDD.csv
6635 The power files have the pattern power_YYYYMMDD.csv
6290 '''
6636 '''
6291 __slots__ =('isConfig','dataDatetimes','txPowers')
6637 __slots__ =('isConfig','dataDatetimes','txPowers')
6292 def __init__(self):
6638 def __init__(self):
6293
6639
6294 Operation.__init__(self)
6640 Operation.__init__(self)
6295 self.isConfig = False
6641 self.isConfig = False
6296 self.dataDatetimes = []
6642 self.dataDatetimes = []
6297 self.txPowers = []
6643 self.txPowers = []
6298
6644
6299 def setup(self, powerFile, dutyCycle):
6645 def setup(self, powerFile, dutyCycle):
6300 if not os.path.isfile(powerFile):
6646 if not os.path.isfile(powerFile):
6301 raise schainpy.admin.SchainError('There is no file named :{}'.format(powerFile))
6647 raise schainpy.admin.SchainError('There is no file named :{}'.format(powerFile))
6302 return
6648 return
6303
6649
6304 with open(powerFile, newline='') as pfile:
6650 with open(powerFile, newline='') as pfile:
6305 reader = csv.reader(pfile, delimiter=',', quotechar='|')
6651 reader = csv.reader(pfile, delimiter=',', quotechar='|')
6306 next(reader)
6652 next(reader)
6307 for row in reader:
6653 for row in reader:
6308 #'2022-10-25 00:00:00'
6654 #'2022-10-25 00:00:00'
6309 self.dataDatetimes.append(datetime.datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S"))
6655 self.dataDatetimes.append(datetime.datetime.strptime(row[0], "%Y-%m-%d %H:%M:%S"))
6310 self.txPowers.append(float(row[1])/dutyCycle)
6656 self.txPowers.append(float(row[1])/dutyCycle)
6311 self.isConfig = True
6657 self.isConfig = True
6312
6658
6313 def run(self, dataOut, path, DS=0.05):
6659 def run(self, dataOut, path, DS=0.05):
6314
6660
6315 #dataOut.flagNoData = True
6661 #dataOut.flagNoData = True
6316
6662
6317 if not(self.isConfig):
6663 if not(self.isConfig):
6318 self.setup(path, DS)
6664 self.setup(path, DS)
6319
6665
6320 dataDate = datetime.datetime.utcfromtimestamp(dataOut.utctime).replace(second=0, microsecond=0)#no seconds
6666 dataDate = datetime.datetime.utcfromtimestamp(dataOut.utctime).replace(second=0, microsecond=0)#no seconds
6321 try:
6667 try:
6322 indx = self.dataDatetimes.index(dataDate)
6668 indx = self.dataDatetimes.index(dataDate)
6323 dataOut.txPower = self.txPowers[indx]
6669 dataOut.txPower = self.txPowers[indx]
6324 except:
6670 except:
6325 log.warning("No power available for the datetime {}, setting power to 0 w", self.name)
6671 log.warning("No power available for the datetime {}, setting power to 0 w", self.name)
6326 dataOut.txPower = 0
6672 dataOut.txPower = 0
6327
6673
6328 return dataOut No newline at end of file
6674 return dataOut
General Comments 0
You need to be logged in to leave comments. Login now