##// END OF EJS Templates
HDFWriter writes standard Weather parameters/Now we can run a type OTHER Operation even if flagNoData is True
rflores -
r1459:52714d4d854d
parent child
Show More
@@ -1,834 +1,838
1 '''
1 '''
2 Created on Jul 3, 2014
2 Created on Jul 3, 2014
3
3
4 @author: roj-idl71
4 @author: roj-idl71
5 '''
5 '''
6 # SUBCHANNELS EN VEZ DE CHANNELS
6 # SUBCHANNELS EN VEZ DE CHANNELS
7 # BENCHMARKS -> PROBLEMAS CON ARCHIVOS GRANDES -> INCONSTANTE EN EL TIEMPO
7 # BENCHMARKS -> PROBLEMAS CON ARCHIVOS GRANDES -> INCONSTANTE EN EL TIEMPO
8 # ACTUALIZACION DE VERSION
8 # ACTUALIZACION DE VERSION
9 # HEADERS
9 # HEADERS
10 # MODULO DE ESCRITURA
10 # MODULO DE ESCRITURA
11 # METADATA
11 # METADATA
12
12
13 import os
13 import os
14 import time
14 import time
15 import datetime
15 import datetime
16 import numpy
16 import numpy
17 import timeit
17 import timeit
18 from fractions import Fraction
18 from fractions import Fraction
19 from time import time
19 from time import time
20 from time import sleep
20 from time import sleep
21
21
22 import schainpy.admin
22 import schainpy.admin
23 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
23 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
24 from schainpy.model.data.jrodata import Voltage
24 from schainpy.model.data.jrodata import Voltage
25 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
25 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
26
26
27 import pickle
27 import pickle
28 try:
28 try:
29 import digital_rf
29 import digital_rf
30 except:
30 except:
31 pass
31 pass
32
32
33
33
34 class DigitalRFReader(ProcessingUnit):
34 class DigitalRFReader(ProcessingUnit):
35 '''
35 '''
36 classdocs
36 classdocs
37 '''
37 '''
38
38
39 def __init__(self):
39 def __init__(self):
40 '''
40 '''
41 Constructor
41 Constructor
42 '''
42 '''
43
43
44 ProcessingUnit.__init__(self)
44 ProcessingUnit.__init__(self)
45
45
46 self.dataOut = Voltage()
46 self.dataOut = Voltage()
47 self.__printInfo = True
47 self.__printInfo = True
48 self.__flagDiscontinuousBlock = False
48 self.__flagDiscontinuousBlock = False
49 self.__bufferIndex = 9999999
49 self.__bufferIndex = 9999999
50 self.__codeType = 0
50 self.__codeType = 0
51 self.__ippKm = None
51 self.__ippKm = None
52 self.__nCode = None
52 self.__nCode = None
53 self.__nBaud = None
53 self.__nBaud = None
54 self.__code = None
54 self.__code = None
55 self.dtype = None
55 self.dtype = None
56 self.oldAverage = None
56 self.oldAverage = None
57 self.path = None
57 self.path = None
58
58
59 def close(self):
59 def close(self):
60 print('Average of writing to digital rf format is ', self.oldAverage * 1000)
60 print('Average of writing to digital rf format is ', self.oldAverage * 1000)
61 return
61 return
62
62
63 def __getCurrentSecond(self):
63 def __getCurrentSecond(self):
64
64
65 return self.__thisUnixSample / self.__sample_rate
65 return self.__thisUnixSample / self.__sample_rate
66
66
67 thisSecond = property(__getCurrentSecond, "I'm the 'thisSecond' property.")
67 thisSecond = property(__getCurrentSecond, "I'm the 'thisSecond' property.")
68
68
69 def __setFileHeader(self):
69 def __setFileHeader(self):
70 '''
70 '''
71 In this method will be initialized every parameter of dataOut object (header, no data)
71 In this method will be initialized every parameter of dataOut object (header, no data)
72 '''
72 '''
73 ippSeconds = 1.0 * self.__nSamples / self.__sample_rate
73 ippSeconds = 1.0 * self.__nSamples / self.__sample_rate
74 if not self.getByBlock:
74 if not self.getByBlock:
75 nProfiles = 1.0 / ippSeconds # Number of profiles in one second
75 nProfiles = 1.0 / ippSeconds # Number of profiles in one second
76 else:
76 else:
77 nProfiles = self.nProfileBlocks # Number of profiles in one block
77 nProfiles = self.nProfileBlocks # Number of profiles in one block
78
78
79 try:
79 try:
80 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(
80 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(
81 self.__radarControllerHeader)
81 self.__radarControllerHeader)
82 except:
82 except:
83 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(
83 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(
84 txA=0,
84 txA=0,
85 txB=0,
85 txB=0,
86 nWindows=1,
86 nWindows=1,
87 nHeights=self.__nSamples,
87 nHeights=self.__nSamples,
88 firstHeight=self.__firstHeigth,
88 firstHeight=self.__firstHeigth,
89 deltaHeight=self.__deltaHeigth,
89 deltaHeight=self.__deltaHeigth,
90 codeType=self.__codeType,
90 codeType=self.__codeType,
91 nCode=self.__nCode, nBaud=self.__nBaud,
91 nCode=self.__nCode, nBaud=self.__nBaud,
92 code=self.__code)
92 code=self.__code)
93
93
94 try:
94 try:
95 self.dataOut.systemHeaderObj = SystemHeader(self.__systemHeader)
95 self.dataOut.systemHeaderObj = SystemHeader(self.__systemHeader)
96 except:
96 except:
97 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
97 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
98 nProfiles=nProfiles,
98 nProfiles=nProfiles,
99 nChannels=len(
99 nChannels=len(
100 self.__channelList),
100 self.__channelList),
101 adcResolution=14)
101 adcResolution=14)
102 self.dataOut.type = "Voltage"
102 self.dataOut.type = "Voltage"
103
103
104 self.dataOut.data = None
104 self.dataOut.data = None
105
105
106 self.dataOut.dtype = self.dtype
106 self.dataOut.dtype = self.dtype
107
107
108 # self.dataOut.nChannels = 0
108 # self.dataOut.nChannels = 0
109
109
110 # self.dataOut.nHeights = 0
110 # self.dataOut.nHeights = 0
111
111
112 self.dataOut.nProfiles = int(nProfiles)
112 self.dataOut.nProfiles = int(nProfiles)
113
113
114 self.dataOut.heightList = self.__firstHeigth + \
114 self.dataOut.heightList = self.__firstHeigth + \
115 numpy.arange(self.__nSamples, dtype=numpy.float) * \
115 numpy.arange(self.__nSamples, dtype=numpy.float) * \
116 self.__deltaHeigth
116 self.__deltaHeigth
117
117
118 #self.dataOut.channelList = list(range(self.__num_subchannels))
118 #self.dataOut.channelList = list(range(self.__num_subchannels))
119 self.dataOut.channelList = list(range(len(self.__channelList)))
119 self.dataOut.channelList = list(range(len(self.__channelList)))
120 if not self.getByBlock:
120 if not self.getByBlock:
121
121
122 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights
122 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights
123 else:
123 else:
124 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights*self.nProfileBlocks
124 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights*self.nProfileBlocks
125
125
126 # self.dataOut.channelIndexList = None
126 # self.dataOut.channelIndexList = None
127
127
128 self.dataOut.flagNoData = True
128 self.dataOut.flagNoData = True
129 if not self.getByBlock:
129 if not self.getByBlock:
130 self.dataOut.flagDataAsBlock = False
130 self.dataOut.flagDataAsBlock = False
131 else:
131 else:
132 self.dataOut.flagDataAsBlock = True
132 self.dataOut.flagDataAsBlock = True
133 # Set to TRUE if the data is discontinuous
133 # Set to TRUE if the data is discontinuous
134 self.dataOut.flagDiscontinuousBlock = False
134 self.dataOut.flagDiscontinuousBlock = False
135
135
136 self.dataOut.utctime = None
136 self.dataOut.utctime = None
137
137
138 # timezone like jroheader, difference in minutes between UTC and localtime
138 # timezone like jroheader, difference in minutes between UTC and localtime
139 self.dataOut.timeZone = self.__timezone / 60
139 self.dataOut.timeZone = self.__timezone / 60
140
140
141 self.dataOut.dstFlag = 0
141 self.dataOut.dstFlag = 0
142
142
143 self.dataOut.errorCount = 0
143 self.dataOut.errorCount = 0
144
144
145 try:
145 try:
146 self.dataOut.nCohInt = self.fixed_metadata_dict.get(
146 self.dataOut.nCohInt = self.fixed_metadata_dict.get(
147 'nCohInt', self.nCohInt)
147 'nCohInt', self.nCohInt)
148
148
149 # asumo que la data esta decodificada
149 # asumo que la data esta decodificada
150 self.dataOut.flagDecodeData = self.fixed_metadata_dict.get(
150 self.dataOut.flagDecodeData = self.fixed_metadata_dict.get(
151 'flagDecodeData', self.flagDecodeData)
151 'flagDecodeData', self.flagDecodeData)
152
152
153 # asumo que la data esta sin flip
153 # asumo que la data esta sin flip
154 self.dataOut.flagDeflipData = self.fixed_metadata_dict['flagDeflipData']
154 self.dataOut.flagDeflipData = self.fixed_metadata_dict['flagDeflipData']
155
155
156 self.dataOut.flagShiftFFT = self.fixed_metadata_dict['flagShiftFFT']
156 self.dataOut.flagShiftFFT = self.fixed_metadata_dict['flagShiftFFT']
157
157
158 self.dataOut.useLocalTime = self.fixed_metadata_dict['useLocalTime']
158 self.dataOut.useLocalTime = self.fixed_metadata_dict['useLocalTime']
159 except:
159 except:
160 pass
160 pass
161
161
162 self.dataOut.ippSeconds = ippSeconds
162 self.dataOut.ippSeconds = ippSeconds
163
163
164 # Time interval between profiles
164 # Time interval between profiles
165 # self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
165 # self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
166
166
167 self.dataOut.frequency = self.__frequency
167 self.dataOut.frequency = self.__frequency
168
168
169 self.dataOut.realtime = self.__online
169 self.dataOut.realtime = self.__online
170
170
171 def findDatafiles(self, path, startDate=None, endDate=None):
171 def findDatafiles(self, path, startDate=None, endDate=None):
172
172
173 if not os.path.isdir(path):
173 if not os.path.isdir(path):
174 return []
174 return []
175
175
176 try:
176 try:
177 digitalReadObj = digital_rf.DigitalRFReader(
177 digitalReadObj = digital_rf.DigitalRFReader(
178 path, load_all_metadata=True)
178 path, load_all_metadata=True)
179 except:
179 except:
180 digitalReadObj = digital_rf.DigitalRFReader(path)
180 digitalReadObj = digital_rf.DigitalRFReader(path)
181
181
182 channelNameList = digitalReadObj.get_channels()
182 channelNameList = digitalReadObj.get_channels()
183
183
184 if not channelNameList:
184 if not channelNameList:
185 return []
185 return []
186
186
187 metadata_dict = digitalReadObj.get_rf_file_metadata(channelNameList[0])
187 metadata_dict = digitalReadObj.get_rf_file_metadata(channelNameList[0])
188
188
189 sample_rate = metadata_dict['sample_rate'][0]
189 sample_rate = metadata_dict['sample_rate'][0]
190
190
191 this_metadata_file = digitalReadObj.get_metadata(channelNameList[0])
191 this_metadata_file = digitalReadObj.get_metadata(channelNameList[0])
192
192
193 try:
193 try:
194 timezone = this_metadata_file['timezone'].value
194 timezone = this_metadata_file['timezone'].value
195 except:
195 except:
196 timezone = 0
196 timezone = 0
197
197
198 startUTCSecond, endUTCSecond = digitalReadObj.get_bounds(
198 startUTCSecond, endUTCSecond = digitalReadObj.get_bounds(
199 channelNameList[0]) / sample_rate - timezone
199 channelNameList[0]) / sample_rate - timezone
200
200
201 startDatetime = datetime.datetime.utcfromtimestamp(startUTCSecond)
201 startDatetime = datetime.datetime.utcfromtimestamp(startUTCSecond)
202 endDatatime = datetime.datetime.utcfromtimestamp(endUTCSecond)
202 endDatatime = datetime.datetime.utcfromtimestamp(endUTCSecond)
203
203
204 if not startDate:
204 if not startDate:
205 startDate = startDatetime.date()
205 startDate = startDatetime.date()
206
206
207 if not endDate:
207 if not endDate:
208 endDate = endDatatime.date()
208 endDate = endDatatime.date()
209
209
210 dateList = []
210 dateList = []
211
211
212 thisDatetime = startDatetime
212 thisDatetime = startDatetime
213
213
214 while(thisDatetime <= endDatatime):
214 while(thisDatetime <= endDatatime):
215
215
216 thisDate = thisDatetime.date()
216 thisDate = thisDatetime.date()
217
217
218 if thisDate < startDate:
218 if thisDate < startDate:
219 continue
219 continue
220
220
221 if thisDate > endDate:
221 if thisDate > endDate:
222 break
222 break
223
223
224 dateList.append(thisDate)
224 dateList.append(thisDate)
225 thisDatetime += datetime.timedelta(1)
225 thisDatetime += datetime.timedelta(1)
226
226
227 return dateList
227 return dateList
228
228
229 def setup(self, path=None,
229 def setup(self, path=None,
230 startDate=None,
230 startDate=None,
231 endDate=None,
231 endDate=None,
232 startTime=datetime.time(0, 0, 0),
232 startTime=datetime.time(0, 0, 0),
233 endTime=datetime.time(23, 59, 59),
233 endTime=datetime.time(23, 59, 59),
234 channelList=None,
234 channelList=None,
235 nSamples=None,
235 nSamples=None,
236 online=False,
236 online=False,
237 delay=60,
237 delay=60,
238 buffer_size=1024,
238 buffer_size=1024,
239 ippKm=None,
239 ippKm=None,
240 nCohInt=1,
240 nCohInt=1,
241 nCode=1,
241 nCode=1,
242 nBaud=1,
242 nBaud=1,
243 flagDecodeData=False,
243 flagDecodeData=False,
244 code=numpy.ones((1, 1), dtype=numpy.int),
244 code=numpy.ones((1, 1), dtype=numpy.int),
245 getByBlock=0,
245 getByBlock=0,
246 nProfileBlocks=1,
246 nProfileBlocks=1,
247 **kwargs):
247 **kwargs):
248 '''
248 '''
249 In this method we should set all initial parameters.
249 In this method we should set all initial parameters.
250
250
251 Inputs:
251 Inputs:
252 path
252 path
253 startDate
253 startDate
254 endDate
254 endDate
255 startTime
255 startTime
256 endTime
256 endTime
257 set
257 set
258 expLabel
258 expLabel
259 ext
259 ext
260 online
260 online
261 delay
261 delay
262 '''
262 '''
263 self.path = path
263 self.path = path
264 self.nCohInt = nCohInt
264 self.nCohInt = nCohInt
265 self.flagDecodeData = flagDecodeData
265 self.flagDecodeData = flagDecodeData
266 self.i = 0
266 self.i = 0
267
267
268 self.getByBlock = getByBlock
268 self.getByBlock = getByBlock
269 self.nProfileBlocks = nProfileBlocks
269 self.nProfileBlocks = nProfileBlocks
270 if not os.path.isdir(path):
270 if not os.path.isdir(path):
271 raise ValueError("[Reading] Directory %s does not exist" % path)
271 raise ValueError("[Reading] Directory %s does not exist" % path)
272
272
273 try:
273 try:
274 self.digitalReadObj = digital_rf.DigitalRFReader(
274 self.digitalReadObj = digital_rf.DigitalRFReader(
275 path, load_all_metadata=True)
275 path, load_all_metadata=True)
276 except:
276 except:
277 self.digitalReadObj = digital_rf.DigitalRFReader(path)
277 self.digitalReadObj = digital_rf.DigitalRFReader(path)
278
278
279 channelNameList = self.digitalReadObj.get_channels()
279 channelNameList = self.digitalReadObj.get_channels()
280
280
281 if not channelNameList:
281 if not channelNameList:
282 raise ValueError("[Reading] Directory %s does not have any files" % path)
282 raise ValueError("[Reading] Directory %s does not have any files" % path)
283
283
284 if not channelList:
284 if not channelList:
285 channelList = list(range(len(channelNameList)))
285 channelList = list(range(len(channelNameList)))
286
286
287 ########## Reading metadata ######################
287 ########## Reading metadata ######################
288
288
289 top_properties = self.digitalReadObj.get_properties(
289 top_properties = self.digitalReadObj.get_properties(
290 channelNameList[channelList[0]])
290 channelNameList[channelList[0]])
291
291
292 self.__num_subchannels = top_properties['num_subchannels']
292 self.__num_subchannels = top_properties['num_subchannels']
293 self.__sample_rate = 1.0 * \
293 self.__sample_rate = 1.0 * \
294 top_properties['sample_rate_numerator'] / \
294 top_properties['sample_rate_numerator'] / \
295 top_properties['sample_rate_denominator']
295 top_properties['sample_rate_denominator']
296 # self.__samples_per_file = top_properties['samples_per_file'][0]
296 # self.__samples_per_file = top_properties['samples_per_file'][0]
297 self.__deltaHeigth = 1e6 * 0.15 / self.__sample_rate # why 0.15?
297 self.__deltaHeigth = 1e6 * 0.15 / self.__sample_rate # why 0.15?
298
298
299 this_metadata_file = self.digitalReadObj.get_digital_metadata(
299 this_metadata_file = self.digitalReadObj.get_digital_metadata(
300 channelNameList[channelList[0]])
300 channelNameList[channelList[0]])
301 metadata_bounds = this_metadata_file.get_bounds()
301 metadata_bounds = this_metadata_file.get_bounds()
302 self.fixed_metadata_dict = this_metadata_file.read(
302 self.fixed_metadata_dict = this_metadata_file.read(
303 metadata_bounds[0])[metadata_bounds[0]] # GET FIRST HEADER
303 metadata_bounds[0])[metadata_bounds[0]] # GET FIRST HEADER
304
304
305 try:
305 try:
306 self.__processingHeader = self.fixed_metadata_dict['processingHeader']
306 self.__processingHeader = self.fixed_metadata_dict['processingHeader']
307 self.__radarControllerHeader = self.fixed_metadata_dict['radarControllerHeader']
307 self.__radarControllerHeader = self.fixed_metadata_dict['radarControllerHeader']
308 self.__systemHeader = self.fixed_metadata_dict['systemHeader']
308 self.__systemHeader = self.fixed_metadata_dict['systemHeader']
309 self.dtype = pickle.loads(self.fixed_metadata_dict['dtype'])
309 self.dtype = pickle.loads(self.fixed_metadata_dict['dtype'])
310 except:
310 except:
311 pass
311 pass
312
312
313 self.__frequency = None
313 self.__frequency = None
314
314
315 self.__frequency = self.fixed_metadata_dict.get('frequency', 1)
315 self.__frequency = self.fixed_metadata_dict.get('frequency', 1)
316
316
317 self.__timezone = self.fixed_metadata_dict.get('timezone', 18000)
317 self.__timezone = self.fixed_metadata_dict.get('timezone', 18000)
318
318
319 try:
319 try:
320 nSamples = self.fixed_metadata_dict['nSamples']
320 nSamples = self.fixed_metadata_dict['nSamples']
321 except:
321 except:
322 nSamples = None
322 nSamples = None
323
323
324 self.__firstHeigth = 0
324 self.__firstHeigth = 0
325
325
326 try:
326 try:
327 codeType = self.__radarControllerHeader['codeType']
327 codeType = self.__radarControllerHeader['codeType']
328 except:
328 except:
329 codeType = 0
329 codeType = 0
330
330
331 try:
331 try:
332 if codeType:
332 if codeType:
333 nCode = self.__radarControllerHeader['nCode']
333 nCode = self.__radarControllerHeader['nCode']
334 nBaud = self.__radarControllerHeader['nBaud']
334 nBaud = self.__radarControllerHeader['nBaud']
335 code = self.__radarControllerHeader['code']
335 code = self.__radarControllerHeader['code']
336 except:
336 except:
337 pass
337 pass
338
338
339 if not ippKm:
339 if not ippKm:
340 try:
340 try:
341 # seconds to km
341 # seconds to km
342 ippKm = self.__radarControllerHeader['ipp']
342 ippKm = self.__radarControllerHeader['ipp']
343 except:
343 except:
344 ippKm = None
344 ippKm = None
345 ####################################################
345 ####################################################
346 self.__ippKm = ippKm
346 self.__ippKm = ippKm
347 startUTCSecond = None
347 startUTCSecond = None
348 endUTCSecond = None
348 endUTCSecond = None
349
349
350 if startDate:
350 if startDate:
351 startDatetime = datetime.datetime.combine(startDate, startTime)
351 startDatetime = datetime.datetime.combine(startDate, startTime)
352 startUTCSecond = (
352 startUTCSecond = (
353 startDatetime - datetime.datetime(1970, 1, 1)).total_seconds() + self.__timezone
353 startDatetime - datetime.datetime(1970, 1, 1)).total_seconds() + self.__timezone
354
354
355 if endDate:
355 if endDate:
356 endDatetime = datetime.datetime.combine(endDate, endTime)
356 endDatetime = datetime.datetime.combine(endDate, endTime)
357 endUTCSecond = (endDatetime - datetime.datetime(1970,
357 endUTCSecond = (endDatetime - datetime.datetime(1970,
358 1, 1)).total_seconds() + self.__timezone
358 1, 1)).total_seconds() + self.__timezone
359
359
360
360
361 #print(startUTCSecond,endUTCSecond)
361 #print(startUTCSecond,endUTCSecond)
362 start_index, end_index = self.digitalReadObj.get_bounds(
362 start_index, end_index = self.digitalReadObj.get_bounds(
363 channelNameList[channelList[0]])
363 channelNameList[channelList[0]])
364
364
365 #print("*****",start_index,end_index)
365 #print("*****",start_index,end_index)
366 if not startUTCSecond:
366 if not startUTCSecond:
367 startUTCSecond = start_index / self.__sample_rate
367 startUTCSecond = start_index / self.__sample_rate
368
368
369 if start_index > startUTCSecond * self.__sample_rate:
369 if start_index > startUTCSecond * self.__sample_rate:
370 startUTCSecond = start_index / self.__sample_rate
370 startUTCSecond = start_index / self.__sample_rate
371
371
372 if not endUTCSecond:
372 if not endUTCSecond:
373 endUTCSecond = end_index / self.__sample_rate
373 endUTCSecond = end_index / self.__sample_rate
374 if end_index < endUTCSecond * self.__sample_rate:
374 if end_index < endUTCSecond * self.__sample_rate:
375 endUTCSecond = end_index / self.__sample_rate #Check UTC and LT time
375 endUTCSecond = end_index / self.__sample_rate #Check UTC and LT time
376 if not nSamples:
376 if not nSamples:
377 if not ippKm:
377 if not ippKm:
378 raise ValueError("[Reading] nSamples or ippKm should be defined")
378 raise ValueError("[Reading] nSamples or ippKm should be defined")
379 nSamples = int(ippKm / (1e6 * 0.15 / self.__sample_rate))
379 nSamples = int(ippKm / (1e6 * 0.15 / self.__sample_rate))
380
380
381 channelBoundList = []
381 channelBoundList = []
382 channelNameListFiltered = []
382 channelNameListFiltered = []
383
383
384 for thisIndexChannel in channelList:
384 for thisIndexChannel in channelList:
385 thisChannelName = channelNameList[thisIndexChannel]
385 thisChannelName = channelNameList[thisIndexChannel]
386 start_index, end_index = self.digitalReadObj.get_bounds(
386 start_index, end_index = self.digitalReadObj.get_bounds(
387 thisChannelName)
387 thisChannelName)
388 channelBoundList.append((start_index, end_index))
388 channelBoundList.append((start_index, end_index))
389 channelNameListFiltered.append(thisChannelName)
389 channelNameListFiltered.append(thisChannelName)
390
390
391 self.profileIndex = 0
391 self.profileIndex = 0
392 self.i = 0
392 self.i = 0
393 self.__delay = delay
393 self.__delay = delay
394
394
395 self.__codeType = codeType
395 self.__codeType = codeType
396 self.__nCode = nCode
396 self.__nCode = nCode
397 self.__nBaud = nBaud
397 self.__nBaud = nBaud
398 self.__code = code
398 self.__code = code
399
399
400 self.__datapath = path
400 self.__datapath = path
401 self.__online = online
401 self.__online = online
402 self.__channelList = channelList
402 self.__channelList = channelList
403 self.__channelNameList = channelNameListFiltered
403 self.__channelNameList = channelNameListFiltered
404 self.__channelBoundList = channelBoundList
404 self.__channelBoundList = channelBoundList
405 self.__nSamples = nSamples
405 self.__nSamples = nSamples
406 if self.getByBlock:
406 if self.getByBlock:
407 nSamples = nSamples*nProfileBlocks
407 nSamples = nSamples*nProfileBlocks
408
408
409
409
410 self.__samples_to_read = int(nSamples) # FIJO: AHORA 40
410 self.__samples_to_read = int(nSamples) # FIJO: AHORA 40
411 #self.__samples_to_read = int(1000000) # FIJO: AHORA 40
411 self.__nChannels = len(self.__channelList)
412 self.__nChannels = len(self.__channelList)
412 #print("------------------------------------------")
413 #print("------------------------------------------")
413 #print("self.__samples_to_read",self.__samples_to_read)
414 #print("self.__samples_to_read",self.__samples_to_read)
414 #print("self.__nSamples",self.__nSamples)
415 #print("self.__nSamples",self.__nSamples)
415 # son iguales y el buffer_index da 0
416 # son iguales y el buffer_index da 0
416 self.__startUTCSecond = startUTCSecond
417 self.__startUTCSecond = startUTCSecond
417 self.__endUTCSecond = endUTCSecond
418 self.__endUTCSecond = endUTCSecond
418
419
419 self.__timeInterval = 1.0 * self.__samples_to_read / \
420 self.__timeInterval = 1.0 * self.__samples_to_read / \
420 self.__sample_rate # Time interval
421 self.__sample_rate # Time interval
421
422
422 if online:
423 if online:
423 # self.__thisUnixSample = int(endUTCSecond*self.__sample_rate - 4*self.__samples_to_read)
424 # self.__thisUnixSample = int(endUTCSecond*self.__sample_rate - 4*self.__samples_to_read)
424 startUTCSecond = numpy.floor(endUTCSecond)
425 startUTCSecond = numpy.floor(endUTCSecond)
425
426
426 # por que en el otro metodo lo primero q se hace es sumar samplestoread
427 # por que en el otro metodo lo primero q se hace es sumar samplestoread
427 self.__thisUnixSample = int(startUTCSecond * self.__sample_rate) - self.__samples_to_read
428 self.__thisUnixSample = int(startUTCSecond * self.__sample_rate) - self.__samples_to_read
428
429
429 #self.__data_buffer = numpy.zeros(
430 #self.__data_buffer = numpy.zeros(
430 # (self.__num_subchannels, self.__samples_to_read), dtype=numpy.complex)
431 # (self.__num_subchannels, self.__samples_to_read), dtype=numpy.complex)
431 self.__data_buffer = numpy.zeros((int(len(channelList)), self.__samples_to_read), dtype=numpy.complex)
432 self.__data_buffer = numpy.zeros((int(len(channelList)), self.__samples_to_read), dtype=numpy.complex)
432
433
433
434
434 self.__setFileHeader()
435 self.__setFileHeader()
435 self.isConfig = True
436 self.isConfig = True
436
437
437 print("[Reading] Digital RF Data was found from %s to %s " % (
438 print("[Reading] Digital RF Data was found from %s to %s " % (
438 datetime.datetime.utcfromtimestamp(
439 datetime.datetime.utcfromtimestamp(
439 self.__startUTCSecond - self.__timezone),
440 self.__startUTCSecond - self.__timezone),
440 datetime.datetime.utcfromtimestamp(
441 datetime.datetime.utcfromtimestamp(
441 self.__endUTCSecond - self.__timezone)
442 self.__endUTCSecond - self.__timezone)
442 ))
443 ))
443
444
444 print("[Reading] Starting process from %s to %s" % (datetime.datetime.utcfromtimestamp(startUTCSecond - self.__timezone),
445 print("[Reading] Starting process from %s to %s" % (datetime.datetime.utcfromtimestamp(startUTCSecond - self.__timezone),
445 datetime.datetime.utcfromtimestamp(
446 datetime.datetime.utcfromtimestamp(
446 endUTCSecond - self.__timezone)
447 endUTCSecond - self.__timezone)
447 ))
448 ))
448 self.oldAverage = None
449 self.oldAverage = None
449 self.count = 0
450 self.count = 0
450 self.executionTime = 0
451 self.executionTime = 0
451
452
452 def __reload(self):
453 def __reload(self):
453 # print
454 # print
454 # print "%s not in range [%s, %s]" %(
455 # print "%s not in range [%s, %s]" %(
455 # datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
456 # datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
456 # datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone),
457 # datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone),
457 # datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone)
458 # datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone)
458 # )
459 # )
459 print("[Reading] reloading metadata ...")
460 print("[Reading] reloading metadata ...")
460
461
461 try:
462 try:
462 self.digitalReadObj.reload(complete_update=True)
463 self.digitalReadObj.reload(complete_update=True)
463 except:
464 except:
464 self.digitalReadObj = digital_rf.DigitalRFReader(self.path)
465 self.digitalReadObj = digital_rf.DigitalRFReader(self.path)
465
466
466 start_index, end_index = self.digitalReadObj.get_bounds(
467 start_index, end_index = self.digitalReadObj.get_bounds(
467 self.__channelNameList[self.__channelList[0]])
468 self.__channelNameList[self.__channelList[0]])
468
469
469 if start_index > self.__startUTCSecond * self.__sample_rate:
470 if start_index > self.__startUTCSecond * self.__sample_rate:
470 self.__startUTCSecond = 1.0 * start_index / self.__sample_rate
471 self.__startUTCSecond = 1.0 * start_index / self.__sample_rate
471
472
472 if end_index > self.__endUTCSecond * self.__sample_rate:
473 if end_index > self.__endUTCSecond * self.__sample_rate:
473 self.__endUTCSecond = 1.0 * end_index / self.__sample_rate
474 self.__endUTCSecond = 1.0 * end_index / self.__sample_rate
474 print()
475 print()
475 print("[Reading] New timerange found [%s, %s] " % (
476 print("[Reading] New timerange found [%s, %s] " % (
476 datetime.datetime.utcfromtimestamp(
477 datetime.datetime.utcfromtimestamp(
477 self.__startUTCSecond - self.__timezone),
478 self.__startUTCSecond - self.__timezone),
478 datetime.datetime.utcfromtimestamp(
479 datetime.datetime.utcfromtimestamp(
479 self.__endUTCSecond - self.__timezone)
480 self.__endUTCSecond - self.__timezone)
480 ))
481 ))
481
482
482 return True
483 return True
483
484
484 return False
485 return False
485
486
486 def timeit(self, toExecute):
487 def timeit(self, toExecute):
487 t0 = time.time()
488 t0 = time.time()
488 toExecute()
489 toExecute()
489 self.executionTime = time.time() - t0
490 self.executionTime = time.time() - t0
490 if self.oldAverage is None:
491 if self.oldAverage is None:
491 self.oldAverage = self.executionTime
492 self.oldAverage = self.executionTime
492 self.oldAverage = (self.executionTime + self.count *
493 self.oldAverage = (self.executionTime + self.count *
493 self.oldAverage) / (self.count + 1.0)
494 self.oldAverage) / (self.count + 1.0)
494 self.count = self.count + 1.0
495 self.count = self.count + 1.0
495 return
496 return
496
497
497 def __readNextBlock(self, seconds=30, volt_scale=1):
498 def __readNextBlock(self, seconds=30, volt_scale=1):
498 '''
499 '''
499 '''
500 '''
500
501
501 # Set the next data
502 # Set the next data
502 self.__flagDiscontinuousBlock = False
503 self.__flagDiscontinuousBlock = False
503 self.__thisUnixSample += self.__samples_to_read
504 self.__thisUnixSample += self.__samples_to_read
504
505
505 if self.__thisUnixSample + 2 * self.__samples_to_read > self.__endUTCSecond * self.__sample_rate:
506 if self.__thisUnixSample + 2 * self.__samples_to_read > self.__endUTCSecond * self.__sample_rate:
506 print ("[Reading] There are no more data into selected time-range")
507 print ("[Reading] There are no more data into selected time-range")
507 if self.__online:
508 if self.__online:
508 sleep(3)
509 sleep(3)
509 self.__reload()
510 self.__reload()
510 else:
511 else:
511 return False
512 return False
512
513
513 if self.__thisUnixSample + 2 * self.__samples_to_read > self.__endUTCSecond * self.__sample_rate:
514 if self.__thisUnixSample + 2 * self.__samples_to_read > self.__endUTCSecond * self.__sample_rate:
514 return False
515 return False
515 self.__thisUnixSample -= self.__samples_to_read
516 self.__thisUnixSample -= self.__samples_to_read
516
517
517 indexChannel = 0
518 indexChannel = 0
518
519
519 dataOk = False
520 dataOk = False
520
521
521 for thisChannelName in self.__channelNameList: # TODO VARIOS CHANNELS?
522 for thisChannelName in self.__channelNameList: # TODO VARIOS CHANNELS?
522 for indexSubchannel in range(self.__num_subchannels):
523 for indexSubchannel in range(self.__num_subchannels):
523 try:
524 try:
524 t0 = time()
525 t0 = time()
526 #print("Unitindex",self.__thisUnixSample)
527 #print("__samples_to_read",self.__samples_to_read)
525 result = self.digitalReadObj.read_vector_c81d(self.__thisUnixSample,
528 result = self.digitalReadObj.read_vector_c81d(self.__thisUnixSample,
526 self.__samples_to_read,
529 self.__samples_to_read,
527 thisChannelName, sub_channel=indexSubchannel)
530 thisChannelName, sub_channel=indexSubchannel)
528 self.executionTime = time() - t0
531 self.executionTime = time() - t0
529 if self.oldAverage is None:
532 if self.oldAverage is None:
530 self.oldAverage = self.executionTime
533 self.oldAverage = self.executionTime
531 self.oldAverage = (
534 self.oldAverage = (
532 self.executionTime + self.count * self.oldAverage) / (self.count + 1.0)
535 self.executionTime + self.count * self.oldAverage) / (self.count + 1.0)
533 self.count = self.count + 1.0
536 self.count = self.count + 1.0
534
537
535 except IOError as e:
538 except IOError as e:
536 # read next profile
539 # read next profile
537 self.__flagDiscontinuousBlock = True
540 self.__flagDiscontinuousBlock = True
538 print("[Reading] %s" % datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), e)
541 print("[Reading] %s" % datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), e)
539 break
542 break
540
543
541 if result.shape[0] != self.__samples_to_read:
544 if result.shape[0] != self.__samples_to_read:
542 self.__flagDiscontinuousBlock = True
545 self.__flagDiscontinuousBlock = True
543 print("[Reading] %s: Too few samples were found, just %d/%d samples" % (datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
546 print("[Reading] %s: Too few samples were found, just %d/%d samples" % (datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
544 result.shape[0],
547 result.shape[0],
545 self.__samples_to_read))
548 self.__samples_to_read))
546 break
549 break
547
550
548 self.__data_buffer[indexChannel, :] = result * volt_scale
551 self.__data_buffer[indexChannel, :] = result * volt_scale
549 indexChannel+=1
552 indexChannel+=1
550
553
551 dataOk = True
554 dataOk = True
552
555
553 self.__utctime = self.__thisUnixSample / self.__sample_rate
556 self.__utctime = self.__thisUnixSample / self.__sample_rate
554
557
555 if not dataOk:
558 if not dataOk:
556 return False
559 return False
557
560
558 print("[Reading] %s: %d samples <> %f sec" % (datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
561 print("[Reading] %s: %d samples <> %f sec" % (datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
559 self.__samples_to_read,
562 self.__samples_to_read,
560 self.__timeInterval))
563 self.__timeInterval))
561
564
562 self.__bufferIndex = 0
565 self.__bufferIndex = 0
563
566
564 return True
567 return True
565
568
566 def __isBufferEmpty(self):
569 def __isBufferEmpty(self):
567
570
568 return self.__bufferIndex > self.__samples_to_read - self.__nSamples # 40960 - 40
571 return self.__bufferIndex > self.__samples_to_read - self.__nSamples # 40960 - 40
569
572
570 def getData(self, seconds=30, nTries=5):
573 def getData(self, seconds=30, nTries=5):
571 '''
574 '''
572 This method gets the data from files and put the data into the dataOut object
575 This method gets the data from files and put the data into the dataOut object
573
576
574 In addition, increase el the buffer counter in one.
577 In addition, increase el the buffer counter in one.
575
578
576 Return:
579 Return:
577 data : retorna un perfil de voltages (alturas * canales) copiados desde el
580 data : retorna un perfil de voltages (alturas * canales) copiados desde el
578 buffer. Si no hay mas archivos a leer retorna None.
581 buffer. Si no hay mas archivos a leer retorna None.
579
582
580 Affected:
583 Affected:
581 self.dataOut
584 self.dataOut
582 self.profileIndex
585 self.profileIndex
583 self.flagDiscontinuousBlock
586 self.flagDiscontinuousBlock
584 self.flagIsNewBlock
587 self.flagIsNewBlock
585 '''
588 '''
586 #print("getdata")
589 #print("getdata")
587 err_counter = 0
590 err_counter = 0
588 self.dataOut.flagNoData = True
591 self.dataOut.flagNoData = True
589
592
590
593
591 if self.__isBufferEmpty():
594 if self.__isBufferEmpty():
592 #print("hi")
595 #print("hi")
593 self.__flagDiscontinuousBlock = False
596 self.__flagDiscontinuousBlock = False
594
597
595 while True:
598 while True:
596 if self.__readNextBlock():
599 if self.__readNextBlock():
597 break
600 break
598 if self.__thisUnixSample > self.__endUTCSecond * self.__sample_rate:
601 if self.__thisUnixSample > self.__endUTCSecond * self.__sample_rate:
599 raise schainpy.admin.SchainError('Error')
602 raise schainpy.admin.SchainError('Error')
600 return
603 return
601
604
602 if self.__flagDiscontinuousBlock:
605 if self.__flagDiscontinuousBlock:
603 raise schainpy.admin.SchainError('discontinuous block found')
606 raise schainpy.admin.SchainError('discontinuous block found')
604 return
607 return
605
608
606 if not self.__online:
609 if not self.__online:
607 raise schainpy.admin.SchainError('Online?')
610 raise schainpy.admin.SchainError('Online?')
608 return
611 return
609
612
610 err_counter += 1
613 err_counter += 1
611 if err_counter > nTries:
614 if err_counter > nTries:
612 raise schainpy.admin.SchainError('Max retrys reach')
615 raise schainpy.admin.SchainError('Max retrys reach')
613 return
616 return
614
617
615 print('[Reading] waiting %d seconds to read a new block' % seconds)
618 print('[Reading] waiting %d seconds to read a new block' % seconds)
616 sleep(seconds)
619 sleep(seconds)
617
620
618
621
619 if not self.getByBlock:
622 if not self.getByBlock:
620
623
621 #print("self.__bufferIndex",self.__bufferIndex)# este valor siempre es cero aparentemente
624 #print("self.__bufferIndex",self.__bufferIndex)# este valor siempre es cero aparentemente
622 self.dataOut.data = self.__data_buffer[:, self.__bufferIndex:self.__bufferIndex + self.__nSamples]
625 self.dataOut.data = self.__data_buffer[:, self.__bufferIndex:self.__bufferIndex + self.__nSamples]
623 self.dataOut.utctime = ( self.__thisUnixSample + self.__bufferIndex) / self.__sample_rate
626 self.dataOut.utctime = ( self.__thisUnixSample + self.__bufferIndex) / self.__sample_rate
624 self.dataOut.flagNoData = False
627 self.dataOut.flagNoData = False
625 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
628 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
626 self.dataOut.profileIndex = self.profileIndex
629 self.dataOut.profileIndex = self.profileIndex
627
630
628 self.__bufferIndex += self.__nSamples
631 self.__bufferIndex += self.__nSamples
629 self.profileIndex += 1
632 self.profileIndex += 1
630
633
631 if self.profileIndex == self.dataOut.nProfiles:
634 if self.profileIndex == self.dataOut.nProfiles:
632 self.profileIndex = 0
635 self.profileIndex = 0
633 else:
636 else:
634 # ojo debo anadir el readNextBLock y el __isBufferEmpty(
637 # ojo debo anadir el readNextBLock y el __isBufferEmpty(
635 self.dataOut.flagNoData = False
638 self.dataOut.flagNoData = False
636 buffer = self.__data_buffer[:,self.__bufferIndex:self.__bufferIndex + self.__samples_to_read]
639 buffer = self.__data_buffer[:,self.__bufferIndex:self.__bufferIndex + self.__samples_to_read]
640 #print("test",self.__bufferIndex)
637 buffer = buffer.reshape((self.__nChannels, self.nProfileBlocks, int(self.__samples_to_read/self.nProfileBlocks)))
641 buffer = buffer.reshape((self.__nChannels, self.nProfileBlocks, int(self.__samples_to_read/self.nProfileBlocks)))
638 self.dataOut.nProfileBlocks = self.nProfileBlocks
642 self.dataOut.nProfileBlocks = self.nProfileBlocks
639 self.dataOut.data = buffer
643 self.dataOut.data = buffer
640 self.dataOut.utctime = ( self.__thisUnixSample + self.__bufferIndex) / self.__sample_rate
644 self.dataOut.utctime = ( self.__thisUnixSample + self.__bufferIndex) / self.__sample_rate
641 self.profileIndex += self.__samples_to_read
645 self.profileIndex += self.__samples_to_read
642 self.__bufferIndex += self.__samples_to_read
646 self.__bufferIndex += self.__samples_to_read
643 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
647 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
644 return True
648 return True
645
649
646
650
647 def printInfo(self):
651 def printInfo(self):
648 '''
652 '''
649 '''
653 '''
650 if self.__printInfo == False:
654 if self.__printInfo == False:
651 return
655 return
652
656
653 # self.systemHeaderObj.printInfo()
657 # self.systemHeaderObj.printInfo()
654 # self.radarControllerHeaderObj.printInfo()
658 # self.radarControllerHeaderObj.printInfo()
655
659
656 self.__printInfo = False
660 self.__printInfo = False
657
661
658 def printNumberOfBlock(self):
662 def printNumberOfBlock(self):
659 '''
663 '''
660 '''
664 '''
661 return
665 return
662 # print self.profileIndex
666 # print self.profileIndex
663
667
664 def run(self, **kwargs):
668 def run(self, **kwargs):
665 '''
669 '''
666 This method will be called many times so here you should put all your code
670 This method will be called many times so here you should put all your code
667 '''
671 '''
668
672
669 if not self.isConfig:
673 if not self.isConfig:
670 self.setup(**kwargs)
674 self.setup(**kwargs)
671
675
672 self.getData(seconds=self.__delay)
676 self.getData(seconds=self.__delay)
673
677
674 return
678 return
675
679
676 @MPDecorator
680 @MPDecorator
677 class DigitalRFWriter(Operation):
681 class DigitalRFWriter(Operation):
678 '''
682 '''
679 classdocs
683 classdocs
680 '''
684 '''
681
685
682 def __init__(self, **kwargs):
686 def __init__(self, **kwargs):
683 '''
687 '''
684 Constructor
688 Constructor
685 '''
689 '''
686 Operation.__init__(self, **kwargs)
690 Operation.__init__(self, **kwargs)
687 self.metadata_dict = {}
691 self.metadata_dict = {}
688 self.dataOut = None
692 self.dataOut = None
689 self.dtype = None
693 self.dtype = None
690 self.oldAverage = 0
694 self.oldAverage = 0
691
695
692 def setHeader(self):
696 def setHeader(self):
693
697
694 self.metadata_dict['frequency'] = self.dataOut.frequency
698 self.metadata_dict['frequency'] = self.dataOut.frequency
695 self.metadata_dict['timezone'] = self.dataOut.timeZone
699 self.metadata_dict['timezone'] = self.dataOut.timeZone
696 self.metadata_dict['dtype'] = pickle.dumps(self.dataOut.dtype)
700 self.metadata_dict['dtype'] = pickle.dumps(self.dataOut.dtype)
697 self.metadata_dict['nProfiles'] = self.dataOut.nProfiles
701 self.metadata_dict['nProfiles'] = self.dataOut.nProfiles
698 self.metadata_dict['heightList'] = self.dataOut.heightList
702 self.metadata_dict['heightList'] = self.dataOut.heightList
699 self.metadata_dict['channelList'] = self.dataOut.channelList
703 self.metadata_dict['channelList'] = self.dataOut.channelList
700 self.metadata_dict['flagDecodeData'] = self.dataOut.flagDecodeData
704 self.metadata_dict['flagDecodeData'] = self.dataOut.flagDecodeData
701 self.metadata_dict['flagDeflipData'] = self.dataOut.flagDeflipData
705 self.metadata_dict['flagDeflipData'] = self.dataOut.flagDeflipData
702 self.metadata_dict['flagShiftFFT'] = self.dataOut.flagShiftFFT
706 self.metadata_dict['flagShiftFFT'] = self.dataOut.flagShiftFFT
703 self.metadata_dict['useLocalTime'] = self.dataOut.useLocalTime
707 self.metadata_dict['useLocalTime'] = self.dataOut.useLocalTime
704 self.metadata_dict['nCohInt'] = self.dataOut.nCohInt
708 self.metadata_dict['nCohInt'] = self.dataOut.nCohInt
705 self.metadata_dict['type'] = self.dataOut.type
709 self.metadata_dict['type'] = self.dataOut.type
706 self.metadata_dict['flagDataAsBlock']= getattr(
710 self.metadata_dict['flagDataAsBlock']= getattr(
707 self.dataOut, 'flagDataAsBlock', None) # chequear
711 self.dataOut, 'flagDataAsBlock', None) # chequear
708
712
709 def setup(self, dataOut, path, frequency, fileCadence, dirCadence, metadataCadence, set=0, metadataFile='metadata', ext='.h5'):
713 def setup(self, dataOut, path, frequency, fileCadence, dirCadence, metadataCadence, set=0, metadataFile='metadata', ext='.h5'):
710 '''
714 '''
711 In this method we should set all initial parameters.
715 In this method we should set all initial parameters.
712 Input:
716 Input:
713 dataOut: Input data will also be outputa data
717 dataOut: Input data will also be outputa data
714 '''
718 '''
715 self.setHeader()
719 self.setHeader()
716 self.__ippSeconds = dataOut.ippSeconds
720 self.__ippSeconds = dataOut.ippSeconds
717 self.__deltaH = dataOut.getDeltaH()
721 self.__deltaH = dataOut.getDeltaH()
718 self.__sample_rate = 1e6 * 0.15 / self.__deltaH
722 self.__sample_rate = 1e6 * 0.15 / self.__deltaH
719 self.__dtype = dataOut.dtype
723 self.__dtype = dataOut.dtype
720 if len(dataOut.dtype) == 2:
724 if len(dataOut.dtype) == 2:
721 self.__dtype = dataOut.dtype[0]
725 self.__dtype = dataOut.dtype[0]
722 self.__nSamples = dataOut.systemHeaderObj.nSamples
726 self.__nSamples = dataOut.systemHeaderObj.nSamples
723 self.__nProfiles = dataOut.nProfiles
727 self.__nProfiles = dataOut.nProfiles
724
728
725 if self.dataOut.type != 'Voltage':
729 if self.dataOut.type != 'Voltage':
726 raise 'Digital RF cannot be used with this data type'
730 raise 'Digital RF cannot be used with this data type'
727 self.arr_data = numpy.ones((1, dataOut.nFFTPoints * len(
731 self.arr_data = numpy.ones((1, dataOut.nFFTPoints * len(
728 self.dataOut.channelList)), dtype=[('r', self.__dtype), ('i', self.__dtype)])
732 self.dataOut.channelList)), dtype=[('r', self.__dtype), ('i', self.__dtype)])
729 else:
733 else:
730 self.arr_data = numpy.ones((self.__nSamples, len(
734 self.arr_data = numpy.ones((self.__nSamples, len(
731 self.dataOut.channelList)), dtype=[('r', self.__dtype), ('i', self.__dtype)])
735 self.dataOut.channelList)), dtype=[('r', self.__dtype), ('i', self.__dtype)])
732
736
733 file_cadence_millisecs = 1000
737 file_cadence_millisecs = 1000
734
738
735 sample_rate_fraction = Fraction(self.__sample_rate).limit_denominator()
739 sample_rate_fraction = Fraction(self.__sample_rate).limit_denominator()
736 sample_rate_numerator = int(sample_rate_fraction.numerator)
740 sample_rate_numerator = int(sample_rate_fraction.numerator)
737 sample_rate_denominator = int(sample_rate_fraction.denominator)
741 sample_rate_denominator = int(sample_rate_fraction.denominator)
738 start_global_index = dataOut.utctime * self.__sample_rate
742 start_global_index = dataOut.utctime * self.__sample_rate
739
743
740 uuid = 'prueba'
744 uuid = 'prueba'
741 compression_level = 0
745 compression_level = 0
742 checksum = False
746 checksum = False
743 is_complex = True
747 is_complex = True
744 num_subchannels = len(dataOut.channelList)
748 num_subchannels = len(dataOut.channelList)
745 is_continuous = True
749 is_continuous = True
746 marching_periods = False
750 marching_periods = False
747
751
748 self.digitalWriteObj = digital_rf.DigitalRFWriter(path, self.__dtype, dirCadence,
752 self.digitalWriteObj = digital_rf.DigitalRFWriter(path, self.__dtype, dirCadence,
749 fileCadence, start_global_index,
753 fileCadence, start_global_index,
750 sample_rate_numerator, sample_rate_denominator, uuid, compression_level, checksum,
754 sample_rate_numerator, sample_rate_denominator, uuid, compression_level, checksum,
751 is_complex, num_subchannels, is_continuous, marching_periods)
755 is_complex, num_subchannels, is_continuous, marching_periods)
752 metadata_dir = os.path.join(path, 'metadata')
756 metadata_dir = os.path.join(path, 'metadata')
753 os.system('mkdir %s' % (metadata_dir))
757 os.system('mkdir %s' % (metadata_dir))
754 self.digitalMetadataWriteObj = digital_rf.DigitalMetadataWriter(metadata_dir, dirCadence, 1, # 236, file_cadence_millisecs / 1000
758 self.digitalMetadataWriteObj = digital_rf.DigitalMetadataWriter(metadata_dir, dirCadence, 1, # 236, file_cadence_millisecs / 1000
755 sample_rate_numerator, sample_rate_denominator,
759 sample_rate_numerator, sample_rate_denominator,
756 metadataFile)
760 metadataFile)
757 self.isConfig = True
761 self.isConfig = True
758 self.currentSample = 0
762 self.currentSample = 0
759 self.oldAverage = 0
763 self.oldAverage = 0
760 self.count = 0
764 self.count = 0
761 return
765 return
762
766
763 def writeMetadata(self):
767 def writeMetadata(self):
764 start_idx = self.__sample_rate * self.dataOut.utctime
768 start_idx = self.__sample_rate * self.dataOut.utctime
765
769
766 self.metadata_dict['processingHeader'] = self.dataOut.processingHeaderObj.getAsDict(
770 self.metadata_dict['processingHeader'] = self.dataOut.processingHeaderObj.getAsDict(
767 )
771 )
768 self.metadata_dict['radarControllerHeader'] = self.dataOut.radarControllerHeaderObj.getAsDict(
772 self.metadata_dict['radarControllerHeader'] = self.dataOut.radarControllerHeaderObj.getAsDict(
769 )
773 )
770 self.metadata_dict['systemHeader'] = self.dataOut.systemHeaderObj.getAsDict(
774 self.metadata_dict['systemHeader'] = self.dataOut.systemHeaderObj.getAsDict(
771 )
775 )
772 self.digitalMetadataWriteObj.write(start_idx, self.metadata_dict)
776 self.digitalMetadataWriteObj.write(start_idx, self.metadata_dict)
773 return
777 return
774
778
775 def timeit(self, toExecute):
779 def timeit(self, toExecute):
776 t0 = time()
780 t0 = time()
777 toExecute()
781 toExecute()
778 self.executionTime = time() - t0
782 self.executionTime = time() - t0
779 if self.oldAverage is None:
783 if self.oldAverage is None:
780 self.oldAverage = self.executionTime
784 self.oldAverage = self.executionTime
781 self.oldAverage = (self.executionTime + self.count *
785 self.oldAverage = (self.executionTime + self.count *
782 self.oldAverage) / (self.count + 1.0)
786 self.oldAverage) / (self.count + 1.0)
783 self.count = self.count + 1.0
787 self.count = self.count + 1.0
784 return
788 return
785
789
786 def writeData(self):
790 def writeData(self):
787 if self.dataOut.type != 'Voltage':
791 if self.dataOut.type != 'Voltage':
788 raise 'Digital RF cannot be used with this data type'
792 raise 'Digital RF cannot be used with this data type'
789 for channel in self.dataOut.channelList:
793 for channel in self.dataOut.channelList:
790 for i in range(self.dataOut.nFFTPoints):
794 for i in range(self.dataOut.nFFTPoints):
791 self.arr_data[1][channel * self.dataOut.nFFTPoints +
795 self.arr_data[1][channel * self.dataOut.nFFTPoints +
792 i]['r'] = self.dataOut.data[channel][i].real
796 i]['r'] = self.dataOut.data[channel][i].real
793 self.arr_data[1][channel * self.dataOut.nFFTPoints +
797 self.arr_data[1][channel * self.dataOut.nFFTPoints +
794 i]['i'] = self.dataOut.data[channel][i].imag
798 i]['i'] = self.dataOut.data[channel][i].imag
795 else:
799 else:
796 for i in range(self.dataOut.systemHeaderObj.nSamples):
800 for i in range(self.dataOut.systemHeaderObj.nSamples):
797 for channel in self.dataOut.channelList:
801 for channel in self.dataOut.channelList:
798 self.arr_data[i][channel]['r'] = self.dataOut.data[channel][i].real
802 self.arr_data[i][channel]['r'] = self.dataOut.data[channel][i].real
799 self.arr_data[i][channel]['i'] = self.dataOut.data[channel][i].imag
803 self.arr_data[i][channel]['i'] = self.dataOut.data[channel][i].imag
800
804
801 def f(): return self.digitalWriteObj.rf_write(self.arr_data)
805 def f(): return self.digitalWriteObj.rf_write(self.arr_data)
802 self.timeit(f)
806 self.timeit(f)
803
807
804 return
808 return
805
809
806 def run(self, dataOut, frequency=49.92e6, path=None, fileCadence=1000, dirCadence=36000, metadataCadence=1, **kwargs):
810 def run(self, dataOut, frequency=49.92e6, path=None, fileCadence=1000, dirCadence=36000, metadataCadence=1, **kwargs):
807 '''
811 '''
808 This method will be called many times so here you should put all your code
812 This method will be called many times so here you should put all your code
809 Inputs:
813 Inputs:
810 dataOut: object with the data
814 dataOut: object with the data
811 '''
815 '''
812 # print dataOut.__dict__
816 # print dataOut.__dict__
813 self.dataOut = dataOut
817 self.dataOut = dataOut
814 if not self.isConfig:
818 if not self.isConfig:
815 self.setup(dataOut, path, frequency, fileCadence,
819 self.setup(dataOut, path, frequency, fileCadence,
816 dirCadence, metadataCadence, **kwargs)
820 dirCadence, metadataCadence, **kwargs)
817 self.writeMetadata()
821 self.writeMetadata()
818
822
819 self.writeData()
823 self.writeData()
820
824
821 ## self.currentSample += 1
825 ## self.currentSample += 1
822 # if self.dataOut.flagDataAsBlock or self.currentSample == 1:
826 # if self.dataOut.flagDataAsBlock or self.currentSample == 1:
823 # self.writeMetadata()
827 # self.writeMetadata()
824 ## if self.currentSample == self.__nProfiles: self.currentSample = 0
828 ## if self.currentSample == self.__nProfiles: self.currentSample = 0
825
829
826 return dataOut# en la version 2.7 no aparece este return
830 return dataOut# en la version 2.7 no aparece este return
827
831
828 def close(self):
832 def close(self):
829 print('[Writing] - Closing files ')
833 print('[Writing] - Closing files ')
830 print('Average of writing to digital rf format is ', self.oldAverage * 1000)
834 print('Average of writing to digital rf format is ', self.oldAverage * 1000)
831 try:
835 try:
832 self.digitalWriteObj.close()
836 self.digitalWriteObj.close()
833 except:
837 except:
834 pass
838 pass
@@ -1,714 +1,731
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 Examples
41 Examples
42 --------
42 --------
43
43
44 desc = {
44 desc = {
45 'Data': {
45 'Data': {
46 'data_output': ['u', 'v', 'w'],
46 'data_output': ['u', 'v', 'w'],
47 'utctime': 'timestamps',
47 'utctime': 'timestamps',
48 } ,
48 } ,
49 'Metadata': {
49 'Metadata': {
50 'heightList': 'heights'
50 'heightList': 'heights'
51 }
51 }
52 }
52 }
53
53
54 desc = {
54 desc = {
55 'Data': {
55 'Data': {
56 'data_output': 'winds',
56 'data_output': 'winds',
57 'utctime': 'timestamps'
57 'utctime': 'timestamps'
58 },
58 },
59 'Metadata': {
59 'Metadata': {
60 'heightList': 'heights'
60 'heightList': 'heights'
61 }
61 }
62 }
62 }
63
63
64 extras = {
64 extras = {
65 'timeZone': 300
65 'timeZone': 300
66 }
66 }
67
67
68 reader = project.addReadUnit(
68 reader = project.addReadUnit(
69 name='HDFReader',
69 name='HDFReader',
70 path='/path/to/files',
70 path='/path/to/files',
71 startDate='2019/01/01',
71 startDate='2019/01/01',
72 endDate='2019/01/31',
72 endDate='2019/01/31',
73 startTime='00:00:00',
73 startTime='00:00:00',
74 endTime='23:59:59',
74 endTime='23:59:59',
75 # description=json.dumps(desc),
75 # description=json.dumps(desc),
76 # extras=json.dumps(extras),
76 # extras=json.dumps(extras),
77 )
77 )
78
78
79 """
79 """
80
80
81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
82
82
83 def __init__(self):
83 def __init__(self):
84 ProcessingUnit.__init__(self)
84 ProcessingUnit.__init__(self)
85 self.dataOut = Parameters()
85 self.dataOut = Parameters()
86 self.ext = ".hdf5"
86 self.ext = ".hdf5"
87 self.optchar = "D"
87 self.optchar = "D"
88 self.meta = {}
88 self.meta = {}
89 self.data = {}
89 self.data = {}
90 self.open_file = h5py.File
90 self.open_file = h5py.File
91 self.open_mode = 'r'
91 self.open_mode = 'r'
92 self.description = {}
92 self.description = {}
93 self.extras = {}
93 self.extras = {}
94 self.filefmt = "*%Y%j***"
94 self.filefmt = "*%Y%j***"
95 self.folderfmt = "*%Y%j"
95 self.folderfmt = "*%Y%j"
96 self.utcoffset = 0
96 self.utcoffset = 0
97
97
98 def setup(self, **kwargs):
98 def setup(self, **kwargs):
99
99
100 self.set_kwargs(**kwargs)
100 self.set_kwargs(**kwargs)
101 if not self.ext.startswith('.'):
101 if not self.ext.startswith('.'):
102 self.ext = '.{}'.format(self.ext)
102 self.ext = '.{}'.format(self.ext)
103
103
104 if self.online:
104 if self.online:
105 log.log("Searching files in online mode...", self.name)
105 log.log("Searching files in online mode...", self.name)
106
106
107 for nTries in range(self.nTries):
107 for nTries in range(self.nTries):
108 fullpath = self.searchFilesOnLine(self.path, self.startDate,
108 fullpath = self.searchFilesOnLine(self.path, self.startDate,
109 self.endDate, self.expLabel, self.ext, self.walk,
109 self.endDate, self.expLabel, self.ext, self.walk,
110 self.filefmt, self.folderfmt)
110 self.filefmt, self.folderfmt)
111 try:
111 try:
112 fullpath = next(fullpath)
112 fullpath = next(fullpath)
113 except:
113 except:
114 fullpath = None
114 fullpath = None
115
115
116 if fullpath:
116 if fullpath:
117 break
117 break
118
118
119 log.warning(
119 log.warning(
120 'Waiting {} sec for a valid file in {}: try {} ...'.format(
120 'Waiting {} sec for a valid file in {}: try {} ...'.format(
121 self.delay, self.path, nTries + 1),
121 self.delay, self.path, nTries + 1),
122 self.name)
122 self.name)
123 time.sleep(self.delay)
123 time.sleep(self.delay)
124
124
125 if not(fullpath):
125 if not(fullpath):
126 raise schainpy.admin.SchainError(
126 raise schainpy.admin.SchainError(
127 'There isn\'t any valid file in {}'.format(self.path))
127 'There isn\'t any valid file in {}'.format(self.path))
128
128
129 pathname, filename = os.path.split(fullpath)
129 pathname, filename = os.path.split(fullpath)
130 self.year = int(filename[1:5])
130 self.year = int(filename[1:5])
131 self.doy = int(filename[5:8])
131 self.doy = int(filename[5:8])
132 self.set = int(filename[8:11]) - 1
132 self.set = int(filename[8:11]) - 1
133 else:
133 else:
134 log.log("Searching files in {}".format(self.path), self.name)
134 log.log("Searching files in {}".format(self.path), self.name)
135 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
135 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
136 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
136 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
137
137
138 self.setNextFile()
138 self.setNextFile()
139
139
140 return
140 return
141
141
142 def readFirstHeader(self):
142 def readFirstHeader(self):
143 '''Read metadata and data'''
143 '''Read metadata and data'''
144
144
145 self.__readMetadata()
145 self.__readMetadata()
146 self.__readData()
146 self.__readData()
147 self.__setBlockList()
147 self.__setBlockList()
148
148
149 if 'type' in self.meta:
149 if 'type' in self.meta:
150 self.dataOut = eval(self.meta['type'])()
150 self.dataOut = eval(self.meta['type'])()
151
151
152 for attr in self.meta:
152 for attr in self.meta:
153 setattr(self.dataOut, attr, self.meta[attr])
153 setattr(self.dataOut, attr, self.meta[attr])
154
154
155 self.blockIndex = 0
155 self.blockIndex = 0
156
156
157 return
157 return
158
158
159 def __setBlockList(self):
159 def __setBlockList(self):
160 '''
160 '''
161 Selects the data within the times defined
161 Selects the data within the times defined
162
162
163 self.fp
163 self.fp
164 self.startTime
164 self.startTime
165 self.endTime
165 self.endTime
166 self.blockList
166 self.blockList
167 self.blocksPerFile
167 self.blocksPerFile
168
168
169 '''
169 '''
170
170
171 startTime = self.startTime
171 startTime = self.startTime
172 endTime = self.endTime
172 endTime = self.endTime
173 thisUtcTime = self.data['utctime'] + self.utcoffset
173 thisUtcTime = self.data['utctime'] + self.utcoffset
174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
175 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
175 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
176
176
177 thisDate = thisDatetime.date()
177 thisDate = thisDatetime.date()
178 thisTime = thisDatetime.time()
178 thisTime = thisDatetime.time()
179
179
180 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
180 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
181 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
181 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
182
182
183 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
183 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
184
184
185 self.blockList = ind
185 self.blockList = ind
186 self.blocksPerFile = len(ind)
186 self.blocksPerFile = len(ind)
187 return
187 return
188
188
189 def __readMetadata(self):
189 def __readMetadata(self):
190 '''
190 '''
191 Reads Metadata
191 Reads Metadata
192 '''
192 '''
193
193
194 meta = {}
194 meta = {}
195
195
196 if self.description:
196 if self.description:
197 for key, value in self.description['Metadata'].items():
197 for key, value in self.description['Metadata'].items():
198 meta[key] = self.fp[value][()]
198 meta[key] = self.fp[value][()]
199 else:
199 else:
200 grp = self.fp['Metadata']
200 grp = self.fp['Metadata']
201 for name in grp:
201 for name in grp:
202 meta[name] = grp[name][()]
202 meta[name] = grp[name][()]
203
203
204 if self.extras:
204 if self.extras:
205 for key, value in self.extras.items():
205 for key, value in self.extras.items():
206 meta[key] = value
206 meta[key] = value
207 self.meta = meta
207 self.meta = meta
208
208
209 return
209 return
210
210
211 def __readData(self):
211 def __readData(self):
212
212
213 data = {}
213 data = {}
214
214
215 if self.description:
215 if self.description:
216 for key, value in self.description['Data'].items():
216 for key, value in self.description['Data'].items():
217 if isinstance(value, str):
217 if isinstance(value, str):
218 if isinstance(self.fp[value], h5py.Dataset):
218 if isinstance(self.fp[value], h5py.Dataset):
219 data[key] = self.fp[value][()]
219 data[key] = self.fp[value][()]
220 elif isinstance(self.fp[value], h5py.Group):
220 elif isinstance(self.fp[value], h5py.Group):
221 array = []
221 array = []
222 for ch in self.fp[value]:
222 for ch in self.fp[value]:
223 array.append(self.fp[value][ch][()])
223 array.append(self.fp[value][ch][()])
224 data[key] = numpy.array(array)
224 data[key] = numpy.array(array)
225 elif isinstance(value, list):
225 elif isinstance(value, list):
226 array = []
226 array = []
227 for ch in value:
227 for ch in value:
228 array.append(self.fp[ch][()])
228 array.append(self.fp[ch][()])
229 data[key] = numpy.array(array)
229 data[key] = numpy.array(array)
230 else:
230 else:
231 grp = self.fp['Data']
231 grp = self.fp['Data']
232 for name in grp:
232 for name in grp:
233 if isinstance(grp[name], h5py.Dataset):
233 if isinstance(grp[name], h5py.Dataset):
234 array = grp[name][()]
234 array = grp[name][()]
235 elif isinstance(grp[name], h5py.Group):
235 elif isinstance(grp[name], h5py.Group):
236 array = []
236 array = []
237 for ch in grp[name]:
237 for ch in grp[name]:
238 array.append(grp[name][ch][()])
238 array.append(grp[name][ch][()])
239 array = numpy.array(array)
239 array = numpy.array(array)
240 else:
240 else:
241 log.warning('Unknown type: {}'.format(name))
241 log.warning('Unknown type: {}'.format(name))
242
242
243 if name in self.description:
243 if name in self.description:
244 key = self.description[name]
244 key = self.description[name]
245 else:
245 else:
246 key = name
246 key = name
247 data[key] = array
247 data[key] = array
248
248
249 self.data = data
249 self.data = data
250 return
250 return
251
251
252 def getData(self):
252 def getData(self):
253
253
254 for attr in self.data:
254 for attr in self.data:
255 if self.data[attr].ndim == 1:
255 if self.data[attr].ndim == 1:
256 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
256 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
257 else:
257 else:
258 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
258 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
259
259
260 self.dataOut.flagNoData = False
260 self.dataOut.flagNoData = False
261 self.blockIndex += 1
261 self.blockIndex += 1
262
262
263 log.log("Block No. {}/{} -> {}".format(
263 log.log("Block No. {}/{} -> {}".format(
264 self.blockIndex,
264 self.blockIndex,
265 self.blocksPerFile,
265 self.blocksPerFile,
266 self.dataOut.datatime.ctime()), self.name)
266 self.dataOut.datatime.ctime()), self.name)
267
267
268 return
268 return
269
269
270 def run(self, **kwargs):
270 def run(self, **kwargs):
271
271
272 if not(self.isConfig):
272 if not(self.isConfig):
273 self.setup(**kwargs)
273 self.setup(**kwargs)
274 self.isConfig = True
274 self.isConfig = True
275
275
276 if self.blockIndex == self.blocksPerFile:
276 if self.blockIndex == self.blocksPerFile:
277 self.setNextFile()
277 self.setNextFile()
278
278
279 self.getData()
279 self.getData()
280
280
281 return
281 return
282
282
283 @MPDecorator
283 @MPDecorator
284 class HDFWriter(Operation):
284 class HDFWriter(Operation):
285 """Operation to write HDF5 files.
285 """Operation to write HDF5 files.
286
286
287 The HDF5 file contains by default two groups Data and Metadata where
287 The HDF5 file contains by default two groups Data and Metadata where
288 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
288 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
289 parameters, data attributes are normaly time dependent where the metadata
289 parameters, data attributes are normaly time dependent where the metadata
290 are not.
290 are not.
291 It is possible to customize the structure of the HDF5 file with the
291 It is possible to customize the structure of the HDF5 file with the
292 optional description parameter see the examples.
292 optional description parameter see the examples.
293
293
294 Parameters:
294 Parameters:
295 -----------
295 -----------
296 path : str
296 path : str
297 Path where files will be saved.
297 Path where files will be saved.
298 blocksPerFile : int
298 blocksPerFile : int
299 Number of blocks per file
299 Number of blocks per file
300 metadataList : list
300 metadataList : list
301 List of the dataOut attributes that will be saved as metadata
301 List of the dataOut attributes that will be saved as metadata
302 dataList : int
302 dataList : int
303 List of the dataOut attributes that will be saved as data
303 List of the dataOut attributes that will be saved as data
304 setType : bool
304 setType : bool
305 If True the name of the files corresponds to the timestamp of the data
305 If True the name of the files corresponds to the timestamp of the data
306 description : dict, optional
306 description : dict, optional
307 Dictionary with the desired description of the HDF5 file
307 Dictionary with the desired description of the HDF5 file
308
308
309 Examples
309 Examples
310 --------
310 --------
311
311
312 desc = {
312 desc = {
313 'data_output': {'winds': ['z', 'w', 'v']},
313 'data_output': {'winds': ['z', 'w', 'v']},
314 'utctime': 'timestamps',
314 'utctime': 'timestamps',
315 'heightList': 'heights'
315 'heightList': 'heights'
316 }
316 }
317 desc = {
317 desc = {
318 'data_output': ['z', 'w', 'v'],
318 'data_output': ['z', 'w', 'v'],
319 'utctime': 'timestamps',
319 'utctime': 'timestamps',
320 'heightList': 'heights'
320 'heightList': 'heights'
321 }
321 }
322 desc = {
322 desc = {
323 'Data': {
323 'Data': {
324 'data_output': 'winds',
324 'data_output': 'winds',
325 'utctime': 'timestamps'
325 'utctime': 'timestamps'
326 },
326 },
327 'Metadata': {
327 'Metadata': {
328 'heightList': 'heights'
328 'heightList': 'heights'
329 }
329 }
330 }
330 }
331
331
332 writer = proc_unit.addOperation(name='HDFWriter')
332 writer = proc_unit.addOperation(name='HDFWriter')
333 writer.addParameter(name='path', value='/path/to/file')
333 writer.addParameter(name='path', value='/path/to/file')
334 writer.addParameter(name='blocksPerFile', value='32')
334 writer.addParameter(name='blocksPerFile', value='32')
335 writer.addParameter(name='metadataList', value='heightList,timeZone')
335 writer.addParameter(name='metadataList', value='heightList,timeZone')
336 writer.addParameter(name='dataList',value='data_output,utctime')
336 writer.addParameter(name='dataList',value='data_output,utctime')
337 # writer.addParameter(name='description',value=json.dumps(desc))
337 # writer.addParameter(name='description',value=json.dumps(desc))
338
338
339 """
339 """
340
340
341 ext = ".hdf5"
341 ext = ".hdf5"
342 optchar = "D"
342 optchar = "D"
343 filename = None
343 filename = None
344 path = None
344 path = None
345 setFile = None
345 setFile = None
346 fp = None
346 fp = None
347 firsttime = True
347 firsttime = True
348 #Configurations
348 #Configurations
349 blocksPerFile = None
349 blocksPerFile = None
350 blockIndex = None
350 blockIndex = None
351 dataOut = None
351 dataOut = None
352 #Data Arrays
352 #Data Arrays
353 dataList = None
353 dataList = None
354 metadataList = None
354 metadataList = None
355 currentDay = None
355 currentDay = None
356 lastTime = None
356 lastTime = None
357 last_Azipos = None
357 last_Azipos = None
358 last_Elepos = None
358 last_Elepos = None
359 mode = None
359 mode = None
360 #-----------------------
360 #-----------------------
361 Typename = None
361 Typename = None
362
362
363
363
364
364
365 def __init__(self):
365 def __init__(self):
366
366
367 Operation.__init__(self)
367 Operation.__init__(self)
368 return
368 return
369
369
370
370
371 def set_kwargs(self, **kwargs):
371 def set_kwargs(self, **kwargs):
372
372
373 for key, value in kwargs.items():
373 for key, value in kwargs.items():
374 setattr(self, key, value)
374 setattr(self, key, value)
375
375
376 def set_kwargs_obj(self,obj, **kwargs):
376 def set_kwargs_obj(self,obj, **kwargs):
377
377
378 for key, value in kwargs.items():
378 for key, value in kwargs.items():
379 setattr(obj, key, value)
379 setattr(obj, key, value)
380
380
381 def generalFlag(self):
381 def generalFlag(self):
382 ####rint("GENERALFLAG")
382 ####rint("GENERALFLAG")
383 if self.mode== "weather":
383 if self.mode== "weather":
384 if self.last_Azipos == None:
384 if self.last_Azipos == None:
385 tmp = self.dataOut.azimuth
385 tmp = self.dataOut.azimuth
386 ####print("ang azimuth writer",tmp)
386 ####print("ang azimuth writer",tmp)
387 self.last_Azipos = tmp
387 self.last_Azipos = tmp
388 flag = False
388 flag = False
389 return flag
389 return flag
390 ####print("ang_azimuth writer",self.dataOut.azimuth)
390 ####print("ang_azimuth writer",self.dataOut.azimuth)
391 result = self.dataOut.azimuth - self.last_Azipos
391 result = self.dataOut.azimuth - self.last_Azipos
392 self.last_Azipos = self.dataOut.azimuth
392 self.last_Azipos = self.dataOut.azimuth
393 if result<0:
393 if result<0:
394 flag = True
394 flag = True
395 return flag
395 return flag
396
396
397 def generalFlag_vRF(self):
397 def generalFlag_vRF(self):
398 ####rint("GENERALFLAG")
398 ####rint("GENERALFLAG")
399
399
400 try:
400 try:
401 self.dataOut.flagBlock360Done
401 self.dataOut.flagBlock360Done
402 return self.dataOut.flagBlock360Done
402 return self.dataOut.flagBlock360Done
403 except:
403 except:
404 return 0
404 return 0
405
405
406
406
407 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None,type_data=None,**kwargs):
407 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None,type_data=None,**kwargs):
408 self.path = path
408 self.path = path
409 self.blocksPerFile = blocksPerFile
409 self.blocksPerFile = blocksPerFile
410 self.metadataList = metadataList
410 self.metadataList = metadataList
411 self.dataList = [s.strip() for s in dataList]
411 self.dataList = [s.strip() for s in dataList]
412 self.setType = setType
412 self.setType = setType
413 if self.mode == "weather":
413 if self.mode == "weather":
414 self.setType = "weather"
414 self.setType = "weather"
415 self.set_kwargs(**kwargs)
415 self.set_kwargs(**kwargs)
416 self.set_kwargs_obj(self.dataOut,**kwargs)
416 self.set_kwargs_obj(self.dataOut,**kwargs)
417
417
418
418
419 self.description = description
419 self.description = description
420 self.type_data=type_data
420 self.type_data=type_data
421
421
422 if self.metadataList is None:
422 if self.metadataList is None:
423 self.metadataList = self.dataOut.metadata_list
423 self.metadataList = self.dataOut.metadata_list
424
424
425 tableList = []
425 tableList = []
426 dsList = []
426 dsList = []
427
427
428 for i in range(len(self.dataList)):
428 for i in range(len(self.dataList)):
429 dsDict = {}
429 dsDict = {}
430 if hasattr(self.dataOut, self.dataList[i]):
430 if hasattr(self.dataOut, self.dataList[i]):
431 dataAux = getattr(self.dataOut, self.dataList[i])
431 dataAux = getattr(self.dataOut, self.dataList[i])
432 dsDict['variable'] = self.dataList[i]
432 dsDict['variable'] = self.dataList[i]
433 else:
433 else:
434 log.warning('Attribute {} not found in dataOut', self.name)
434 log.warning('Attribute {} not found in dataOut', self.name)
435 continue
435 continue
436
436
437 if dataAux is None:
437 if dataAux is None:
438 continue
438 continue
439 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
439 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
440 dsDict['nDim'] = 0
440 dsDict['nDim'] = 0
441 else:
441 else:
442 dsDict['nDim'] = len(dataAux.shape)
442 dsDict['nDim'] = len(dataAux.shape)
443 dsDict['shape'] = dataAux.shape
443 dsDict['shape'] = dataAux.shape
444 dsDict['dsNumber'] = dataAux.shape[0]
444 dsDict['dsNumber'] = dataAux.shape[0]
445 dsDict['dtype'] = dataAux.dtype
445 dsDict['dtype'] = dataAux.dtype
446 dsList.append(dsDict)
446 dsList.append(dsDict)
447
447
448 self.dsList = dsList
448 self.dsList = dsList
449 self.currentDay = self.dataOut.datatime.date()
449 self.currentDay = self.dataOut.datatime.date()
450
450
451 def timeFlag(self):
451 def timeFlag(self):
452 currentTime = self.dataOut.utctime
452 currentTime = self.dataOut.utctime
453 timeTuple = time.localtime(currentTime)
453 timeTuple = time.localtime(currentTime)
454 dataDay = timeTuple.tm_yday
454 dataDay = timeTuple.tm_yday
455
455
456 if self.lastTime is None:
456 if self.lastTime is None:
457 self.lastTime = currentTime
457 self.lastTime = currentTime
458 self.currentDay = dataDay
458 self.currentDay = dataDay
459 return False
459 return False
460
460
461 timeDiff = currentTime - self.lastTime
461 timeDiff = currentTime - self.lastTime
462
462
463 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
463 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
464 if dataDay != self.currentDay:
464 if dataDay != self.currentDay:
465 self.currentDay = dataDay
465 self.currentDay = dataDay
466 return True
466 return True
467 elif timeDiff > 3*60*60:
467 elif timeDiff > 3*60*60:
468 self.lastTime = currentTime
468 self.lastTime = currentTime
469 return True
469 return True
470 else:
470 else:
471 self.lastTime = currentTime
471 self.lastTime = currentTime
472 return False
472 return False
473
473
474 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
474 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
475 dataList=[], setType=None, description={},mode= None,type_data=None,Reset = False,**kwargs):
475 dataList=[], setType=None, description={},mode= None,type_data=None,Reset = False,**kwargs):
476
476
477 if Reset:
477 if Reset:
478 self.isConfig = False
478 self.isConfig = False
479 self.closeFile()
479 self.closeFile()
480 self.lastTime = None
480 self.lastTime = None
481 self.blockIndex = 0
481 self.blockIndex = 0
482
482
483 self.dataOut = dataOut
483 self.dataOut = dataOut
484 self.mode = mode
484 self.mode = mode
485 self.var = dataList[0]
486
485 if not(self.isConfig):
487 if not(self.isConfig):
486 self.setup(path=path, blocksPerFile=blocksPerFile,
488 self.setup(path=path, blocksPerFile=blocksPerFile,
487 metadataList=metadataList, dataList=dataList,
489 metadataList=metadataList, dataList=dataList,
488 setType=setType, description=description,type_data=type_data,**kwargs)
490 setType=setType, description=description,type_data=type_data,**kwargs)
489
491
490 self.isConfig = True
492 self.isConfig = True
491 self.setNextFile()
493 self.setNextFile()
492
494
493 self.putData()
495 self.putData()
494 return
496 return
495
497
496 def setNextFile(self):
498 def setNextFile(self):
497 ###print("HELLO WORLD--------------------------------")
499 ###print("HELLO WORLD--------------------------------")
498 ext = self.ext
500 ext = self.ext
499 path = self.path
501 path = self.path
500 setFile = self.setFile
502 setFile = self.setFile
501 type_data = self.type_data
503 type_data = self.type_data
502
504
503 timeTuple = time.localtime(self.dataOut.utctime)
505 timeTuple = time.localtime(self.dataOut.utctime)
504 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
506 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
505 fullpath = os.path.join(path, subfolder)
507 fullpath = os.path.join(path, subfolder)
506
508
507 if os.path.exists(fullpath):
509 if os.path.exists(fullpath):
508 filesList = os.listdir(fullpath)
510 filesList = os.listdir(fullpath)
509 filesList = [k for k in filesList if k.startswith(self.optchar)]
511 filesList = [k for k in filesList if k.startswith(self.optchar)]
510 if len( filesList ) > 0:
512 if len( filesList ) > 0:
511 filesList = sorted(filesList, key=str.lower)
513 filesList = sorted(filesList, key=str.lower)
512 filen = filesList[-1]
514 filen = filesList[-1]
513 # el filename debera tener el siguiente formato
515 # el filename debera tener el siguiente formato
514 # 0 1234 567 89A BCDE (hex)
516 # 0 1234 567 89A BCDE (hex)
515 # x YYYY DDD SSS .ext
517 # x YYYY DDD SSS .ext
516 if isNumber(filen[8:11]):
518 if isNumber(filen[8:11]):
517 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
519 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
518 else:
520 else:
519 setFile = -1
521 setFile = -1
520 else:
522 else:
521 setFile = -1 #inicializo mi contador de seteo
523 setFile = -1 #inicializo mi contador de seteo
522 else:
524 else:
523 os.makedirs(fullpath)
525 os.makedirs(fullpath)
524 setFile = -1 #inicializo mi contador de seteo
526 setFile = -1 #inicializo mi contador de seteo
525
527
526 ###print("**************************",self.setType)
528 ###print("**************************",self.setType)
527 if self.setType is None:
529 if self.setType is None:
528 setFile += 1
530 setFile += 1
529 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
531 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
530 timeTuple.tm_year,
532 timeTuple.tm_year,
531 timeTuple.tm_yday,
533 timeTuple.tm_yday,
532 setFile,
534 setFile,
533 ext )
535 ext )
534 elif self.setType == "weather":
536 elif self.setType == "weather":
535 print("HOLA AMIGOS")
536 wr_exp = self.dataOut.wr_exp
537 if wr_exp== "PPI":
538 wr_type = 'E'
539 ang_ = numpy.mean(self.dataOut.elevation)
540 else:
541 wr_type = 'A'
542 ang_ = numpy.mean(self.dataOut.azimuth)
543
544 wr_writer = '%s%s%2.1f%s'%('-',
545 wr_type,
546 ang_,
547 '-')
548 ###print("wr_writer********************",wr_writer)
549 file = '%s%4.4d%2.2d%2.2d%s%2.2d%2.2d%2.2d%s%s%s' % (self.optchar,
550 timeTuple.tm_year,
551 timeTuple.tm_mon,
552 timeTuple.tm_mday,
553 '-',
554 timeTuple.tm_hour,
555 timeTuple.tm_min,
556 timeTuple.tm_sec,
557 wr_writer,
558 type_data,
559 ext )
560 ###print("FILENAME", file)
561
537
538 if self.var.lower() == 'Zdb'.lower():
539 wr_type = 'Z'
540 elif self.var.lower() == 'Zdb_D'.lower():
541 wr_type = 'D'
542 elif self.var.lower() == 'PhiD_P'.lower():
543 wr_type = 'P'
544 elif self.var.lower() == 'RhoHV_R'.lower():
545 wr_type = 'R'
546 elif self.var.lower() == 'velRadial_V'.lower():
547 wr_type = 'V'
548 elif self.var.lower() == 'Sigmav_W'.lower():
549 wr_type = 'S'
550 elif self.var.lower() == 'dataPP_POWER'.lower():
551 wr_type = 'Pow'
552 elif self.var.lower() == 'dataPP_DOP'.lower():
553 wr_type = 'Dop'
554
555
556 #Z_SOPHy_El10.0_20200505_14:02:15.h5
557 #Z_SOPHy_Az40.0_20200505_14:02:15.h5
558 if self.dataOut.flagMode == 1: #'AZI' #PPI
559 ang_type = 'El'
560 ang_ = round(numpy.mean(self.dataOut.data_ele),1)
561 elif self.dataOut.flagMode == 0: #'ELE' #RHI
562 ang_type = 'Az'
563 ang_ = round(numpy.mean(self.dataOut.data_azi),1)
564
565 file = '%s%s%s%2.1f%s%2.2d%2.2d%2.2d%s%2.2d%2.2d%2.2d%s' % (wr_type,
566 '_SOPHy_',
567 ang_type,
568 ang_,
569 '_',
570 timeTuple.tm_year,
571 timeTuple.tm_mon,
572 timeTuple.tm_mday,
573 '_',
574 timeTuple.tm_hour,
575 timeTuple.tm_min,
576 timeTuple.tm_sec,
577 ext )
562
578
563 else:
579 else:
564 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
580 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
565 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
581 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
566 timeTuple.tm_year,
582 timeTuple.tm_year,
567 timeTuple.tm_yday,
583 timeTuple.tm_yday,
568 setFile,
584 setFile,
569 ext )
585 ext )
570
586
571 self.filename = os.path.join( path, subfolder, file )
587 self.filename = os.path.join( path, subfolder, file )
572
588
573 #Setting HDF5 File
589 #Setting HDF5 File
574
590 print("filename",self.filename)
575 self.fp = h5py.File(self.filename, 'w')
591 self.fp = h5py.File(self.filename, 'w')
576 #write metadata
592 #write metadata
577 self.writeMetadata(self.fp)
593 self.writeMetadata(self.fp)
578 #Write data
594 #Write data
579 self.writeData(self.fp)
595 self.writeData(self.fp)
580
596
581 def getLabel(self, name, x=None):
597 def getLabel(self, name, x=None):
582
598
583 if x is None:
599 if x is None:
584 if 'Data' in self.description:
600 if 'Data' in self.description:
585 data = self.description['Data']
601 data = self.description['Data']
586 if 'Metadata' in self.description:
602 if 'Metadata' in self.description:
587 data.update(self.description['Metadata'])
603 data.update(self.description['Metadata'])
588 else:
604 else:
589 data = self.description
605 data = self.description
590 if name in data:
606 if name in data:
591 if isinstance(data[name], str):
607 if isinstance(data[name], str):
592 return data[name]
608 return data[name]
593 elif isinstance(data[name], list):
609 elif isinstance(data[name], list):
594 return None
610 return None
595 elif isinstance(data[name], dict):
611 elif isinstance(data[name], dict):
596 for key, value in data[name].items():
612 for key, value in data[name].items():
597 return key
613 return key
598 return name
614 return name
599 else:
615 else:
600 if 'Metadata' in self.description:
616 if 'Metadata' in self.description:
601 meta = self.description['Metadata']
617 meta = self.description['Metadata']
602 else:
618 else:
603 meta = self.description
619 meta = self.description
604 if name in meta:
620 if name in meta:
605 if isinstance(meta[name], list):
621 if isinstance(meta[name], list):
606 return meta[name][x]
622 return meta[name][x]
607 elif isinstance(meta[name], dict):
623 elif isinstance(meta[name], dict):
608 for key, value in meta[name].items():
624 for key, value in meta[name].items():
609 return value[x]
625 return value[x]
610 if 'cspc' in name:
626 if 'cspc' in name:
611 return 'pair{:02d}'.format(x)
627 return 'pair{:02d}'.format(x)
612 else:
628 else:
613 return 'channel{:02d}'.format(x)
629 return 'channel{:02d}'.format(x)
614
630
615 def writeMetadata(self, fp):
631 def writeMetadata(self, fp):
616
632
617 if self.description:
633 if self.description:
618 if 'Metadata' in self.description:
634 if 'Metadata' in self.description:
619 grp = fp.create_group('Metadata')
635 grp = fp.create_group('Metadata')
620 else:
636 else:
621 grp = fp
637 grp = fp
622 else:
638 else:
623 grp = fp.create_group('Metadata')
639 grp = fp.create_group('Metadata')
624
640
625 for i in range(len(self.metadataList)):
641 for i in range(len(self.metadataList)):
626 if not hasattr(self.dataOut, self.metadataList[i]):
642 if not hasattr(self.dataOut, self.metadataList[i]):
627 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
643 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
628 continue
644 continue
629 value = getattr(self.dataOut, self.metadataList[i])
645 value = getattr(self.dataOut, self.metadataList[i])
630 if isinstance(value, bool):
646 if isinstance(value, bool):
631 if value is True:
647 if value is True:
632 value = 1
648 value = 1
633 else:
649 else:
634 value = 0
650 value = 0
635 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
651 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
636 return
652 return
637
653
638 def writeData(self, fp):
654 def writeData(self, fp):
639
655
640 if self.description:
656 if self.description:
641 if 'Data' in self.description:
657 if 'Data' in self.description:
642 grp = fp.create_group('Data')
658 grp = fp.create_group('Data')
643 else:
659 else:
644 grp = fp
660 grp = fp
645 else:
661 else:
646 grp = fp.create_group('Data')
662 grp = fp.create_group('Data')
647
663
648 dtsets = []
664 dtsets = []
649 data = []
665 data = []
650
666
651 for dsInfo in self.dsList:
667 for dsInfo in self.dsList:
652 if dsInfo['nDim'] == 0:
668 if dsInfo['nDim'] == 0:
653 ds = grp.create_dataset(
669 ds = grp.create_dataset(
654 self.getLabel(dsInfo['variable']),
670 self.getLabel(dsInfo['variable']),
655 (self.blocksPerFile, ),
671 (self.blocksPerFile, ),
656 chunks=True,
672 chunks=True,
657 dtype=numpy.float64)
673 dtype=numpy.float64)
658 dtsets.append(ds)
674 dtsets.append(ds)
659 data.append((dsInfo['variable'], -1))
675 data.append((dsInfo['variable'], -1))
660 else:
676 else:
661 label = self.getLabel(dsInfo['variable'])
677 label = self.getLabel(dsInfo['variable'])
662 if label is not None:
678 if label is not None:
663 sgrp = grp.create_group(label)
679 sgrp = grp.create_group(label)
664 else:
680 else:
665 sgrp = grp
681 sgrp = grp
666 for i in range(dsInfo['dsNumber']):
682 for i in range(dsInfo['dsNumber']):
667 ds = sgrp.create_dataset(
683 ds = sgrp.create_dataset(
668 self.getLabel(dsInfo['variable'], i),
684 self.getLabel(dsInfo['variable'], i),
669 (self.blocksPerFile, ) + dsInfo['shape'][1:],
685 (self.blocksPerFile, ) + dsInfo['shape'][1:],
670 chunks=True,
686 chunks=True,
671 dtype=dsInfo['dtype'])
687 dtype=dsInfo['dtype'])
672 dtsets.append(ds)
688 dtsets.append(ds)
673 data.append((dsInfo['variable'], i))
689 data.append((dsInfo['variable'], i))
674 fp.flush()
690 fp.flush()
675
691
676 log.log('Creating file: {}'.format(fp.filename), self.name)
692 log.log('Creating file: {}'.format(fp.filename), self.name)
677
693
678 self.ds = dtsets
694 self.ds = dtsets
679 self.data = data
695 self.data = data
680 self.firsttime = True
696 self.firsttime = True
681 self.blockIndex = 0
697 self.blockIndex = 0
682 return
698 return
683
699
684 def putData(self):
700 def putData(self):
701
685 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():# or self.generalFlag_vRF():
702 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():# or self.generalFlag_vRF():
686 self.closeFile()
703 self.closeFile()
687 self.setNextFile()
704 self.setNextFile()
688
705
689 for i, ds in enumerate(self.ds):
706 for i, ds in enumerate(self.ds):
690 attr, ch = self.data[i]
707 attr, ch = self.data[i]
691 if ch == -1:
708 if ch == -1:
692 ds[self.blockIndex] = getattr(self.dataOut, attr)
709 ds[self.blockIndex] = getattr(self.dataOut, attr)
693 else:
710 else:
694 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
711 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
695
712
696 self.fp.flush()
713 self.fp.flush()
697 self.blockIndex += 1
714 self.blockIndex += 1
698 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
715 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
699
716
700 return
717 return
701
718
702 def closeFile(self):
719 def closeFile(self):
703
720
704 if self.blockIndex != self.blocksPerFile:
721 if self.blockIndex != self.blocksPerFile:
705 for ds in self.ds:
722 for ds in self.ds:
706 ds.resize(self.blockIndex, axis=0)
723 ds.resize(self.blockIndex, axis=0)
707
724
708 if self.fp:
725 if self.fp:
709 self.fp.flush()
726 self.fp.flush()
710 self.fp.close()
727 self.fp.close()
711
728
712 def close(self):
729 def close(self):
713
730
714 self.closeFile()
731 self.closeFile()
@@ -1,226 +1,236
1 '''
1 '''
2 Base clases to create Processing units and operations, the MPDecorator
2 Base clases to create Processing units and operations, the MPDecorator
3 must be used in plotting and writing operations to allow to run as an
3 must be used in plotting and writing operations to allow to run as an
4 external process.
4 external process.
5 '''
5 '''
6
6
7 import os
7 import os
8 import inspect
8 import inspect
9 import zmq
9 import zmq
10 import time
10 import time
11 import pickle
11 import pickle
12 import traceback
12 import traceback
13 from threading import Thread
13 from threading import Thread
14 from multiprocessing import Process, Queue
14 from multiprocessing import Process, Queue
15 from schainpy.utils import log
15 from schainpy.utils import log
16
16
17 QUEUE_SIZE = int(os.environ.get('QUEUE_MAX_SIZE', '10'))
17 QUEUE_SIZE = int(os.environ.get('QUEUE_MAX_SIZE', '10'))
18
18
19 class ProcessingUnit(object):
19 class ProcessingUnit(object):
20 '''
20 '''
21 Base class to create Signal Chain Units
21 Base class to create Signal Chain Units
22 '''
22 '''
23
23
24 proc_type = 'processing'
24 proc_type = 'processing'
25
25
26 def __init__(self):
26 def __init__(self):
27
27
28 self.dataIn = None
28 self.dataIn = None
29 self.dataOut = None
29 self.dataOut = None
30 self.isConfig = False
30 self.isConfig = False
31 self.operations = []
31 self.operations = []
32 self.name = 'Test'
32 self.name = 'Test'
33 self.inputs = []
33 self.inputs = []
34
34
35 def setInput(self, unit):
35 def setInput(self, unit):
36
36
37 attr = 'dataIn'
37 attr = 'dataIn'
38 for i, u in enumerate(unit):
38 for i, u in enumerate(unit):
39 if i==0:
39 if i==0:
40 self.dataIn = u.dataOut
40 self.dataIn = u.dataOut
41 self.inputs.append('dataIn')
41 self.inputs.append('dataIn')
42 else:
42 else:
43 setattr(self, 'dataIn{}'.format(i), u.dataOut)
43 setattr(self, 'dataIn{}'.format(i), u.dataOut)
44 self.inputs.append('dataIn{}'.format(i))
44 self.inputs.append('dataIn{}'.format(i))
45
45
46 def getAllowedArgs(self):
46 def getAllowedArgs(self):
47 if hasattr(self, '__attrs__'):
47 if hasattr(self, '__attrs__'):
48 return self.__attrs__
48 return self.__attrs__
49 else:
49 else:
50 return inspect.getargspec(self.run).args
50 return inspect.getargspec(self.run).args
51
51
52 def addOperation(self, conf, operation):
52 def addOperation(self, conf, operation):
53 '''
53 '''
54 '''
54 '''
55
55
56 self.operations.append((operation, conf.type, conf.getKwargs()))
56 self.operations.append((operation, conf.type, conf.getKwargs()))
57
57
58 def getOperationObj(self, objId):
58 def getOperationObj(self, objId):
59
59
60 if objId not in list(self.operations.keys()):
60 if objId not in list(self.operations.keys()):
61 return None
61 return None
62
62
63 return self.operations[objId]
63 return self.operations[objId]
64
64
65 def call(self, **kwargs):
65 def call(self, **kwargs):
66 '''
66 '''
67 '''
67 '''
68
68
69 try:
69 try:
70 if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error:
70 if self.dataIn is not None and self.dataIn.flagNoData and not self.dataIn.error:
71 return self.dataIn.isReady()
71 return self.dataIn.isReady()
72 elif self.dataIn is None or not self.dataIn.error:
72 elif self.dataIn is None or not self.dataIn.error:
73 self.run(**kwargs)
73 self.run(**kwargs)
74 elif self.dataIn.error:
74 elif self.dataIn.error:
75 self.dataOut.error = self.dataIn.error
75 self.dataOut.error = self.dataIn.error
76 self.dataOut.flagNoData = True
76 self.dataOut.flagNoData = True
77 except:
77 except:
78 err = traceback.format_exc()
78 err = traceback.format_exc()
79 if 'SchainWarning' in err:
79 if 'SchainWarning' in err:
80 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), self.name)
80 log.warning(err.split('SchainWarning:')[-1].split('\n')[0].strip(), self.name)
81 elif 'SchainError' in err:
81 elif 'SchainError' in err:
82 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), self.name)
82 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), self.name)
83 else:
83 else:
84 log.error(err, self.name)
84 log.error(err, self.name)
85 self.dataOut.error = True
85 self.dataOut.error = True
86 ##### correcion de la declaracion Out
86 ##### correcion de la declaracion Out
87 for op, optype, opkwargs in self.operations:
87 for op, optype, opkwargs in self.operations:
88 aux = self.dataOut.copy()
88 aux = self.dataOut.copy()
89 if optype == 'other' and not self.dataOut.flagNoData:
89 '''
90 print("op",op)
91 try:
92 print("runNextOp",self.dataOut.runNextOp)
93 except:
94 pass
95 '''
96 if not hasattr(self.dataOut, 'runNextOp'):
97 self.dataOut.runNextOp = False
98 if optype == 'other' and (not self.dataOut.flagNoData or self.dataOut.runNextOp):
99 #if optype == 'other' and not self.dataOut.flagNoData:
90 self.dataOut = op.run(self.dataOut, **opkwargs)
100 self.dataOut = op.run(self.dataOut, **opkwargs)
91 elif optype == 'external' and not self.dataOut.flagNoData:
101 elif optype == 'external' and not self.dataOut.flagNoData:
92 #op.queue.put(self.dataOut)
102 #op.queue.put(self.dataOut)
93 op.queue.put(aux)
103 op.queue.put(aux)
94 elif optype == 'external' and self.dataOut.error:
104 elif optype == 'external' and self.dataOut.error:
95 #op.queue.put(self.dataOut)
105 #op.queue.put(self.dataOut)
96 op.queue.put(aux)
106 op.queue.put(aux)
97
107
98 try:
108 try:
99 if self.dataOut.runNextUnit:
109 if self.dataOut.runNextUnit:
100 runNextUnit = self.dataOut.runNextUnit
110 runNextUnit = self.dataOut.runNextUnit
101
111
102 else:
112 else:
103 runNextUnit = self.dataOut.isReady()
113 runNextUnit = self.dataOut.isReady()
104 except:
114 except:
105 runNextUnit = self.dataOut.isReady()
115 runNextUnit = self.dataOut.isReady()
106
116
107 return 'Error' if self.dataOut.error else runNextUnit
117 return 'Error' if self.dataOut.error else runNextUnit
108
118
109 def setup(self):
119 def setup(self):
110
120
111 raise NotImplementedError
121 raise NotImplementedError
112
122
113 def run(self):
123 def run(self):
114
124
115 raise NotImplementedError
125 raise NotImplementedError
116
126
117 def close(self):
127 def close(self):
118
128
119 return
129 return
120
130
121
131
122 class Operation(object):
132 class Operation(object):
123
133
124 '''
134 '''
125 '''
135 '''
126
136
127 proc_type = 'operation'
137 proc_type = 'operation'
128
138
129 def __init__(self):
139 def __init__(self):
130
140
131 self.id = None
141 self.id = None
132 self.isConfig = False
142 self.isConfig = False
133
143
134 if not hasattr(self, 'name'):
144 if not hasattr(self, 'name'):
135 self.name = self.__class__.__name__
145 self.name = self.__class__.__name__
136
146
137 def getAllowedArgs(self):
147 def getAllowedArgs(self):
138 if hasattr(self, '__attrs__'):
148 if hasattr(self, '__attrs__'):
139 return self.__attrs__
149 return self.__attrs__
140 else:
150 else:
141 return inspect.getargspec(self.run).args
151 return inspect.getargspec(self.run).args
142
152
143 def setup(self):
153 def setup(self):
144
154
145 self.isConfig = True
155 self.isConfig = True
146
156
147 raise NotImplementedError
157 raise NotImplementedError
148
158
149 def run(self, dataIn, **kwargs):
159 def run(self, dataIn, **kwargs):
150 """
160 """
151 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
161 Realiza las operaciones necesarias sobre la dataIn.data y actualiza los
152 atributos del objeto dataIn.
162 atributos del objeto dataIn.
153
163
154 Input:
164 Input:
155
165
156 dataIn : objeto del tipo JROData
166 dataIn : objeto del tipo JROData
157
167
158 Return:
168 Return:
159
169
160 None
170 None
161
171
162 Affected:
172 Affected:
163 __buffer : buffer de recepcion de datos.
173 __buffer : buffer de recepcion de datos.
164
174
165 """
175 """
166 if not self.isConfig:
176 if not self.isConfig:
167 self.setup(**kwargs)
177 self.setup(**kwargs)
168
178
169 raise NotImplementedError
179 raise NotImplementedError
170
180
171 def close(self):
181 def close(self):
172
182
173 return
183 return
174
184
175
185
176 def MPDecorator(BaseClass):
186 def MPDecorator(BaseClass):
177 """
187 """
178 Multiprocessing class decorator
188 Multiprocessing class decorator
179
189
180 This function add multiprocessing features to a BaseClass.
190 This function add multiprocessing features to a BaseClass.
181 """
191 """
182
192
183 class MPClass(BaseClass, Process):
193 class MPClass(BaseClass, Process):
184
194
185 def __init__(self, *args, **kwargs):
195 def __init__(self, *args, **kwargs):
186 super(MPClass, self).__init__()
196 super(MPClass, self).__init__()
187 Process.__init__(self)
197 Process.__init__(self)
188
198
189 self.args = args
199 self.args = args
190 self.kwargs = kwargs
200 self.kwargs = kwargs
191 self.t = time.time()
201 self.t = time.time()
192 self.op_type = 'external'
202 self.op_type = 'external'
193 self.name = BaseClass.__name__
203 self.name = BaseClass.__name__
194 self.__doc__ = BaseClass.__doc__
204 self.__doc__ = BaseClass.__doc__
195
205
196 if 'plot' in self.name.lower() and not self.name.endswith('_'):
206 if 'plot' in self.name.lower() and not self.name.endswith('_'):
197 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
207 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
198
208
199 self.start_time = time.time()
209 self.start_time = time.time()
200 self.err_queue = args[3]
210 self.err_queue = args[3]
201 self.queue = Queue(maxsize=QUEUE_SIZE)
211 self.queue = Queue(maxsize=QUEUE_SIZE)
202 self.myrun = BaseClass.run
212 self.myrun = BaseClass.run
203
213
204 def run(self):
214 def run(self):
205
215
206 while True:
216 while True:
207
217
208 dataOut = self.queue.get()
218 dataOut = self.queue.get()
209
219
210 if not dataOut.error:
220 if not dataOut.error:
211 try:
221 try:
212 BaseClass.run(self, dataOut, **self.kwargs)
222 BaseClass.run(self, dataOut, **self.kwargs)
213 except:
223 except:
214 err = traceback.format_exc()
224 err = traceback.format_exc()
215 log.error(err, self.name)
225 log.error(err, self.name)
216 else:
226 else:
217 break
227 break
218
228
219 self.close()
229 self.close()
220
230
221 def close(self):
231 def close(self):
222
232
223 BaseClass.close(self)
233 BaseClass.close(self)
224 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
234 log.success('Done...(Time:{:4.2f} secs)'.format(time.time()-self.start_time), self.name)
225
235
226 return MPClass
236 return MPClass
@@ -1,5106 +1,5107
1
1
2 import os
2 import os
3 import time
3 import time
4 import math
4 import math
5
5
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
12
13 from multiprocessing import Pool, TimeoutError
13 from multiprocessing import Pool, TimeoutError
14 from multiprocessing.pool import ThreadPool
14 from multiprocessing.pool import ThreadPool
15 import numpy
15 import numpy
16 import glob
16 import glob
17 import scipy
17 import scipy
18 import h5py
18 import h5py
19 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
19 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
20 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
20 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
21 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
21 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
22 from scipy import asarray as ar,exp
22 from scipy import asarray as ar,exp
23 from scipy.optimize import curve_fit
23 from scipy.optimize import curve_fit
24 from schainpy.utils import log
24 from schainpy.utils import log
25 import schainpy.admin
25 import schainpy.admin
26 import warnings
26 import warnings
27 from scipy import optimize, interpolate, signal, stats, ndimage
27 from scipy import optimize, interpolate, signal, stats, ndimage
28 from scipy.optimize.optimize import OptimizeWarning
28 from scipy.optimize.optimize import OptimizeWarning
29 warnings.filterwarnings('ignore')
29 warnings.filterwarnings('ignore')
30
30
31
31
32 SPEED_OF_LIGHT = 299792458
32 SPEED_OF_LIGHT = 299792458
33
33
34 '''solving pickling issue'''
34 '''solving pickling issue'''
35
35
36 def _pickle_method(method):
36 def _pickle_method(method):
37 func_name = method.__func__.__name__
37 func_name = method.__func__.__name__
38 obj = method.__self__
38 obj = method.__self__
39 cls = method.__self__.__class__
39 cls = method.__self__.__class__
40 return _unpickle_method, (func_name, obj, cls)
40 return _unpickle_method, (func_name, obj, cls)
41
41
42 def _unpickle_method(func_name, obj, cls):
42 def _unpickle_method(func_name, obj, cls):
43 for cls in cls.mro():
43 for cls in cls.mro():
44 try:
44 try:
45 func = cls.__dict__[func_name]
45 func = cls.__dict__[func_name]
46 except KeyError:
46 except KeyError:
47 pass
47 pass
48 else:
48 else:
49 break
49 break
50 return func.__get__(obj, cls)
50 return func.__get__(obj, cls)
51
51
52 def isNumber(str):
52 def isNumber(str):
53 try:
53 try:
54 float(str)
54 float(str)
55 return True
55 return True
56 except:
56 except:
57 return False
57 return False
58
58
59 class ParametersProc(ProcessingUnit):
59 class ParametersProc(ProcessingUnit):
60
60
61 METHODS = {}
61 METHODS = {}
62 nSeconds = None
62 nSeconds = None
63
63
64 def __init__(self):
64 def __init__(self):
65 ProcessingUnit.__init__(self)
65 ProcessingUnit.__init__(self)
66
66
67 # self.objectDict = {}
67 # self.objectDict = {}
68 self.buffer = None
68 self.buffer = None
69 self.firstdatatime = None
69 self.firstdatatime = None
70 self.profIndex = 0
70 self.profIndex = 0
71 self.dataOut = Parameters()
71 self.dataOut = Parameters()
72 self.setupReq = False #Agregar a todas las unidades de proc
72 self.setupReq = False #Agregar a todas las unidades de proc
73
73
74 def __updateObjFromInput(self):
74 def __updateObjFromInput(self):
75
75
76 self.dataOut.inputUnit = self.dataIn.type
76 self.dataOut.inputUnit = self.dataIn.type
77
77
78 self.dataOut.timeZone = self.dataIn.timeZone
78 self.dataOut.timeZone = self.dataIn.timeZone
79 self.dataOut.dstFlag = self.dataIn.dstFlag
79 self.dataOut.dstFlag = self.dataIn.dstFlag
80 self.dataOut.errorCount = self.dataIn.errorCount
80 self.dataOut.errorCount = self.dataIn.errorCount
81 self.dataOut.useLocalTime = self.dataIn.useLocalTime
81 self.dataOut.useLocalTime = self.dataIn.useLocalTime
82
82
83 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
83 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
84 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
84 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
85 self.dataOut.channelList = self.dataIn.channelList
85 self.dataOut.channelList = self.dataIn.channelList
86 self.dataOut.heightList = self.dataIn.heightList
86 self.dataOut.heightList = self.dataIn.heightList
87 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
87 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
88 # self.dataOut.nHeights = self.dataIn.nHeights
88 # self.dataOut.nHeights = self.dataIn.nHeights
89 # self.dataOut.nChannels = self.dataIn.nChannels
89 # self.dataOut.nChannels = self.dataIn.nChannels
90 # self.dataOut.nBaud = self.dataIn.nBaud
90 # self.dataOut.nBaud = self.dataIn.nBaud
91 # self.dataOut.nCode = self.dataIn.nCode
91 # self.dataOut.nCode = self.dataIn.nCode
92 # self.dataOut.code = self.dataIn.code
92 # self.dataOut.code = self.dataIn.code
93 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
93 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
94 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
94 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
95 # self.dataOut.utctime = self.firstdatatime
95 # self.dataOut.utctime = self.firstdatatime
96 self.dataOut.utctime = self.dataIn.utctime
96 self.dataOut.utctime = self.dataIn.utctime
97 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
97 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
98 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
98 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
99 self.dataOut.nCohInt = self.dataIn.nCohInt
99 self.dataOut.nCohInt = self.dataIn.nCohInt
100 # self.dataOut.nIncohInt = 1
100 # self.dataOut.nIncohInt = 1
101 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
101 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
102 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
102 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
103 self.dataOut.timeInterval1 = self.dataIn.timeInterval
103 self.dataOut.timeInterval1 = self.dataIn.timeInterval
104 self.dataOut.heightList = self.dataIn.heightList
104 self.dataOut.heightList = self.dataIn.heightList
105 self.dataOut.frequency = self.dataIn.frequency
105 self.dataOut.frequency = self.dataIn.frequency
106 # self.dataOut.noise = self.dataIn.noise
106 # self.dataOut.noise = self.dataIn.noise
107 self.dataOut.runNextUnit = self.dataIn.runNextUnit
107 self.dataOut.runNextUnit = self.dataIn.runNextUnit
108
108
109 def run(self, runNextUnit = 0):
109 def run(self, runNextUnit = 0):
110
110
111 self.dataIn.runNextUnit = runNextUnit
111 self.dataIn.runNextUnit = runNextUnit
112 #print("HOLA MUNDO SOY YO")
112 #print("HOLA MUNDO SOY YO")
113 #---------------------- Voltage Data ---------------------------
113 #---------------------- Voltage Data ---------------------------
114
114
115 if self.dataIn.type == "Voltage":
115 if self.dataIn.type == "Voltage":
116
116
117 self.__updateObjFromInput()
117 self.__updateObjFromInput()
118 self.dataOut.data_pre = self.dataIn.data.copy()
118 self.dataOut.data_pre = self.dataIn.data.copy()
119 self.dataOut.flagNoData = False
119 self.dataOut.flagNoData = False
120 self.dataOut.utctimeInit = self.dataIn.utctime
120 self.dataOut.utctimeInit = self.dataIn.utctime
121 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
121 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
122
122
123 if hasattr(self.dataIn, 'flagDataAsBlock'):
123 if hasattr(self.dataIn, 'flagDataAsBlock'):
124 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
124 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
125
125
126 if hasattr(self.dataIn, 'profileIndex'):
126 if hasattr(self.dataIn, 'profileIndex'):
127 self.dataOut.profileIndex = self.dataIn.profileIndex
127 self.dataOut.profileIndex = self.dataIn.profileIndex
128
128
129 if hasattr(self.dataIn, 'dataPP_POW'):
129 if hasattr(self.dataIn, 'dataPP_POW'):
130 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
130 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
131
131
132 if hasattr(self.dataIn, 'dataPP_POWER'):
132 if hasattr(self.dataIn, 'dataPP_POWER'):
133 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
133 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
134
134
135 if hasattr(self.dataIn, 'dataPP_DOP'):
135 if hasattr(self.dataIn, 'dataPP_DOP'):
136 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
136 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
137
137
138 if hasattr(self.dataIn, 'dataPP_SNR'):
138 if hasattr(self.dataIn, 'dataPP_SNR'):
139 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
139 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
140
140
141 if hasattr(self.dataIn, 'dataPP_WIDTH'):
141 if hasattr(self.dataIn, 'dataPP_WIDTH'):
142 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
142 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
143
143
144 if hasattr(self.dataIn, 'dataPP_CCF'):
144 if hasattr(self.dataIn, 'dataPP_CCF'):
145 self.dataOut.dataPP_CCF = self.dataIn.dataPP_CCF
145 self.dataOut.dataPP_CCF = self.dataIn.dataPP_CCF
146
146
147 return
147 return
148
148
149 #---------------------- Spectra Data ---------------------------
149 #---------------------- Spectra Data ---------------------------
150
150
151 if self.dataIn.type == "Spectra":
151 if self.dataIn.type == "Spectra":
152 #print("que paso en spectra")
152 #print("que paso en spectra")
153 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
153 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
154 self.dataOut.data_spc = self.dataIn.data_spc
154 self.dataOut.data_spc = self.dataIn.data_spc
155 self.dataOut.data_cspc = self.dataIn.data_cspc
155 self.dataOut.data_cspc = self.dataIn.data_cspc
156 self.dataOut.nProfiles = self.dataIn.nProfiles
156 self.dataOut.nProfiles = self.dataIn.nProfiles
157 self.dataOut.nIncohInt = self.dataIn.nIncohInt
157 self.dataOut.nIncohInt = self.dataIn.nIncohInt
158 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
158 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
159 self.dataOut.ippFactor = self.dataIn.ippFactor
159 self.dataOut.ippFactor = self.dataIn.ippFactor
160 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
160 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
161 self.dataOut.spc_noise = self.dataIn.getNoise()
161 self.dataOut.spc_noise = self.dataIn.getNoise()
162 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
162 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
163 # self.dataOut.normFactor = self.dataIn.normFactor
163 # self.dataOut.normFactor = self.dataIn.normFactor
164 self.dataOut.pairsList = self.dataIn.pairsList
164 self.dataOut.pairsList = self.dataIn.pairsList
165 self.dataOut.groupList = self.dataIn.pairsList
165 self.dataOut.groupList = self.dataIn.pairsList
166 self.dataOut.flagNoData = False
166 self.dataOut.flagNoData = False
167
167
168 if hasattr(self.dataIn, 'flagDataAsBlock'):
168 if hasattr(self.dataIn, 'flagDataAsBlock'):
169 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
169 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
170
170
171 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
171 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
172 self.dataOut.ChanDist = self.dataIn.ChanDist
172 self.dataOut.ChanDist = self.dataIn.ChanDist
173 else: self.dataOut.ChanDist = None
173 else: self.dataOut.ChanDist = None
174
174
175 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
175 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
176 # self.dataOut.VelRange = self.dataIn.VelRange
176 # self.dataOut.VelRange = self.dataIn.VelRange
177 #else: self.dataOut.VelRange = None
177 #else: self.dataOut.VelRange = None
178
178
179 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
179 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
180 self.dataOut.RadarConst = self.dataIn.RadarConst
180 self.dataOut.RadarConst = self.dataIn.RadarConst
181
181
182 if hasattr(self.dataIn, 'NPW'): #NPW
182 if hasattr(self.dataIn, 'NPW'): #NPW
183 self.dataOut.NPW = self.dataIn.NPW
183 self.dataOut.NPW = self.dataIn.NPW
184
184
185 if hasattr(self.dataIn, 'COFA'): #COFA
185 if hasattr(self.dataIn, 'COFA'): #COFA
186 self.dataOut.COFA = self.dataIn.COFA
186 self.dataOut.COFA = self.dataIn.COFA
187
187
188
188
189
189
190 #---------------------- Correlation Data ---------------------------
190 #---------------------- Correlation Data ---------------------------
191
191
192 if self.dataIn.type == "Correlation":
192 if self.dataIn.type == "Correlation":
193 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
193 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
194
194
195 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
195 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
196 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
196 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
197 self.dataOut.groupList = (acf_pairs, ccf_pairs)
197 self.dataOut.groupList = (acf_pairs, ccf_pairs)
198
198
199 self.dataOut.abscissaList = self.dataIn.lagRange
199 self.dataOut.abscissaList = self.dataIn.lagRange
200 self.dataOut.noise = self.dataIn.noise
200 self.dataOut.noise = self.dataIn.noise
201 self.dataOut.data_snr = self.dataIn.SNR
201 self.dataOut.data_snr = self.dataIn.SNR
202 self.dataOut.flagNoData = False
202 self.dataOut.flagNoData = False
203 self.dataOut.nAvg = self.dataIn.nAvg
203 self.dataOut.nAvg = self.dataIn.nAvg
204
204
205 #---------------------- Parameters Data ---------------------------
205 #---------------------- Parameters Data ---------------------------
206
206
207 if self.dataIn.type == "Parameters":
207 if self.dataIn.type == "Parameters":
208 self.dataOut.copy(self.dataIn)
208 self.dataOut.copy(self.dataIn)
209 self.dataOut.flagNoData = False
209 self.dataOut.flagNoData = False
210 #print("yo si entre")
210 #print("yo si entre")
211
211
212 return True
212 return True
213
213
214 self.__updateObjFromInput()
214 self.__updateObjFromInput()
215 #print("yo si entre2")
215 #print("yo si entre2")
216
216
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 #print("soy spectra ",self.dataOut.utctimeInit)
219 #print("soy spectra ",self.dataOut.utctimeInit)
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 # print ('Entering RemoveWideGC ... ')
253 # print ('Entering RemoveWideGC ... ')
254
254
255 self.spc = dataOut.data_pre[0].copy()
255 self.spc = dataOut.data_pre[0].copy()
256 self.spc_out = dataOut.data_pre[0].copy()
256 self.spc_out = dataOut.data_pre[0].copy()
257 self.Num_Chn = self.spc.shape[0]
257 self.Num_Chn = self.spc.shape[0]
258 self.Num_Hei = self.spc.shape[2]
258 self.Num_Hei = self.spc.shape[2]
259 VelRange = dataOut.spc_range[2][:-1]
259 VelRange = dataOut.spc_range[2][:-1]
260 dv = VelRange[1]-VelRange[0]
260 dv = VelRange[1]-VelRange[0]
261
261
262 # Find the velocities that corresponds to zero
262 # Find the velocities that corresponds to zero
263 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
263 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
264
264
265 # Removing novalid data from the spectra
265 # Removing novalid data from the spectra
266 for ich in range(self.Num_Chn) :
266 for ich in range(self.Num_Chn) :
267 for ir in range(self.Num_Hei) :
267 for ir in range(self.Num_Hei) :
268 # Estimate the noise at each range
268 # Estimate the noise at each range
269 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
269 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
270
270
271 # Removing the noise floor at each range
271 # Removing the noise floor at each range
272 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
272 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
273 self.spc[ich,novalid,ir] = HSn
273 self.spc[ich,novalid,ir] = HSn
274
274
275 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
275 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
276 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
276 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
277 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
277 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
278 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
278 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
279 continue
279 continue
280 junk3 = numpy.squeeze(numpy.diff(j1index))
280 junk3 = numpy.squeeze(numpy.diff(j1index))
281 junk4 = numpy.squeeze(numpy.diff(j2index))
281 junk4 = numpy.squeeze(numpy.diff(j2index))
282
282
283 valleyindex = j2index[numpy.where(junk4>1)]
283 valleyindex = j2index[numpy.where(junk4>1)]
284 peakindex = j1index[numpy.where(junk3>1)]
284 peakindex = j1index[numpy.where(junk3>1)]
285
285
286 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
286 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
287 if numpy.size(isvalid) == 0 :
287 if numpy.size(isvalid) == 0 :
288 continue
288 continue
289 if numpy.size(isvalid) >1 :
289 if numpy.size(isvalid) >1 :
290 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
290 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
291 isvalid = isvalid[vindex]
291 isvalid = isvalid[vindex]
292
292
293 # clutter peak
293 # clutter peak
294 gcpeak = peakindex[isvalid]
294 gcpeak = peakindex[isvalid]
295 vl = numpy.where(valleyindex < gcpeak)
295 vl = numpy.where(valleyindex < gcpeak)
296 if numpy.size(vl) == 0:
296 if numpy.size(vl) == 0:
297 continue
297 continue
298 gcvl = valleyindex[vl[0][-1]]
298 gcvl = valleyindex[vl[0][-1]]
299 vr = numpy.where(valleyindex > gcpeak)
299 vr = numpy.where(valleyindex > gcpeak)
300 if numpy.size(vr) == 0:
300 if numpy.size(vr) == 0:
301 continue
301 continue
302 gcvr = valleyindex[vr[0][0]]
302 gcvr = valleyindex[vr[0][0]]
303
303
304 # Removing the clutter
304 # Removing the clutter
305 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
305 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
306 gcindex = gc_values[gcvl+1:gcvr-1]
306 gcindex = gc_values[gcvl+1:gcvr-1]
307 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
307 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
308
308
309 dataOut.data_pre[0] = self.spc_out
309 dataOut.data_pre[0] = self.spc_out
310 #print ('Leaving RemoveWideGC ... ')
310 #print ('Leaving RemoveWideGC ... ')
311 return dataOut
311 return dataOut
312
312
313 class SpectralFilters(Operation):
313 class SpectralFilters(Operation):
314 ''' This class allows to replace the novalid values with noise for each channel
314 ''' This class allows to replace the novalid values with noise for each channel
315 This applies to CLAIRE RADAR
315 This applies to CLAIRE RADAR
316
316
317 PositiveLimit : RightLimit of novalid data
317 PositiveLimit : RightLimit of novalid data
318 NegativeLimit : LeftLimit of novalid data
318 NegativeLimit : LeftLimit of novalid data
319
319
320 Input:
320 Input:
321
321
322 self.dataOut.data_pre : SPC and CSPC
322 self.dataOut.data_pre : SPC and CSPC
323 self.dataOut.spc_range : To select wind and rainfall velocities
323 self.dataOut.spc_range : To select wind and rainfall velocities
324
324
325 Affected:
325 Affected:
326
326
327 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
327 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
328
328
329 Written by D. ScipiΓ³n 29.01.2021
329 Written by D. ScipiΓ³n 29.01.2021
330 '''
330 '''
331 def __init__(self):
331 def __init__(self):
332 Operation.__init__(self)
332 Operation.__init__(self)
333 self.i = 0
333 self.i = 0
334
334
335 def run(self, dataOut, ):
335 def run(self, dataOut, ):
336
336
337 self.spc = dataOut.data_pre[0].copy()
337 self.spc = dataOut.data_pre[0].copy()
338 self.Num_Chn = self.spc.shape[0]
338 self.Num_Chn = self.spc.shape[0]
339 VelRange = dataOut.spc_range[2]
339 VelRange = dataOut.spc_range[2]
340
340
341 # novalid corresponds to data within the Negative and PositiveLimit
341 # novalid corresponds to data within the Negative and PositiveLimit
342
342
343
343
344 # Removing novalid data from the spectra
344 # Removing novalid data from the spectra
345 for i in range(self.Num_Chn):
345 for i in range(self.Num_Chn):
346 self.spc[i,novalid,:] = dataOut.noise[i]
346 self.spc[i,novalid,:] = dataOut.noise[i]
347 dataOut.data_pre[0] = self.spc
347 dataOut.data_pre[0] = self.spc
348 return dataOut
348 return dataOut
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
368
369 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
369 # def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
370 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
370 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
371 """This routine will find a couple of generalized Gaussians to a power spectrum
371 """This routine will find a couple of generalized Gaussians to a power spectrum
372 methods: generalized, squared
372 methods: generalized, squared
373 input: spc
373 input: spc
374 output:
374 output:
375 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
375 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
376 """
376 """
377 print ('Entering ',method,' double Gaussian fit')
377 print ('Entering ',method,' double Gaussian fit')
378 self.spc = dataOut.data_pre[0].copy()
378 self.spc = dataOut.data_pre[0].copy()
379 self.Num_Hei = self.spc.shape[2]
379 self.Num_Hei = self.spc.shape[2]
380 self.Num_Bin = self.spc.shape[1]
380 self.Num_Bin = self.spc.shape[1]
381 self.Num_Chn = self.spc.shape[0]
381 self.Num_Chn = self.spc.shape[0]
382
382
383 start_time = time.time()
383 start_time = time.time()
384
384
385 pool = Pool(processes=self.Num_Chn)
385 pool = Pool(processes=self.Num_Chn)
386 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
386 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
387 objs = [self for __ in range(self.Num_Chn)]
387 objs = [self for __ in range(self.Num_Chn)]
388 attrs = list(zip(objs, args))
388 attrs = list(zip(objs, args))
389 DGauFitParam = pool.map(target, attrs)
389 DGauFitParam = pool.map(target, attrs)
390 # Parameters:
390 # Parameters:
391 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
391 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
392 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
392 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
393
393
394 # Double Gaussian Curves
394 # Double Gaussian Curves
395 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
395 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
396 gau0[:] = numpy.NaN
396 gau0[:] = numpy.NaN
397 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
397 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
398 gau1[:] = numpy.NaN
398 gau1[:] = numpy.NaN
399 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
399 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
400 for iCh in range(self.Num_Chn):
400 for iCh in range(self.Num_Chn):
401 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
401 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
402 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
402 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
403 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
403 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
404 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
404 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
405 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
405 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
406 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
406 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
407 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
407 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
408 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
408 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
409 if method == 'genealized':
409 if method == 'genealized':
410 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
410 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
411 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
411 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
412 elif method == 'squared':
412 elif method == 'squared':
413 p0 = 2.
413 p0 = 2.
414 p1 = 2.
414 p1 = 2.
415 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
415 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
416 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
416 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
417 dataOut.GaussFit0 = gau0
417 dataOut.GaussFit0 = gau0
418 dataOut.GaussFit1 = gau1
418 dataOut.GaussFit1 = gau1
419
419
420 print('Leaving ',method ,' double Gaussian fit')
420 print('Leaving ',method ,' double Gaussian fit')
421 return dataOut
421 return dataOut
422
422
423 def FitGau(self, X):
423 def FitGau(self, X):
424 # print('Entering FitGau')
424 # print('Entering FitGau')
425 # Assigning the variables
425 # Assigning the variables
426 Vrange, ch, wnoise, num_intg, SNRlimit = X
426 Vrange, ch, wnoise, num_intg, SNRlimit = X
427 # Noise Limits
427 # Noise Limits
428 noisebl = wnoise * 0.9
428 noisebl = wnoise * 0.9
429 noisebh = wnoise * 1.1
429 noisebh = wnoise * 1.1
430 # Radar Velocity
430 # Radar Velocity
431 Va = max(Vrange)
431 Va = max(Vrange)
432 deltav = Vrange[1] - Vrange[0]
432 deltav = Vrange[1] - Vrange[0]
433 x = numpy.arange(self.Num_Bin)
433 x = numpy.arange(self.Num_Bin)
434
434
435 # print ('stop 0')
435 # print ('stop 0')
436
436
437 # 5 parameters, 2 Gaussians
437 # 5 parameters, 2 Gaussians
438 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
438 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
439 DGauFitParam[:] = numpy.NaN
439 DGauFitParam[:] = numpy.NaN
440
440
441 # SPCparam = []
441 # SPCparam = []
442 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
442 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
443 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
443 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
444 # SPC_ch1[:] = 0 #numpy.NaN
444 # SPC_ch1[:] = 0 #numpy.NaN
445 # SPC_ch2[:] = 0 #numpy.NaN
445 # SPC_ch2[:] = 0 #numpy.NaN
446 # print ('stop 1')
446 # print ('stop 1')
447 for ht in range(self.Num_Hei):
447 for ht in range(self.Num_Hei):
448 # print (ht)
448 # print (ht)
449 # print ('stop 2')
449 # print ('stop 2')
450 # Spectra at each range
450 # Spectra at each range
451 spc = numpy.asarray(self.spc)[ch,:,ht]
451 spc = numpy.asarray(self.spc)[ch,:,ht]
452 snr = ( spc.mean() - wnoise ) / wnoise
452 snr = ( spc.mean() - wnoise ) / wnoise
453 snrdB = 10.*numpy.log10(snr)
453 snrdB = 10.*numpy.log10(snr)
454
454
455 #print ('stop 3')
455 #print ('stop 3')
456 if snrdB < SNRlimit :
456 if snrdB < SNRlimit :
457 # snr = numpy.NaN
457 # snr = numpy.NaN
458 # SPC_ch1[:,ht] = 0#numpy.NaN
458 # SPC_ch1[:,ht] = 0#numpy.NaN
459 # SPC_ch1[:,ht] = 0#numpy.NaN
459 # SPC_ch1[:,ht] = 0#numpy.NaN
460 # SPCparam = (SPC_ch1,SPC_ch2)
460 # SPCparam = (SPC_ch1,SPC_ch2)
461 # print ('SNR less than SNRth')
461 # print ('SNR less than SNRth')
462 continue
462 continue
463 # wnoise = hildebrand_sekhon(spc,num_intg)
463 # wnoise = hildebrand_sekhon(spc,num_intg)
464 # print ('stop 2.01')
464 # print ('stop 2.01')
465 #############################################
465 #############################################
466 # normalizing spc and noise
466 # normalizing spc and noise
467 # This part differs from gg1
467 # This part differs from gg1
468 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
468 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
469 #spc = spc / spc_norm_max
469 #spc = spc / spc_norm_max
470 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
470 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
471 #############################################
471 #############################################
472
472
473 # print ('stop 2.1')
473 # print ('stop 2.1')
474 fatspectra=1.0
474 fatspectra=1.0
475 # noise per channel.... we might want to use the noise at each range
475 # noise per channel.... we might want to use the noise at each range
476
476
477 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
477 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
478 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
478 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
479 #if wnoise>1.1*pnoise: # to be tested later
479 #if wnoise>1.1*pnoise: # to be tested later
480 # wnoise=pnoise
480 # wnoise=pnoise
481 # noisebl = wnoise*0.9
481 # noisebl = wnoise*0.9
482 # noisebh = wnoise*1.1
482 # noisebh = wnoise*1.1
483 spc = spc - wnoise # signal
483 spc = spc - wnoise # signal
484
484
485 # print ('stop 2.2')
485 # print ('stop 2.2')
486 minx = numpy.argmin(spc)
486 minx = numpy.argmin(spc)
487 #spcs=spc.copy()
487 #spcs=spc.copy()
488 spcs = numpy.roll(spc,-minx)
488 spcs = numpy.roll(spc,-minx)
489 cum = numpy.cumsum(spcs)
489 cum = numpy.cumsum(spcs)
490 # tot_noise = wnoise * self.Num_Bin #64;
490 # tot_noise = wnoise * self.Num_Bin #64;
491
491
492 # print ('stop 2.3')
492 # print ('stop 2.3')
493 # snr = sum(spcs) / tot_noise
493 # snr = sum(spcs) / tot_noise
494 # snrdB = 10.*numpy.log10(snr)
494 # snrdB = 10.*numpy.log10(snr)
495 #print ('stop 3')
495 #print ('stop 3')
496 # if snrdB < SNRlimit :
496 # if snrdB < SNRlimit :
497 # snr = numpy.NaN
497 # snr = numpy.NaN
498 # SPC_ch1[:,ht] = 0#numpy.NaN
498 # SPC_ch1[:,ht] = 0#numpy.NaN
499 # SPC_ch1[:,ht] = 0#numpy.NaN
499 # SPC_ch1[:,ht] = 0#numpy.NaN
500 # SPCparam = (SPC_ch1,SPC_ch2)
500 # SPCparam = (SPC_ch1,SPC_ch2)
501 # print ('SNR less than SNRth')
501 # print ('SNR less than SNRth')
502 # continue
502 # continue
503
503
504
504
505 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
505 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
506 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
506 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
507 # print ('stop 4')
507 # print ('stop 4')
508 cummax = max(cum)
508 cummax = max(cum)
509 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
509 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
510 cumlo = cummax * epsi
510 cumlo = cummax * epsi
511 cumhi = cummax * (1-epsi)
511 cumhi = cummax * (1-epsi)
512 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
512 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
513
513
514 # print ('stop 5')
514 # print ('stop 5')
515 if len(powerindex) < 1:# case for powerindex 0
515 if len(powerindex) < 1:# case for powerindex 0
516 # print ('powerindex < 1')
516 # print ('powerindex < 1')
517 continue
517 continue
518 powerlo = powerindex[0]
518 powerlo = powerindex[0]
519 powerhi = powerindex[-1]
519 powerhi = powerindex[-1]
520 powerwidth = powerhi-powerlo
520 powerwidth = powerhi-powerlo
521 if powerwidth <= 1:
521 if powerwidth <= 1:
522 # print('powerwidth <= 1')
522 # print('powerwidth <= 1')
523 continue
523 continue
524
524
525 # print ('stop 6')
525 # print ('stop 6')
526 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
526 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
527 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
527 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
528 midpeak = (firstpeak + secondpeak)/2.
528 midpeak = (firstpeak + secondpeak)/2.
529 firstamp = spcs[int(firstpeak)]
529 firstamp = spcs[int(firstpeak)]
530 secondamp = spcs[int(secondpeak)]
530 secondamp = spcs[int(secondpeak)]
531 midamp = spcs[int(midpeak)]
531 midamp = spcs[int(midpeak)]
532
532
533 y_data = spc + wnoise
533 y_data = spc + wnoise
534
534
535 ''' single Gaussian '''
535 ''' single Gaussian '''
536 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
536 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
537 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
537 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
538 power0 = 2.
538 power0 = 2.
539 amplitude0 = midamp
539 amplitude0 = midamp
540 state0 = [shift0,width0,amplitude0,power0,wnoise]
540 state0 = [shift0,width0,amplitude0,power0,wnoise]
541 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
541 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
542 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
542 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
543 # print ('stop 7.1')
543 # print ('stop 7.1')
544 # print (bnds)
544 # print (bnds)
545
545
546 chiSq1=lsq1[1]
546 chiSq1=lsq1[1]
547
547
548 # print ('stop 8')
548 # print ('stop 8')
549 if fatspectra<1.0 and powerwidth<4:
549 if fatspectra<1.0 and powerwidth<4:
550 choice=0
550 choice=0
551 Amplitude0=lsq1[0][2]
551 Amplitude0=lsq1[0][2]
552 shift0=lsq1[0][0]
552 shift0=lsq1[0][0]
553 width0=lsq1[0][1]
553 width0=lsq1[0][1]
554 p0=lsq1[0][3]
554 p0=lsq1[0][3]
555 Amplitude1=0.
555 Amplitude1=0.
556 shift1=0.
556 shift1=0.
557 width1=0.
557 width1=0.
558 p1=0.
558 p1=0.
559 noise=lsq1[0][4]
559 noise=lsq1[0][4]
560 #return (numpy.array([shift0,width0,Amplitude0,p0]),
560 #return (numpy.array([shift0,width0,Amplitude0,p0]),
561 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
561 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
562
562
563 # print ('stop 9')
563 # print ('stop 9')
564 ''' two Gaussians '''
564 ''' two Gaussians '''
565 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
565 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
566 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
566 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
567 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
567 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
568 width0 = powerwidth/6.
568 width0 = powerwidth/6.
569 width1 = width0
569 width1 = width0
570 power0 = 2.
570 power0 = 2.
571 power1 = power0
571 power1 = power0
572 amplitude0 = firstamp
572 amplitude0 = firstamp
573 amplitude1 = secondamp
573 amplitude1 = secondamp
574 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
574 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
575 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
575 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
576 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))
576 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))
577 #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))
577 #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))
578
578
579 # print ('stop 10')
579 # print ('stop 10')
580 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
580 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
581
581
582 # print ('stop 11')
582 # print ('stop 11')
583 chiSq2 = lsq2[1]
583 chiSq2 = lsq2[1]
584
584
585 # print ('stop 12')
585 # print ('stop 12')
586
586
587 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)
587 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)
588
588
589 # print ('stop 13')
589 # print ('stop 13')
590 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
590 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
591 if oneG:
591 if oneG:
592 choice = 0
592 choice = 0
593 else:
593 else:
594 w1 = lsq2[0][1]; w2 = lsq2[0][5]
594 w1 = lsq2[0][1]; w2 = lsq2[0][5]
595 a1 = lsq2[0][2]; a2 = lsq2[0][6]
595 a1 = lsq2[0][2]; a2 = lsq2[0][6]
596 p1 = lsq2[0][3]; p2 = lsq2[0][7]
596 p1 = lsq2[0][3]; p2 = lsq2[0][7]
597 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
597 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
598 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
598 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
599 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
599 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
600
600
601 if gp1>gp2:
601 if gp1>gp2:
602 if a1>0.7*a2:
602 if a1>0.7*a2:
603 choice = 1
603 choice = 1
604 else:
604 else:
605 choice = 2
605 choice = 2
606 elif gp2>gp1:
606 elif gp2>gp1:
607 if a2>0.7*a1:
607 if a2>0.7*a1:
608 choice = 2
608 choice = 2
609 else:
609 else:
610 choice = 1
610 choice = 1
611 else:
611 else:
612 choice = numpy.argmax([a1,a2])+1
612 choice = numpy.argmax([a1,a2])+1
613 #else:
613 #else:
614 #choice=argmin([std2a,std2b])+1
614 #choice=argmin([std2a,std2b])+1
615
615
616 else: # with low SNR go to the most energetic peak
616 else: # with low SNR go to the most energetic peak
617 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
617 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
618
618
619 # print ('stop 14')
619 # print ('stop 14')
620 shift0 = lsq2[0][0]
620 shift0 = lsq2[0][0]
621 vel0 = Vrange[0] + shift0 * deltav
621 vel0 = Vrange[0] + shift0 * deltav
622 shift1 = lsq2[0][4]
622 shift1 = lsq2[0][4]
623 # vel1=Vrange[0] + shift1 * deltav
623 # vel1=Vrange[0] + shift1 * deltav
624
624
625 # max_vel = 1.0
625 # max_vel = 1.0
626 # Va = max(Vrange)
626 # Va = max(Vrange)
627 # deltav = Vrange[1]-Vrange[0]
627 # deltav = Vrange[1]-Vrange[0]
628 # print ('stop 15')
628 # print ('stop 15')
629 #first peak will be 0, second peak will be 1
629 #first peak will be 0, second peak will be 1
630 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
630 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
631 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
631 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
632 shift0 = lsq2[0][0]
632 shift0 = lsq2[0][0]
633 width0 = lsq2[0][1]
633 width0 = lsq2[0][1]
634 Amplitude0 = lsq2[0][2]
634 Amplitude0 = lsq2[0][2]
635 p0 = lsq2[0][3]
635 p0 = lsq2[0][3]
636
636
637 shift1 = lsq2[0][4]
637 shift1 = lsq2[0][4]
638 width1 = lsq2[0][5]
638 width1 = lsq2[0][5]
639 Amplitude1 = lsq2[0][6]
639 Amplitude1 = lsq2[0][6]
640 p1 = lsq2[0][7]
640 p1 = lsq2[0][7]
641 noise = lsq2[0][8]
641 noise = lsq2[0][8]
642 else:
642 else:
643 shift1 = lsq2[0][0]
643 shift1 = lsq2[0][0]
644 width1 = lsq2[0][1]
644 width1 = lsq2[0][1]
645 Amplitude1 = lsq2[0][2]
645 Amplitude1 = lsq2[0][2]
646 p1 = lsq2[0][3]
646 p1 = lsq2[0][3]
647
647
648 shift0 = lsq2[0][4]
648 shift0 = lsq2[0][4]
649 width0 = lsq2[0][5]
649 width0 = lsq2[0][5]
650 Amplitude0 = lsq2[0][6]
650 Amplitude0 = lsq2[0][6]
651 p0 = lsq2[0][7]
651 p0 = lsq2[0][7]
652 noise = lsq2[0][8]
652 noise = lsq2[0][8]
653
653
654 if Amplitude0<0.05: # in case the peak is noise
654 if Amplitude0<0.05: # in case the peak is noise
655 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
655 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
656 if Amplitude1<0.05:
656 if Amplitude1<0.05:
657 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
657 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
658
658
659 # print ('stop 16 ')
659 # print ('stop 16 ')
660 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
660 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
661 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
661 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
662 # SPCparam = (SPC_ch1,SPC_ch2)
662 # SPCparam = (SPC_ch1,SPC_ch2)
663
663
664 DGauFitParam[0,ht,0] = noise
664 DGauFitParam[0,ht,0] = noise
665 DGauFitParam[0,ht,1] = noise
665 DGauFitParam[0,ht,1] = noise
666 DGauFitParam[1,ht,0] = Amplitude0
666 DGauFitParam[1,ht,0] = Amplitude0
667 DGauFitParam[1,ht,1] = Amplitude1
667 DGauFitParam[1,ht,1] = Amplitude1
668 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
668 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
669 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
669 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
670 DGauFitParam[3,ht,0] = width0 * deltav
670 DGauFitParam[3,ht,0] = width0 * deltav
671 DGauFitParam[3,ht,1] = width1 * deltav
671 DGauFitParam[3,ht,1] = width1 * deltav
672 DGauFitParam[4,ht,0] = p0
672 DGauFitParam[4,ht,0] = p0
673 DGauFitParam[4,ht,1] = p1
673 DGauFitParam[4,ht,1] = p1
674
674
675 # print (DGauFitParam.shape)
675 # print (DGauFitParam.shape)
676 # print ('Leaving FitGau')
676 # print ('Leaving FitGau')
677 return DGauFitParam
677 return DGauFitParam
678 # return SPCparam
678 # return SPCparam
679 # return GauSPC
679 # return GauSPC
680
680
681 def y_model1(self,x,state):
681 def y_model1(self,x,state):
682 shift0, width0, amplitude0, power0, noise = state
682 shift0, width0, amplitude0, power0, 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 return model0 + model0u + model0d + noise
686 return model0 + model0u + model0d + noise
687
687
688 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
688 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
689 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
689 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
690 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
690 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
691 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
691 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
692 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
692 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
693
693
694 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
694 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
695 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
695 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
696 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
696 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
697 return model0 + model0u + model0d + model1 + model1u + model1d + noise
697 return model0 + model0u + model0d + model1 + model1u + model1d + noise
698
698
699 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.
699 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.
700
700
701 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
701 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
702
702
703 def misfit2(self,state,y_data,x,num_intg):
703 def misfit2(self,state,y_data,x,num_intg):
704 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
704 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
705
705
706
706
707
707
708 class PrecipitationProc(Operation):
708 class PrecipitationProc(Operation):
709
709
710 '''
710 '''
711 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
711 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
712
712
713 Input:
713 Input:
714 self.dataOut.data_pre : SelfSpectra
714 self.dataOut.data_pre : SelfSpectra
715
715
716 Output:
716 Output:
717
717
718 self.dataOut.data_output : Reflectivity factor, rainfall Rate
718 self.dataOut.data_output : Reflectivity factor, rainfall Rate
719
719
720
720
721 Parameters affected:
721 Parameters affected:
722 '''
722 '''
723
723
724 def __init__(self):
724 def __init__(self):
725 Operation.__init__(self)
725 Operation.__init__(self)
726 self.i=0
726 self.i=0
727
727
728 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
728 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
729 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
729 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
730
730
731 # print ('Entering PrecepitationProc ... ')
731 # print ('Entering PrecepitationProc ... ')
732
732
733 if radar == "MIRA35C" :
733 if radar == "MIRA35C" :
734
734
735 self.spc = dataOut.data_pre[0].copy()
735 self.spc = dataOut.data_pre[0].copy()
736 self.Num_Hei = self.spc.shape[2]
736 self.Num_Hei = self.spc.shape[2]
737 self.Num_Bin = self.spc.shape[1]
737 self.Num_Bin = self.spc.shape[1]
738 self.Num_Chn = self.spc.shape[0]
738 self.Num_Chn = self.spc.shape[0]
739 Ze = self.dBZeMODE2(dataOut)
739 Ze = self.dBZeMODE2(dataOut)
740
740
741 else:
741 else:
742
742
743 self.spc = dataOut.data_pre[0].copy()
743 self.spc = dataOut.data_pre[0].copy()
744
744
745 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
745 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
746 self.spc[:,:,0:7]= numpy.NaN
746 self.spc[:,:,0:7]= numpy.NaN
747
747
748 self.Num_Hei = self.spc.shape[2]
748 self.Num_Hei = self.spc.shape[2]
749 self.Num_Bin = self.spc.shape[1]
749 self.Num_Bin = self.spc.shape[1]
750 self.Num_Chn = self.spc.shape[0]
750 self.Num_Chn = self.spc.shape[0]
751
751
752 VelRange = dataOut.spc_range[2]
752 VelRange = dataOut.spc_range[2]
753
753
754 ''' Se obtiene la constante del RADAR '''
754 ''' Se obtiene la constante del RADAR '''
755
755
756 self.Pt = Pt
756 self.Pt = Pt
757 self.Gt = Gt
757 self.Gt = Gt
758 self.Gr = Gr
758 self.Gr = Gr
759 self.Lambda = Lambda
759 self.Lambda = Lambda
760 self.aL = aL
760 self.aL = aL
761 self.tauW = tauW
761 self.tauW = tauW
762 self.ThetaT = ThetaT
762 self.ThetaT = ThetaT
763 self.ThetaR = ThetaR
763 self.ThetaR = ThetaR
764 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
764 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
765 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
765 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
766 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
766 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
767
767
768 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
768 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
769 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
769 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
770 RadarConstant = 10e-26 * Numerator / Denominator #
770 RadarConstant = 10e-26 * Numerator / Denominator #
771 ExpConstant = 10**(40/10) #Constante Experimental
771 ExpConstant = 10**(40/10) #Constante Experimental
772
772
773 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
773 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
774 for i in range(self.Num_Chn):
774 for i in range(self.Num_Chn):
775 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
775 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
776 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
776 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
777
777
778 SPCmean = numpy.mean(SignalPower, 0)
778 SPCmean = numpy.mean(SignalPower, 0)
779 Pr = SPCmean[:,:]/dataOut.normFactor
779 Pr = SPCmean[:,:]/dataOut.normFactor
780
780
781 # Declaring auxiliary variables
781 # Declaring auxiliary variables
782 Range = dataOut.heightList*1000. #Range in m
782 Range = dataOut.heightList*1000. #Range in m
783 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
783 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
784 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
784 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
785 zMtrx = rMtrx+Altitude
785 zMtrx = rMtrx+Altitude
786 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
786 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
787 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
787 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
788
788
789 # height dependence to air density Foote and Du Toit (1969)
789 # height dependence to air density Foote and Du Toit (1969)
790 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
790 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
791 VMtrx = VelMtrx / delv_z #Normalized velocity
791 VMtrx = VelMtrx / delv_z #Normalized velocity
792 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
792 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
793 # Diameter is related to the fall speed of falling drops
793 # Diameter is related to the fall speed of falling drops
794 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
794 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
795 # Only valid for D>= 0.16 mm
795 # Only valid for D>= 0.16 mm
796 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
796 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
797
797
798 #Calculate Radar Reflectivity ETAn
798 #Calculate Radar Reflectivity ETAn
799 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
799 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
800 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
800 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
801 # Radar Cross Section
801 # Radar Cross Section
802 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
802 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
803 # Drop Size Distribution
803 # Drop Size Distribution
804 DSD = ETAn / sigmaD
804 DSD = ETAn / sigmaD
805 # Equivalente Reflectivy
805 # Equivalente Reflectivy
806 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
806 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
807 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
807 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
808 # RainFall Rate
808 # RainFall Rate
809 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
809 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
810
810
811 # Censoring the data
811 # Censoring the data
812 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
812 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
813 SNRth = 10**(SNRdBlimit/10) #-30dB
813 SNRth = 10**(SNRdBlimit/10) #-30dB
814 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
814 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
815 W = numpy.nanmean(dataOut.data_dop,0)
815 W = numpy.nanmean(dataOut.data_dop,0)
816 W[novalid] = numpy.NaN
816 W[novalid] = numpy.NaN
817 Ze_org[novalid] = numpy.NaN
817 Ze_org[novalid] = numpy.NaN
818 RR[novalid] = numpy.NaN
818 RR[novalid] = numpy.NaN
819
819
820 dataOut.data_output = RR[8]
820 dataOut.data_output = RR[8]
821 dataOut.data_param = numpy.ones([3,self.Num_Hei])
821 dataOut.data_param = numpy.ones([3,self.Num_Hei])
822 dataOut.channelList = [0,1,2]
822 dataOut.channelList = [0,1,2]
823
823
824 dataOut.data_param[0]=10*numpy.log10(Ze_org)
824 dataOut.data_param[0]=10*numpy.log10(Ze_org)
825 dataOut.data_param[1]=-W
825 dataOut.data_param[1]=-W
826 dataOut.data_param[2]=RR
826 dataOut.data_param[2]=RR
827
827
828 # print ('Leaving PrecepitationProc ... ')
828 # print ('Leaving PrecepitationProc ... ')
829 return dataOut
829 return dataOut
830
830
831 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
831 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
832
832
833 NPW = dataOut.NPW
833 NPW = dataOut.NPW
834 COFA = dataOut.COFA
834 COFA = dataOut.COFA
835
835
836 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
836 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
837 RadarConst = dataOut.RadarConst
837 RadarConst = dataOut.RadarConst
838 #frequency = 34.85*10**9
838 #frequency = 34.85*10**9
839
839
840 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
840 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
841 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
841 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
842
842
843 ETA = numpy.sum(SNR,1)
843 ETA = numpy.sum(SNR,1)
844
844
845 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
845 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
846
846
847 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
847 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
848
848
849 for r in range(self.Num_Hei):
849 for r in range(self.Num_Hei):
850
850
851 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
851 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
852 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
852 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
853
853
854 return Ze
854 return Ze
855
855
856 # def GetRadarConstant(self):
856 # def GetRadarConstant(self):
857 #
857 #
858 # """
858 # """
859 # Constants:
859 # Constants:
860 #
860 #
861 # Pt: Transmission Power dB 5kW 5000
861 # Pt: Transmission Power dB 5kW 5000
862 # Gt: Transmission Gain dB 24.7 dB 295.1209
862 # Gt: Transmission Gain dB 24.7 dB 295.1209
863 # Gr: Reception Gain dB 18.5 dB 70.7945
863 # Gr: Reception Gain dB 18.5 dB 70.7945
864 # Lambda: Wavelenght m 0.6741 m 0.6741
864 # Lambda: Wavelenght m 0.6741 m 0.6741
865 # aL: Attenuation loses dB 4dB 2.5118
865 # aL: Attenuation loses dB 4dB 2.5118
866 # tauW: Width of transmission pulse s 4us 4e-6
866 # tauW: Width of transmission pulse s 4us 4e-6
867 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
867 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
868 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
868 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
869 #
869 #
870 # """
870 # """
871 #
871 #
872 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
872 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
873 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
873 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
874 # RadarConstant = Numerator / Denominator
874 # RadarConstant = Numerator / Denominator
875 #
875 #
876 # return RadarConstant
876 # return RadarConstant
877
877
878
878
879
879
880 class FullSpectralAnalysis(Operation):
880 class FullSpectralAnalysis(Operation):
881
881
882 """
882 """
883 Function that implements Full Spectral Analysis technique.
883 Function that implements Full Spectral Analysis technique.
884
884
885 Input:
885 Input:
886 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
886 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
887 self.dataOut.groupList : Pairlist of channels
887 self.dataOut.groupList : Pairlist of channels
888 self.dataOut.ChanDist : Physical distance between receivers
888 self.dataOut.ChanDist : Physical distance between receivers
889
889
890
890
891 Output:
891 Output:
892
892
893 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
893 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
894
894
895
895
896 Parameters affected: Winds, height range, SNR
896 Parameters affected: Winds, height range, SNR
897
897
898 """
898 """
899 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
899 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
900 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
900 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
901
901
902 spc = dataOut.data_pre[0].copy()
902 spc = dataOut.data_pre[0].copy()
903 cspc = dataOut.data_pre[1]
903 cspc = dataOut.data_pre[1]
904 nHeights = spc.shape[2]
904 nHeights = spc.shape[2]
905
905
906 # first_height = 0.75 #km (ref: data header 20170822)
906 # first_height = 0.75 #km (ref: data header 20170822)
907 # resolution_height = 0.075 #km
907 # resolution_height = 0.075 #km
908 '''
908 '''
909 finding height range. check this when radar parameters are changed!
909 finding height range. check this when radar parameters are changed!
910 '''
910 '''
911 if maxheight is not None:
911 if maxheight is not None:
912 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
912 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
913 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
913 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
914 else:
914 else:
915 range_max = nHeights
915 range_max = nHeights
916 if minheight is not None:
916 if minheight is not None:
917 # range_min = int((minheight - first_height) / resolution_height) # theoretical
917 # range_min = int((minheight - first_height) / resolution_height) # theoretical
918 range_min = int(13.26 * minheight - 5) # empirical, works better
918 range_min = int(13.26 * minheight - 5) # empirical, works better
919 if range_min < 0:
919 if range_min < 0:
920 range_min = 0
920 range_min = 0
921 else:
921 else:
922 range_min = 0
922 range_min = 0
923
923
924 pairsList = dataOut.groupList
924 pairsList = dataOut.groupList
925 if dataOut.ChanDist is not None :
925 if dataOut.ChanDist is not None :
926 ChanDist = dataOut.ChanDist
926 ChanDist = dataOut.ChanDist
927 else:
927 else:
928 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
928 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
929
929
930 # 4 variables: zonal, meridional, vertical, and average SNR
930 # 4 variables: zonal, meridional, vertical, and average SNR
931 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
931 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
932 velocityX = numpy.zeros([nHeights]) * numpy.NaN
932 velocityX = numpy.zeros([nHeights]) * numpy.NaN
933 velocityY = numpy.zeros([nHeights]) * numpy.NaN
933 velocityY = numpy.zeros([nHeights]) * numpy.NaN
934 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
934 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
935
935
936 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
936 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
937
937
938 '''***********************************************WIND ESTIMATION**************************************'''
938 '''***********************************************WIND ESTIMATION**************************************'''
939 for Height in range(nHeights):
939 for Height in range(nHeights):
940
940
941 if Height >= range_min and Height < range_max:
941 if Height >= range_min and Height < range_max:
942 # error_code will be useful in future analysis
942 # error_code will be useful in future analysis
943 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
943 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
944 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
944 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
945
945
946 if abs(Vzon) < 100. and abs(Vmer) < 100.:
946 if abs(Vzon) < 100. and abs(Vmer) < 100.:
947 velocityX[Height] = Vzon
947 velocityX[Height] = Vzon
948 velocityY[Height] = -Vmer
948 velocityY[Height] = -Vmer
949 velocityZ[Height] = Vver
949 velocityZ[Height] = Vver
950
950
951 # Censoring data with SNR threshold
951 # Censoring data with SNR threshold
952 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
952 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
953
953
954 data_param[0] = velocityX
954 data_param[0] = velocityX
955 data_param[1] = velocityY
955 data_param[1] = velocityY
956 data_param[2] = velocityZ
956 data_param[2] = velocityZ
957 data_param[3] = dbSNR
957 data_param[3] = dbSNR
958 dataOut.data_param = data_param
958 dataOut.data_param = data_param
959 return dataOut
959 return dataOut
960
960
961 def moving_average(self,x, N=2):
961 def moving_average(self,x, N=2):
962 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
962 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
963 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
963 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
964
964
965 def gaus(self,xSamples,Amp,Mu,Sigma):
965 def gaus(self,xSamples,Amp,Mu,Sigma):
966 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
966 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
967
967
968 def Moments(self, ySamples, xSamples):
968 def Moments(self, ySamples, xSamples):
969 Power = numpy.nanmean(ySamples) # Power, 0th Moment
969 Power = numpy.nanmean(ySamples) # Power, 0th Moment
970 yNorm = ySamples / numpy.nansum(ySamples)
970 yNorm = ySamples / numpy.nansum(ySamples)
971 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
971 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
972 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
972 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
973 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
973 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
974 return numpy.array([Power,RadVel,StdDev])
974 return numpy.array([Power,RadVel,StdDev])
975
975
976 def StopWindEstimation(self, error_code):
976 def StopWindEstimation(self, error_code):
977 Vzon = numpy.NaN
977 Vzon = numpy.NaN
978 Vmer = numpy.NaN
978 Vmer = numpy.NaN
979 Vver = numpy.NaN
979 Vver = numpy.NaN
980 return Vzon, Vmer, Vver, error_code
980 return Vzon, Vmer, Vver, error_code
981
981
982 def AntiAliasing(self, interval, maxstep):
982 def AntiAliasing(self, interval, maxstep):
983 """
983 """
984 function to prevent errors from aliased values when computing phaseslope
984 function to prevent errors from aliased values when computing phaseslope
985 """
985 """
986 antialiased = numpy.zeros(len(interval))
986 antialiased = numpy.zeros(len(interval))
987 copyinterval = interval.copy()
987 copyinterval = interval.copy()
988
988
989 antialiased[0] = copyinterval[0]
989 antialiased[0] = copyinterval[0]
990
990
991 for i in range(1,len(antialiased)):
991 for i in range(1,len(antialiased)):
992 step = interval[i] - interval[i-1]
992 step = interval[i] - interval[i-1]
993 if step > maxstep:
993 if step > maxstep:
994 copyinterval -= 2*numpy.pi
994 copyinterval -= 2*numpy.pi
995 antialiased[i] = copyinterval[i]
995 antialiased[i] = copyinterval[i]
996 elif step < maxstep*(-1):
996 elif step < maxstep*(-1):
997 copyinterval += 2*numpy.pi
997 copyinterval += 2*numpy.pi
998 antialiased[i] = copyinterval[i]
998 antialiased[i] = copyinterval[i]
999 else:
999 else:
1000 antialiased[i] = copyinterval[i].copy()
1000 antialiased[i] = copyinterval[i].copy()
1001
1001
1002 return antialiased
1002 return antialiased
1003
1003
1004 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1004 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1005 """
1005 """
1006 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1006 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1007 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1007 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1008
1008
1009 Input:
1009 Input:
1010 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1010 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1011 pairsList : Pairlist of channels
1011 pairsList : Pairlist of channels
1012 ChanDist : array of xi_ij and eta_ij
1012 ChanDist : array of xi_ij and eta_ij
1013 Height : height at which data is processed
1013 Height : height at which data is processed
1014 noise : noise in [channels] format for specific height
1014 noise : noise in [channels] format for specific height
1015 Abbsisarange : range of the frequencies or velocities
1015 Abbsisarange : range of the frequencies or velocities
1016 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1016 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1017
1017
1018 Output:
1018 Output:
1019 Vzon, Vmer, Vver : wind velocities
1019 Vzon, Vmer, Vver : wind velocities
1020 error_code : int that states where code is terminated
1020 error_code : int that states where code is terminated
1021
1021
1022 0 : no error detected
1022 0 : no error detected
1023 1 : Gaussian of mean spc exceeds widthlimit
1023 1 : Gaussian of mean spc exceeds widthlimit
1024 2 : no Gaussian of mean spc found
1024 2 : no Gaussian of mean spc found
1025 3 : SNR to low or velocity to high -> prec. e.g.
1025 3 : SNR to low or velocity to high -> prec. e.g.
1026 4 : at least one Gaussian of cspc exceeds widthlimit
1026 4 : at least one Gaussian of cspc exceeds widthlimit
1027 5 : zero out of three cspc Gaussian fits converged
1027 5 : zero out of three cspc Gaussian fits converged
1028 6 : phase slope fit could not be found
1028 6 : phase slope fit could not be found
1029 7 : arrays used to fit phase have different length
1029 7 : arrays used to fit phase have different length
1030 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1030 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1031
1031
1032 """
1032 """
1033
1033
1034 error_code = 0
1034 error_code = 0
1035
1035
1036 nChan = spc.shape[0]
1036 nChan = spc.shape[0]
1037 nProf = spc.shape[1]
1037 nProf = spc.shape[1]
1038 nPair = cspc.shape[0]
1038 nPair = cspc.shape[0]
1039
1039
1040 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1040 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1041 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1041 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1042 phase = numpy.zeros([nPair, nProf]) # phase between channels
1042 phase = numpy.zeros([nPair, nProf]) # phase between channels
1043 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1043 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1044 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1044 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1045 xFrec = AbbsisaRange[0][:-1] # frequency range
1045 xFrec = AbbsisaRange[0][:-1] # frequency range
1046 xVel = AbbsisaRange[2][:-1] # velocity range
1046 xVel = AbbsisaRange[2][:-1] # velocity range
1047 xSamples = xFrec # the frequency range is taken
1047 xSamples = xFrec # the frequency range is taken
1048 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1048 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1049
1049
1050 # only consider velocities with in NegativeLimit and PositiveLimit
1050 # only consider velocities with in NegativeLimit and PositiveLimit
1051 if (NegativeLimit is None):
1051 if (NegativeLimit is None):
1052 NegativeLimit = numpy.min(xVel)
1052 NegativeLimit = numpy.min(xVel)
1053 if (PositiveLimit is None):
1053 if (PositiveLimit is None):
1054 PositiveLimit = numpy.max(xVel)
1054 PositiveLimit = numpy.max(xVel)
1055 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1055 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1056 xSamples_zoom = xSamples[xvalid]
1056 xSamples_zoom = xSamples[xvalid]
1057
1057
1058 '''Getting Eij and Nij'''
1058 '''Getting Eij and Nij'''
1059 Xi01, Xi02, Xi12 = ChanDist[:,0]
1059 Xi01, Xi02, Xi12 = ChanDist[:,0]
1060 Eta01, Eta02, Eta12 = ChanDist[:,1]
1060 Eta01, Eta02, Eta12 = ChanDist[:,1]
1061
1061
1062 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1062 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1063 widthlimit = 10
1063 widthlimit = 10
1064 '''************************* SPC is normalized ********************************'''
1064 '''************************* SPC is normalized ********************************'''
1065 spc_norm = spc.copy()
1065 spc_norm = spc.copy()
1066 # For each channel
1066 # For each channel
1067 for i in range(nChan):
1067 for i in range(nChan):
1068 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1068 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1069 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1069 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1070
1070
1071 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1071 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1072
1072
1073 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1073 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1074 you only fit the curve and don't need the absolute value of height for calculation,
1074 you only fit the curve and don't need the absolute value of height for calculation,
1075 only for estimation of width. for normalization of cross spectra, you need initial,
1075 only for estimation of width. for normalization of cross spectra, you need initial,
1076 unnormalized self-spectra With noise.
1076 unnormalized self-spectra With noise.
1077
1077
1078 Technically, you don't even need to normalize the self-spectra, as you only need the
1078 Technically, you don't even need to normalize the self-spectra, as you only need the
1079 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1079 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1080 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1080 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1081 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1081 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1082 """
1082 """
1083 # initial conditions
1083 # initial conditions
1084 popt = [1e-10,0,1e-10]
1084 popt = [1e-10,0,1e-10]
1085 # Spectra average
1085 # Spectra average
1086 SPCMean = numpy.average(SPC_Samples,0)
1086 SPCMean = numpy.average(SPC_Samples,0)
1087 # Moments in frequency
1087 # Moments in frequency
1088 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1088 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1089
1089
1090 # Gauss Fit SPC in frequency domain
1090 # Gauss Fit SPC in frequency domain
1091 if dbSNR > SNRlimit: # only if SNR > SNRth
1091 if dbSNR > SNRlimit: # only if SNR > SNRth
1092 try:
1092 try:
1093 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1093 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1094 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1094 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1095 return self.StopWindEstimation(error_code = 1)
1095 return self.StopWindEstimation(error_code = 1)
1096 FitGauss = self.gaus(xSamples_zoom,*popt)
1096 FitGauss = self.gaus(xSamples_zoom,*popt)
1097 except :#RuntimeError:
1097 except :#RuntimeError:
1098 return self.StopWindEstimation(error_code = 2)
1098 return self.StopWindEstimation(error_code = 2)
1099 else:
1099 else:
1100 return self.StopWindEstimation(error_code = 3)
1100 return self.StopWindEstimation(error_code = 3)
1101
1101
1102 '''***************************** CSPC Normalization *************************
1102 '''***************************** CSPC Normalization *************************
1103 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1103 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1104 influence the norm which is not desired. First, a range is identified where the
1104 influence the norm which is not desired. First, a range is identified where the
1105 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1105 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1106 around it gets cut off and values replaced by mean determined by the boundary
1106 around it gets cut off and values replaced by mean determined by the boundary
1107 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1107 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1108
1108
1109 The sums are then added and multiplied by range/datapoints, because you need
1109 The sums are then added and multiplied by range/datapoints, because you need
1110 an integral and not a sum for normalization.
1110 an integral and not a sum for normalization.
1111
1111
1112 A norm is found according to Briggs 92.
1112 A norm is found according to Briggs 92.
1113 '''
1113 '''
1114 # for each pair
1114 # for each pair
1115 for i in range(nPair):
1115 for i in range(nPair):
1116 cspc_norm = cspc[i,:].copy()
1116 cspc_norm = cspc[i,:].copy()
1117 chan_index0 = pairsList[i][0]
1117 chan_index0 = pairsList[i][0]
1118 chan_index1 = pairsList[i][1]
1118 chan_index1 = pairsList[i][1]
1119 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1119 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1120 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1120 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1121
1121
1122 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1122 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1123 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1123 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1124 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1124 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1125
1125
1126 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1126 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1127 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1127 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1128
1128
1129 '''*******************************FIT GAUSS CSPC************************************'''
1129 '''*******************************FIT GAUSS CSPC************************************'''
1130 try:
1130 try:
1131 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1131 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1132 if popt01[2] > widthlimit: # CONDITION
1132 if popt01[2] > widthlimit: # CONDITION
1133 return self.StopWindEstimation(error_code = 4)
1133 return self.StopWindEstimation(error_code = 4)
1134 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1134 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1135 if popt02[2] > widthlimit: # CONDITION
1135 if popt02[2] > widthlimit: # CONDITION
1136 return self.StopWindEstimation(error_code = 4)
1136 return self.StopWindEstimation(error_code = 4)
1137 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1137 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1138 if popt12[2] > widthlimit: # CONDITION
1138 if popt12[2] > widthlimit: # CONDITION
1139 return self.StopWindEstimation(error_code = 4)
1139 return self.StopWindEstimation(error_code = 4)
1140
1140
1141 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1141 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1142 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1142 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1143 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1143 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1144 except:
1144 except:
1145 return self.StopWindEstimation(error_code = 5)
1145 return self.StopWindEstimation(error_code = 5)
1146
1146
1147
1147
1148 '''************* Getting Fij ***************'''
1148 '''************* Getting Fij ***************'''
1149 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1149 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1150 GaussCenter = popt[1]
1150 GaussCenter = popt[1]
1151 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1151 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1152 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1152 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1153
1153
1154 # Point where e^-1 is located in the gaussian
1154 # Point where e^-1 is located in the gaussian
1155 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1155 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1156 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1156 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1157 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1157 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1158 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1158 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1159
1159
1160 '''********** Taking frequency ranges from mean SPCs **********'''
1160 '''********** Taking frequency ranges from mean SPCs **********'''
1161 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1161 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1162 Range = numpy.empty(2)
1162 Range = numpy.empty(2)
1163 Range[0] = GaussCenter - GauWidth
1163 Range[0] = GaussCenter - GauWidth
1164 Range[1] = GaussCenter + GauWidth
1164 Range[1] = GaussCenter + GauWidth
1165 # Point in x-axis where the bandwidth is located (min:max)
1165 # Point in x-axis where the bandwidth is located (min:max)
1166 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1166 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1167 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1167 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1168 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1168 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1169 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1169 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1170 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1170 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1171 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1171 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1172
1172
1173 '''************************** Getting Phase Slope ***************************'''
1173 '''************************** Getting Phase Slope ***************************'''
1174 for i in range(nPair):
1174 for i in range(nPair):
1175 if len(FrecRange) > 5:
1175 if len(FrecRange) > 5:
1176 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1176 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1177 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1177 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1178 if len(FrecRange) == len(PhaseRange):
1178 if len(FrecRange) == len(PhaseRange):
1179 try:
1179 try:
1180 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1180 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1181 PhaseSlope[i] = slope
1181 PhaseSlope[i] = slope
1182 PhaseInter[i] = intercept
1182 PhaseInter[i] = intercept
1183 except:
1183 except:
1184 return self.StopWindEstimation(error_code = 6)
1184 return self.StopWindEstimation(error_code = 6)
1185 else:
1185 else:
1186 return self.StopWindEstimation(error_code = 7)
1186 return self.StopWindEstimation(error_code = 7)
1187 else:
1187 else:
1188 return self.StopWindEstimation(error_code = 8)
1188 return self.StopWindEstimation(error_code = 8)
1189
1189
1190 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1190 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1191
1191
1192 '''Getting constant C'''
1192 '''Getting constant C'''
1193 cC=(Fij*numpy.pi)**2
1193 cC=(Fij*numpy.pi)**2
1194
1194
1195 '''****** Getting constants F and G ******'''
1195 '''****** Getting constants F and G ******'''
1196 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1196 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1197 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1197 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1198 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1198 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1199 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1199 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1200 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1200 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1201 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1201 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1202 MijResults = numpy.array([MijResult1, MijResult2])
1202 MijResults = numpy.array([MijResult1, MijResult2])
1203 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1203 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1204
1204
1205 '''****** Getting constants A, B and H ******'''
1205 '''****** Getting constants A, B and H ******'''
1206 W01 = numpy.nanmax( FitGauss01 )
1206 W01 = numpy.nanmax( FitGauss01 )
1207 W02 = numpy.nanmax( FitGauss02 )
1207 W02 = numpy.nanmax( FitGauss02 )
1208 W12 = numpy.nanmax( FitGauss12 )
1208 W12 = numpy.nanmax( FitGauss12 )
1209
1209
1210 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1210 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1211 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1211 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1212 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1212 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1213 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1213 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1214
1214
1215 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1215 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1216 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1216 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1217
1217
1218 VxVy = numpy.array([[cA,cH],[cH,cB]])
1218 VxVy = numpy.array([[cA,cH],[cH,cB]])
1219 VxVyResults = numpy.array([-cF,-cG])
1219 VxVyResults = numpy.array([-cF,-cG])
1220 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1220 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1221 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1221 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1222 error_code = 0
1222 error_code = 0
1223
1223
1224 return Vzon, Vmer, Vver, error_code
1224 return Vzon, Vmer, Vver, error_code
1225
1225
1226 class SpectralMoments(Operation):
1226 class SpectralMoments(Operation):
1227
1227
1228 '''
1228 '''
1229 Function SpectralMoments()
1229 Function SpectralMoments()
1230
1230
1231 Calculates moments (power, mean, standard deviation) and SNR of the signal
1231 Calculates moments (power, mean, standard deviation) and SNR of the signal
1232
1232
1233 Type of dataIn: Spectra
1233 Type of dataIn: Spectra
1234
1234
1235 Configuration Parameters:
1235 Configuration Parameters:
1236
1236
1237 dirCosx : Cosine director in X axis
1237 dirCosx : Cosine director in X axis
1238 dirCosy : Cosine director in Y axis
1238 dirCosy : Cosine director in Y axis
1239
1239
1240 elevation :
1240 elevation :
1241 azimuth :
1241 azimuth :
1242
1242
1243 Input:
1243 Input:
1244 channelList : simple channel list to select e.g. [2,3,7]
1244 channelList : simple channel list to select e.g. [2,3,7]
1245 self.dataOut.data_pre : Spectral data
1245 self.dataOut.data_pre : Spectral data
1246 self.dataOut.abscissaList : List of frequencies
1246 self.dataOut.abscissaList : List of frequencies
1247 self.dataOut.noise : Noise level per channel
1247 self.dataOut.noise : Noise level per channel
1248
1248
1249 Affected:
1249 Affected:
1250 self.dataOut.moments : Parameters per channel
1250 self.dataOut.moments : Parameters per channel
1251 self.dataOut.data_snr : SNR per channel
1251 self.dataOut.data_snr : SNR per channel
1252
1252
1253 '''
1253 '''
1254
1254
1255 def run(self, dataOut):
1255 def run(self, dataOut):
1256
1256
1257 data = dataOut.data_pre[0]
1257 data = dataOut.data_pre[0]
1258 absc = dataOut.abscissaList[:-1]
1258 absc = dataOut.abscissaList[:-1]
1259 noise = dataOut.noise
1259 noise = dataOut.noise
1260 nChannel = data.shape[0]
1260 nChannel = data.shape[0]
1261 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1261 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1262
1262
1263 for ind in range(nChannel):
1263 for ind in range(nChannel):
1264 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1264 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1265
1265
1266 dataOut.moments = data_param[:,1:,:]
1266 dataOut.moments = data_param[:,1:,:]
1267 dataOut.data_snr = data_param[:,0]
1267 dataOut.data_snr = data_param[:,0]
1268 dataOut.data_pow = data_param[:,1]
1268 dataOut.data_pow = data_param[:,1]
1269 dataOut.data_dop = data_param[:,2]
1269 dataOut.data_dop = data_param[:,2]
1270 dataOut.data_width = data_param[:,3]
1270 dataOut.data_width = data_param[:,3]
1271 return dataOut
1271 return dataOut
1272
1272
1273 def __calculateMoments(self, oldspec, oldfreq, n0,
1273 def __calculateMoments(self, oldspec, oldfreq, n0,
1274 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1274 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1275
1275
1276 if (nicoh is None): nicoh = 1
1276 if (nicoh is None): nicoh = 1
1277 if (graph is None): graph = 0
1277 if (graph is None): graph = 0
1278 if (smooth is None): smooth = 0
1278 if (smooth is None): smooth = 0
1279 elif (self.smooth < 3): smooth = 0
1279 elif (self.smooth < 3): smooth = 0
1280
1280
1281 if (type1 is None): type1 = 0
1281 if (type1 is None): type1 = 0
1282 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1282 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1283 if (snrth is None): snrth = -3
1283 if (snrth is None): snrth = -3
1284 if (dc is None): dc = 0
1284 if (dc is None): dc = 0
1285 if (aliasing is None): aliasing = 0
1285 if (aliasing is None): aliasing = 0
1286 if (oldfd is None): oldfd = 0
1286 if (oldfd is None): oldfd = 0
1287 if (wwauto is None): wwauto = 0
1287 if (wwauto is None): wwauto = 0
1288
1288
1289 if (n0 < 1.e-20): n0 = 1.e-20
1289 if (n0 < 1.e-20): n0 = 1.e-20
1290
1290
1291 freq = oldfreq
1291 freq = oldfreq
1292 vec_power = numpy.zeros(oldspec.shape[1])
1292 vec_power = numpy.zeros(oldspec.shape[1])
1293 vec_fd = numpy.zeros(oldspec.shape[1])
1293 vec_fd = numpy.zeros(oldspec.shape[1])
1294 vec_w = numpy.zeros(oldspec.shape[1])
1294 vec_w = numpy.zeros(oldspec.shape[1])
1295 vec_snr = numpy.zeros(oldspec.shape[1])
1295 vec_snr = numpy.zeros(oldspec.shape[1])
1296
1296
1297 # oldspec = numpy.ma.masked_invalid(oldspec)
1297 # oldspec = numpy.ma.masked_invalid(oldspec)
1298 for ind in range(oldspec.shape[1]):
1298 for ind in range(oldspec.shape[1]):
1299
1299
1300 spec = oldspec[:,ind]
1300 spec = oldspec[:,ind]
1301 aux = spec*fwindow
1301 aux = spec*fwindow
1302 max_spec = aux.max()
1302 max_spec = aux.max()
1303 m = aux.tolist().index(max_spec)
1303 m = aux.tolist().index(max_spec)
1304
1304
1305 # Smooth
1305 # Smooth
1306 if (smooth == 0):
1306 if (smooth == 0):
1307 spec2 = spec
1307 spec2 = spec
1308 else:
1308 else:
1309 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1309 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1310
1310
1311 # Moments Estimation
1311 # Moments Estimation
1312 bb = spec2[numpy.arange(m,spec2.size)]
1312 bb = spec2[numpy.arange(m,spec2.size)]
1313 bb = (bb<n0).nonzero()
1313 bb = (bb<n0).nonzero()
1314 bb = bb[0]
1314 bb = bb[0]
1315
1315
1316 ss = spec2[numpy.arange(0,m + 1)]
1316 ss = spec2[numpy.arange(0,m + 1)]
1317 ss = (ss<n0).nonzero()
1317 ss = (ss<n0).nonzero()
1318 ss = ss[0]
1318 ss = ss[0]
1319
1319
1320 if (bb.size == 0):
1320 if (bb.size == 0):
1321 bb0 = spec.size - 1 - m
1321 bb0 = spec.size - 1 - m
1322 else:
1322 else:
1323 bb0 = bb[0] - 1
1323 bb0 = bb[0] - 1
1324 if (bb0 < 0):
1324 if (bb0 < 0):
1325 bb0 = 0
1325 bb0 = 0
1326
1326
1327 if (ss.size == 0):
1327 if (ss.size == 0):
1328 ss1 = 1
1328 ss1 = 1
1329 else:
1329 else:
1330 ss1 = max(ss) + 1
1330 ss1 = max(ss) + 1
1331
1331
1332 if (ss1 > m):
1332 if (ss1 > m):
1333 ss1 = m
1333 ss1 = m
1334
1334
1335 #valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1335 #valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1336 valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1336 valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1337 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1337 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1338 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1338 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1339 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1339 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1340 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1340 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1341 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1341 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1342 snr = (spec2.mean()-n0)/n0
1342 snr = (spec2.mean()-n0)/n0
1343 if (snr < 1.e-20) :
1343 if (snr < 1.e-20) :
1344 snr = 1.e-20
1344 snr = 1.e-20
1345
1345
1346 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1346 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1347 vec_power[ind] = total_power
1347 vec_power[ind] = total_power
1348 vec_fd[ind] = fd
1348 vec_fd[ind] = fd
1349 vec_w[ind] = w
1349 vec_w[ind] = w
1350 vec_snr[ind] = snr
1350 vec_snr[ind] = snr
1351
1351
1352 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1352 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1353
1353
1354 #------------------ Get SA Parameters --------------------------
1354 #------------------ Get SA Parameters --------------------------
1355
1355
1356 def GetSAParameters(self):
1356 def GetSAParameters(self):
1357 #SA en frecuencia
1357 #SA en frecuencia
1358 pairslist = self.dataOut.groupList
1358 pairslist = self.dataOut.groupList
1359 num_pairs = len(pairslist)
1359 num_pairs = len(pairslist)
1360
1360
1361 vel = self.dataOut.abscissaList
1361 vel = self.dataOut.abscissaList
1362 spectra = self.dataOut.data_pre
1362 spectra = self.dataOut.data_pre
1363 cspectra = self.dataIn.data_cspc
1363 cspectra = self.dataIn.data_cspc
1364 delta_v = vel[1] - vel[0]
1364 delta_v = vel[1] - vel[0]
1365
1365
1366 #Calculating the power spectrum
1366 #Calculating the power spectrum
1367 spc_pow = numpy.sum(spectra, 3)*delta_v
1367 spc_pow = numpy.sum(spectra, 3)*delta_v
1368 #Normalizing Spectra
1368 #Normalizing Spectra
1369 norm_spectra = spectra/spc_pow
1369 norm_spectra = spectra/spc_pow
1370 #Calculating the norm_spectra at peak
1370 #Calculating the norm_spectra at peak
1371 max_spectra = numpy.max(norm_spectra, 3)
1371 max_spectra = numpy.max(norm_spectra, 3)
1372
1372
1373 #Normalizing Cross Spectra
1373 #Normalizing Cross Spectra
1374 norm_cspectra = numpy.zeros(cspectra.shape)
1374 norm_cspectra = numpy.zeros(cspectra.shape)
1375
1375
1376 for i in range(num_chan):
1376 for i in range(num_chan):
1377 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1377 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1378
1378
1379 max_cspectra = numpy.max(norm_cspectra,2)
1379 max_cspectra = numpy.max(norm_cspectra,2)
1380 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1380 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1381
1381
1382 for i in range(num_pairs):
1382 for i in range(num_pairs):
1383 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1383 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1384 #------------------- Get Lags ----------------------------------
1384 #------------------- Get Lags ----------------------------------
1385
1385
1386 class SALags(Operation):
1386 class SALags(Operation):
1387 '''
1387 '''
1388 Function GetMoments()
1388 Function GetMoments()
1389
1389
1390 Input:
1390 Input:
1391 self.dataOut.data_pre
1391 self.dataOut.data_pre
1392 self.dataOut.abscissaList
1392 self.dataOut.abscissaList
1393 self.dataOut.noise
1393 self.dataOut.noise
1394 self.dataOut.normFactor
1394 self.dataOut.normFactor
1395 self.dataOut.data_snr
1395 self.dataOut.data_snr
1396 self.dataOut.groupList
1396 self.dataOut.groupList
1397 self.dataOut.nChannels
1397 self.dataOut.nChannels
1398
1398
1399 Affected:
1399 Affected:
1400 self.dataOut.data_param
1400 self.dataOut.data_param
1401
1401
1402 '''
1402 '''
1403 def run(self, dataOut):
1403 def run(self, dataOut):
1404 data_acf = dataOut.data_pre[0]
1404 data_acf = dataOut.data_pre[0]
1405 data_ccf = dataOut.data_pre[1]
1405 data_ccf = dataOut.data_pre[1]
1406 normFactor_acf = dataOut.normFactor[0]
1406 normFactor_acf = dataOut.normFactor[0]
1407 normFactor_ccf = dataOut.normFactor[1]
1407 normFactor_ccf = dataOut.normFactor[1]
1408 pairs_acf = dataOut.groupList[0]
1408 pairs_acf = dataOut.groupList[0]
1409 pairs_ccf = dataOut.groupList[1]
1409 pairs_ccf = dataOut.groupList[1]
1410
1410
1411 nHeights = dataOut.nHeights
1411 nHeights = dataOut.nHeights
1412 absc = dataOut.abscissaList
1412 absc = dataOut.abscissaList
1413 noise = dataOut.noise
1413 noise = dataOut.noise
1414 SNR = dataOut.data_snr
1414 SNR = dataOut.data_snr
1415 nChannels = dataOut.nChannels
1415 nChannels = dataOut.nChannels
1416 # pairsList = dataOut.groupList
1416 # pairsList = dataOut.groupList
1417 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1417 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1418
1418
1419 for l in range(len(pairs_acf)):
1419 for l in range(len(pairs_acf)):
1420 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1420 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1421
1421
1422 for l in range(len(pairs_ccf)):
1422 for l in range(len(pairs_ccf)):
1423 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1423 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1424
1424
1425 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1425 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1426 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1426 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1427 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1427 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1428 return
1428 return
1429
1429
1430 # def __getPairsAutoCorr(self, pairsList, nChannels):
1430 # def __getPairsAutoCorr(self, pairsList, nChannels):
1431 #
1431 #
1432 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1432 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1433 #
1433 #
1434 # for l in range(len(pairsList)):
1434 # for l in range(len(pairsList)):
1435 # firstChannel = pairsList[l][0]
1435 # firstChannel = pairsList[l][0]
1436 # secondChannel = pairsList[l][1]
1436 # secondChannel = pairsList[l][1]
1437 #
1437 #
1438 # #Obteniendo pares de Autocorrelacion
1438 # #Obteniendo pares de Autocorrelacion
1439 # if firstChannel == secondChannel:
1439 # if firstChannel == secondChannel:
1440 # pairsAutoCorr[firstChannel] = int(l)
1440 # pairsAutoCorr[firstChannel] = int(l)
1441 #
1441 #
1442 # pairsAutoCorr = pairsAutoCorr.astype(int)
1442 # pairsAutoCorr = pairsAutoCorr.astype(int)
1443 #
1443 #
1444 # pairsCrossCorr = range(len(pairsList))
1444 # pairsCrossCorr = range(len(pairsList))
1445 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1445 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1446 #
1446 #
1447 # return pairsAutoCorr, pairsCrossCorr
1447 # return pairsAutoCorr, pairsCrossCorr
1448
1448
1449 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1449 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1450
1450
1451 lag0 = data_acf.shape[1]/2
1451 lag0 = data_acf.shape[1]/2
1452 #Funcion de Autocorrelacion
1452 #Funcion de Autocorrelacion
1453 mean_acf = stats.nanmean(data_acf, axis = 0)
1453 mean_acf = stats.nanmean(data_acf, axis = 0)
1454
1454
1455 #Obtencion Indice de TauCross
1455 #Obtencion Indice de TauCross
1456 ind_ccf = data_ccf.argmax(axis = 1)
1456 ind_ccf = data_ccf.argmax(axis = 1)
1457 #Obtencion Indice de TauAuto
1457 #Obtencion Indice de TauAuto
1458 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1458 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1459 ccf_lag0 = data_ccf[:,lag0,:]
1459 ccf_lag0 = data_ccf[:,lag0,:]
1460
1460
1461 for i in range(ccf_lag0.shape[0]):
1461 for i in range(ccf_lag0.shape[0]):
1462 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1462 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1463
1463
1464 #Obtencion de TauCross y TauAuto
1464 #Obtencion de TauCross y TauAuto
1465 tau_ccf = lagRange[ind_ccf]
1465 tau_ccf = lagRange[ind_ccf]
1466 tau_acf = lagRange[ind_acf]
1466 tau_acf = lagRange[ind_acf]
1467
1467
1468 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1468 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1469
1469
1470 tau_ccf[Nan1,Nan2] = numpy.nan
1470 tau_ccf[Nan1,Nan2] = numpy.nan
1471 tau_acf[Nan1,Nan2] = numpy.nan
1471 tau_acf[Nan1,Nan2] = numpy.nan
1472 tau = numpy.vstack((tau_ccf,tau_acf))
1472 tau = numpy.vstack((tau_ccf,tau_acf))
1473
1473
1474 return tau
1474 return tau
1475
1475
1476 def __calculateLag1Phase(self, data, lagTRange):
1476 def __calculateLag1Phase(self, data, lagTRange):
1477 data1 = stats.nanmean(data, axis = 0)
1477 data1 = stats.nanmean(data, axis = 0)
1478 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1478 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1479
1479
1480 phase = numpy.angle(data1[lag1,:])
1480 phase = numpy.angle(data1[lag1,:])
1481
1481
1482 return phase
1482 return phase
1483
1483
1484 class SpectralFitting(Operation):
1484 class SpectralFitting(Operation):
1485 '''
1485 '''
1486 Function GetMoments()
1486 Function GetMoments()
1487
1487
1488 Input:
1488 Input:
1489 Output:
1489 Output:
1490 Variables modified:
1490 Variables modified:
1491 '''
1491 '''
1492
1492
1493 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1493 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1494
1494
1495
1495
1496 if path != None:
1496 if path != None:
1497 sys.path.append(path)
1497 sys.path.append(path)
1498 self.dataOut.library = importlib.import_module(file)
1498 self.dataOut.library = importlib.import_module(file)
1499
1499
1500 #To be inserted as a parameter
1500 #To be inserted as a parameter
1501 groupArray = numpy.array(groupList)
1501 groupArray = numpy.array(groupList)
1502 # groupArray = numpy.array([[0,1],[2,3]])
1502 # groupArray = numpy.array([[0,1],[2,3]])
1503 self.dataOut.groupList = groupArray
1503 self.dataOut.groupList = groupArray
1504
1504
1505 nGroups = groupArray.shape[0]
1505 nGroups = groupArray.shape[0]
1506 nChannels = self.dataIn.nChannels
1506 nChannels = self.dataIn.nChannels
1507 nHeights=self.dataIn.heightList.size
1507 nHeights=self.dataIn.heightList.size
1508
1508
1509 #Parameters Array
1509 #Parameters Array
1510 self.dataOut.data_param = None
1510 self.dataOut.data_param = None
1511
1511
1512 #Set constants
1512 #Set constants
1513 constants = self.dataOut.library.setConstants(self.dataIn)
1513 constants = self.dataOut.library.setConstants(self.dataIn)
1514 self.dataOut.constants = constants
1514 self.dataOut.constants = constants
1515 M = self.dataIn.normFactor
1515 M = self.dataIn.normFactor
1516 N = self.dataIn.nFFTPoints
1516 N = self.dataIn.nFFTPoints
1517 ippSeconds = self.dataIn.ippSeconds
1517 ippSeconds = self.dataIn.ippSeconds
1518 K = self.dataIn.nIncohInt
1518 K = self.dataIn.nIncohInt
1519 pairsArray = numpy.array(self.dataIn.pairsList)
1519 pairsArray = numpy.array(self.dataIn.pairsList)
1520
1520
1521 #List of possible combinations
1521 #List of possible combinations
1522 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1522 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1523 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1523 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1524
1524
1525 if getSNR:
1525 if getSNR:
1526 listChannels = groupArray.reshape((groupArray.size))
1526 listChannels = groupArray.reshape((groupArray.size))
1527 listChannels.sort()
1527 listChannels.sort()
1528 noise = self.dataIn.getNoise()
1528 noise = self.dataIn.getNoise()
1529 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1529 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1530
1530
1531 for i in range(nGroups):
1531 for i in range(nGroups):
1532 coord = groupArray[i,:]
1532 coord = groupArray[i,:]
1533
1533
1534 #Input data array
1534 #Input data array
1535 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1535 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1536 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1536 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1537
1537
1538 #Cross Spectra data array for Covariance Matrixes
1538 #Cross Spectra data array for Covariance Matrixes
1539 ind = 0
1539 ind = 0
1540 for pairs in listComb:
1540 for pairs in listComb:
1541 pairsSel = numpy.array([coord[x],coord[y]])
1541 pairsSel = numpy.array([coord[x],coord[y]])
1542 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1542 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1543 ind += 1
1543 ind += 1
1544 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1544 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1545 dataCross = dataCross**2/K
1545 dataCross = dataCross**2/K
1546
1546
1547 for h in range(nHeights):
1547 for h in range(nHeights):
1548
1548
1549 #Input
1549 #Input
1550 d = data[:,h]
1550 d = data[:,h]
1551
1551
1552 #Covariance Matrix
1552 #Covariance Matrix
1553 D = numpy.diag(d**2/K)
1553 D = numpy.diag(d**2/K)
1554 ind = 0
1554 ind = 0
1555 for pairs in listComb:
1555 for pairs in listComb:
1556 #Coordinates in Covariance Matrix
1556 #Coordinates in Covariance Matrix
1557 x = pairs[0]
1557 x = pairs[0]
1558 y = pairs[1]
1558 y = pairs[1]
1559 #Channel Index
1559 #Channel Index
1560 S12 = dataCross[ind,:,h]
1560 S12 = dataCross[ind,:,h]
1561 D12 = numpy.diag(S12)
1561 D12 = numpy.diag(S12)
1562 #Completing Covariance Matrix with Cross Spectras
1562 #Completing Covariance Matrix with Cross Spectras
1563 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1563 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1564 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1564 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1565 ind += 1
1565 ind += 1
1566 Dinv=numpy.linalg.inv(D)
1566 Dinv=numpy.linalg.inv(D)
1567 L=numpy.linalg.cholesky(Dinv)
1567 L=numpy.linalg.cholesky(Dinv)
1568 LT=L.T
1568 LT=L.T
1569
1569
1570 dp = numpy.dot(LT,d)
1570 dp = numpy.dot(LT,d)
1571
1571
1572 #Initial values
1572 #Initial values
1573 data_spc = self.dataIn.data_spc[coord,:,h]
1573 data_spc = self.dataIn.data_spc[coord,:,h]
1574
1574
1575 if (h>0)and(error1[3]<5):
1575 if (h>0)and(error1[3]<5):
1576 p0 = self.dataOut.data_param[i,:,h-1]
1576 p0 = self.dataOut.data_param[i,:,h-1]
1577 else:
1577 else:
1578 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1578 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1579
1579
1580 try:
1580 try:
1581 #Least Squares
1581 #Least Squares
1582 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1582 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1583 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1583 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1584 #Chi square error
1584 #Chi square error
1585 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1585 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1586 #Error with Jacobian
1586 #Error with Jacobian
1587 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1587 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1588 except:
1588 except:
1589 minp = p0*numpy.nan
1589 minp = p0*numpy.nan
1590 error0 = numpy.nan
1590 error0 = numpy.nan
1591 error1 = p0*numpy.nan
1591 error1 = p0*numpy.nan
1592
1592
1593 #Save
1593 #Save
1594 if self.dataOut.data_param is None:
1594 if self.dataOut.data_param is None:
1595 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1595 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1596 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1596 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1597
1597
1598 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1598 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1599 self.dataOut.data_param[i,:,h] = minp
1599 self.dataOut.data_param[i,:,h] = minp
1600 return
1600 return
1601
1601
1602 def __residFunction(self, p, dp, LT, constants):
1602 def __residFunction(self, p, dp, LT, constants):
1603
1603
1604 fm = self.dataOut.library.modelFunction(p, constants)
1604 fm = self.dataOut.library.modelFunction(p, constants)
1605 fmp=numpy.dot(LT,fm)
1605 fmp=numpy.dot(LT,fm)
1606
1606
1607 return dp-fmp
1607 return dp-fmp
1608
1608
1609 def __getSNR(self, z, noise):
1609 def __getSNR(self, z, noise):
1610
1610
1611 avg = numpy.average(z, axis=1)
1611 avg = numpy.average(z, axis=1)
1612 SNR = (avg.T-noise)/noise
1612 SNR = (avg.T-noise)/noise
1613 SNR = SNR.T
1613 SNR = SNR.T
1614 return SNR
1614 return SNR
1615
1615
1616 def __chisq(p,chindex,hindex):
1616 def __chisq(p,chindex,hindex):
1617 #similar to Resid but calculates CHI**2
1617 #similar to Resid but calculates CHI**2
1618 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1618 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1619 dp=numpy.dot(LT,d)
1619 dp=numpy.dot(LT,d)
1620 fmp=numpy.dot(LT,fm)
1620 fmp=numpy.dot(LT,fm)
1621 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1621 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1622 return chisq
1622 return chisq
1623
1623
1624 class WindProfiler(Operation):
1624 class WindProfiler(Operation):
1625
1625
1626 __isConfig = False
1626 __isConfig = False
1627
1627
1628 __initime = None
1628 __initime = None
1629 __lastdatatime = None
1629 __lastdatatime = None
1630 __integrationtime = None
1630 __integrationtime = None
1631
1631
1632 __buffer = None
1632 __buffer = None
1633
1633
1634 __dataReady = False
1634 __dataReady = False
1635
1635
1636 __firstdata = None
1636 __firstdata = None
1637
1637
1638 n = None
1638 n = None
1639
1639
1640 def __init__(self):
1640 def __init__(self):
1641 Operation.__init__(self)
1641 Operation.__init__(self)
1642
1642
1643 def __calculateCosDir(self, elev, azim):
1643 def __calculateCosDir(self, elev, azim):
1644 zen = (90 - elev)*numpy.pi/180
1644 zen = (90 - elev)*numpy.pi/180
1645 azim = azim*numpy.pi/180
1645 azim = azim*numpy.pi/180
1646 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1646 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1647 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1647 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1648
1648
1649 signX = numpy.sign(numpy.cos(azim))
1649 signX = numpy.sign(numpy.cos(azim))
1650 signY = numpy.sign(numpy.sin(azim))
1650 signY = numpy.sign(numpy.sin(azim))
1651
1651
1652 cosDirX = numpy.copysign(cosDirX, signX)
1652 cosDirX = numpy.copysign(cosDirX, signX)
1653 cosDirY = numpy.copysign(cosDirY, signY)
1653 cosDirY = numpy.copysign(cosDirY, signY)
1654 return cosDirX, cosDirY
1654 return cosDirX, cosDirY
1655
1655
1656 def __calculateAngles(self, theta_x, theta_y, azimuth):
1656 def __calculateAngles(self, theta_x, theta_y, azimuth):
1657
1657
1658 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1658 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1659 zenith_arr = numpy.arccos(dir_cosw)
1659 zenith_arr = numpy.arccos(dir_cosw)
1660 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1660 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1661
1661
1662 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1662 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1663 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1663 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1664
1664
1665 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1665 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1666
1666
1667 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1667 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1668
1668
1669 #
1669 #
1670 if horOnly:
1670 if horOnly:
1671 A = numpy.c_[dir_cosu,dir_cosv]
1671 A = numpy.c_[dir_cosu,dir_cosv]
1672 else:
1672 else:
1673 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1673 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1674 A = numpy.asmatrix(A)
1674 A = numpy.asmatrix(A)
1675 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1675 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1676
1676
1677 return A1
1677 return A1
1678
1678
1679 def __correctValues(self, heiRang, phi, velRadial, SNR):
1679 def __correctValues(self, heiRang, phi, velRadial, SNR):
1680 listPhi = phi.tolist()
1680 listPhi = phi.tolist()
1681 maxid = listPhi.index(max(listPhi))
1681 maxid = listPhi.index(max(listPhi))
1682 minid = listPhi.index(min(listPhi))
1682 minid = listPhi.index(min(listPhi))
1683
1683
1684 rango = list(range(len(phi)))
1684 rango = list(range(len(phi)))
1685 # rango = numpy.delete(rango,maxid)
1685 # rango = numpy.delete(rango,maxid)
1686
1686
1687 heiRang1 = heiRang*math.cos(phi[maxid])
1687 heiRang1 = heiRang*math.cos(phi[maxid])
1688 heiRangAux = heiRang*math.cos(phi[minid])
1688 heiRangAux = heiRang*math.cos(phi[minid])
1689 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1689 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1690 heiRang1 = numpy.delete(heiRang1,indOut)
1690 heiRang1 = numpy.delete(heiRang1,indOut)
1691
1691
1692 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1692 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1693 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1693 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1694
1694
1695 for i in rango:
1695 for i in rango:
1696 x = heiRang*math.cos(phi[i])
1696 x = heiRang*math.cos(phi[i])
1697 y1 = velRadial[i,:]
1697 y1 = velRadial[i,:]
1698 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1698 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1699
1699
1700 x1 = heiRang1
1700 x1 = heiRang1
1701 y11 = f1(x1)
1701 y11 = f1(x1)
1702
1702
1703 y2 = SNR[i,:]
1703 y2 = SNR[i,:]
1704 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1704 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1705 y21 = f2(x1)
1705 y21 = f2(x1)
1706
1706
1707 velRadial1[i,:] = y11
1707 velRadial1[i,:] = y11
1708 SNR1[i,:] = y21
1708 SNR1[i,:] = y21
1709
1709
1710 return heiRang1, velRadial1, SNR1
1710 return heiRang1, velRadial1, SNR1
1711
1711
1712 def __calculateVelUVW(self, A, velRadial):
1712 def __calculateVelUVW(self, A, velRadial):
1713
1713
1714 #Operacion Matricial
1714 #Operacion Matricial
1715 # velUVW = numpy.zeros((velRadial.shape[1],3))
1715 # velUVW = numpy.zeros((velRadial.shape[1],3))
1716 # for ind in range(velRadial.shape[1]):
1716 # for ind in range(velRadial.shape[1]):
1717 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1717 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1718 # velUVW = velUVW.transpose()
1718 # velUVW = velUVW.transpose()
1719 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1719 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1720 velUVW[:,:] = numpy.dot(A,velRadial)
1720 velUVW[:,:] = numpy.dot(A,velRadial)
1721
1721
1722
1722
1723 return velUVW
1723 return velUVW
1724
1724
1725 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1725 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1726
1726
1727 def techniqueDBS(self, kwargs):
1727 def techniqueDBS(self, kwargs):
1728 """
1728 """
1729 Function that implements Doppler Beam Swinging (DBS) technique.
1729 Function that implements Doppler Beam Swinging (DBS) technique.
1730
1730
1731 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1731 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1732 Direction correction (if necessary), Ranges and SNR
1732 Direction correction (if necessary), Ranges and SNR
1733
1733
1734 Output: Winds estimation (Zonal, Meridional and Vertical)
1734 Output: Winds estimation (Zonal, Meridional and Vertical)
1735
1735
1736 Parameters affected: Winds, height range, SNR
1736 Parameters affected: Winds, height range, SNR
1737 """
1737 """
1738 velRadial0 = kwargs['velRadial']
1738 velRadial0 = kwargs['velRadial']
1739 heiRang = kwargs['heightList']
1739 heiRang = kwargs['heightList']
1740 SNR0 = kwargs['SNR']
1740 SNR0 = kwargs['SNR']
1741
1741
1742 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1742 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1743 theta_x = numpy.array(kwargs['dirCosx'])
1743 theta_x = numpy.array(kwargs['dirCosx'])
1744 theta_y = numpy.array(kwargs['dirCosy'])
1744 theta_y = numpy.array(kwargs['dirCosy'])
1745 else:
1745 else:
1746 elev = numpy.array(kwargs['elevation'])
1746 elev = numpy.array(kwargs['elevation'])
1747 azim = numpy.array(kwargs['azimuth'])
1747 azim = numpy.array(kwargs['azimuth'])
1748 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1748 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1749 azimuth = kwargs['correctAzimuth']
1749 azimuth = kwargs['correctAzimuth']
1750 if 'horizontalOnly' in kwargs:
1750 if 'horizontalOnly' in kwargs:
1751 horizontalOnly = kwargs['horizontalOnly']
1751 horizontalOnly = kwargs['horizontalOnly']
1752 else: horizontalOnly = False
1752 else: horizontalOnly = False
1753 if 'correctFactor' in kwargs:
1753 if 'correctFactor' in kwargs:
1754 correctFactor = kwargs['correctFactor']
1754 correctFactor = kwargs['correctFactor']
1755 else: correctFactor = 1
1755 else: correctFactor = 1
1756 if 'channelList' in kwargs:
1756 if 'channelList' in kwargs:
1757 channelList = kwargs['channelList']
1757 channelList = kwargs['channelList']
1758 if len(channelList) == 2:
1758 if len(channelList) == 2:
1759 horizontalOnly = True
1759 horizontalOnly = True
1760 arrayChannel = numpy.array(channelList)
1760 arrayChannel = numpy.array(channelList)
1761 param = param[arrayChannel,:,:]
1761 param = param[arrayChannel,:,:]
1762 theta_x = theta_x[arrayChannel]
1762 theta_x = theta_x[arrayChannel]
1763 theta_y = theta_y[arrayChannel]
1763 theta_y = theta_y[arrayChannel]
1764
1764
1765 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1765 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1766 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1766 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1767 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1767 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1768
1768
1769 #Calculo de Componentes de la velocidad con DBS
1769 #Calculo de Componentes de la velocidad con DBS
1770 winds = self.__calculateVelUVW(A,velRadial1)
1770 winds = self.__calculateVelUVW(A,velRadial1)
1771
1771
1772 return winds, heiRang1, SNR1
1772 return winds, heiRang1, SNR1
1773
1773
1774 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1774 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1775
1775
1776 nPairs = len(pairs_ccf)
1776 nPairs = len(pairs_ccf)
1777 posx = numpy.asarray(posx)
1777 posx = numpy.asarray(posx)
1778 posy = numpy.asarray(posy)
1778 posy = numpy.asarray(posy)
1779
1779
1780 #Rotacion Inversa para alinear con el azimuth
1780 #Rotacion Inversa para alinear con el azimuth
1781 if azimuth!= None:
1781 if azimuth!= None:
1782 azimuth = azimuth*math.pi/180
1782 azimuth = azimuth*math.pi/180
1783 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1783 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1784 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1784 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1785 else:
1785 else:
1786 posx1 = posx
1786 posx1 = posx
1787 posy1 = posy
1787 posy1 = posy
1788
1788
1789 #Calculo de Distancias
1789 #Calculo de Distancias
1790 distx = numpy.zeros(nPairs)
1790 distx = numpy.zeros(nPairs)
1791 disty = numpy.zeros(nPairs)
1791 disty = numpy.zeros(nPairs)
1792 dist = numpy.zeros(nPairs)
1792 dist = numpy.zeros(nPairs)
1793 ang = numpy.zeros(nPairs)
1793 ang = numpy.zeros(nPairs)
1794
1794
1795 for i in range(nPairs):
1795 for i in range(nPairs):
1796 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1796 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1797 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1797 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1798 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1798 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1799 ang[i] = numpy.arctan2(disty[i],distx[i])
1799 ang[i] = numpy.arctan2(disty[i],distx[i])
1800
1800
1801 return distx, disty, dist, ang
1801 return distx, disty, dist, ang
1802 #Calculo de Matrices
1802 #Calculo de Matrices
1803 # nPairs = len(pairs)
1803 # nPairs = len(pairs)
1804 # ang1 = numpy.zeros((nPairs, 2, 1))
1804 # ang1 = numpy.zeros((nPairs, 2, 1))
1805 # dist1 = numpy.zeros((nPairs, 2, 1))
1805 # dist1 = numpy.zeros((nPairs, 2, 1))
1806 #
1806 #
1807 # for j in range(nPairs):
1807 # for j in range(nPairs):
1808 # dist1[j,0,0] = dist[pairs[j][0]]
1808 # dist1[j,0,0] = dist[pairs[j][0]]
1809 # dist1[j,1,0] = dist[pairs[j][1]]
1809 # dist1[j,1,0] = dist[pairs[j][1]]
1810 # ang1[j,0,0] = ang[pairs[j][0]]
1810 # ang1[j,0,0] = ang[pairs[j][0]]
1811 # ang1[j,1,0] = ang[pairs[j][1]]
1811 # ang1[j,1,0] = ang[pairs[j][1]]
1812 #
1812 #
1813 # return distx,disty, dist1,ang1
1813 # return distx,disty, dist1,ang1
1814
1814
1815
1815
1816 def __calculateVelVer(self, phase, lagTRange, _lambda):
1816 def __calculateVelVer(self, phase, lagTRange, _lambda):
1817
1817
1818 Ts = lagTRange[1] - lagTRange[0]
1818 Ts = lagTRange[1] - lagTRange[0]
1819 velW = -_lambda*phase/(4*math.pi*Ts)
1819 velW = -_lambda*phase/(4*math.pi*Ts)
1820
1820
1821 return velW
1821 return velW
1822
1822
1823 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1823 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1824 nPairs = tau1.shape[0]
1824 nPairs = tau1.shape[0]
1825 nHeights = tau1.shape[1]
1825 nHeights = tau1.shape[1]
1826 vel = numpy.zeros((nPairs,3,nHeights))
1826 vel = numpy.zeros((nPairs,3,nHeights))
1827 dist1 = numpy.reshape(dist, (dist.size,1))
1827 dist1 = numpy.reshape(dist, (dist.size,1))
1828
1828
1829 angCos = numpy.cos(ang)
1829 angCos = numpy.cos(ang)
1830 angSin = numpy.sin(ang)
1830 angSin = numpy.sin(ang)
1831
1831
1832 vel0 = dist1*tau1/(2*tau2**2)
1832 vel0 = dist1*tau1/(2*tau2**2)
1833 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1833 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1834 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1834 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1835
1835
1836 ind = numpy.where(numpy.isinf(vel))
1836 ind = numpy.where(numpy.isinf(vel))
1837 vel[ind] = numpy.nan
1837 vel[ind] = numpy.nan
1838
1838
1839 return vel
1839 return vel
1840
1840
1841 # def __getPairsAutoCorr(self, pairsList, nChannels):
1841 # def __getPairsAutoCorr(self, pairsList, nChannels):
1842 #
1842 #
1843 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1843 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1844 #
1844 #
1845 # for l in range(len(pairsList)):
1845 # for l in range(len(pairsList)):
1846 # firstChannel = pairsList[l][0]
1846 # firstChannel = pairsList[l][0]
1847 # secondChannel = pairsList[l][1]
1847 # secondChannel = pairsList[l][1]
1848 #
1848 #
1849 # #Obteniendo pares de Autocorrelacion
1849 # #Obteniendo pares de Autocorrelacion
1850 # if firstChannel == secondChannel:
1850 # if firstChannel == secondChannel:
1851 # pairsAutoCorr[firstChannel] = int(l)
1851 # pairsAutoCorr[firstChannel] = int(l)
1852 #
1852 #
1853 # pairsAutoCorr = pairsAutoCorr.astype(int)
1853 # pairsAutoCorr = pairsAutoCorr.astype(int)
1854 #
1854 #
1855 # pairsCrossCorr = range(len(pairsList))
1855 # pairsCrossCorr = range(len(pairsList))
1856 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1856 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1857 #
1857 #
1858 # return pairsAutoCorr, pairsCrossCorr
1858 # return pairsAutoCorr, pairsCrossCorr
1859
1859
1860 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1860 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1861 def techniqueSA(self, kwargs):
1861 def techniqueSA(self, kwargs):
1862
1862
1863 """
1863 """
1864 Function that implements Spaced Antenna (SA) technique.
1864 Function that implements Spaced Antenna (SA) technique.
1865
1865
1866 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1866 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1867 Direction correction (if necessary), Ranges and SNR
1867 Direction correction (if necessary), Ranges and SNR
1868
1868
1869 Output: Winds estimation (Zonal, Meridional and Vertical)
1869 Output: Winds estimation (Zonal, Meridional and Vertical)
1870
1870
1871 Parameters affected: Winds
1871 Parameters affected: Winds
1872 """
1872 """
1873 position_x = kwargs['positionX']
1873 position_x = kwargs['positionX']
1874 position_y = kwargs['positionY']
1874 position_y = kwargs['positionY']
1875 azimuth = kwargs['azimuth']
1875 azimuth = kwargs['azimuth']
1876
1876
1877 if 'correctFactor' in kwargs:
1877 if 'correctFactor' in kwargs:
1878 correctFactor = kwargs['correctFactor']
1878 correctFactor = kwargs['correctFactor']
1879 else:
1879 else:
1880 correctFactor = 1
1880 correctFactor = 1
1881
1881
1882 groupList = kwargs['groupList']
1882 groupList = kwargs['groupList']
1883 pairs_ccf = groupList[1]
1883 pairs_ccf = groupList[1]
1884 tau = kwargs['tau']
1884 tau = kwargs['tau']
1885 _lambda = kwargs['_lambda']
1885 _lambda = kwargs['_lambda']
1886
1886
1887 #Cross Correlation pairs obtained
1887 #Cross Correlation pairs obtained
1888 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1888 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1889 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1889 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1890 # pairsSelArray = numpy.array(pairsSelected)
1890 # pairsSelArray = numpy.array(pairsSelected)
1891 # pairs = []
1891 # pairs = []
1892 #
1892 #
1893 # #Wind estimation pairs obtained
1893 # #Wind estimation pairs obtained
1894 # for i in range(pairsSelArray.shape[0]/2):
1894 # for i in range(pairsSelArray.shape[0]/2):
1895 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1895 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1896 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1896 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1897 # pairs.append((ind1,ind2))
1897 # pairs.append((ind1,ind2))
1898
1898
1899 indtau = tau.shape[0]/2
1899 indtau = tau.shape[0]/2
1900 tau1 = tau[:indtau,:]
1900 tau1 = tau[:indtau,:]
1901 tau2 = tau[indtau:-1,:]
1901 tau2 = tau[indtau:-1,:]
1902 # tau1 = tau1[pairs,:]
1902 # tau1 = tau1[pairs,:]
1903 # tau2 = tau2[pairs,:]
1903 # tau2 = tau2[pairs,:]
1904 phase1 = tau[-1,:]
1904 phase1 = tau[-1,:]
1905
1905
1906 #---------------------------------------------------------------------
1906 #---------------------------------------------------------------------
1907 #Metodo Directo
1907 #Metodo Directo
1908 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1908 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1909 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1909 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1910 winds = stats.nanmean(winds, axis=0)
1910 winds = stats.nanmean(winds, axis=0)
1911 #---------------------------------------------------------------------
1911 #---------------------------------------------------------------------
1912 #Metodo General
1912 #Metodo General
1913 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1913 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1914 # #Calculo Coeficientes de Funcion de Correlacion
1914 # #Calculo Coeficientes de Funcion de Correlacion
1915 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1915 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1916 # #Calculo de Velocidades
1916 # #Calculo de Velocidades
1917 # winds = self.calculateVelUV(F,G,A,B,H)
1917 # winds = self.calculateVelUV(F,G,A,B,H)
1918
1918
1919 #---------------------------------------------------------------------
1919 #---------------------------------------------------------------------
1920 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1920 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1921 winds = correctFactor*winds
1921 winds = correctFactor*winds
1922 return winds
1922 return winds
1923
1923
1924 def __checkTime(self, currentTime, paramInterval, outputInterval):
1924 def __checkTime(self, currentTime, paramInterval, outputInterval):
1925
1925
1926 dataTime = currentTime + paramInterval
1926 dataTime = currentTime + paramInterval
1927 deltaTime = dataTime - self.__initime
1927 deltaTime = dataTime - self.__initime
1928
1928
1929 if deltaTime >= outputInterval or deltaTime < 0:
1929 if deltaTime >= outputInterval or deltaTime < 0:
1930 self.__dataReady = True
1930 self.__dataReady = True
1931 return
1931 return
1932
1932
1933 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1933 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1934 '''
1934 '''
1935 Function that implements winds estimation technique with detected meteors.
1935 Function that implements winds estimation technique with detected meteors.
1936
1936
1937 Input: Detected meteors, Minimum meteor quantity to wind estimation
1937 Input: Detected meteors, Minimum meteor quantity to wind estimation
1938
1938
1939 Output: Winds estimation (Zonal and Meridional)
1939 Output: Winds estimation (Zonal and Meridional)
1940
1940
1941 Parameters affected: Winds
1941 Parameters affected: Winds
1942 '''
1942 '''
1943 #Settings
1943 #Settings
1944 nInt = (heightMax - heightMin)/2
1944 nInt = (heightMax - heightMin)/2
1945 nInt = int(nInt)
1945 nInt = int(nInt)
1946 winds = numpy.zeros((2,nInt))*numpy.nan
1946 winds = numpy.zeros((2,nInt))*numpy.nan
1947
1947
1948 #Filter errors
1948 #Filter errors
1949 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1949 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1950 finalMeteor = arrayMeteor[error,:]
1950 finalMeteor = arrayMeteor[error,:]
1951
1951
1952 #Meteor Histogram
1952 #Meteor Histogram
1953 finalHeights = finalMeteor[:,2]
1953 finalHeights = finalMeteor[:,2]
1954 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1954 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1955 nMeteorsPerI = hist[0]
1955 nMeteorsPerI = hist[0]
1956 heightPerI = hist[1]
1956 heightPerI = hist[1]
1957
1957
1958 #Sort of meteors
1958 #Sort of meteors
1959 indSort = finalHeights.argsort()
1959 indSort = finalHeights.argsort()
1960 finalMeteor2 = finalMeteor[indSort,:]
1960 finalMeteor2 = finalMeteor[indSort,:]
1961
1961
1962 # Calculating winds
1962 # Calculating winds
1963 ind1 = 0
1963 ind1 = 0
1964 ind2 = 0
1964 ind2 = 0
1965
1965
1966 for i in range(nInt):
1966 for i in range(nInt):
1967 nMet = nMeteorsPerI[i]
1967 nMet = nMeteorsPerI[i]
1968 ind1 = ind2
1968 ind1 = ind2
1969 ind2 = ind1 + nMet
1969 ind2 = ind1 + nMet
1970
1970
1971 meteorAux = finalMeteor2[ind1:ind2,:]
1971 meteorAux = finalMeteor2[ind1:ind2,:]
1972
1972
1973 if meteorAux.shape[0] >= meteorThresh:
1973 if meteorAux.shape[0] >= meteorThresh:
1974 vel = meteorAux[:, 6]
1974 vel = meteorAux[:, 6]
1975 zen = meteorAux[:, 4]*numpy.pi/180
1975 zen = meteorAux[:, 4]*numpy.pi/180
1976 azim = meteorAux[:, 3]*numpy.pi/180
1976 azim = meteorAux[:, 3]*numpy.pi/180
1977
1977
1978 n = numpy.cos(zen)
1978 n = numpy.cos(zen)
1979 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1979 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1980 # l = m*numpy.tan(azim)
1980 # l = m*numpy.tan(azim)
1981 l = numpy.sin(zen)*numpy.sin(azim)
1981 l = numpy.sin(zen)*numpy.sin(azim)
1982 m = numpy.sin(zen)*numpy.cos(azim)
1982 m = numpy.sin(zen)*numpy.cos(azim)
1983
1983
1984 A = numpy.vstack((l, m)).transpose()
1984 A = numpy.vstack((l, m)).transpose()
1985 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1985 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1986 windsAux = numpy.dot(A1, vel)
1986 windsAux = numpy.dot(A1, vel)
1987
1987
1988 winds[0,i] = windsAux[0]
1988 winds[0,i] = windsAux[0]
1989 winds[1,i] = windsAux[1]
1989 winds[1,i] = windsAux[1]
1990
1990
1991 return winds, heightPerI[:-1]
1991 return winds, heightPerI[:-1]
1992
1992
1993 def techniqueNSM_SA(self, **kwargs):
1993 def techniqueNSM_SA(self, **kwargs):
1994 metArray = kwargs['metArray']
1994 metArray = kwargs['metArray']
1995 heightList = kwargs['heightList']
1995 heightList = kwargs['heightList']
1996 timeList = kwargs['timeList']
1996 timeList = kwargs['timeList']
1997
1997
1998 rx_location = kwargs['rx_location']
1998 rx_location = kwargs['rx_location']
1999 groupList = kwargs['groupList']
1999 groupList = kwargs['groupList']
2000 azimuth = kwargs['azimuth']
2000 azimuth = kwargs['azimuth']
2001 dfactor = kwargs['dfactor']
2001 dfactor = kwargs['dfactor']
2002 k = kwargs['k']
2002 k = kwargs['k']
2003
2003
2004 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
2004 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
2005 d = dist*dfactor
2005 d = dist*dfactor
2006 #Phase calculation
2006 #Phase calculation
2007 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2007 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2008
2008
2009 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2009 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2010
2010
2011 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2011 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2012 azimuth1 = azimuth1*numpy.pi/180
2012 azimuth1 = azimuth1*numpy.pi/180
2013
2013
2014 for i in range(heightList.size):
2014 for i in range(heightList.size):
2015 h = heightList[i]
2015 h = heightList[i]
2016 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2016 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2017 metHeight = metArray1[indH,:]
2017 metHeight = metArray1[indH,:]
2018 if metHeight.shape[0] >= 2:
2018 if metHeight.shape[0] >= 2:
2019 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2019 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2020 iazim = metHeight[:,1].astype(int)
2020 iazim = metHeight[:,1].astype(int)
2021 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2021 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2022 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2022 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2023 A = numpy.asmatrix(A)
2023 A = numpy.asmatrix(A)
2024 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2024 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2025 velHor = numpy.dot(A1,velAux)
2025 velHor = numpy.dot(A1,velAux)
2026
2026
2027 velEst[i,:] = numpy.squeeze(velHor)
2027 velEst[i,:] = numpy.squeeze(velHor)
2028 return velEst
2028 return velEst
2029
2029
2030 def __getPhaseSlope(self, metArray, heightList, timeList):
2030 def __getPhaseSlope(self, metArray, heightList, timeList):
2031 meteorList = []
2031 meteorList = []
2032 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2032 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2033 #Putting back together the meteor matrix
2033 #Putting back together the meteor matrix
2034 utctime = metArray[:,0]
2034 utctime = metArray[:,0]
2035 uniqueTime = numpy.unique(utctime)
2035 uniqueTime = numpy.unique(utctime)
2036
2036
2037 phaseDerThresh = 0.5
2037 phaseDerThresh = 0.5
2038 ippSeconds = timeList[1] - timeList[0]
2038 ippSeconds = timeList[1] - timeList[0]
2039 sec = numpy.where(timeList>1)[0][0]
2039 sec = numpy.where(timeList>1)[0][0]
2040 nPairs = metArray.shape[1] - 6
2040 nPairs = metArray.shape[1] - 6
2041 nHeights = len(heightList)
2041 nHeights = len(heightList)
2042
2042
2043 for t in uniqueTime:
2043 for t in uniqueTime:
2044 metArray1 = metArray[utctime==t,:]
2044 metArray1 = metArray[utctime==t,:]
2045 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2045 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2046 tmet = metArray1[:,1].astype(int)
2046 tmet = metArray1[:,1].astype(int)
2047 hmet = metArray1[:,2].astype(int)
2047 hmet = metArray1[:,2].astype(int)
2048
2048
2049 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2049 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2050 metPhase[:,:] = numpy.nan
2050 metPhase[:,:] = numpy.nan
2051 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2051 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2052
2052
2053 #Delete short trails
2053 #Delete short trails
2054 metBool = ~numpy.isnan(metPhase[0,:,:])
2054 metBool = ~numpy.isnan(metPhase[0,:,:])
2055 heightVect = numpy.sum(metBool, axis = 1)
2055 heightVect = numpy.sum(metBool, axis = 1)
2056 metBool[heightVect<sec,:] = False
2056 metBool[heightVect<sec,:] = False
2057 metPhase[:,heightVect<sec,:] = numpy.nan
2057 metPhase[:,heightVect<sec,:] = numpy.nan
2058
2058
2059 #Derivative
2059 #Derivative
2060 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2060 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2061 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2061 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2062 metPhase[phDerAux] = numpy.nan
2062 metPhase[phDerAux] = numpy.nan
2063
2063
2064 #--------------------------METEOR DETECTION -----------------------------------------
2064 #--------------------------METEOR DETECTION -----------------------------------------
2065 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2065 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2066
2066
2067 for p in numpy.arange(nPairs):
2067 for p in numpy.arange(nPairs):
2068 phase = metPhase[p,:,:]
2068 phase = metPhase[p,:,:]
2069 phDer = metDer[p,:,:]
2069 phDer = metDer[p,:,:]
2070
2070
2071 for h in indMet:
2071 for h in indMet:
2072 height = heightList[h]
2072 height = heightList[h]
2073 phase1 = phase[h,:] #82
2073 phase1 = phase[h,:] #82
2074 phDer1 = phDer[h,:]
2074 phDer1 = phDer[h,:]
2075
2075
2076 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2076 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2077
2077
2078 indValid = numpy.where(~numpy.isnan(phase1))[0]
2078 indValid = numpy.where(~numpy.isnan(phase1))[0]
2079 initMet = indValid[0]
2079 initMet = indValid[0]
2080 endMet = 0
2080 endMet = 0
2081
2081
2082 for i in range(len(indValid)-1):
2082 for i in range(len(indValid)-1):
2083
2083
2084 #Time difference
2084 #Time difference
2085 inow = indValid[i]
2085 inow = indValid[i]
2086 inext = indValid[i+1]
2086 inext = indValid[i+1]
2087 idiff = inext - inow
2087 idiff = inext - inow
2088 #Phase difference
2088 #Phase difference
2089 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2089 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2090
2090
2091 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2091 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2092 sizeTrail = inow - initMet + 1
2092 sizeTrail = inow - initMet + 1
2093 if sizeTrail>3*sec: #Too short meteors
2093 if sizeTrail>3*sec: #Too short meteors
2094 x = numpy.arange(initMet,inow+1)*ippSeconds
2094 x = numpy.arange(initMet,inow+1)*ippSeconds
2095 y = phase1[initMet:inow+1]
2095 y = phase1[initMet:inow+1]
2096 ynnan = ~numpy.isnan(y)
2096 ynnan = ~numpy.isnan(y)
2097 x = x[ynnan]
2097 x = x[ynnan]
2098 y = y[ynnan]
2098 y = y[ynnan]
2099 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2099 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2100 ylin = x*slope + intercept
2100 ylin = x*slope + intercept
2101 rsq = r_value**2
2101 rsq = r_value**2
2102 if rsq > 0.5:
2102 if rsq > 0.5:
2103 vel = slope#*height*1000/(k*d)
2103 vel = slope#*height*1000/(k*d)
2104 estAux = numpy.array([utctime,p,height, vel, rsq])
2104 estAux = numpy.array([utctime,p,height, vel, rsq])
2105 meteorList.append(estAux)
2105 meteorList.append(estAux)
2106 initMet = inext
2106 initMet = inext
2107 metArray2 = numpy.array(meteorList)
2107 metArray2 = numpy.array(meteorList)
2108
2108
2109 return metArray2
2109 return metArray2
2110
2110
2111 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2111 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2112
2112
2113 azimuth1 = numpy.zeros(len(pairslist))
2113 azimuth1 = numpy.zeros(len(pairslist))
2114 dist = numpy.zeros(len(pairslist))
2114 dist = numpy.zeros(len(pairslist))
2115
2115
2116 for i in range(len(rx_location)):
2116 for i in range(len(rx_location)):
2117 ch0 = pairslist[i][0]
2117 ch0 = pairslist[i][0]
2118 ch1 = pairslist[i][1]
2118 ch1 = pairslist[i][1]
2119
2119
2120 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2120 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2121 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2121 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2122 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2122 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2123 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2123 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2124
2124
2125 azimuth1 -= azimuth0
2125 azimuth1 -= azimuth0
2126 return azimuth1, dist
2126 return azimuth1, dist
2127
2127
2128 def techniqueNSM_DBS(self, **kwargs):
2128 def techniqueNSM_DBS(self, **kwargs):
2129 metArray = kwargs['metArray']
2129 metArray = kwargs['metArray']
2130 heightList = kwargs['heightList']
2130 heightList = kwargs['heightList']
2131 timeList = kwargs['timeList']
2131 timeList = kwargs['timeList']
2132 azimuth = kwargs['azimuth']
2132 azimuth = kwargs['azimuth']
2133 theta_x = numpy.array(kwargs['theta_x'])
2133 theta_x = numpy.array(kwargs['theta_x'])
2134 theta_y = numpy.array(kwargs['theta_y'])
2134 theta_y = numpy.array(kwargs['theta_y'])
2135
2135
2136 utctime = metArray[:,0]
2136 utctime = metArray[:,0]
2137 cmet = metArray[:,1].astype(int)
2137 cmet = metArray[:,1].astype(int)
2138 hmet = metArray[:,3].astype(int)
2138 hmet = metArray[:,3].astype(int)
2139 SNRmet = metArray[:,4]
2139 SNRmet = metArray[:,4]
2140 vmet = metArray[:,5]
2140 vmet = metArray[:,5]
2141 spcmet = metArray[:,6]
2141 spcmet = metArray[:,6]
2142
2142
2143 nChan = numpy.max(cmet) + 1
2143 nChan = numpy.max(cmet) + 1
2144 nHeights = len(heightList)
2144 nHeights = len(heightList)
2145
2145
2146 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2146 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2147 hmet = heightList[hmet]
2147 hmet = heightList[hmet]
2148 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2148 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2149
2149
2150 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2150 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2151
2151
2152 for i in range(nHeights - 1):
2152 for i in range(nHeights - 1):
2153 hmin = heightList[i]
2153 hmin = heightList[i]
2154 hmax = heightList[i + 1]
2154 hmax = heightList[i + 1]
2155
2155
2156 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2156 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2157 indthisH = numpy.where(thisH)
2157 indthisH = numpy.where(thisH)
2158
2158
2159 if numpy.size(indthisH) > 3:
2159 if numpy.size(indthisH) > 3:
2160
2160
2161 vel_aux = vmet[thisH]
2161 vel_aux = vmet[thisH]
2162 chan_aux = cmet[thisH]
2162 chan_aux = cmet[thisH]
2163 cosu_aux = dir_cosu[chan_aux]
2163 cosu_aux = dir_cosu[chan_aux]
2164 cosv_aux = dir_cosv[chan_aux]
2164 cosv_aux = dir_cosv[chan_aux]
2165 cosw_aux = dir_cosw[chan_aux]
2165 cosw_aux = dir_cosw[chan_aux]
2166
2166
2167 nch = numpy.size(numpy.unique(chan_aux))
2167 nch = numpy.size(numpy.unique(chan_aux))
2168 if nch > 1:
2168 if nch > 1:
2169 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2169 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2170 velEst[i,:] = numpy.dot(A,vel_aux)
2170 velEst[i,:] = numpy.dot(A,vel_aux)
2171
2171
2172 return velEst
2172 return velEst
2173
2173
2174 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2174 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2175
2175
2176 param = dataOut.data_param
2176 param = dataOut.data_param
2177 if dataOut.abscissaList != None:
2177 if dataOut.abscissaList != None:
2178 absc = dataOut.abscissaList[:-1]
2178 absc = dataOut.abscissaList[:-1]
2179 # noise = dataOut.noise
2179 # noise = dataOut.noise
2180 heightList = dataOut.heightList
2180 heightList = dataOut.heightList
2181 SNR = dataOut.data_snr
2181 SNR = dataOut.data_snr
2182
2182
2183 if technique == 'DBS':
2183 if technique == 'DBS':
2184
2184
2185 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2185 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2186 kwargs['heightList'] = heightList
2186 kwargs['heightList'] = heightList
2187 kwargs['SNR'] = SNR
2187 kwargs['SNR'] = SNR
2188
2188
2189 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2189 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2190 dataOut.utctimeInit = dataOut.utctime
2190 dataOut.utctimeInit = dataOut.utctime
2191 dataOut.outputInterval = dataOut.paramInterval
2191 dataOut.outputInterval = dataOut.paramInterval
2192
2192
2193 elif technique == 'SA':
2193 elif technique == 'SA':
2194
2194
2195 #Parameters
2195 #Parameters
2196 # position_x = kwargs['positionX']
2196 # position_x = kwargs['positionX']
2197 # position_y = kwargs['positionY']
2197 # position_y = kwargs['positionY']
2198 # azimuth = kwargs['azimuth']
2198 # azimuth = kwargs['azimuth']
2199 #
2199 #
2200 # if kwargs.has_key('crosspairsList'):
2200 # if kwargs.has_key('crosspairsList'):
2201 # pairs = kwargs['crosspairsList']
2201 # pairs = kwargs['crosspairsList']
2202 # else:
2202 # else:
2203 # pairs = None
2203 # pairs = None
2204 #
2204 #
2205 # if kwargs.has_key('correctFactor'):
2205 # if kwargs.has_key('correctFactor'):
2206 # correctFactor = kwargs['correctFactor']
2206 # correctFactor = kwargs['correctFactor']
2207 # else:
2207 # else:
2208 # correctFactor = 1
2208 # correctFactor = 1
2209
2209
2210 # tau = dataOut.data_param
2210 # tau = dataOut.data_param
2211 # _lambda = dataOut.C/dataOut.frequency
2211 # _lambda = dataOut.C/dataOut.frequency
2212 # pairsList = dataOut.groupList
2212 # pairsList = dataOut.groupList
2213 # nChannels = dataOut.nChannels
2213 # nChannels = dataOut.nChannels
2214
2214
2215 kwargs['groupList'] = dataOut.groupList
2215 kwargs['groupList'] = dataOut.groupList
2216 kwargs['tau'] = dataOut.data_param
2216 kwargs['tau'] = dataOut.data_param
2217 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2217 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2218 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2218 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2219 dataOut.data_output = self.techniqueSA(kwargs)
2219 dataOut.data_output = self.techniqueSA(kwargs)
2220 dataOut.utctimeInit = dataOut.utctime
2220 dataOut.utctimeInit = dataOut.utctime
2221 dataOut.outputInterval = dataOut.timeInterval
2221 dataOut.outputInterval = dataOut.timeInterval
2222
2222
2223 elif technique == 'Meteors':
2223 elif technique == 'Meteors':
2224 dataOut.flagNoData = True
2224 dataOut.flagNoData = True
2225 self.__dataReady = False
2225 self.__dataReady = False
2226
2226
2227 if 'nHours' in kwargs:
2227 if 'nHours' in kwargs:
2228 nHours = kwargs['nHours']
2228 nHours = kwargs['nHours']
2229 else:
2229 else:
2230 nHours = 1
2230 nHours = 1
2231
2231
2232 if 'meteorsPerBin' in kwargs:
2232 if 'meteorsPerBin' in kwargs:
2233 meteorThresh = kwargs['meteorsPerBin']
2233 meteorThresh = kwargs['meteorsPerBin']
2234 else:
2234 else:
2235 meteorThresh = 6
2235 meteorThresh = 6
2236
2236
2237 if 'hmin' in kwargs:
2237 if 'hmin' in kwargs:
2238 hmin = kwargs['hmin']
2238 hmin = kwargs['hmin']
2239 else: hmin = 70
2239 else: hmin = 70
2240 if 'hmax' in kwargs:
2240 if 'hmax' in kwargs:
2241 hmax = kwargs['hmax']
2241 hmax = kwargs['hmax']
2242 else: hmax = 110
2242 else: hmax = 110
2243
2243
2244 dataOut.outputInterval = nHours*3600
2244 dataOut.outputInterval = nHours*3600
2245
2245
2246 if self.__isConfig == False:
2246 if self.__isConfig == False:
2247 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2247 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2248 #Get Initial LTC time
2248 #Get Initial LTC time
2249 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2249 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2250 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2250 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2251
2251
2252 self.__isConfig = True
2252 self.__isConfig = True
2253
2253
2254 if self.__buffer is None:
2254 if self.__buffer is None:
2255 self.__buffer = dataOut.data_param
2255 self.__buffer = dataOut.data_param
2256 self.__firstdata = copy.copy(dataOut)
2256 self.__firstdata = copy.copy(dataOut)
2257
2257
2258 else:
2258 else:
2259 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2259 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2260
2260
2261 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2261 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2262
2262
2263 if self.__dataReady:
2263 if self.__dataReady:
2264 dataOut.utctimeInit = self.__initime
2264 dataOut.utctimeInit = self.__initime
2265
2265
2266 self.__initime += dataOut.outputInterval #to erase time offset
2266 self.__initime += dataOut.outputInterval #to erase time offset
2267
2267
2268 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2268 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2269 dataOut.flagNoData = False
2269 dataOut.flagNoData = False
2270 self.__buffer = None
2270 self.__buffer = None
2271
2271
2272 elif technique == 'Meteors1':
2272 elif technique == 'Meteors1':
2273 dataOut.flagNoData = True
2273 dataOut.flagNoData = True
2274 self.__dataReady = False
2274 self.__dataReady = False
2275
2275
2276 if 'nMins' in kwargs:
2276 if 'nMins' in kwargs:
2277 nMins = kwargs['nMins']
2277 nMins = kwargs['nMins']
2278 else: nMins = 20
2278 else: nMins = 20
2279 if 'rx_location' in kwargs:
2279 if 'rx_location' in kwargs:
2280 rx_location = kwargs['rx_location']
2280 rx_location = kwargs['rx_location']
2281 else: rx_location = [(0,1),(1,1),(1,0)]
2281 else: rx_location = [(0,1),(1,1),(1,0)]
2282 if 'azimuth' in kwargs:
2282 if 'azimuth' in kwargs:
2283 azimuth = kwargs['azimuth']
2283 azimuth = kwargs['azimuth']
2284 else: azimuth = 51.06
2284 else: azimuth = 51.06
2285 if 'dfactor' in kwargs:
2285 if 'dfactor' in kwargs:
2286 dfactor = kwargs['dfactor']
2286 dfactor = kwargs['dfactor']
2287 if 'mode' in kwargs:
2287 if 'mode' in kwargs:
2288 mode = kwargs['mode']
2288 mode = kwargs['mode']
2289 if 'theta_x' in kwargs:
2289 if 'theta_x' in kwargs:
2290 theta_x = kwargs['theta_x']
2290 theta_x = kwargs['theta_x']
2291 if 'theta_y' in kwargs:
2291 if 'theta_y' in kwargs:
2292 theta_y = kwargs['theta_y']
2292 theta_y = kwargs['theta_y']
2293 else: mode = 'SA'
2293 else: mode = 'SA'
2294
2294
2295 #Borrar luego esto
2295 #Borrar luego esto
2296 if dataOut.groupList is None:
2296 if dataOut.groupList is None:
2297 dataOut.groupList = [(0,1),(0,2),(1,2)]
2297 dataOut.groupList = [(0,1),(0,2),(1,2)]
2298 groupList = dataOut.groupList
2298 groupList = dataOut.groupList
2299 C = 3e8
2299 C = 3e8
2300 freq = 50e6
2300 freq = 50e6
2301 lamb = C/freq
2301 lamb = C/freq
2302 k = 2*numpy.pi/lamb
2302 k = 2*numpy.pi/lamb
2303
2303
2304 timeList = dataOut.abscissaList
2304 timeList = dataOut.abscissaList
2305 heightList = dataOut.heightList
2305 heightList = dataOut.heightList
2306
2306
2307 if self.__isConfig == False:
2307 if self.__isConfig == False:
2308 dataOut.outputInterval = nMins*60
2308 dataOut.outputInterval = nMins*60
2309 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2309 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2310 #Get Initial LTC time
2310 #Get Initial LTC time
2311 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2311 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2312 minuteAux = initime.minute
2312 minuteAux = initime.minute
2313 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2313 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2314 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2314 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2315
2315
2316 self.__isConfig = True
2316 self.__isConfig = True
2317
2317
2318 if self.__buffer is None:
2318 if self.__buffer is None:
2319 self.__buffer = dataOut.data_param
2319 self.__buffer = dataOut.data_param
2320 self.__firstdata = copy.copy(dataOut)
2320 self.__firstdata = copy.copy(dataOut)
2321
2321
2322 else:
2322 else:
2323 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2323 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2324
2324
2325 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2325 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2326
2326
2327 if self.__dataReady:
2327 if self.__dataReady:
2328 dataOut.utctimeInit = self.__initime
2328 dataOut.utctimeInit = self.__initime
2329 self.__initime += dataOut.outputInterval #to erase time offset
2329 self.__initime += dataOut.outputInterval #to erase time offset
2330
2330
2331 metArray = self.__buffer
2331 metArray = self.__buffer
2332 if mode == 'SA':
2332 if mode == 'SA':
2333 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2333 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2334 elif mode == 'DBS':
2334 elif mode == 'DBS':
2335 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2335 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2336 dataOut.data_output = dataOut.data_output.T
2336 dataOut.data_output = dataOut.data_output.T
2337 dataOut.flagNoData = False
2337 dataOut.flagNoData = False
2338 self.__buffer = None
2338 self.__buffer = None
2339
2339
2340 return
2340 return
2341
2341
2342 class EWDriftsEstimation(Operation):
2342 class EWDriftsEstimation(Operation):
2343
2343
2344 def __init__(self):
2344 def __init__(self):
2345 Operation.__init__(self)
2345 Operation.__init__(self)
2346
2346
2347 def __correctValues(self, heiRang, phi, velRadial, SNR):
2347 def __correctValues(self, heiRang, phi, velRadial, SNR):
2348 listPhi = phi.tolist()
2348 listPhi = phi.tolist()
2349 maxid = listPhi.index(max(listPhi))
2349 maxid = listPhi.index(max(listPhi))
2350 minid = listPhi.index(min(listPhi))
2350 minid = listPhi.index(min(listPhi))
2351
2351
2352 rango = list(range(len(phi)))
2352 rango = list(range(len(phi)))
2353 # rango = numpy.delete(rango,maxid)
2353 # rango = numpy.delete(rango,maxid)
2354
2354
2355 heiRang1 = heiRang*math.cos(phi[maxid])
2355 heiRang1 = heiRang*math.cos(phi[maxid])
2356 heiRangAux = heiRang*math.cos(phi[minid])
2356 heiRangAux = heiRang*math.cos(phi[minid])
2357 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2357 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2358 heiRang1 = numpy.delete(heiRang1,indOut)
2358 heiRang1 = numpy.delete(heiRang1,indOut)
2359
2359
2360 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2360 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2361 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2361 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2362
2362
2363 for i in rango:
2363 for i in rango:
2364 x = heiRang*math.cos(phi[i])
2364 x = heiRang*math.cos(phi[i])
2365 y1 = velRadial[i,:]
2365 y1 = velRadial[i,:]
2366 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2366 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2367
2367
2368 x1 = heiRang1
2368 x1 = heiRang1
2369 y11 = f1(x1)
2369 y11 = f1(x1)
2370
2370
2371 y2 = SNR[i,:]
2371 y2 = SNR[i,:]
2372 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2372 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2373 y21 = f2(x1)
2373 y21 = f2(x1)
2374
2374
2375 velRadial1[i,:] = y11
2375 velRadial1[i,:] = y11
2376 SNR1[i,:] = y21
2376 SNR1[i,:] = y21
2377
2377
2378 return heiRang1, velRadial1, SNR1
2378 return heiRang1, velRadial1, SNR1
2379
2379
2380 def run(self, dataOut, zenith, zenithCorrection):
2380 def run(self, dataOut, zenith, zenithCorrection):
2381 heiRang = dataOut.heightList
2381 heiRang = dataOut.heightList
2382 velRadial = dataOut.data_param[:,3,:]
2382 velRadial = dataOut.data_param[:,3,:]
2383 SNR = dataOut.data_snr
2383 SNR = dataOut.data_snr
2384
2384
2385 zenith = numpy.array(zenith)
2385 zenith = numpy.array(zenith)
2386 zenith -= zenithCorrection
2386 zenith -= zenithCorrection
2387 zenith *= numpy.pi/180
2387 zenith *= numpy.pi/180
2388
2388
2389 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2389 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2390
2390
2391 alp = zenith[0]
2391 alp = zenith[0]
2392 bet = zenith[1]
2392 bet = zenith[1]
2393
2393
2394 w_w = velRadial1[0,:]
2394 w_w = velRadial1[0,:]
2395 w_e = velRadial1[1,:]
2395 w_e = velRadial1[1,:]
2396
2396
2397 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2397 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2398 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2398 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2399
2399
2400 winds = numpy.vstack((u,w))
2400 winds = numpy.vstack((u,w))
2401
2401
2402 dataOut.heightList = heiRang1
2402 dataOut.heightList = heiRang1
2403 dataOut.data_output = winds
2403 dataOut.data_output = winds
2404 dataOut.data_snr = SNR1
2404 dataOut.data_snr = SNR1
2405
2405
2406 dataOut.utctimeInit = dataOut.utctime
2406 dataOut.utctimeInit = dataOut.utctime
2407 dataOut.outputInterval = dataOut.timeInterval
2407 dataOut.outputInterval = dataOut.timeInterval
2408 return
2408 return
2409
2409
2410 #--------------- Non Specular Meteor ----------------
2410 #--------------- Non Specular Meteor ----------------
2411
2411
2412 class NonSpecularMeteorDetection(Operation):
2412 class NonSpecularMeteorDetection(Operation):
2413
2413
2414 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2414 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2415 data_acf = dataOut.data_pre[0]
2415 data_acf = dataOut.data_pre[0]
2416 data_ccf = dataOut.data_pre[1]
2416 data_ccf = dataOut.data_pre[1]
2417 pairsList = dataOut.groupList[1]
2417 pairsList = dataOut.groupList[1]
2418
2418
2419 lamb = dataOut.C/dataOut.frequency
2419 lamb = dataOut.C/dataOut.frequency
2420 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2420 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2421 paramInterval = dataOut.paramInterval
2421 paramInterval = dataOut.paramInterval
2422
2422
2423 nChannels = data_acf.shape[0]
2423 nChannels = data_acf.shape[0]
2424 nLags = data_acf.shape[1]
2424 nLags = data_acf.shape[1]
2425 nProfiles = data_acf.shape[2]
2425 nProfiles = data_acf.shape[2]
2426 nHeights = dataOut.nHeights
2426 nHeights = dataOut.nHeights
2427 nCohInt = dataOut.nCohInt
2427 nCohInt = dataOut.nCohInt
2428 sec = numpy.round(nProfiles/dataOut.paramInterval)
2428 sec = numpy.round(nProfiles/dataOut.paramInterval)
2429 heightList = dataOut.heightList
2429 heightList = dataOut.heightList
2430 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2430 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2431 utctime = dataOut.utctime
2431 utctime = dataOut.utctime
2432
2432
2433 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2433 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2434
2434
2435 #------------------------ SNR --------------------------------------
2435 #------------------------ SNR --------------------------------------
2436 power = data_acf[:,0,:,:].real
2436 power = data_acf[:,0,:,:].real
2437 noise = numpy.zeros(nChannels)
2437 noise = numpy.zeros(nChannels)
2438 SNR = numpy.zeros(power.shape)
2438 SNR = numpy.zeros(power.shape)
2439 for i in range(nChannels):
2439 for i in range(nChannels):
2440 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2440 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2441 SNR[i] = (power[i]-noise[i])/noise[i]
2441 SNR[i] = (power[i]-noise[i])/noise[i]
2442 SNRm = numpy.nanmean(SNR, axis = 0)
2442 SNRm = numpy.nanmean(SNR, axis = 0)
2443 SNRdB = 10*numpy.log10(SNR)
2443 SNRdB = 10*numpy.log10(SNR)
2444
2444
2445 if mode == 'SA':
2445 if mode == 'SA':
2446 dataOut.groupList = dataOut.groupList[1]
2446 dataOut.groupList = dataOut.groupList[1]
2447 nPairs = data_ccf.shape[0]
2447 nPairs = data_ccf.shape[0]
2448 #---------------------- Coherence and Phase --------------------------
2448 #---------------------- Coherence and Phase --------------------------
2449 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2449 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2450 # phase1 = numpy.copy(phase)
2450 # phase1 = numpy.copy(phase)
2451 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2451 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2452
2452
2453 for p in range(nPairs):
2453 for p in range(nPairs):
2454 ch0 = pairsList[p][0]
2454 ch0 = pairsList[p][0]
2455 ch1 = pairsList[p][1]
2455 ch1 = pairsList[p][1]
2456 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2456 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2457 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2457 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2458 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2458 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2459 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2459 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2460 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2460 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2461 coh = numpy.nanmax(coh1, axis = 0)
2461 coh = numpy.nanmax(coh1, axis = 0)
2462 # struc = numpy.ones((5,1))
2462 # struc = numpy.ones((5,1))
2463 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2463 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2464 #---------------------- Radial Velocity ----------------------------
2464 #---------------------- Radial Velocity ----------------------------
2465 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2465 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2466 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2466 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2467
2467
2468 if allData:
2468 if allData:
2469 boolMetFin = ~numpy.isnan(SNRm)
2469 boolMetFin = ~numpy.isnan(SNRm)
2470 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2470 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2471 else:
2471 else:
2472 #------------------------ Meteor mask ---------------------------------
2472 #------------------------ Meteor mask ---------------------------------
2473 # #SNR mask
2473 # #SNR mask
2474 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2474 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2475 #
2475 #
2476 # #Erase small objects
2476 # #Erase small objects
2477 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2477 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2478 #
2478 #
2479 # auxEEJ = numpy.sum(boolMet1,axis=0)
2479 # auxEEJ = numpy.sum(boolMet1,axis=0)
2480 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2480 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2481 # indEEJ = numpy.where(indOver)[0]
2481 # indEEJ = numpy.where(indOver)[0]
2482 # indNEEJ = numpy.where(~indOver)[0]
2482 # indNEEJ = numpy.where(~indOver)[0]
2483 #
2483 #
2484 # boolMetFin = boolMet1
2484 # boolMetFin = boolMet1
2485 #
2485 #
2486 # if indEEJ.size > 0:
2486 # if indEEJ.size > 0:
2487 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2487 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2488 #
2488 #
2489 # boolMet2 = coh > cohThresh
2489 # boolMet2 = coh > cohThresh
2490 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2490 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2491 #
2491 #
2492 # #Final Meteor mask
2492 # #Final Meteor mask
2493 # boolMetFin = boolMet1|boolMet2
2493 # boolMetFin = boolMet1|boolMet2
2494
2494
2495 #Coherence mask
2495 #Coherence mask
2496 boolMet1 = coh > 0.75
2496 boolMet1 = coh > 0.75
2497 struc = numpy.ones((30,1))
2497 struc = numpy.ones((30,1))
2498 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2498 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2499
2499
2500 #Derivative mask
2500 #Derivative mask
2501 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2501 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2502 boolMet2 = derPhase < 0.2
2502 boolMet2 = derPhase < 0.2
2503 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2503 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2504 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2504 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2505 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2505 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2506 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2506 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2507 # #Final mask
2507 # #Final mask
2508 # boolMetFin = boolMet2
2508 # boolMetFin = boolMet2
2509 boolMetFin = boolMet1&boolMet2
2509 boolMetFin = boolMet1&boolMet2
2510 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2510 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2511 #Creating data_param
2511 #Creating data_param
2512 coordMet = numpy.where(boolMetFin)
2512 coordMet = numpy.where(boolMetFin)
2513
2513
2514 tmet = coordMet[0]
2514 tmet = coordMet[0]
2515 hmet = coordMet[1]
2515 hmet = coordMet[1]
2516
2516
2517 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2517 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2518 data_param[:,0] = utctime
2518 data_param[:,0] = utctime
2519 data_param[:,1] = tmet
2519 data_param[:,1] = tmet
2520 data_param[:,2] = hmet
2520 data_param[:,2] = hmet
2521 data_param[:,3] = SNRm[tmet,hmet]
2521 data_param[:,3] = SNRm[tmet,hmet]
2522 data_param[:,4] = velRad[tmet,hmet]
2522 data_param[:,4] = velRad[tmet,hmet]
2523 data_param[:,5] = coh[tmet,hmet]
2523 data_param[:,5] = coh[tmet,hmet]
2524 data_param[:,6:] = phase[:,tmet,hmet].T
2524 data_param[:,6:] = phase[:,tmet,hmet].T
2525
2525
2526 elif mode == 'DBS':
2526 elif mode == 'DBS':
2527 dataOut.groupList = numpy.arange(nChannels)
2527 dataOut.groupList = numpy.arange(nChannels)
2528
2528
2529 #Radial Velocities
2529 #Radial Velocities
2530 phase = numpy.angle(data_acf[:,1,:,:])
2530 phase = numpy.angle(data_acf[:,1,:,:])
2531 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2531 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2532 velRad = phase*lamb/(4*numpy.pi*tSamp)
2532 velRad = phase*lamb/(4*numpy.pi*tSamp)
2533
2533
2534 #Spectral width
2534 #Spectral width
2535 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2535 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2536 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2536 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2537 acf1 = data_acf[:,1,:,:]
2537 acf1 = data_acf[:,1,:,:]
2538 acf2 = data_acf[:,2,:,:]
2538 acf2 = data_acf[:,2,:,:]
2539
2539
2540 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2540 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2541 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2541 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2542 if allData:
2542 if allData:
2543 boolMetFin = ~numpy.isnan(SNRdB)
2543 boolMetFin = ~numpy.isnan(SNRdB)
2544 else:
2544 else:
2545 #SNR
2545 #SNR
2546 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2546 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2547 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2547 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2548
2548
2549 #Radial velocity
2549 #Radial velocity
2550 boolMet2 = numpy.abs(velRad) < 20
2550 boolMet2 = numpy.abs(velRad) < 20
2551 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2551 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2552
2552
2553 #Spectral Width
2553 #Spectral Width
2554 boolMet3 = spcWidth < 30
2554 boolMet3 = spcWidth < 30
2555 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2555 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2556 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2556 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2557 boolMetFin = boolMet1&boolMet2&boolMet3
2557 boolMetFin = boolMet1&boolMet2&boolMet3
2558
2558
2559 #Creating data_param
2559 #Creating data_param
2560 coordMet = numpy.where(boolMetFin)
2560 coordMet = numpy.where(boolMetFin)
2561
2561
2562 cmet = coordMet[0]
2562 cmet = coordMet[0]
2563 tmet = coordMet[1]
2563 tmet = coordMet[1]
2564 hmet = coordMet[2]
2564 hmet = coordMet[2]
2565
2565
2566 data_param = numpy.zeros((tmet.size, 7))
2566 data_param = numpy.zeros((tmet.size, 7))
2567 data_param[:,0] = utctime
2567 data_param[:,0] = utctime
2568 data_param[:,1] = cmet
2568 data_param[:,1] = cmet
2569 data_param[:,2] = tmet
2569 data_param[:,2] = tmet
2570 data_param[:,3] = hmet
2570 data_param[:,3] = hmet
2571 data_param[:,4] = SNR[cmet,tmet,hmet].T
2571 data_param[:,4] = SNR[cmet,tmet,hmet].T
2572 data_param[:,5] = velRad[cmet,tmet,hmet].T
2572 data_param[:,5] = velRad[cmet,tmet,hmet].T
2573 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2573 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2574
2574
2575 # self.dataOut.data_param = data_int
2575 # self.dataOut.data_param = data_int
2576 if len(data_param) == 0:
2576 if len(data_param) == 0:
2577 dataOut.flagNoData = True
2577 dataOut.flagNoData = True
2578 else:
2578 else:
2579 dataOut.data_param = data_param
2579 dataOut.data_param = data_param
2580
2580
2581 def __erase_small(self, binArray, threshX, threshY):
2581 def __erase_small(self, binArray, threshX, threshY):
2582 labarray, numfeat = ndimage.measurements.label(binArray)
2582 labarray, numfeat = ndimage.measurements.label(binArray)
2583 binArray1 = numpy.copy(binArray)
2583 binArray1 = numpy.copy(binArray)
2584
2584
2585 for i in range(1,numfeat + 1):
2585 for i in range(1,numfeat + 1):
2586 auxBin = (labarray==i)
2586 auxBin = (labarray==i)
2587 auxSize = auxBin.sum()
2587 auxSize = auxBin.sum()
2588
2588
2589 x,y = numpy.where(auxBin)
2589 x,y = numpy.where(auxBin)
2590 widthX = x.max() - x.min()
2590 widthX = x.max() - x.min()
2591 widthY = y.max() - y.min()
2591 widthY = y.max() - y.min()
2592
2592
2593 #width X: 3 seg -> 12.5*3
2593 #width X: 3 seg -> 12.5*3
2594 #width Y:
2594 #width Y:
2595
2595
2596 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2596 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2597 binArray1[auxBin] = False
2597 binArray1[auxBin] = False
2598
2598
2599 return binArray1
2599 return binArray1
2600
2600
2601 #--------------- Specular Meteor ----------------
2601 #--------------- Specular Meteor ----------------
2602
2602
2603 class SMDetection(Operation):
2603 class SMDetection(Operation):
2604 '''
2604 '''
2605 Function DetectMeteors()
2605 Function DetectMeteors()
2606 Project developed with paper:
2606 Project developed with paper:
2607 HOLDSWORTH ET AL. 2004
2607 HOLDSWORTH ET AL. 2004
2608
2608
2609 Input:
2609 Input:
2610 self.dataOut.data_pre
2610 self.dataOut.data_pre
2611
2611
2612 centerReceiverIndex: From the channels, which is the center receiver
2612 centerReceiverIndex: From the channels, which is the center receiver
2613
2613
2614 hei_ref: Height reference for the Beacon signal extraction
2614 hei_ref: Height reference for the Beacon signal extraction
2615 tauindex:
2615 tauindex:
2616 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2616 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2617
2617
2618 cohDetection: Whether to user Coherent detection or not
2618 cohDetection: Whether to user Coherent detection or not
2619 cohDet_timeStep: Coherent Detection calculation time step
2619 cohDet_timeStep: Coherent Detection calculation time step
2620 cohDet_thresh: Coherent Detection phase threshold to correct phases
2620 cohDet_thresh: Coherent Detection phase threshold to correct phases
2621
2621
2622 noise_timeStep: Noise calculation time step
2622 noise_timeStep: Noise calculation time step
2623 noise_multiple: Noise multiple to define signal threshold
2623 noise_multiple: Noise multiple to define signal threshold
2624
2624
2625 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2625 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2626 multDet_rangeLimit: Multiple Detection Removal range limit in km
2626 multDet_rangeLimit: Multiple Detection Removal range limit in km
2627
2627
2628 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2628 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2629 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2629 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2630
2630
2631 hmin: Minimum Height of the meteor to use it in the further wind estimations
2631 hmin: Minimum Height of the meteor to use it in the further wind estimations
2632 hmax: Maximum Height of the meteor to use it in the further wind estimations
2632 hmax: Maximum Height of the meteor to use it in the further wind estimations
2633 azimuth: Azimuth angle correction
2633 azimuth: Azimuth angle correction
2634
2634
2635 Affected:
2635 Affected:
2636 self.dataOut.data_param
2636 self.dataOut.data_param
2637
2637
2638 Rejection Criteria (Errors):
2638 Rejection Criteria (Errors):
2639 0: No error; analysis OK
2639 0: No error; analysis OK
2640 1: SNR < SNR threshold
2640 1: SNR < SNR threshold
2641 2: angle of arrival (AOA) ambiguously determined
2641 2: angle of arrival (AOA) ambiguously determined
2642 3: AOA estimate not feasible
2642 3: AOA estimate not feasible
2643 4: Large difference in AOAs obtained from different antenna baselines
2643 4: Large difference in AOAs obtained from different antenna baselines
2644 5: echo at start or end of time series
2644 5: echo at start or end of time series
2645 6: echo less than 5 examples long; too short for analysis
2645 6: echo less than 5 examples long; too short for analysis
2646 7: echo rise exceeds 0.3s
2646 7: echo rise exceeds 0.3s
2647 8: echo decay time less than twice rise time
2647 8: echo decay time less than twice rise time
2648 9: large power level before echo
2648 9: large power level before echo
2649 10: large power level after echo
2649 10: large power level after echo
2650 11: poor fit to amplitude for estimation of decay time
2650 11: poor fit to amplitude for estimation of decay time
2651 12: poor fit to CCF phase variation for estimation of radial drift velocity
2651 12: poor fit to CCF phase variation for estimation of radial drift velocity
2652 13: height unresolvable echo: not valid height within 70 to 110 km
2652 13: height unresolvable echo: not valid height within 70 to 110 km
2653 14: height ambiguous echo: more then one possible height within 70 to 110 km
2653 14: height ambiguous echo: more then one possible height within 70 to 110 km
2654 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2654 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2655 16: oscilatory echo, indicating event most likely not an underdense echo
2655 16: oscilatory echo, indicating event most likely not an underdense echo
2656
2656
2657 17: phase difference in meteor Reestimation
2657 17: phase difference in meteor Reestimation
2658
2658
2659 Data Storage:
2659 Data Storage:
2660 Meteors for Wind Estimation (8):
2660 Meteors for Wind Estimation (8):
2661 Utc Time | Range Height
2661 Utc Time | Range Height
2662 Azimuth Zenith errorCosDir
2662 Azimuth Zenith errorCosDir
2663 VelRad errorVelRad
2663 VelRad errorVelRad
2664 Phase0 Phase1 Phase2 Phase3
2664 Phase0 Phase1 Phase2 Phase3
2665 TypeError
2665 TypeError
2666
2666
2667 '''
2667 '''
2668
2668
2669 def run(self, dataOut, hei_ref = None, tauindex = 0,
2669 def run(self, dataOut, hei_ref = None, tauindex = 0,
2670 phaseOffsets = None,
2670 phaseOffsets = None,
2671 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2671 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2672 noise_timeStep = 4, noise_multiple = 4,
2672 noise_timeStep = 4, noise_multiple = 4,
2673 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2673 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2674 phaseThresh = 20, SNRThresh = 5,
2674 phaseThresh = 20, SNRThresh = 5,
2675 hmin = 50, hmax=150, azimuth = 0,
2675 hmin = 50, hmax=150, azimuth = 0,
2676 channelPositions = None) :
2676 channelPositions = None) :
2677
2677
2678
2678
2679 #Getting Pairslist
2679 #Getting Pairslist
2680 if channelPositions is None:
2680 if channelPositions is None:
2681 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2681 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2682 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2682 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2683 meteorOps = SMOperations()
2683 meteorOps = SMOperations()
2684 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2684 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2685 heiRang = dataOut.heightList
2685 heiRang = dataOut.heightList
2686 #Get Beacon signal - No Beacon signal anymore
2686 #Get Beacon signal - No Beacon signal anymore
2687 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2687 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2688 #
2688 #
2689 # if hei_ref != None:
2689 # if hei_ref != None:
2690 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2690 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2691 #
2691 #
2692
2692
2693
2693
2694 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2694 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2695 # see if the user put in pre defined phase shifts
2695 # see if the user put in pre defined phase shifts
2696 voltsPShift = dataOut.data_pre.copy()
2696 voltsPShift = dataOut.data_pre.copy()
2697
2697
2698 # if predefinedPhaseShifts != None:
2698 # if predefinedPhaseShifts != None:
2699 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2699 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2700 #
2700 #
2701 # # elif beaconPhaseShifts:
2701 # # elif beaconPhaseShifts:
2702 # # #get hardware phase shifts using beacon signal
2702 # # #get hardware phase shifts using beacon signal
2703 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2703 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2704 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2704 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2705 #
2705 #
2706 # else:
2706 # else:
2707 # hardwarePhaseShifts = numpy.zeros(5)
2707 # hardwarePhaseShifts = numpy.zeros(5)
2708 #
2708 #
2709 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2709 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2710 # for i in range(self.dataOut.data_pre.shape[0]):
2710 # for i in range(self.dataOut.data_pre.shape[0]):
2711 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2711 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2712
2712
2713 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2713 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2714
2714
2715 #Remove DC
2715 #Remove DC
2716 voltsDC = numpy.mean(voltsPShift,1)
2716 voltsDC = numpy.mean(voltsPShift,1)
2717 voltsDC = numpy.mean(voltsDC,1)
2717 voltsDC = numpy.mean(voltsDC,1)
2718 for i in range(voltsDC.shape[0]):
2718 for i in range(voltsDC.shape[0]):
2719 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2719 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2720
2720
2721 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2721 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2722 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2722 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2723
2723
2724 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2724 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2725 #Coherent Detection
2725 #Coherent Detection
2726 if cohDetection:
2726 if cohDetection:
2727 #use coherent detection to get the net power
2727 #use coherent detection to get the net power
2728 cohDet_thresh = cohDet_thresh*numpy.pi/180
2728 cohDet_thresh = cohDet_thresh*numpy.pi/180
2729 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2729 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2730
2730
2731 #Non-coherent detection!
2731 #Non-coherent detection!
2732 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2732 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2733 #********** END OF COH/NON-COH POWER CALCULATION**********************
2733 #********** END OF COH/NON-COH POWER CALCULATION**********************
2734
2734
2735 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2735 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2736 #Get noise
2736 #Get noise
2737 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2737 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2738 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2738 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2739 #Get signal threshold
2739 #Get signal threshold
2740 signalThresh = noise_multiple*noise
2740 signalThresh = noise_multiple*noise
2741 #Meteor echoes detection
2741 #Meteor echoes detection
2742 listMeteors = self.__findMeteors(powerNet, signalThresh)
2742 listMeteors = self.__findMeteors(powerNet, signalThresh)
2743 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2743 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2744
2744
2745 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2745 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2746 #Parameters
2746 #Parameters
2747 heiRange = dataOut.heightList
2747 heiRange = dataOut.heightList
2748 rangeInterval = heiRange[1] - heiRange[0]
2748 rangeInterval = heiRange[1] - heiRange[0]
2749 rangeLimit = multDet_rangeLimit/rangeInterval
2749 rangeLimit = multDet_rangeLimit/rangeInterval
2750 timeLimit = multDet_timeLimit/dataOut.timeInterval
2750 timeLimit = multDet_timeLimit/dataOut.timeInterval
2751 #Multiple detection removals
2751 #Multiple detection removals
2752 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2752 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2753 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2753 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2754
2754
2755 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2755 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2756 #Parameters
2756 #Parameters
2757 phaseThresh = phaseThresh*numpy.pi/180
2757 phaseThresh = phaseThresh*numpy.pi/180
2758 thresh = [phaseThresh, noise_multiple, SNRThresh]
2758 thresh = [phaseThresh, noise_multiple, SNRThresh]
2759 #Meteor reestimation (Errors N 1, 6, 12, 17)
2759 #Meteor reestimation (Errors N 1, 6, 12, 17)
2760 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2760 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2761 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2761 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2762 #Estimation of decay times (Errors N 7, 8, 11)
2762 #Estimation of decay times (Errors N 7, 8, 11)
2763 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2763 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2764 #******************* END OF METEOR REESTIMATION *******************
2764 #******************* END OF METEOR REESTIMATION *******************
2765
2765
2766 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2766 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2767 #Calculating Radial Velocity (Error N 15)
2767 #Calculating Radial Velocity (Error N 15)
2768 radialStdThresh = 10
2768 radialStdThresh = 10
2769 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2769 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2770
2770
2771 if len(listMeteors4) > 0:
2771 if len(listMeteors4) > 0:
2772 #Setting New Array
2772 #Setting New Array
2773 date = dataOut.utctime
2773 date = dataOut.utctime
2774 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2774 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2775
2775
2776 #Correcting phase offset
2776 #Correcting phase offset
2777 if phaseOffsets != None:
2777 if phaseOffsets != None:
2778 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2778 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2779 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2779 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2780
2780
2781 #Second Pairslist
2781 #Second Pairslist
2782 pairsList = []
2782 pairsList = []
2783 pairx = (0,1)
2783 pairx = (0,1)
2784 pairy = (2,3)
2784 pairy = (2,3)
2785 pairsList.append(pairx)
2785 pairsList.append(pairx)
2786 pairsList.append(pairy)
2786 pairsList.append(pairy)
2787
2787
2788 jph = numpy.array([0,0,0,0])
2788 jph = numpy.array([0,0,0,0])
2789 h = (hmin,hmax)
2789 h = (hmin,hmax)
2790 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2790 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2791
2791
2792 # #Calculate AOA (Error N 3, 4)
2792 # #Calculate AOA (Error N 3, 4)
2793 # #JONES ET AL. 1998
2793 # #JONES ET AL. 1998
2794 # error = arrayParameters[:,-1]
2794 # error = arrayParameters[:,-1]
2795 # AOAthresh = numpy.pi/8
2795 # AOAthresh = numpy.pi/8
2796 # phases = -arrayParameters[:,9:13]
2796 # phases = -arrayParameters[:,9:13]
2797 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2797 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2798 #
2798 #
2799 # #Calculate Heights (Error N 13 and 14)
2799 # #Calculate Heights (Error N 13 and 14)
2800 # error = arrayParameters[:,-1]
2800 # error = arrayParameters[:,-1]
2801 # Ranges = arrayParameters[:,2]
2801 # Ranges = arrayParameters[:,2]
2802 # zenith = arrayParameters[:,5]
2802 # zenith = arrayParameters[:,5]
2803 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2803 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2804 # error = arrayParameters[:,-1]
2804 # error = arrayParameters[:,-1]
2805 #********************* END OF PARAMETERS CALCULATION **************************
2805 #********************* END OF PARAMETERS CALCULATION **************************
2806
2806
2807 #***************************+ PASS DATA TO NEXT STEP **********************
2807 #***************************+ PASS DATA TO NEXT STEP **********************
2808 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2808 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2809 dataOut.data_param = arrayParameters
2809 dataOut.data_param = arrayParameters
2810
2810
2811 if arrayParameters is None:
2811 if arrayParameters is None:
2812 dataOut.flagNoData = True
2812 dataOut.flagNoData = True
2813 else:
2813 else:
2814 dataOut.flagNoData = True
2814 dataOut.flagNoData = True
2815
2815
2816 return
2816 return
2817
2817
2818 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2818 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2819
2819
2820 minIndex = min(newheis[0])
2820 minIndex = min(newheis[0])
2821 maxIndex = max(newheis[0])
2821 maxIndex = max(newheis[0])
2822
2822
2823 voltage = voltage0[:,:,minIndex:maxIndex+1]
2823 voltage = voltage0[:,:,minIndex:maxIndex+1]
2824 nLength = voltage.shape[1]/n
2824 nLength = voltage.shape[1]/n
2825 nMin = 0
2825 nMin = 0
2826 nMax = 0
2826 nMax = 0
2827 phaseOffset = numpy.zeros((len(pairslist),n))
2827 phaseOffset = numpy.zeros((len(pairslist),n))
2828
2828
2829 for i in range(n):
2829 for i in range(n):
2830 nMax += nLength
2830 nMax += nLength
2831 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2831 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2832 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2832 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2833 phaseOffset[:,i] = phaseCCF.transpose()
2833 phaseOffset[:,i] = phaseCCF.transpose()
2834 nMin = nMax
2834 nMin = nMax
2835 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2835 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2836
2836
2837 #Remove Outliers
2837 #Remove Outliers
2838 factor = 2
2838 factor = 2
2839 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2839 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2840 dw = numpy.std(wt,axis = 1)
2840 dw = numpy.std(wt,axis = 1)
2841 dw = dw.reshape((dw.size,1))
2841 dw = dw.reshape((dw.size,1))
2842 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2842 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2843 phaseOffset[ind] = numpy.nan
2843 phaseOffset[ind] = numpy.nan
2844 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2844 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2845
2845
2846 return phaseOffset
2846 return phaseOffset
2847
2847
2848 def __shiftPhase(self, data, phaseShift):
2848 def __shiftPhase(self, data, phaseShift):
2849 #this will shift the phase of a complex number
2849 #this will shift the phase of a complex number
2850 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2850 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2851 return dataShifted
2851 return dataShifted
2852
2852
2853 def __estimatePhaseDifference(self, array, pairslist):
2853 def __estimatePhaseDifference(self, array, pairslist):
2854 nChannel = array.shape[0]
2854 nChannel = array.shape[0]
2855 nHeights = array.shape[2]
2855 nHeights = array.shape[2]
2856 numPairs = len(pairslist)
2856 numPairs = len(pairslist)
2857 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2857 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2858 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2858 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2859
2859
2860 #Correct phases
2860 #Correct phases
2861 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2861 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2862 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2862 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2863
2863
2864 if indDer[0].shape[0] > 0:
2864 if indDer[0].shape[0] > 0:
2865 for i in range(indDer[0].shape[0]):
2865 for i in range(indDer[0].shape[0]):
2866 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2866 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2867 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2867 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2868
2868
2869 # for j in range(numSides):
2869 # for j in range(numSides):
2870 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2870 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2871 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2871 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2872 #
2872 #
2873 #Linear
2873 #Linear
2874 phaseInt = numpy.zeros((numPairs,1))
2874 phaseInt = numpy.zeros((numPairs,1))
2875 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2875 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2876 for j in range(numPairs):
2876 for j in range(numPairs):
2877 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2877 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2878 phaseInt[j] = fit[1]
2878 phaseInt[j] = fit[1]
2879 #Phase Differences
2879 #Phase Differences
2880 phaseDiff = phaseInt - phaseCCF[:,2,:]
2880 phaseDiff = phaseInt - phaseCCF[:,2,:]
2881 phaseArrival = phaseInt.reshape(phaseInt.size)
2881 phaseArrival = phaseInt.reshape(phaseInt.size)
2882
2882
2883 #Dealias
2883 #Dealias
2884 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2884 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2885 # indAlias = numpy.where(phaseArrival > numpy.pi)
2885 # indAlias = numpy.where(phaseArrival > numpy.pi)
2886 # phaseArrival[indAlias] -= 2*numpy.pi
2886 # phaseArrival[indAlias] -= 2*numpy.pi
2887 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2887 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2888 # phaseArrival[indAlias] += 2*numpy.pi
2888 # phaseArrival[indAlias] += 2*numpy.pi
2889
2889
2890 return phaseDiff, phaseArrival
2890 return phaseDiff, phaseArrival
2891
2891
2892 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2892 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2893 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2893 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2894 #find the phase shifts of each channel over 1 second intervals
2894 #find the phase shifts of each channel over 1 second intervals
2895 #only look at ranges below the beacon signal
2895 #only look at ranges below the beacon signal
2896 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2896 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2897 numBlocks = int(volts.shape[1]/numProfPerBlock)
2897 numBlocks = int(volts.shape[1]/numProfPerBlock)
2898 numHeights = volts.shape[2]
2898 numHeights = volts.shape[2]
2899 nChannel = volts.shape[0]
2899 nChannel = volts.shape[0]
2900 voltsCohDet = volts.copy()
2900 voltsCohDet = volts.copy()
2901
2901
2902 pairsarray = numpy.array(pairslist)
2902 pairsarray = numpy.array(pairslist)
2903 indSides = pairsarray[:,1]
2903 indSides = pairsarray[:,1]
2904 # indSides = numpy.array(range(nChannel))
2904 # indSides = numpy.array(range(nChannel))
2905 # indSides = numpy.delete(indSides, indCenter)
2905 # indSides = numpy.delete(indSides, indCenter)
2906 #
2906 #
2907 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2907 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2908 listBlocks = numpy.array_split(volts, numBlocks, 1)
2908 listBlocks = numpy.array_split(volts, numBlocks, 1)
2909
2909
2910 startInd = 0
2910 startInd = 0
2911 endInd = 0
2911 endInd = 0
2912
2912
2913 for i in range(numBlocks):
2913 for i in range(numBlocks):
2914 startInd = endInd
2914 startInd = endInd
2915 endInd = endInd + listBlocks[i].shape[1]
2915 endInd = endInd + listBlocks[i].shape[1]
2916
2916
2917 arrayBlock = listBlocks[i]
2917 arrayBlock = listBlocks[i]
2918 # arrayBlockCenter = listCenter[i]
2918 # arrayBlockCenter = listCenter[i]
2919
2919
2920 #Estimate the Phase Difference
2920 #Estimate the Phase Difference
2921 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2921 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2922 #Phase Difference RMS
2922 #Phase Difference RMS
2923 arrayPhaseRMS = numpy.abs(phaseDiff)
2923 arrayPhaseRMS = numpy.abs(phaseDiff)
2924 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2924 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2925 indPhase = numpy.where(phaseRMSaux==4)
2925 indPhase = numpy.where(phaseRMSaux==4)
2926 #Shifting
2926 #Shifting
2927 if indPhase[0].shape[0] > 0:
2927 if indPhase[0].shape[0] > 0:
2928 for j in range(indSides.size):
2928 for j in range(indSides.size):
2929 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2929 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2930 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2930 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2931
2931
2932 return voltsCohDet
2932 return voltsCohDet
2933
2933
2934 def __calculateCCF(self, volts, pairslist ,laglist):
2934 def __calculateCCF(self, volts, pairslist ,laglist):
2935
2935
2936 nHeights = volts.shape[2]
2936 nHeights = volts.shape[2]
2937 nPoints = volts.shape[1]
2937 nPoints = volts.shape[1]
2938 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2938 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2939
2939
2940 for i in range(len(pairslist)):
2940 for i in range(len(pairslist)):
2941 volts1 = volts[pairslist[i][0]]
2941 volts1 = volts[pairslist[i][0]]
2942 volts2 = volts[pairslist[i][1]]
2942 volts2 = volts[pairslist[i][1]]
2943
2943
2944 for t in range(len(laglist)):
2944 for t in range(len(laglist)):
2945 idxT = laglist[t]
2945 idxT = laglist[t]
2946 if idxT >= 0:
2946 if idxT >= 0:
2947 vStacked = numpy.vstack((volts2[idxT:,:],
2947 vStacked = numpy.vstack((volts2[idxT:,:],
2948 numpy.zeros((idxT, nHeights),dtype='complex')))
2948 numpy.zeros((idxT, nHeights),dtype='complex')))
2949 else:
2949 else:
2950 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2950 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2951 volts2[:(nPoints + idxT),:]))
2951 volts2[:(nPoints + idxT),:]))
2952 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2952 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2953
2953
2954 vStacked = None
2954 vStacked = None
2955 return voltsCCF
2955 return voltsCCF
2956
2956
2957 def __getNoise(self, power, timeSegment, timeInterval):
2957 def __getNoise(self, power, timeSegment, timeInterval):
2958 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2958 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2959 numBlocks = int(power.shape[0]/numProfPerBlock)
2959 numBlocks = int(power.shape[0]/numProfPerBlock)
2960 numHeights = power.shape[1]
2960 numHeights = power.shape[1]
2961
2961
2962 listPower = numpy.array_split(power, numBlocks, 0)
2962 listPower = numpy.array_split(power, numBlocks, 0)
2963 noise = numpy.zeros((power.shape[0], power.shape[1]))
2963 noise = numpy.zeros((power.shape[0], power.shape[1]))
2964 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2964 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2965
2965
2966 startInd = 0
2966 startInd = 0
2967 endInd = 0
2967 endInd = 0
2968
2968
2969 for i in range(numBlocks): #split por canal
2969 for i in range(numBlocks): #split por canal
2970 startInd = endInd
2970 startInd = endInd
2971 endInd = endInd + listPower[i].shape[0]
2971 endInd = endInd + listPower[i].shape[0]
2972
2972
2973 arrayBlock = listPower[i]
2973 arrayBlock = listPower[i]
2974 noiseAux = numpy.mean(arrayBlock, 0)
2974 noiseAux = numpy.mean(arrayBlock, 0)
2975 # noiseAux = numpy.median(noiseAux)
2975 # noiseAux = numpy.median(noiseAux)
2976 # noiseAux = numpy.mean(arrayBlock)
2976 # noiseAux = numpy.mean(arrayBlock)
2977 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2977 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2978
2978
2979 noiseAux1 = numpy.mean(arrayBlock)
2979 noiseAux1 = numpy.mean(arrayBlock)
2980 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2980 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2981
2981
2982 return noise, noise1
2982 return noise, noise1
2983
2983
2984 def __findMeteors(self, power, thresh):
2984 def __findMeteors(self, power, thresh):
2985 nProf = power.shape[0]
2985 nProf = power.shape[0]
2986 nHeights = power.shape[1]
2986 nHeights = power.shape[1]
2987 listMeteors = []
2987 listMeteors = []
2988
2988
2989 for i in range(nHeights):
2989 for i in range(nHeights):
2990 powerAux = power[:,i]
2990 powerAux = power[:,i]
2991 threshAux = thresh[:,i]
2991 threshAux = thresh[:,i]
2992
2992
2993 indUPthresh = numpy.where(powerAux > threshAux)[0]
2993 indUPthresh = numpy.where(powerAux > threshAux)[0]
2994 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2994 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2995
2995
2996 j = 0
2996 j = 0
2997
2997
2998 while (j < indUPthresh.size - 2):
2998 while (j < indUPthresh.size - 2):
2999 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2999 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
3000 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
3000 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
3001 indDNthresh = indDNthresh[indDNAux]
3001 indDNthresh = indDNthresh[indDNAux]
3002
3002
3003 if (indDNthresh.size > 0):
3003 if (indDNthresh.size > 0):
3004 indEnd = indDNthresh[0] - 1
3004 indEnd = indDNthresh[0] - 1
3005 indInit = indUPthresh[j]
3005 indInit = indUPthresh[j]
3006
3006
3007 meteor = powerAux[indInit:indEnd + 1]
3007 meteor = powerAux[indInit:indEnd + 1]
3008 indPeak = meteor.argmax() + indInit
3008 indPeak = meteor.argmax() + indInit
3009 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3009 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3010
3010
3011 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3011 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3012 j = numpy.where(indUPthresh == indEnd)[0] + 1
3012 j = numpy.where(indUPthresh == indEnd)[0] + 1
3013 else: j+=1
3013 else: j+=1
3014 else: j+=1
3014 else: j+=1
3015
3015
3016 return listMeteors
3016 return listMeteors
3017
3017
3018 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3018 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3019
3019
3020 arrayMeteors = numpy.asarray(listMeteors)
3020 arrayMeteors = numpy.asarray(listMeteors)
3021 listMeteors1 = []
3021 listMeteors1 = []
3022
3022
3023 while arrayMeteors.shape[0] > 0:
3023 while arrayMeteors.shape[0] > 0:
3024 FLAs = arrayMeteors[:,4]
3024 FLAs = arrayMeteors[:,4]
3025 maxFLA = FLAs.argmax()
3025 maxFLA = FLAs.argmax()
3026 listMeteors1.append(arrayMeteors[maxFLA,:])
3026 listMeteors1.append(arrayMeteors[maxFLA,:])
3027
3027
3028 MeteorInitTime = arrayMeteors[maxFLA,1]
3028 MeteorInitTime = arrayMeteors[maxFLA,1]
3029 MeteorEndTime = arrayMeteors[maxFLA,3]
3029 MeteorEndTime = arrayMeteors[maxFLA,3]
3030 MeteorHeight = arrayMeteors[maxFLA,0]
3030 MeteorHeight = arrayMeteors[maxFLA,0]
3031
3031
3032 #Check neighborhood
3032 #Check neighborhood
3033 maxHeightIndex = MeteorHeight + rangeLimit
3033 maxHeightIndex = MeteorHeight + rangeLimit
3034 minHeightIndex = MeteorHeight - rangeLimit
3034 minHeightIndex = MeteorHeight - rangeLimit
3035 minTimeIndex = MeteorInitTime - timeLimit
3035 minTimeIndex = MeteorInitTime - timeLimit
3036 maxTimeIndex = MeteorEndTime + timeLimit
3036 maxTimeIndex = MeteorEndTime + timeLimit
3037
3037
3038 #Check Heights
3038 #Check Heights
3039 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3039 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3040 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3040 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3041 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3041 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3042
3042
3043 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3043 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3044
3044
3045 return listMeteors1
3045 return listMeteors1
3046
3046
3047 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3047 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3048 numHeights = volts.shape[2]
3048 numHeights = volts.shape[2]
3049 nChannel = volts.shape[0]
3049 nChannel = volts.shape[0]
3050
3050
3051 thresholdPhase = thresh[0]
3051 thresholdPhase = thresh[0]
3052 thresholdNoise = thresh[1]
3052 thresholdNoise = thresh[1]
3053 thresholdDB = float(thresh[2])
3053 thresholdDB = float(thresh[2])
3054
3054
3055 thresholdDB1 = 10**(thresholdDB/10)
3055 thresholdDB1 = 10**(thresholdDB/10)
3056 pairsarray = numpy.array(pairslist)
3056 pairsarray = numpy.array(pairslist)
3057 indSides = pairsarray[:,1]
3057 indSides = pairsarray[:,1]
3058
3058
3059 pairslist1 = list(pairslist)
3059 pairslist1 = list(pairslist)
3060 pairslist1.append((0,1))
3060 pairslist1.append((0,1))
3061 pairslist1.append((3,4))
3061 pairslist1.append((3,4))
3062
3062
3063 listMeteors1 = []
3063 listMeteors1 = []
3064 listPowerSeries = []
3064 listPowerSeries = []
3065 listVoltageSeries = []
3065 listVoltageSeries = []
3066 #volts has the war data
3066 #volts has the war data
3067
3067
3068 if frequency == 30e6:
3068 if frequency == 30e6:
3069 timeLag = 45*10**-3
3069 timeLag = 45*10**-3
3070 else:
3070 else:
3071 timeLag = 15*10**-3
3071 timeLag = 15*10**-3
3072 lag = numpy.ceil(timeLag/timeInterval)
3072 lag = numpy.ceil(timeLag/timeInterval)
3073
3073
3074 for i in range(len(listMeteors)):
3074 for i in range(len(listMeteors)):
3075
3075
3076 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3076 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3077 meteorAux = numpy.zeros(16)
3077 meteorAux = numpy.zeros(16)
3078
3078
3079 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3079 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3080 mHeight = listMeteors[i][0]
3080 mHeight = listMeteors[i][0]
3081 mStart = listMeteors[i][1]
3081 mStart = listMeteors[i][1]
3082 mPeak = listMeteors[i][2]
3082 mPeak = listMeteors[i][2]
3083 mEnd = listMeteors[i][3]
3083 mEnd = listMeteors[i][3]
3084
3084
3085 #get the volt data between the start and end times of the meteor
3085 #get the volt data between the start and end times of the meteor
3086 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3086 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3087 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3087 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3088
3088
3089 #3.6. Phase Difference estimation
3089 #3.6. Phase Difference estimation
3090 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3090 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3091
3091
3092 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3092 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3093 #meteorVolts0.- all Channels, all Profiles
3093 #meteorVolts0.- all Channels, all Profiles
3094 meteorVolts0 = volts[:,:,mHeight]
3094 meteorVolts0 = volts[:,:,mHeight]
3095 meteorThresh = noise[:,mHeight]*thresholdNoise
3095 meteorThresh = noise[:,mHeight]*thresholdNoise
3096 meteorNoise = noise[:,mHeight]
3096 meteorNoise = noise[:,mHeight]
3097 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3097 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3098 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3098 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3099
3099
3100 #Times reestimation
3100 #Times reestimation
3101 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3101 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3102 if mStart1.size > 0:
3102 if mStart1.size > 0:
3103 mStart1 = mStart1[-1] + 1
3103 mStart1 = mStart1[-1] + 1
3104
3104
3105 else:
3105 else:
3106 mStart1 = mPeak
3106 mStart1 = mPeak
3107
3107
3108 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3108 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3109 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3109 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3110 if mEndDecayTime1.size == 0:
3110 if mEndDecayTime1.size == 0:
3111 mEndDecayTime1 = powerNet0.size
3111 mEndDecayTime1 = powerNet0.size
3112 else:
3112 else:
3113 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3113 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3114 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3114 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3115
3115
3116 #meteorVolts1.- all Channels, from start to end
3116 #meteorVolts1.- all Channels, from start to end
3117 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3117 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3118 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3118 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3119 if meteorVolts2.shape[1] == 0:
3119 if meteorVolts2.shape[1] == 0:
3120 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3120 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3121 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3121 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3122 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3122 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3123 ##################### END PARAMETERS REESTIMATION #########################
3123 ##################### END PARAMETERS REESTIMATION #########################
3124
3124
3125 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3125 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3126 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3126 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3127 if meteorVolts2.shape[1] > 0:
3127 if meteorVolts2.shape[1] > 0:
3128 #Phase Difference re-estimation
3128 #Phase Difference re-estimation
3129 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3129 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3130 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3130 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3131 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3131 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3132 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3132 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3133 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3133 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3134
3134
3135 #Phase Difference RMS
3135 #Phase Difference RMS
3136 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3136 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3137 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3137 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3138 #Data from Meteor
3138 #Data from Meteor
3139 mPeak1 = powerNet1.argmax() + mStart1
3139 mPeak1 = powerNet1.argmax() + mStart1
3140 mPeakPower1 = powerNet1.max()
3140 mPeakPower1 = powerNet1.max()
3141 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3141 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3142 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3142 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3143 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3143 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3144 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3144 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3145 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3145 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3146 #Vectorize
3146 #Vectorize
3147 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3147 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3148 meteorAux[7:11] = phaseDiffint[0:4]
3148 meteorAux[7:11] = phaseDiffint[0:4]
3149
3149
3150 #Rejection Criterions
3150 #Rejection Criterions
3151 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3151 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3152 meteorAux[-1] = 17
3152 meteorAux[-1] = 17
3153 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3153 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3154 meteorAux[-1] = 1
3154 meteorAux[-1] = 1
3155
3155
3156
3156
3157 else:
3157 else:
3158 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3158 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3159 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3159 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3160 PowerSeries = 0
3160 PowerSeries = 0
3161
3161
3162 listMeteors1.append(meteorAux)
3162 listMeteors1.append(meteorAux)
3163 listPowerSeries.append(PowerSeries)
3163 listPowerSeries.append(PowerSeries)
3164 listVoltageSeries.append(meteorVolts1)
3164 listVoltageSeries.append(meteorVolts1)
3165
3165
3166 return listMeteors1, listPowerSeries, listVoltageSeries
3166 return listMeteors1, listPowerSeries, listVoltageSeries
3167
3167
3168 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3168 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3169
3169
3170 threshError = 10
3170 threshError = 10
3171 #Depending if it is 30 or 50 MHz
3171 #Depending if it is 30 or 50 MHz
3172 if frequency == 30e6:
3172 if frequency == 30e6:
3173 timeLag = 45*10**-3
3173 timeLag = 45*10**-3
3174 else:
3174 else:
3175 timeLag = 15*10**-3
3175 timeLag = 15*10**-3
3176 lag = numpy.ceil(timeLag/timeInterval)
3176 lag = numpy.ceil(timeLag/timeInterval)
3177
3177
3178 listMeteors1 = []
3178 listMeteors1 = []
3179
3179
3180 for i in range(len(listMeteors)):
3180 for i in range(len(listMeteors)):
3181 meteorPower = listPower[i]
3181 meteorPower = listPower[i]
3182 meteorAux = listMeteors[i]
3182 meteorAux = listMeteors[i]
3183
3183
3184 if meteorAux[-1] == 0:
3184 if meteorAux[-1] == 0:
3185
3185
3186 try:
3186 try:
3187 indmax = meteorPower.argmax()
3187 indmax = meteorPower.argmax()
3188 indlag = indmax + lag
3188 indlag = indmax + lag
3189
3189
3190 y = meteorPower[indlag:]
3190 y = meteorPower[indlag:]
3191 x = numpy.arange(0, y.size)*timeLag
3191 x = numpy.arange(0, y.size)*timeLag
3192
3192
3193 #first guess
3193 #first guess
3194 a = y[0]
3194 a = y[0]
3195 tau = timeLag
3195 tau = timeLag
3196 #exponential fit
3196 #exponential fit
3197 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3197 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3198 y1 = self.__exponential_function(x, *popt)
3198 y1 = self.__exponential_function(x, *popt)
3199 #error estimation
3199 #error estimation
3200 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3200 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3201
3201
3202 decayTime = popt[1]
3202 decayTime = popt[1]
3203 riseTime = indmax*timeInterval
3203 riseTime = indmax*timeInterval
3204 meteorAux[11:13] = [decayTime, error]
3204 meteorAux[11:13] = [decayTime, error]
3205
3205
3206 #Table items 7, 8 and 11
3206 #Table items 7, 8 and 11
3207 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3207 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3208 meteorAux[-1] = 7
3208 meteorAux[-1] = 7
3209 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3209 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3210 meteorAux[-1] = 8
3210 meteorAux[-1] = 8
3211 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3211 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3212 meteorAux[-1] = 11
3212 meteorAux[-1] = 11
3213
3213
3214
3214
3215 except:
3215 except:
3216 meteorAux[-1] = 11
3216 meteorAux[-1] = 11
3217
3217
3218
3218
3219 listMeteors1.append(meteorAux)
3219 listMeteors1.append(meteorAux)
3220
3220
3221 return listMeteors1
3221 return listMeteors1
3222
3222
3223 #Exponential Function
3223 #Exponential Function
3224
3224
3225 def __exponential_function(self, x, a, tau):
3225 def __exponential_function(self, x, a, tau):
3226 y = a*numpy.exp(-x/tau)
3226 y = a*numpy.exp(-x/tau)
3227 return y
3227 return y
3228
3228
3229 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3229 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3230
3230
3231 pairslist1 = list(pairslist)
3231 pairslist1 = list(pairslist)
3232 pairslist1.append((0,1))
3232 pairslist1.append((0,1))
3233 pairslist1.append((3,4))
3233 pairslist1.append((3,4))
3234 numPairs = len(pairslist1)
3234 numPairs = len(pairslist1)
3235 #Time Lag
3235 #Time Lag
3236 timeLag = 45*10**-3
3236 timeLag = 45*10**-3
3237 c = 3e8
3237 c = 3e8
3238 lag = numpy.ceil(timeLag/timeInterval)
3238 lag = numpy.ceil(timeLag/timeInterval)
3239 freq = 30e6
3239 freq = 30e6
3240
3240
3241 listMeteors1 = []
3241 listMeteors1 = []
3242
3242
3243 for i in range(len(listMeteors)):
3243 for i in range(len(listMeteors)):
3244 meteorAux = listMeteors[i]
3244 meteorAux = listMeteors[i]
3245 if meteorAux[-1] == 0:
3245 if meteorAux[-1] == 0:
3246 mStart = listMeteors[i][1]
3246 mStart = listMeteors[i][1]
3247 mPeak = listMeteors[i][2]
3247 mPeak = listMeteors[i][2]
3248 mLag = mPeak - mStart + lag
3248 mLag = mPeak - mStart + lag
3249
3249
3250 #get the volt data between the start and end times of the meteor
3250 #get the volt data between the start and end times of the meteor
3251 meteorVolts = listVolts[i]
3251 meteorVolts = listVolts[i]
3252 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3252 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3253
3253
3254 #Get CCF
3254 #Get CCF
3255 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3255 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3256
3256
3257 #Method 2
3257 #Method 2
3258 slopes = numpy.zeros(numPairs)
3258 slopes = numpy.zeros(numPairs)
3259 time = numpy.array([-2,-1,1,2])*timeInterval
3259 time = numpy.array([-2,-1,1,2])*timeInterval
3260 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3260 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3261
3261
3262 #Correct phases
3262 #Correct phases
3263 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3263 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3264 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3264 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3265
3265
3266 if indDer[0].shape[0] > 0:
3266 if indDer[0].shape[0] > 0:
3267 for i in range(indDer[0].shape[0]):
3267 for i in range(indDer[0].shape[0]):
3268 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3268 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3269 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3269 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3270
3270
3271 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3271 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3272 for j in range(numPairs):
3272 for j in range(numPairs):
3273 fit = stats.linregress(time, angAllCCF[j,:])
3273 fit = stats.linregress(time, angAllCCF[j,:])
3274 slopes[j] = fit[0]
3274 slopes[j] = fit[0]
3275
3275
3276 #Remove Outlier
3276 #Remove Outlier
3277 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3277 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3278 # slopes = numpy.delete(slopes,indOut)
3278 # slopes = numpy.delete(slopes,indOut)
3279 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3279 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3280 # slopes = numpy.delete(slopes,indOut)
3280 # slopes = numpy.delete(slopes,indOut)
3281
3281
3282 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3282 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3283 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3283 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3284 meteorAux[-2] = radialError
3284 meteorAux[-2] = radialError
3285 meteorAux[-3] = radialVelocity
3285 meteorAux[-3] = radialVelocity
3286
3286
3287 #Setting Error
3287 #Setting Error
3288 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3288 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3289 if numpy.abs(radialVelocity) > 200:
3289 if numpy.abs(radialVelocity) > 200:
3290 meteorAux[-1] = 15
3290 meteorAux[-1] = 15
3291 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3291 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3292 elif radialError > radialStdThresh:
3292 elif radialError > radialStdThresh:
3293 meteorAux[-1] = 12
3293 meteorAux[-1] = 12
3294
3294
3295 listMeteors1.append(meteorAux)
3295 listMeteors1.append(meteorAux)
3296 return listMeteors1
3296 return listMeteors1
3297
3297
3298 def __setNewArrays(self, listMeteors, date, heiRang):
3298 def __setNewArrays(self, listMeteors, date, heiRang):
3299
3299
3300 #New arrays
3300 #New arrays
3301 arrayMeteors = numpy.array(listMeteors)
3301 arrayMeteors = numpy.array(listMeteors)
3302 arrayParameters = numpy.zeros((len(listMeteors), 13))
3302 arrayParameters = numpy.zeros((len(listMeteors), 13))
3303
3303
3304 #Date inclusion
3304 #Date inclusion
3305 # date = re.findall(r'\((.*?)\)', date)
3305 # date = re.findall(r'\((.*?)\)', date)
3306 # date = date[0].split(',')
3306 # date = date[0].split(',')
3307 # date = map(int, date)
3307 # date = map(int, date)
3308 #
3308 #
3309 # if len(date)<6:
3309 # if len(date)<6:
3310 # date.append(0)
3310 # date.append(0)
3311 #
3311 #
3312 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3312 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3313 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3313 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3314 arrayDate = numpy.tile(date, (len(listMeteors)))
3314 arrayDate = numpy.tile(date, (len(listMeteors)))
3315
3315
3316 #Meteor array
3316 #Meteor array
3317 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3317 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3318 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3318 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3319
3319
3320 #Parameters Array
3320 #Parameters Array
3321 arrayParameters[:,0] = arrayDate #Date
3321 arrayParameters[:,0] = arrayDate #Date
3322 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3322 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3323 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3323 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3324 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3324 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3325 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3325 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3326
3326
3327
3327
3328 return arrayParameters
3328 return arrayParameters
3329
3329
3330 class CorrectSMPhases(Operation):
3330 class CorrectSMPhases(Operation):
3331
3331
3332 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3332 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3333
3333
3334 arrayParameters = dataOut.data_param
3334 arrayParameters = dataOut.data_param
3335 pairsList = []
3335 pairsList = []
3336 pairx = (0,1)
3336 pairx = (0,1)
3337 pairy = (2,3)
3337 pairy = (2,3)
3338 pairsList.append(pairx)
3338 pairsList.append(pairx)
3339 pairsList.append(pairy)
3339 pairsList.append(pairy)
3340 jph = numpy.zeros(4)
3340 jph = numpy.zeros(4)
3341
3341
3342 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3342 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3343 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3343 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3344 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3344 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3345
3345
3346 meteorOps = SMOperations()
3346 meteorOps = SMOperations()
3347 if channelPositions is None:
3347 if channelPositions is None:
3348 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3348 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3349 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3349 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3350
3350
3351 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3351 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3352 h = (hmin,hmax)
3352 h = (hmin,hmax)
3353
3353
3354 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3354 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3355
3355
3356 dataOut.data_param = arrayParameters
3356 dataOut.data_param = arrayParameters
3357 return
3357 return
3358
3358
3359 class SMPhaseCalibration(Operation):
3359 class SMPhaseCalibration(Operation):
3360
3360
3361 __buffer = None
3361 __buffer = None
3362
3362
3363 __initime = None
3363 __initime = None
3364
3364
3365 __dataReady = False
3365 __dataReady = False
3366
3366
3367 __isConfig = False
3367 __isConfig = False
3368
3368
3369 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3369 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3370
3370
3371 dataTime = currentTime + paramInterval
3371 dataTime = currentTime + paramInterval
3372 deltaTime = dataTime - initTime
3372 deltaTime = dataTime - initTime
3373
3373
3374 if deltaTime >= outputInterval or deltaTime < 0:
3374 if deltaTime >= outputInterval or deltaTime < 0:
3375 return True
3375 return True
3376
3376
3377 return False
3377 return False
3378
3378
3379 def __getGammas(self, pairs, d, phases):
3379 def __getGammas(self, pairs, d, phases):
3380 gammas = numpy.zeros(2)
3380 gammas = numpy.zeros(2)
3381
3381
3382 for i in range(len(pairs)):
3382 for i in range(len(pairs)):
3383
3383
3384 pairi = pairs[i]
3384 pairi = pairs[i]
3385
3385
3386 phip3 = phases[:,pairi[0]]
3386 phip3 = phases[:,pairi[0]]
3387 d3 = d[pairi[0]]
3387 d3 = d[pairi[0]]
3388 phip2 = phases[:,pairi[1]]
3388 phip2 = phases[:,pairi[1]]
3389 d2 = d[pairi[1]]
3389 d2 = d[pairi[1]]
3390 #Calculating gamma
3390 #Calculating gamma
3391 # jdcos = alp1/(k*d1)
3391 # jdcos = alp1/(k*d1)
3392 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3392 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3393 jgamma = -phip2*d3/d2 - phip3
3393 jgamma = -phip2*d3/d2 - phip3
3394 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3394 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3395 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3395 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3396 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3396 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3397
3397
3398 #Revised distribution
3398 #Revised distribution
3399 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3399 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3400
3400
3401 #Histogram
3401 #Histogram
3402 nBins = 64
3402 nBins = 64
3403 rmin = -0.5*numpy.pi
3403 rmin = -0.5*numpy.pi
3404 rmax = 0.5*numpy.pi
3404 rmax = 0.5*numpy.pi
3405 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3405 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3406
3406
3407 meteorsY = phaseHisto[0]
3407 meteorsY = phaseHisto[0]
3408 phasesX = phaseHisto[1][:-1]
3408 phasesX = phaseHisto[1][:-1]
3409 width = phasesX[1] - phasesX[0]
3409 width = phasesX[1] - phasesX[0]
3410 phasesX += width/2
3410 phasesX += width/2
3411
3411
3412 #Gaussian aproximation
3412 #Gaussian aproximation
3413 bpeak = meteorsY.argmax()
3413 bpeak = meteorsY.argmax()
3414 peak = meteorsY.max()
3414 peak = meteorsY.max()
3415 jmin = bpeak - 5
3415 jmin = bpeak - 5
3416 jmax = bpeak + 5 + 1
3416 jmax = bpeak + 5 + 1
3417
3417
3418 if jmin<0:
3418 if jmin<0:
3419 jmin = 0
3419 jmin = 0
3420 jmax = 6
3420 jmax = 6
3421 elif jmax > meteorsY.size:
3421 elif jmax > meteorsY.size:
3422 jmin = meteorsY.size - 6
3422 jmin = meteorsY.size - 6
3423 jmax = meteorsY.size
3423 jmax = meteorsY.size
3424
3424
3425 x0 = numpy.array([peak,bpeak,50])
3425 x0 = numpy.array([peak,bpeak,50])
3426 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3426 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3427
3427
3428 #Gammas
3428 #Gammas
3429 gammas[i] = coeff[0][1]
3429 gammas[i] = coeff[0][1]
3430
3430
3431 return gammas
3431 return gammas
3432
3432
3433 def __residualFunction(self, coeffs, y, t):
3433 def __residualFunction(self, coeffs, y, t):
3434
3434
3435 return y - self.__gauss_function(t, coeffs)
3435 return y - self.__gauss_function(t, coeffs)
3436
3436
3437 def __gauss_function(self, t, coeffs):
3437 def __gauss_function(self, t, coeffs):
3438
3438
3439 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3439 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3440
3440
3441 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3441 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3442 meteorOps = SMOperations()
3442 meteorOps = SMOperations()
3443 nchan = 4
3443 nchan = 4
3444 pairx = pairsList[0] #x es 0
3444 pairx = pairsList[0] #x es 0
3445 pairy = pairsList[1] #y es 1
3445 pairy = pairsList[1] #y es 1
3446 center_xangle = 0
3446 center_xangle = 0
3447 center_yangle = 0
3447 center_yangle = 0
3448 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3448 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3449 ntimes = len(range_angle)
3449 ntimes = len(range_angle)
3450
3450
3451 nstepsx = 20
3451 nstepsx = 20
3452 nstepsy = 20
3452 nstepsy = 20
3453
3453
3454 for iz in range(ntimes):
3454 for iz in range(ntimes):
3455 min_xangle = -range_angle[iz]/2 + center_xangle
3455 min_xangle = -range_angle[iz]/2 + center_xangle
3456 max_xangle = range_angle[iz]/2 + center_xangle
3456 max_xangle = range_angle[iz]/2 + center_xangle
3457 min_yangle = -range_angle[iz]/2 + center_yangle
3457 min_yangle = -range_angle[iz]/2 + center_yangle
3458 max_yangle = range_angle[iz]/2 + center_yangle
3458 max_yangle = range_angle[iz]/2 + center_yangle
3459
3459
3460 inc_x = (max_xangle-min_xangle)/nstepsx
3460 inc_x = (max_xangle-min_xangle)/nstepsx
3461 inc_y = (max_yangle-min_yangle)/nstepsy
3461 inc_y = (max_yangle-min_yangle)/nstepsy
3462
3462
3463 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3463 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3464 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3464 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3465 penalty = numpy.zeros((nstepsx,nstepsy))
3465 penalty = numpy.zeros((nstepsx,nstepsy))
3466 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3466 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3467 jph = numpy.zeros(nchan)
3467 jph = numpy.zeros(nchan)
3468
3468
3469 # Iterations looking for the offset
3469 # Iterations looking for the offset
3470 for iy in range(int(nstepsy)):
3470 for iy in range(int(nstepsy)):
3471 for ix in range(int(nstepsx)):
3471 for ix in range(int(nstepsx)):
3472 d3 = d[pairsList[1][0]]
3472 d3 = d[pairsList[1][0]]
3473 d2 = d[pairsList[1][1]]
3473 d2 = d[pairsList[1][1]]
3474 d5 = d[pairsList[0][0]]
3474 d5 = d[pairsList[0][0]]
3475 d4 = d[pairsList[0][1]]
3475 d4 = d[pairsList[0][1]]
3476
3476
3477 alp2 = alpha_y[iy] #gamma 1
3477 alp2 = alpha_y[iy] #gamma 1
3478 alp4 = alpha_x[ix] #gamma 0
3478 alp4 = alpha_x[ix] #gamma 0
3479
3479
3480 alp3 = -alp2*d3/d2 - gammas[1]
3480 alp3 = -alp2*d3/d2 - gammas[1]
3481 alp5 = -alp4*d5/d4 - gammas[0]
3481 alp5 = -alp4*d5/d4 - gammas[0]
3482 # jph[pairy[1]] = alpha_y[iy]
3482 # jph[pairy[1]] = alpha_y[iy]
3483 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3483 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3484
3484
3485 # jph[pairx[1]] = alpha_x[ix]
3485 # jph[pairx[1]] = alpha_x[ix]
3486 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3486 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3487 jph[pairsList[0][1]] = alp4
3487 jph[pairsList[0][1]] = alp4
3488 jph[pairsList[0][0]] = alp5
3488 jph[pairsList[0][0]] = alp5
3489 jph[pairsList[1][0]] = alp3
3489 jph[pairsList[1][0]] = alp3
3490 jph[pairsList[1][1]] = alp2
3490 jph[pairsList[1][1]] = alp2
3491 jph_array[:,ix,iy] = jph
3491 jph_array[:,ix,iy] = jph
3492 # d = [2.0,2.5,2.5,2.0]
3492 # d = [2.0,2.5,2.5,2.0]
3493 #falta chequear si va a leer bien los meteoros
3493 #falta chequear si va a leer bien los meteoros
3494 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3494 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3495 error = meteorsArray1[:,-1]
3495 error = meteorsArray1[:,-1]
3496 ind1 = numpy.where(error==0)[0]
3496 ind1 = numpy.where(error==0)[0]
3497 penalty[ix,iy] = ind1.size
3497 penalty[ix,iy] = ind1.size
3498
3498
3499 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3499 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3500 phOffset = jph_array[:,i,j]
3500 phOffset = jph_array[:,i,j]
3501
3501
3502 center_xangle = phOffset[pairx[1]]
3502 center_xangle = phOffset[pairx[1]]
3503 center_yangle = phOffset[pairy[1]]
3503 center_yangle = phOffset[pairy[1]]
3504
3504
3505 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3505 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3506 phOffset = phOffset*180/numpy.pi
3506 phOffset = phOffset*180/numpy.pi
3507 return phOffset
3507 return phOffset
3508
3508
3509
3509
3510 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3510 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3511
3511
3512 dataOut.flagNoData = True
3512 dataOut.flagNoData = True
3513 self.__dataReady = False
3513 self.__dataReady = False
3514 dataOut.outputInterval = nHours*3600
3514 dataOut.outputInterval = nHours*3600
3515
3515
3516 if self.__isConfig == False:
3516 if self.__isConfig == False:
3517 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3517 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3518 #Get Initial LTC time
3518 #Get Initial LTC time
3519 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3519 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3520 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3520 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3521
3521
3522 self.__isConfig = True
3522 self.__isConfig = True
3523
3523
3524 if self.__buffer is None:
3524 if self.__buffer is None:
3525 self.__buffer = dataOut.data_param.copy()
3525 self.__buffer = dataOut.data_param.copy()
3526
3526
3527 else:
3527 else:
3528 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3528 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3529
3529
3530 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3530 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3531
3531
3532 if self.__dataReady:
3532 if self.__dataReady:
3533 dataOut.utctimeInit = self.__initime
3533 dataOut.utctimeInit = self.__initime
3534 self.__initime += dataOut.outputInterval #to erase time offset
3534 self.__initime += dataOut.outputInterval #to erase time offset
3535
3535
3536 freq = dataOut.frequency
3536 freq = dataOut.frequency
3537 c = dataOut.C #m/s
3537 c = dataOut.C #m/s
3538 lamb = c/freq
3538 lamb = c/freq
3539 k = 2*numpy.pi/lamb
3539 k = 2*numpy.pi/lamb
3540 azimuth = 0
3540 azimuth = 0
3541 h = (hmin, hmax)
3541 h = (hmin, hmax)
3542 # pairs = ((0,1),(2,3)) #Estrella
3542 # pairs = ((0,1),(2,3)) #Estrella
3543 # pairs = ((1,0),(2,3)) #T
3543 # pairs = ((1,0),(2,3)) #T
3544
3544
3545 if channelPositions is None:
3545 if channelPositions is None:
3546 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3546 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3547 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3547 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3548 meteorOps = SMOperations()
3548 meteorOps = SMOperations()
3549 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3549 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3550
3550
3551 #Checking correct order of pairs
3551 #Checking correct order of pairs
3552 pairs = []
3552 pairs = []
3553 if distances[1] > distances[0]:
3553 if distances[1] > distances[0]:
3554 pairs.append((1,0))
3554 pairs.append((1,0))
3555 else:
3555 else:
3556 pairs.append((0,1))
3556 pairs.append((0,1))
3557
3557
3558 if distances[3] > distances[2]:
3558 if distances[3] > distances[2]:
3559 pairs.append((3,2))
3559 pairs.append((3,2))
3560 else:
3560 else:
3561 pairs.append((2,3))
3561 pairs.append((2,3))
3562 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3562 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3563
3563
3564 meteorsArray = self.__buffer
3564 meteorsArray = self.__buffer
3565 error = meteorsArray[:,-1]
3565 error = meteorsArray[:,-1]
3566 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3566 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3567 ind1 = numpy.where(boolError)[0]
3567 ind1 = numpy.where(boolError)[0]
3568 meteorsArray = meteorsArray[ind1,:]
3568 meteorsArray = meteorsArray[ind1,:]
3569 meteorsArray[:,-1] = 0
3569 meteorsArray[:,-1] = 0
3570 phases = meteorsArray[:,8:12]
3570 phases = meteorsArray[:,8:12]
3571
3571
3572 #Calculate Gammas
3572 #Calculate Gammas
3573 gammas = self.__getGammas(pairs, distances, phases)
3573 gammas = self.__getGammas(pairs, distances, phases)
3574 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3574 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3575 #Calculate Phases
3575 #Calculate Phases
3576 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3576 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3577 phasesOff = phasesOff.reshape((1,phasesOff.size))
3577 phasesOff = phasesOff.reshape((1,phasesOff.size))
3578 dataOut.data_output = -phasesOff
3578 dataOut.data_output = -phasesOff
3579 dataOut.flagNoData = False
3579 dataOut.flagNoData = False
3580 self.__buffer = None
3580 self.__buffer = None
3581
3581
3582
3582
3583 return
3583 return
3584
3584
3585 class SMOperations():
3585 class SMOperations():
3586
3586
3587 def __init__(self):
3587 def __init__(self):
3588
3588
3589 return
3589 return
3590
3590
3591 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3591 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3592
3592
3593 arrayParameters = arrayParameters0.copy()
3593 arrayParameters = arrayParameters0.copy()
3594 hmin = h[0]
3594 hmin = h[0]
3595 hmax = h[1]
3595 hmax = h[1]
3596
3596
3597 #Calculate AOA (Error N 3, 4)
3597 #Calculate AOA (Error N 3, 4)
3598 #JONES ET AL. 1998
3598 #JONES ET AL. 1998
3599 AOAthresh = numpy.pi/8
3599 AOAthresh = numpy.pi/8
3600 error = arrayParameters[:,-1]
3600 error = arrayParameters[:,-1]
3601 phases = -arrayParameters[:,8:12] + jph
3601 phases = -arrayParameters[:,8:12] + jph
3602 # phases = numpy.unwrap(phases)
3602 # phases = numpy.unwrap(phases)
3603 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3603 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3604
3604
3605 #Calculate Heights (Error N 13 and 14)
3605 #Calculate Heights (Error N 13 and 14)
3606 error = arrayParameters[:,-1]
3606 error = arrayParameters[:,-1]
3607 Ranges = arrayParameters[:,1]
3607 Ranges = arrayParameters[:,1]
3608 zenith = arrayParameters[:,4]
3608 zenith = arrayParameters[:,4]
3609 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3609 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3610
3610
3611 #----------------------- Get Final data ------------------------------------
3611 #----------------------- Get Final data ------------------------------------
3612 # error = arrayParameters[:,-1]
3612 # error = arrayParameters[:,-1]
3613 # ind1 = numpy.where(error==0)[0]
3613 # ind1 = numpy.where(error==0)[0]
3614 # arrayParameters = arrayParameters[ind1,:]
3614 # arrayParameters = arrayParameters[ind1,:]
3615
3615
3616 return arrayParameters
3616 return arrayParameters
3617
3617
3618 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3618 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3619
3619
3620 arrayAOA = numpy.zeros((phases.shape[0],3))
3620 arrayAOA = numpy.zeros((phases.shape[0],3))
3621 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3621 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3622
3622
3623 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3623 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3624 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3624 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3625 arrayAOA[:,2] = cosDirError
3625 arrayAOA[:,2] = cosDirError
3626
3626
3627 azimuthAngle = arrayAOA[:,0]
3627 azimuthAngle = arrayAOA[:,0]
3628 zenithAngle = arrayAOA[:,1]
3628 zenithAngle = arrayAOA[:,1]
3629
3629
3630 #Setting Error
3630 #Setting Error
3631 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3631 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3632 error[indError] = 0
3632 error[indError] = 0
3633 #Number 3: AOA not fesible
3633 #Number 3: AOA not fesible
3634 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3634 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3635 error[indInvalid] = 3
3635 error[indInvalid] = 3
3636 #Number 4: Large difference in AOAs obtained from different antenna baselines
3636 #Number 4: Large difference in AOAs obtained from different antenna baselines
3637 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3637 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3638 error[indInvalid] = 4
3638 error[indInvalid] = 4
3639 return arrayAOA, error
3639 return arrayAOA, error
3640
3640
3641 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3641 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3642
3642
3643 #Initializing some variables
3643 #Initializing some variables
3644 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3644 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3645 ang_aux = ang_aux.reshape(1,ang_aux.size)
3645 ang_aux = ang_aux.reshape(1,ang_aux.size)
3646
3646
3647 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3647 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3648 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3648 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3649
3649
3650
3650
3651 for i in range(2):
3651 for i in range(2):
3652 ph0 = arrayPhase[:,pairsList[i][0]]
3652 ph0 = arrayPhase[:,pairsList[i][0]]
3653 ph1 = arrayPhase[:,pairsList[i][1]]
3653 ph1 = arrayPhase[:,pairsList[i][1]]
3654 d0 = distances[pairsList[i][0]]
3654 d0 = distances[pairsList[i][0]]
3655 d1 = distances[pairsList[i][1]]
3655 d1 = distances[pairsList[i][1]]
3656
3656
3657 ph0_aux = ph0 + ph1
3657 ph0_aux = ph0 + ph1
3658 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3658 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3659 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3659 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3660 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3660 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3661 #First Estimation
3661 #First Estimation
3662 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3662 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3663
3663
3664 #Most-Accurate Second Estimation
3664 #Most-Accurate Second Estimation
3665 phi1_aux = ph0 - ph1
3665 phi1_aux = ph0 - ph1
3666 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3666 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3667 #Direction Cosine 1
3667 #Direction Cosine 1
3668 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3668 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3669
3669
3670 #Searching the correct Direction Cosine
3670 #Searching the correct Direction Cosine
3671 cosdir0_aux = cosdir0[:,i]
3671 cosdir0_aux = cosdir0[:,i]
3672 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3672 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3673 #Minimum Distance
3673 #Minimum Distance
3674 cosDiff = (cosdir1 - cosdir0_aux)**2
3674 cosDiff = (cosdir1 - cosdir0_aux)**2
3675 indcos = cosDiff.argmin(axis = 1)
3675 indcos = cosDiff.argmin(axis = 1)
3676 #Saving Value obtained
3676 #Saving Value obtained
3677 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3677 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3678
3678
3679 return cosdir0, cosdir
3679 return cosdir0, cosdir
3680
3680
3681 def __calculateAOA(self, cosdir, azimuth):
3681 def __calculateAOA(self, cosdir, azimuth):
3682 cosdirX = cosdir[:,0]
3682 cosdirX = cosdir[:,0]
3683 cosdirY = cosdir[:,1]
3683 cosdirY = cosdir[:,1]
3684
3684
3685 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3685 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3686 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3686 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3687 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3687 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3688
3688
3689 return angles
3689 return angles
3690
3690
3691 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3691 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3692
3692
3693 Ramb = 375 #Ramb = c/(2*PRF)
3693 Ramb = 375 #Ramb = c/(2*PRF)
3694 Re = 6371 #Earth Radius
3694 Re = 6371 #Earth Radius
3695 heights = numpy.zeros(Ranges.shape)
3695 heights = numpy.zeros(Ranges.shape)
3696
3696
3697 R_aux = numpy.array([0,1,2])*Ramb
3697 R_aux = numpy.array([0,1,2])*Ramb
3698 R_aux = R_aux.reshape(1,R_aux.size)
3698 R_aux = R_aux.reshape(1,R_aux.size)
3699
3699
3700 Ranges = Ranges.reshape(Ranges.size,1)
3700 Ranges = Ranges.reshape(Ranges.size,1)
3701
3701
3702 Ri = Ranges + R_aux
3702 Ri = Ranges + R_aux
3703 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3703 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3704
3704
3705 #Check if there is a height between 70 and 110 km
3705 #Check if there is a height between 70 and 110 km
3706 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3706 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3707 ind_h = numpy.where(h_bool == 1)[0]
3707 ind_h = numpy.where(h_bool == 1)[0]
3708
3708
3709 hCorr = hi[ind_h, :]
3709 hCorr = hi[ind_h, :]
3710 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3710 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3711
3711
3712 hCorr = hi[ind_hCorr][:len(ind_h)]
3712 hCorr = hi[ind_hCorr][:len(ind_h)]
3713 heights[ind_h] = hCorr
3713 heights[ind_h] = hCorr
3714
3714
3715 #Setting Error
3715 #Setting Error
3716 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3716 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3717 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3717 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3718 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3718 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3719 error[indError] = 0
3719 error[indError] = 0
3720 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3720 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3721 error[indInvalid2] = 14
3721 error[indInvalid2] = 14
3722 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3722 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3723 error[indInvalid1] = 13
3723 error[indInvalid1] = 13
3724
3724
3725 return heights, error
3725 return heights, error
3726
3726
3727 def getPhasePairs(self, channelPositions):
3727 def getPhasePairs(self, channelPositions):
3728 chanPos = numpy.array(channelPositions)
3728 chanPos = numpy.array(channelPositions)
3729 listOper = list(itertools.combinations(list(range(5)),2))
3729 listOper = list(itertools.combinations(list(range(5)),2))
3730
3730
3731 distances = numpy.zeros(4)
3731 distances = numpy.zeros(4)
3732 axisX = []
3732 axisX = []
3733 axisY = []
3733 axisY = []
3734 distX = numpy.zeros(3)
3734 distX = numpy.zeros(3)
3735 distY = numpy.zeros(3)
3735 distY = numpy.zeros(3)
3736 ix = 0
3736 ix = 0
3737 iy = 0
3737 iy = 0
3738
3738
3739 pairX = numpy.zeros((2,2))
3739 pairX = numpy.zeros((2,2))
3740 pairY = numpy.zeros((2,2))
3740 pairY = numpy.zeros((2,2))
3741
3741
3742 for i in range(len(listOper)):
3742 for i in range(len(listOper)):
3743 pairi = listOper[i]
3743 pairi = listOper[i]
3744
3744
3745 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3745 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3746
3746
3747 if posDif[0] == 0:
3747 if posDif[0] == 0:
3748 axisY.append(pairi)
3748 axisY.append(pairi)
3749 distY[iy] = posDif[1]
3749 distY[iy] = posDif[1]
3750 iy += 1
3750 iy += 1
3751 elif posDif[1] == 0:
3751 elif posDif[1] == 0:
3752 axisX.append(pairi)
3752 axisX.append(pairi)
3753 distX[ix] = posDif[0]
3753 distX[ix] = posDif[0]
3754 ix += 1
3754 ix += 1
3755
3755
3756 for i in range(2):
3756 for i in range(2):
3757 if i==0:
3757 if i==0:
3758 dist0 = distX
3758 dist0 = distX
3759 axis0 = axisX
3759 axis0 = axisX
3760 else:
3760 else:
3761 dist0 = distY
3761 dist0 = distY
3762 axis0 = axisY
3762 axis0 = axisY
3763
3763
3764 side = numpy.argsort(dist0)[:-1]
3764 side = numpy.argsort(dist0)[:-1]
3765 axis0 = numpy.array(axis0)[side,:]
3765 axis0 = numpy.array(axis0)[side,:]
3766 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3766 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3767 axis1 = numpy.unique(numpy.reshape(axis0,4))
3767 axis1 = numpy.unique(numpy.reshape(axis0,4))
3768 side = axis1[axis1 != chanC]
3768 side = axis1[axis1 != chanC]
3769 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3769 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3770 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3770 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3771 if diff1<0:
3771 if diff1<0:
3772 chan2 = side[0]
3772 chan2 = side[0]
3773 d2 = numpy.abs(diff1)
3773 d2 = numpy.abs(diff1)
3774 chan1 = side[1]
3774 chan1 = side[1]
3775 d1 = numpy.abs(diff2)
3775 d1 = numpy.abs(diff2)
3776 else:
3776 else:
3777 chan2 = side[1]
3777 chan2 = side[1]
3778 d2 = numpy.abs(diff2)
3778 d2 = numpy.abs(diff2)
3779 chan1 = side[0]
3779 chan1 = side[0]
3780 d1 = numpy.abs(diff1)
3780 d1 = numpy.abs(diff1)
3781
3781
3782 if i==0:
3782 if i==0:
3783 chanCX = chanC
3783 chanCX = chanC
3784 chan1X = chan1
3784 chan1X = chan1
3785 chan2X = chan2
3785 chan2X = chan2
3786 distances[0:2] = numpy.array([d1,d2])
3786 distances[0:2] = numpy.array([d1,d2])
3787 else:
3787 else:
3788 chanCY = chanC
3788 chanCY = chanC
3789 chan1Y = chan1
3789 chan1Y = chan1
3790 chan2Y = chan2
3790 chan2Y = chan2
3791 distances[2:4] = numpy.array([d1,d2])
3791 distances[2:4] = numpy.array([d1,d2])
3792 # axisXsides = numpy.reshape(axisX[ix,:],4)
3792 # axisXsides = numpy.reshape(axisX[ix,:],4)
3793 #
3793 #
3794 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3794 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3795 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3795 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3796 #
3796 #
3797 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3797 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3798 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3798 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3799 # channel25X = int(pairX[0,ind25X])
3799 # channel25X = int(pairX[0,ind25X])
3800 # channel20X = int(pairX[1,ind20X])
3800 # channel20X = int(pairX[1,ind20X])
3801 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3801 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3802 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3802 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3803 # channel25Y = int(pairY[0,ind25Y])
3803 # channel25Y = int(pairY[0,ind25Y])
3804 # channel20Y = int(pairY[1,ind20Y])
3804 # channel20Y = int(pairY[1,ind20Y])
3805
3805
3806 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3806 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3807 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3807 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3808
3808
3809 return pairslist, distances
3809 return pairslist, distances
3810 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3810 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3811 #
3811 #
3812 # arrayAOA = numpy.zeros((phases.shape[0],3))
3812 # arrayAOA = numpy.zeros((phases.shape[0],3))
3813 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3813 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3814 #
3814 #
3815 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3815 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3816 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3816 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3817 # arrayAOA[:,2] = cosDirError
3817 # arrayAOA[:,2] = cosDirError
3818 #
3818 #
3819 # azimuthAngle = arrayAOA[:,0]
3819 # azimuthAngle = arrayAOA[:,0]
3820 # zenithAngle = arrayAOA[:,1]
3820 # zenithAngle = arrayAOA[:,1]
3821 #
3821 #
3822 # #Setting Error
3822 # #Setting Error
3823 # #Number 3: AOA not fesible
3823 # #Number 3: AOA not fesible
3824 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3824 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3825 # error[indInvalid] = 3
3825 # error[indInvalid] = 3
3826 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3826 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3827 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3827 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3828 # error[indInvalid] = 4
3828 # error[indInvalid] = 4
3829 # return arrayAOA, error
3829 # return arrayAOA, error
3830 #
3830 #
3831 # def __getDirectionCosines(self, arrayPhase, pairsList):
3831 # def __getDirectionCosines(self, arrayPhase, pairsList):
3832 #
3832 #
3833 # #Initializing some variables
3833 # #Initializing some variables
3834 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3834 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3835 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3835 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3836 #
3836 #
3837 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3837 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3838 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3838 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3839 #
3839 #
3840 #
3840 #
3841 # for i in range(2):
3841 # for i in range(2):
3842 # #First Estimation
3842 # #First Estimation
3843 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3843 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3844 # #Dealias
3844 # #Dealias
3845 # indcsi = numpy.where(phi0_aux > numpy.pi)
3845 # indcsi = numpy.where(phi0_aux > numpy.pi)
3846 # phi0_aux[indcsi] -= 2*numpy.pi
3846 # phi0_aux[indcsi] -= 2*numpy.pi
3847 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3847 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3848 # phi0_aux[indcsi] += 2*numpy.pi
3848 # phi0_aux[indcsi] += 2*numpy.pi
3849 # #Direction Cosine 0
3849 # #Direction Cosine 0
3850 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3850 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3851 #
3851 #
3852 # #Most-Accurate Second Estimation
3852 # #Most-Accurate Second Estimation
3853 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3853 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3854 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3854 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3855 # #Direction Cosine 1
3855 # #Direction Cosine 1
3856 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3856 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3857 #
3857 #
3858 # #Searching the correct Direction Cosine
3858 # #Searching the correct Direction Cosine
3859 # cosdir0_aux = cosdir0[:,i]
3859 # cosdir0_aux = cosdir0[:,i]
3860 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3860 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3861 # #Minimum Distance
3861 # #Minimum Distance
3862 # cosDiff = (cosdir1 - cosdir0_aux)**2
3862 # cosDiff = (cosdir1 - cosdir0_aux)**2
3863 # indcos = cosDiff.argmin(axis = 1)
3863 # indcos = cosDiff.argmin(axis = 1)
3864 # #Saving Value obtained
3864 # #Saving Value obtained
3865 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3865 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3866 #
3866 #
3867 # return cosdir0, cosdir
3867 # return cosdir0, cosdir
3868 #
3868 #
3869 # def __calculateAOA(self, cosdir, azimuth):
3869 # def __calculateAOA(self, cosdir, azimuth):
3870 # cosdirX = cosdir[:,0]
3870 # cosdirX = cosdir[:,0]
3871 # cosdirY = cosdir[:,1]
3871 # cosdirY = cosdir[:,1]
3872 #
3872 #
3873 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3873 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3874 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3874 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3875 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3875 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3876 #
3876 #
3877 # return angles
3877 # return angles
3878 #
3878 #
3879 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3879 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3880 #
3880 #
3881 # Ramb = 375 #Ramb = c/(2*PRF)
3881 # Ramb = 375 #Ramb = c/(2*PRF)
3882 # Re = 6371 #Earth Radius
3882 # Re = 6371 #Earth Radius
3883 # heights = numpy.zeros(Ranges.shape)
3883 # heights = numpy.zeros(Ranges.shape)
3884 #
3884 #
3885 # R_aux = numpy.array([0,1,2])*Ramb
3885 # R_aux = numpy.array([0,1,2])*Ramb
3886 # R_aux = R_aux.reshape(1,R_aux.size)
3886 # R_aux = R_aux.reshape(1,R_aux.size)
3887 #
3887 #
3888 # Ranges = Ranges.reshape(Ranges.size,1)
3888 # Ranges = Ranges.reshape(Ranges.size,1)
3889 #
3889 #
3890 # Ri = Ranges + R_aux
3890 # Ri = Ranges + R_aux
3891 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3891 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3892 #
3892 #
3893 # #Check if there is a height between 70 and 110 km
3893 # #Check if there is a height between 70 and 110 km
3894 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3894 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3895 # ind_h = numpy.where(h_bool == 1)[0]
3895 # ind_h = numpy.where(h_bool == 1)[0]
3896 #
3896 #
3897 # hCorr = hi[ind_h, :]
3897 # hCorr = hi[ind_h, :]
3898 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3898 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3899 #
3899 #
3900 # hCorr = hi[ind_hCorr]
3900 # hCorr = hi[ind_hCorr]
3901 # heights[ind_h] = hCorr
3901 # heights[ind_h] = hCorr
3902 #
3902 #
3903 # #Setting Error
3903 # #Setting Error
3904 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3904 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3905 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3905 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3906 #
3906 #
3907 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3907 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3908 # error[indInvalid2] = 14
3908 # error[indInvalid2] = 14
3909 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3909 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3910 # error[indInvalid1] = 13
3910 # error[indInvalid1] = 13
3911 #
3911 #
3912 # return heights, error
3912 # return heights, error
3913
3913
3914
3914
3915 class WeatherRadar(Operation):
3915 class WeatherRadar(Operation):
3916 '''
3916 '''
3917 Function tat implements Weather Radar operations-
3917 Function tat implements Weather Radar operations-
3918 Input:
3918 Input:
3919 Output:
3919 Output:
3920 Parameters affected:
3920 Parameters affected:
3921 '''
3921 '''
3922 isConfig = False
3922 isConfig = False
3923 variableList = None
3923 variableList = None
3924
3924
3925 def __init__(self):
3925 def __init__(self):
3926 Operation.__init__(self)
3926 Operation.__init__(self)
3927
3927
3928 def setup(self,dataOut,variableList= None,Pt=0,Gt=0,Gr=0,Glna=0,lambda_=0, aL=0,
3928 def setup(self,dataOut,variableList= None,Pt=0,Gt=0,Gr=0,Glna=0,lambda_=0, aL=0,
3929 tauW= 0,thetaT=0,thetaR=0,Km =0):
3929 tauW= 0,thetaT=0,thetaR=0,Km =0):
3930 print("INICIO")
3930 print("INICIO")
3931 self.nCh = dataOut.nChannels
3931 self.nCh = dataOut.nChannels
3932 self.nHeis = dataOut.nHeights
3932 self.nHeis = dataOut.nHeights
3933 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3933 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3934 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3934 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3935 self.Range = self.Range.reshape(1,self.nHeis)
3935 self.Range = self.Range.reshape(1,self.nHeis)
3936 self.Range = numpy.tile(self.Range,[self.nCh,1])
3936 self.Range = numpy.tile(self.Range,[self.nCh,1])
3937 '''-----------1 Constante del Radar----------'''
3937 '''-----------1 Constante del Radar----------'''
3938 self.Pt = Pt # Pmax =200 W x DC=(0.2 useg/400useg)
3938 self.Pt = Pt # Pmax =200 W x DC=(0.2 useg/400useg)
3939 self.Gt = Gt # 38 db
3939 self.Gt = Gt # 38 db
3940 self.Gr = Gr # 38 dB
3940 self.Gr = Gr # 38 dB
3941 self.Glna = Glna # 60 dB
3941 self.Glna = Glna # 60 dB
3942 self.lambda_ = lambda_ # 3.2 cm 0.032 m.
3942 self.lambda_ = lambda_ # 3.2 cm 0.032 m.
3943 self.aL = aL # Perdidas
3943 self.aL = aL # Perdidas
3944 self.tauW = tauW #ancho de pulso 0.2useg pulso corto.
3944 self.tauW = tauW #ancho de pulso 0.2useg pulso corto.
3945 self.thetaT = thetaT # 1.8ΒΊ -- 0.0314 rad
3945 self.thetaT = thetaT # 1.8ΒΊ -- 0.0314 rad
3946 self.thetaR = thetaR # 1.8Βͺ --0.0314 rad
3946 self.thetaR = thetaR # 1.8Βͺ --0.0314 rad
3947 self.Km = Km
3947 self.Km = Km
3948 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2)*(10**18))
3948 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2)*(10**18))
3949 Denominator = (Pt *(10**(Gt/10.0))*(10**(Gr/10.0))*(10**(Glna/10.0))* lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3949 Denominator = (Pt *(10**(Gt/10.0))*(10**(Gr/10.0))*(10**(Glna/10.0))* lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3950 self.RadarConstant = Numerator/Denominator
3950 self.RadarConstant = Numerator/Denominator
3951 if self.variableList== None:
3951 if self.variableList== None:
3952 self.variableList= ['Reflectividad','ReflectividadDiferencial','CoeficienteCorrelacion','FaseDiferencial','VelocidadRadial','AnchoEspectral']
3952 self.variableList= ['Reflectividad','ReflectividadDiferencial','CoeficienteCorrelacion','FaseDiferencial','VelocidadRadial','AnchoEspectral']
3953 print('FIN')
3953 print('FIN')
3954 def setMoments(self,dataOut,i):
3954 def setMoments(self,dataOut,i):
3955
3955
3956 type = dataOut.inputUnit
3956 type = dataOut.inputUnit
3957 nCh = dataOut.nChannels
3957 nCh = dataOut.nChannels
3958 nHeis = dataOut.nHeights
3958 nHeis = dataOut.nHeights
3959 data_param = numpy.zeros((nCh,4,nHeis))
3959 data_param = numpy.zeros((nCh,4,nHeis))
3960 if type == "Voltage":
3960 if type == "Voltage":
3961 factor = 1
3961 factor = 1
3962 data_param[:,0,:] = dataOut.dataPP_POW/(factor)
3962 data_param[:,0,:] = dataOut.dataPP_POW/(factor)
3963 data_param[:,1,:] = dataOut.dataPP_DOP
3963 data_param[:,1,:] = dataOut.dataPP_DOP
3964 data_param[:,2,:] = dataOut.dataPP_WIDTH
3964 data_param[:,2,:] = dataOut.dataPP_WIDTH
3965 data_param[:,3,:] = dataOut.dataPP_SNR
3965 data_param[:,3,:] = dataOut.dataPP_SNR
3966 if type == "Spectra":
3966 if type == "Spectra":
3967 factor = dataOut.normFactor
3967 factor = dataOut.normFactor
3968 data_param[:,0,:] = dataOut.data_POW/(factor)
3968 data_param[:,0,:] = dataOut.data_POW/(factor)
3969 data_param[:,1,:] = dataOut.data_DOP
3969 data_param[:,1,:] = dataOut.data_DOP
3970 data_param[:,2,:] = dataOut.data_WIDTH
3970 data_param[:,2,:] = dataOut.data_WIDTH
3971 data_param[:,3,:] = dataOut.data_SNR
3971 data_param[:,3,:] = dataOut.data_SNR
3972
3972
3973 return data_param[:,i,:]
3973 return data_param[:,i,:]
3974
3974
3975 def getCoeficienteCorrelacionROhv_R(self,dataOut):
3975 def getCoeficienteCorrelacionROhv_R(self,dataOut):
3976 type = dataOut.inputUnit
3976 type = dataOut.inputUnit
3977 nHeis = dataOut.nHeights
3977 nHeis = dataOut.nHeights
3978 data_RhoHV_R = numpy.zeros((nHeis))
3978 data_RhoHV_R = numpy.zeros((nHeis))
3979 if type == "Voltage":
3979 if type == "Voltage":
3980 powa = dataOut.dataPP_POWER[0]
3980 powa = dataOut.dataPP_POWER[0]
3981 powb = dataOut.dataPP_POWER[1]
3981 powb = dataOut.dataPP_POWER[1]
3982 ccf = dataOut.dataPP_CCF
3982 ccf = dataOut.dataPP_CCF
3983 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
3983 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
3984 data_RhoHV_R = numpy.abs(avgcoherenceComplex)
3984 data_RhoHV_R = numpy.abs(avgcoherenceComplex)
3985 if type == "Spectra":
3985 if type == "Spectra":
3986 data_RhoHV_R = dataOut.getCoherence()
3986 data_RhoHV_R = dataOut.getCoherence()
3987
3987
3988 return data_RhoHV_R
3988 return data_RhoHV_R
3989
3989
3990 def getFasediferencialPhiD_P(self,dataOut,phase= True):
3990 def getFasediferencialPhiD_P(self,dataOut,phase= True):
3991 type = dataOut.inputUnit
3991 type = dataOut.inputUnit
3992 nHeis = dataOut.nHeights
3992 nHeis = dataOut.nHeights
3993 data_PhiD_P = numpy.zeros((nHeis))
3993 data_PhiD_P = numpy.zeros((nHeis))
3994 if type == "Voltage":
3994 if type == "Voltage":
3995 powa = dataOut.dataPP_POWER[0]
3995 powa = dataOut.dataPP_POWER[0]
3996 powb = dataOut.dataPP_POWER[1]
3996 powb = dataOut.dataPP_POWER[1]
3997 ccf = dataOut.dataPP_CCF
3997 ccf = dataOut.dataPP_CCF
3998 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
3998 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
3999 if phase:
3999 if phase:
4000 data_PhiD_P = numpy.arctan2(avgcoherenceComplex.imag,
4000 data_PhiD_P = numpy.arctan2(avgcoherenceComplex.imag,
4001 avgcoherenceComplex.real) * 180 / numpy.pi
4001 avgcoherenceComplex.real) * 180 / numpy.pi
4002 if type == "Spectra":
4002 if type == "Spectra":
4003 data_PhiD_P = dataOut.getCoherence(phase = phase)
4003 data_PhiD_P = dataOut.getCoherence(phase = phase)
4004
4004
4005 return data_PhiD_P
4005 return data_PhiD_P
4006
4006
4007 def getReflectividad_D(self,dataOut,type):
4007 def getReflectividad_D(self,dataOut,type):
4008 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
4008 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
4009
4009
4010 Pr = self.setMoments(dataOut,0)
4010 Pr = self.setMoments(dataOut,0)
4011
4011
4012 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
4012 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
4013 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
4013 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
4014 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
4014 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
4015 for R in range(self.nHeis):
4015 for R in range(self.nHeis):
4016 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
4016 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
4017
4017
4018 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
4018 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
4019
4019
4020 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
4020 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
4021 Zeh = self.Z_radar
4021 Zeh = self.Z_radar
4022 dBZeh = 10*numpy.log10(Zeh)
4022 dBZeh = 10*numpy.log10(Zeh)
4023 if type=='N':
4023 if type=='N':
4024 return dBZeh
4024 return dBZeh
4025 elif type=='D':
4025 elif type=='D':
4026 Zdb_D = dBZeh[0] - dBZeh[1]
4026 Zdb_D = dBZeh[0] - dBZeh[1]
4027 return Zdb_D
4027 return Zdb_D
4028
4028
4029 def getRadialVelocity_V(self,dataOut):
4029 def getRadialVelocity_V(self,dataOut):
4030 velRadial_V = self.setMoments(dataOut,1)
4030 velRadial_V = self.setMoments(dataOut,1)
4031 return velRadial_V
4031 return velRadial_V
4032
4032
4033 def getAnchoEspectral_W(self,dataOut):
4033 def getAnchoEspectral_W(self,dataOut):
4034 Sigmav_W = self.setMoments(dataOut,2)
4034 Sigmav_W = self.setMoments(dataOut,2)
4035 return Sigmav_W
4035 return Sigmav_W
4036
4036
4037
4037
4038 def run(self,dataOut,variableList=variableList,Pt=0.158,Gt=38.5,Gr=38.5,Glna=70.0,lambda_=0.032, aL=1,
4038 def run(self,dataOut,variableList=variableList,Pt=0.158,Gt=38.5,Gr=38.5,Glna=70.0,lambda_=0.032, aL=1,
4039 tauW= 0.2*1e-6,thetaT=0.0314,thetaR=0.0314,Km =0.93):
4039 tauW= 0.2*1e-6,thetaT=0.0314,thetaR=0.0314,Km =0.93):
4040
4040
4041 if not self.isConfig:
4041 if not self.isConfig:
4042 self.setup(dataOut= dataOut,variableList=variableList,Pt=Pt,Gt=Gt,Gr=Gr,Glna=Glna,lambda_=lambda_, aL=aL,
4042 self.setup(dataOut= dataOut,variableList=variableList,Pt=Pt,Gt=Gt,Gr=Gr,Glna=Glna,lambda_=lambda_, aL=aL,
4043 tauW= tauW,thetaT=thetaT,thetaR=thetaR,Km =Km)
4043 tauW= tauW,thetaT=thetaT,thetaR=thetaR,Km =Km)
4044 self.isConfig = True
4044 self.isConfig = True
4045 for i in range(len(self.variableList)):
4045 for i in range(len(self.variableList)):
4046 if self.variableList[i]=='Reflectividad':
4046 if self.variableList[i]=='Reflectividad':
4047 dataOut.Zdb =self.getReflectividad_D(dataOut=dataOut,type='N')
4047 dataOut.Zdb =self.getReflectividad_D(dataOut=dataOut,type='N')
4048 print(dataOut.Zdb)
4048 print(dataOut.Zdb)
4049 if self.variableList[i]=='ReflectividadDiferencial':
4049 if self.variableList[i]=='ReflectividadDiferencial':
4050 dataOut.Zdb_D =self.getReflectividad_D(dataOut=dataOut,type='D')
4050 dataOut.Zdb_D =self.getReflectividad_D(dataOut=dataOut,type='D')
4051 if self.variableList[i]=='FaseDiferencial':
4051 if self.variableList[i]=='FaseDiferencial':
4052 dataOut.PhiD_P =self.getFasediferencialPhiD_P(dataOut=dataOut, phase=True)
4052 dataOut.PhiD_P =self.getFasediferencialPhiD_P(dataOut=dataOut, phase=True)
4053 if self.variableList[i] == "CoeficienteCorrelacion":
4053 if self.variableList[i] == "CoeficienteCorrelacion":
4054 dataOut.RhoHV_R = self.getCoeficienteCorrelacionROhv_R(dataOut)
4054 dataOut.RhoHV_R = self.getCoeficienteCorrelacionROhv_R(dataOut)
4055 if self.variableList[i] =="VelocidadRadial":
4055 if self.variableList[i] =="VelocidadRadial":
4056 dataOut.velRadial_V = self.getRadialVelocity_V(dataOut)
4056 dataOut.velRadial_V = self.getRadialVelocity_V(dataOut)
4057 if self.variableList[i] =="AnchoEspectral":
4057 if self.variableList[i] =="AnchoEspectral":
4058 dataOut.Sigmav_W = self.getAnchoEspectral_W(dataOut)
4058 dataOut.Sigmav_W = self.getAnchoEspectral_W(dataOut)
4059 return dataOut
4059 return dataOut
4060
4060
4061 class PedestalInformation(Operation):
4061 class PedestalInformation(Operation):
4062
4062
4063 def __init__(self):
4063 def __init__(self):
4064 Operation.__init__(self)
4064 Operation.__init__(self)
4065 self.filename = False
4065 self.filename = False
4066 self.delay = 30
4066 self.delay = 30
4067 self.nTries = 3
4067 self.nTries = 3
4068
4068
4069 def find_file(self, timestamp):
4069 def find_file(self, timestamp):
4070
4070
4071 dt = datetime.datetime.utcfromtimestamp(timestamp)
4071 dt = datetime.datetime.utcfromtimestamp(timestamp)
4072 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4072 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4073
4073
4074 if not os.path.exists(path):
4074 if not os.path.exists(path):
4075 return False, False
4075 return False, False
4076 fileList = glob.glob(os.path.join(path, '*.h5'))
4076 fileList = glob.glob(os.path.join(path, '*.h5'))
4077 fileList.sort()
4077 fileList.sort()
4078 return fileList
4078 return fileList
4079
4079
4080 def find_next_file(self):
4080 def find_next_file(self):
4081
4081
4082 while True:
4082 while True:
4083 if self.utctime < self.utcfile:
4083 if self.utctime < self.utcfile:
4084 self.flagNoData = True
4084 self.flagNoData = True
4085 break
4085 break
4086 self.flagNoData = False
4086 self.flagNoData = False
4087 file_size = len(self.fp['Data']['utc'])
4087 file_size = len(self.fp['Data']['utc'])
4088 if self.utctime < self.utcfile+file_size*self.interval:
4088 if self.utctime < self.utcfile+file_size*self.interval:
4089 break
4089 break
4090 dt = datetime.datetime.utcfromtimestamp(self.utcfile)
4090 dt = datetime.datetime.utcfromtimestamp(self.utcfile)
4091 if dt.second > 0:
4091 if dt.second > 0:
4092 self.utcfile -= dt.second
4092 self.utcfile -= dt.second
4093 self.utcfile += self.samples*self.interval
4093 self.utcfile += self.samples*self.interval
4094 dt = datetime.datetime.utcfromtimestamp(self.utctime)
4094 dt = datetime.datetime.utcfromtimestamp(self.utctime)
4095 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4095 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4096 self.filename = os.path.join(path, 'pos@{}.000.h5'.format(int(self.utcfile)))
4096 self.filename = os.path.join(path, 'pos@{}.000.h5'.format(int(self.utcfile)))
4097
4097
4098 for n in range(self.nTries):
4098 for n in range(self.nTries):
4099 ok = False
4099 ok = False
4100 try:
4100 try:
4101 if not os.path.exists(self.filename):
4101 if not os.path.exists(self.filename):
4102 log.warning('Waiting {}s for position files...'.format(self.delay), self.name)
4102 log.warning('Waiting {}s for position files...'.format(self.delay), self.name)
4103 time.sleep(self.delay)
4103 time.sleep(self.delay)
4104 continue
4104 continue
4105 self.fp.close()
4105 self.fp.close()
4106 self.fp = h5py.File(self.filename, 'r')
4106 self.fp = h5py.File(self.filename, 'r')
4107 log.log('Opening file: {}'.format(self.filename), self.name)
4107 log.log('Opening file: {}'.format(self.filename), self.name)
4108 ok = True
4108 ok = True
4109 break
4109 break
4110 except:
4110 except:
4111 log.warning('Waiting {}s for position file to be ready...'.format(self.delay), self.name)
4111 log.warning('Waiting {}s for position file to be ready...'.format(self.delay), self.name)
4112 time.sleep(self.delay)
4112 time.sleep(self.delay)
4113 continue
4113 continue
4114
4114
4115 if not ok:
4115 if not ok:
4116 log.error('No new position files found in {}'.format(path))
4116 log.error('No new position files found in {}'.format(path))
4117 raise IOError('No new position files found in {}'.format(path))
4117 raise IOError('No new position files found in {}'.format(path))
4118
4118
4119
4119
4120 def get_values(self):
4120 def get_values(self):
4121
4121
4122 if self.flagNoData:
4122 if self.flagNoData:
4123 return numpy.nan, numpy.nan
4123 return numpy.nan, numpy.nan
4124 else:
4124 else:
4125 index = int((self.utctime-self.utcfile)/self.interval)
4125 index = int((self.utctime-self.utcfile)/self.interval)
4126 return self.fp['Data']['azi_pos'][index], self.fp['Data']['ele_pos'][index]
4126 return self.fp['Data']['azi_pos'][index], self.fp['Data']['ele_pos'][index]
4127
4127
4128 def setup(self, dataOut, path, conf, samples, interval, az_offset):
4128 def setup(self, dataOut, path, conf, samples, interval, az_offset):
4129
4129
4130 self.path = path
4130 self.path = path
4131 self.conf = conf
4131 self.conf = conf
4132 self.samples = samples
4132 self.samples = samples
4133 self.interval = interval
4133 self.interval = interval
4134 filelist = self.find_file(dataOut.utctime)
4134 filelist = self.find_file(dataOut.utctime)
4135
4135
4136 if not filelist:
4136 if not filelist:
4137 log.error('No position files found in {}'.format(path), self.name)
4137 log.error('No position files found in {}'.format(path), self.name)
4138 raise IOError('No position files found in {}'.format(path))
4138 raise IOError('No position files found in {}'.format(path))
4139 else:
4139 else:
4140 self.filename = filelist[0]
4140 self.filename = filelist[0]
4141 self.utcfile = int(self.filename.split('/')[-1][4:14])
4141 self.utcfile = int(self.filename.split('/')[-1][4:14])
4142 log.log('Opening file: {}'.format(self.filename), self.name)
4142 log.log('Opening file: {}'.format(self.filename), self.name)
4143 self.fp = h5py.File(self.filename, 'r')
4143 self.fp = h5py.File(self.filename, 'r')
4144
4144
4145 def run(self, dataOut, path, conf=None, samples=1500, interval=0.04, az_offset=0, time_offset=0):
4145 def run(self, dataOut, path, conf=None, samples=1500, interval=0.04, az_offset=0, time_offset=0):
4146
4146
4147 if not self.isConfig:
4147 if not self.isConfig:
4148 self.setup(dataOut, path, conf, samples, interval, az_offset)
4148 self.setup(dataOut, path, conf, samples, interval, az_offset)
4149 self.isConfig = True
4149 self.isConfig = True
4150
4150
4151 self.utctime = dataOut.utctime + time_offset
4151 self.utctime = dataOut.utctime + time_offset
4152
4152
4153 self.find_next_file()
4153 self.find_next_file()
4154
4154
4155 az, el = self.get_values()
4155 az, el = self.get_values()
4156 dataOut.flagNoData = False
4156 dataOut.flagNoData = False
4157
4157
4158 if numpy.isnan(az) or numpy.isnan(el) :
4158 if numpy.isnan(az) or numpy.isnan(el) :
4159 dataOut.flagNoData = True
4159 dataOut.flagNoData = True
4160 return dataOut
4160 return dataOut
4161
4161
4162 dataOut.azimuth = az - az_offset
4162 dataOut.azimuth = az - az_offset
4163 if dataOut.azimuth < 0:
4163 if dataOut.azimuth < 0:
4164 dataOut.azimuth += 360
4164 dataOut.azimuth += 360
4165 dataOut.elevation = el
4165 dataOut.elevation = el
4166
4166
4167 return dataOut
4167 return dataOut
4168
4168
4169 class Block360(Operation):
4169 class Block360(Operation):
4170 '''
4170 '''
4171 '''
4171 '''
4172 isConfig = False
4172 isConfig = False
4173 __profIndex = 0
4173 __profIndex = 0
4174 __initime = None
4174 __initime = None
4175 __lastdatatime = None
4175 __lastdatatime = None
4176 __buffer = None
4176 __buffer = None
4177 __dataReady = False
4177 __dataReady = False
4178 n = None
4178 n = None
4179 __nch = 0
4179 __nch = 0
4180 __nHeis = 0
4180 __nHeis = 0
4181 index = 0
4181 index = 0
4182 mode = 0
4182 mode = 0
4183
4183
4184 def __init__(self,**kwargs):
4184 def __init__(self,**kwargs):
4185 Operation.__init__(self,**kwargs)
4185 Operation.__init__(self,**kwargs)
4186
4186
4187 def setup(self, dataOut, n = None, mode = None):
4187 def setup(self, dataOut, n = None, mode = None):
4188 '''
4188 '''
4189 n= Numero de PRF's de entrada
4189 n= Numero de PRF's de entrada
4190 '''
4190 '''
4191 self.__initime = None
4191 self.__initime = None
4192 self.__lastdatatime = 0
4192 self.__lastdatatime = 0
4193 self.__dataReady = False
4193 self.__dataReady = False
4194 self.__buffer = 0
4194 self.__buffer = 0
4195 self.__buffer_1D = 0
4195 self.__buffer_1D = 0
4196 self.__profIndex = 0
4196 self.__profIndex = 0
4197 self.index = 0
4197 self.index = 0
4198 self.__nch = dataOut.nChannels
4198 self.__nch = dataOut.nChannels
4199 self.__nHeis = dataOut.nHeights
4199 self.__nHeis = dataOut.nHeights
4200 ##print("ELVALOR DE n es:", n)
4200 ##print("ELVALOR DE n es:", n)
4201 if n == None:
4201 if n == None:
4202 raise ValueError("n should be specified.")
4202 raise ValueError("n should be specified.")
4203
4203
4204 if mode == None:
4204 if mode == None:
4205 raise ValueError("mode should be specified.")
4205 raise ValueError("mode should be specified.")
4206
4206
4207 if n != None:
4207 if n != None:
4208 if n<1:
4208 if n<1:
4209 print("n should be greater than 2")
4209 print("n should be greater than 2")
4210 raise ValueError("n should be greater than 2")
4210 raise ValueError("n should be greater than 2")
4211
4211
4212 self.n = n
4212 self.n = n
4213 self.mode = mode
4213 self.mode = mode
4214 #print("self.mode",self.mode)
4214 #print("self.mode",self.mode)
4215 #print("nHeights")
4215 #print("nHeights")
4216 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4216 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4217 self.__buffer2 = numpy.zeros(n)
4217 self.__buffer2 = numpy.zeros(n)
4218 self.__buffer3 = numpy.zeros(n)
4218 self.__buffer3 = numpy.zeros(n)
4219
4219
4220
4220
4221
4221
4222
4222
4223 def putData(self,data,mode):
4223 def putData(self,data,mode):
4224 '''
4224 '''
4225 Add a profile to he __buffer and increase in one the __profiel Index
4225 Add a profile to he __buffer and increase in one the __profiel Index
4226 '''
4226 '''
4227 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4227 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4228 #print("line 4049",data.azimuth.shape,data.azimuth)
4228 #print("line 4049",data.azimuth.shape,data.azimuth)
4229 if self.mode==0:
4229 if self.mode==0:
4230 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4230 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4231 if self.mode==1:
4231 if self.mode==1:
4232 self.__buffer[:,self.__profIndex,:]= data.data_pow
4232 self.__buffer[:,self.__profIndex,:]= data.data_pow
4233 #print("me casi",self.index,data.azimuth[self.index])
4233 #print("me casi",self.index,data.azimuth[self.index])
4234 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4234 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4235 #print("magic",data.profileIndex)
4235 #print("magic",data.profileIndex)
4236 #print(data.azimuth[self.index])
4236 #print(data.azimuth[self.index])
4237 #print("index",self.index)
4237 #print("index",self.index)
4238
4238
4239 #####self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4239 #####self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4240 self.__buffer2[self.__profIndex] = data.azimuth
4240 self.__buffer2[self.__profIndex] = data.azimuth
4241 self.__buffer3[self.__profIndex] = data.elevation
4241 self.__buffer3[self.__profIndex] = data.elevation
4242 #print("q pasa")
4242 #print("q pasa")
4243 #####self.index+=1
4243 #####self.index+=1
4244 #print("index",self.index,data.azimuth[:10])
4244 #print("index",self.index,data.azimuth[:10])
4245 self.__profIndex += 1
4245 self.__profIndex += 1
4246 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4246 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4247
4247
4248 def pushData(self,data):
4248 def pushData(self,data):
4249 '''
4249 '''
4250 Return the PULSEPAIR and the profiles used in the operation
4250 Return the PULSEPAIR and the profiles used in the operation
4251 Affected : self.__profileIndex
4251 Affected : self.__profileIndex
4252 '''
4252 '''
4253 #print("pushData")
4253 #print("pushData")
4254
4254
4255 data_360 = self.__buffer
4255 data_360 = self.__buffer
4256 data_p = self.__buffer2
4256 data_p = self.__buffer2
4257 data_e = self.__buffer3
4257 data_e = self.__buffer3
4258 n = self.__profIndex
4258 n = self.__profIndex
4259
4259
4260 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4260 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4261 self.__buffer2 = numpy.zeros(self.n)
4261 self.__buffer2 = numpy.zeros(self.n)
4262 self.__buffer3 = numpy.zeros(self.n)
4262 self.__buffer3 = numpy.zeros(self.n)
4263 self.__profIndex = 0
4263 self.__profIndex = 0
4264 #print("pushData")
4264 #print("pushData")
4265 return data_360,n,data_p,data_e
4265 return data_360,n,data_p,data_e
4266
4266
4267
4267
4268 def byProfiles(self,dataOut):
4268 def byProfiles(self,dataOut):
4269
4269
4270 self.__dataReady = False
4270 self.__dataReady = False
4271 data_360 = None
4271 data_360 = None
4272 data_p = None
4272 data_p = None
4273 data_e = None
4273 data_e = None
4274 #print("dataOu",dataOut.dataPP_POW)
4274 #print("dataOu",dataOut.dataPP_POW)
4275 self.putData(data=dataOut,mode = self.mode)
4275 self.putData(data=dataOut,mode = self.mode)
4276 ##### print("profIndex",self.__profIndex)
4276 ##### print("profIndex",self.__profIndex)
4277 if self.__profIndex == self.n:
4277 if self.__profIndex == self.n:
4278 data_360,n,data_p,data_e = self.pushData(data=dataOut)
4278 data_360,n,data_p,data_e = self.pushData(data=dataOut)
4279 self.__dataReady = True
4279 self.__dataReady = True
4280
4280
4281 return data_360,data_p,data_e
4281 return data_360,data_p,data_e
4282
4282
4283
4283
4284 def blockOp(self, dataOut, datatime= None):
4284 def blockOp(self, dataOut, datatime= None):
4285 if self.__initime == None:
4285 if self.__initime == None:
4286 self.__initime = datatime
4286 self.__initime = datatime
4287 data_360,data_p,data_e = self.byProfiles(dataOut)
4287 data_360,data_p,data_e = self.byProfiles(dataOut)
4288 self.__lastdatatime = datatime
4288 self.__lastdatatime = datatime
4289
4289
4290 if data_360 is None:
4290 if data_360 is None:
4291 return None, None,None,None
4291 return None, None,None,None
4292
4292
4293
4293
4294 avgdatatime = self.__initime
4294 avgdatatime = self.__initime
4295 if self.n==1:
4295 if self.n==1:
4296 avgdatatime = datatime
4296 avgdatatime = datatime
4297 deltatime = datatime - self.__lastdatatime
4297 deltatime = datatime - self.__lastdatatime
4298 self.__initime = datatime
4298 self.__initime = datatime
4299 #print(data_360.shape,avgdatatime,data_p.shape)
4299 #print(data_360.shape,avgdatatime,data_p.shape)
4300 return data_360,avgdatatime,data_p,data_e
4300 return data_360,avgdatatime,data_p,data_e
4301
4301
4302 def run(self, dataOut,n = None,mode=None,**kwargs):
4302 def run(self, dataOut,n = None,mode=None,**kwargs):
4303 #print("BLOCK 360 HERE WE GO MOMENTOS")
4303 #print("BLOCK 360 HERE WE GO MOMENTOS")
4304 print("Block 360")
4304 print("Block 360")
4305 #exit(1)
4305 #exit(1)
4306 if not self.isConfig:
4306 if not self.isConfig:
4307 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4307 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4308 ####self.index = 0
4308 ####self.index = 0
4309 #print("comova",self.isConfig)
4309 #print("comova",self.isConfig)
4310 self.isConfig = True
4310 self.isConfig = True
4311 ####if self.index==dataOut.azimuth.shape[0]:
4311 ####if self.index==dataOut.azimuth.shape[0]:
4312 #### self.index=0
4312 #### self.index=0
4313 data_360, avgdatatime,data_p,data_e = self.blockOp(dataOut, dataOut.utctime)
4313 data_360, avgdatatime,data_p,data_e = self.blockOp(dataOut, dataOut.utctime)
4314 dataOut.flagNoData = True
4314 dataOut.flagNoData = True
4315
4315
4316 if self.__dataReady:
4316 if self.__dataReady:
4317 dataOut.data_360 = data_360 # S
4317 dataOut.data_360 = data_360 # S
4318 #print("DATA 360")
4318 #print("DATA 360")
4319 #print(dataOut.data_360)
4319 #print(dataOut.data_360)
4320 #print("---------------------------------------------------------------------------------")
4320 #print("---------------------------------------------------------------------------------")
4321 print("---------------------------DATAREADY---------------------------------------------")
4321 print("---------------------------DATAREADY---------------------------------------------")
4322 #print("---------------------------------------------------------------------------------")
4322 #print("---------------------------------------------------------------------------------")
4323 #print("data_360",dataOut.data_360.shape)
4323 #print("data_360",dataOut.data_360.shape)
4324 dataOut.data_azi = data_p
4324 dataOut.data_azi = data_p
4325 dataOut.data_ele = data_e
4325 dataOut.data_ele = data_e
4326 ###print("azi: ",dataOut.data_azi)
4326 ###print("azi: ",dataOut.data_azi)
4327 #print("ele: ",dataOut.data_ele)
4327 #print("ele: ",dataOut.data_ele)
4328 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4328 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4329 dataOut.utctime = avgdatatime
4329 dataOut.utctime = avgdatatime
4330 dataOut.flagNoData = False
4330 dataOut.flagNoData = False
4331 return dataOut
4331 return dataOut
4332
4332
4333 class Block360_vRF(Operation):
4333 class Block360_vRF(Operation):
4334 '''
4334 '''
4335 '''
4335 '''
4336 isConfig = False
4336 isConfig = False
4337 __profIndex = 0
4337 __profIndex = 0
4338 __initime = None
4338 __initime = None
4339 __lastdatatime = None
4339 __lastdatatime = None
4340 __buffer = None
4340 __buffer = None
4341 __dataReady = False
4341 __dataReady = False
4342 n = None
4342 n = None
4343 __nch = 0
4343 __nch = 0
4344 __nHeis = 0
4344 __nHeis = 0
4345 index = 0
4345 index = 0
4346 mode = 0
4346 mode = 0
4347
4347
4348 def __init__(self,**kwargs):
4348 def __init__(self,**kwargs):
4349 Operation.__init__(self,**kwargs)
4349 Operation.__init__(self,**kwargs)
4350
4350
4351 def setup(self, dataOut, n = None, mode = None):
4351 def setup(self, dataOut, n = None, mode = None):
4352 '''
4352 '''
4353 n= Numero de PRF's de entrada
4353 n= Numero de PRF's de entrada
4354 '''
4354 '''
4355 self.__initime = None
4355 self.__initime = None
4356 self.__lastdatatime = 0
4356 self.__lastdatatime = 0
4357 self.__dataReady = False
4357 self.__dataReady = False
4358 self.__buffer = 0
4358 self.__buffer = 0
4359 self.__buffer_1D = 0
4359 self.__buffer_1D = 0
4360 self.__profIndex = 0
4360 self.__profIndex = 0
4361 self.index = 0
4361 self.index = 0
4362 self.__nch = dataOut.nChannels
4362 self.__nch = dataOut.nChannels
4363 self.__nHeis = dataOut.nHeights
4363 self.__nHeis = dataOut.nHeights
4364 ##print("ELVALOR DE n es:", n)
4364 ##print("ELVALOR DE n es:", n)
4365 if n == None:
4365 if n == None:
4366 raise ValueError("n should be specified.")
4366 raise ValueError("n should be specified.")
4367
4367
4368 if mode == None:
4368 if mode == None:
4369 raise ValueError("mode should be specified.")
4369 raise ValueError("mode should be specified.")
4370
4370
4371 if n != None:
4371 if n != None:
4372 if n<1:
4372 if n<1:
4373 print("n should be greater than 2")
4373 print("n should be greater than 2")
4374 raise ValueError("n should be greater than 2")
4374 raise ValueError("n should be greater than 2")
4375
4375
4376 self.n = n
4376 self.n = n
4377 self.mode = mode
4377 self.mode = mode
4378 #print("self.mode",self.mode)
4378 #print("self.mode",self.mode)
4379 #print("nHeights")
4379 #print("nHeights")
4380 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4380 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4381 self.__buffer2 = numpy.zeros(n)
4381 self.__buffer2 = numpy.zeros(n)
4382 self.__buffer3 = numpy.zeros(n)
4382 self.__buffer3 = numpy.zeros(n)
4383
4383
4384
4384
4385
4385
4386
4386
4387 def putData(self,data,mode):
4387 def putData(self,data,mode):
4388 '''
4388 '''
4389 Add a profile to he __buffer and increase in one the __profiel Index
4389 Add a profile to he __buffer and increase in one the __profiel Index
4390 '''
4390 '''
4391 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4391 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4392 #print("line 4049",data.azimuth.shape,data.azimuth)
4392 #print("line 4049",data.azimuth.shape,data.azimuth)
4393 if self.mode==0:
4393 if self.mode==0:
4394 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4394 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4395 if self.mode==1:
4395 if self.mode==1:
4396 self.__buffer[:,self.__profIndex,:]= data.data_pow
4396 self.__buffer[:,self.__profIndex,:]= data.data_pow
4397 #print("me casi",self.index,data.azimuth[self.index])
4397 #print("me casi",self.index,data.azimuth[self.index])
4398 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4398 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4399 #print("magic",data.profileIndex)
4399 #print("magic",data.profileIndex)
4400 #print(data.azimuth[self.index])
4400 #print(data.azimuth[self.index])
4401 #print("index",self.index)
4401 #print("index",self.index)
4402
4402
4403 #####self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4403 #####self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4404 self.__buffer2[self.__profIndex] = data.azimuth
4404 self.__buffer2[self.__profIndex] = data.azimuth
4405 self.__buffer3[self.__profIndex] = data.elevation
4405 self.__buffer3[self.__profIndex] = data.elevation
4406 #print("q pasa")
4406 #print("q pasa")
4407 #####self.index+=1
4407 #####self.index+=1
4408 #print("index",self.index,data.azimuth[:10])
4408 #print("index",self.index,data.azimuth[:10])
4409 self.__profIndex += 1
4409 self.__profIndex += 1
4410 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4410 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4411
4411
4412 def pushData(self,data):
4412 def pushData(self,data):
4413 '''
4413 '''
4414 Return the PULSEPAIR and the profiles used in the operation
4414 Return the PULSEPAIR and the profiles used in the operation
4415 Affected : self.__profileIndex
4415 Affected : self.__profileIndex
4416 '''
4416 '''
4417 #print("pushData")
4417 #print("pushData")
4418
4418
4419 data_360 = self.__buffer
4419 data_360 = self.__buffer
4420 data_p = self.__buffer2
4420 data_p = self.__buffer2
4421 data_e = self.__buffer3
4421 data_e = self.__buffer3
4422 n = self.__profIndex
4422 n = self.__profIndex
4423
4423
4424 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4424 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4425 self.__buffer2 = numpy.zeros(self.n)
4425 self.__buffer2 = numpy.zeros(self.n)
4426 self.__buffer3 = numpy.zeros(self.n)
4426 self.__buffer3 = numpy.zeros(self.n)
4427 self.__profIndex = 0
4427 self.__profIndex = 0
4428 #print("pushData")
4428 #print("pushData")
4429 return data_360,n,data_p,data_e
4429 return data_360,n,data_p,data_e
4430
4430
4431
4431
4432 def byProfiles(self,dataOut):
4432 def byProfiles(self,dataOut):
4433
4433
4434 self.__dataReady = False
4434 self.__dataReady = False
4435 data_360 = None
4435 data_360 = None
4436 data_p = None
4436 data_p = None
4437 data_e = None
4437 data_e = None
4438 #print("dataOu",dataOut.dataPP_POW)
4438 #print("dataOu",dataOut.dataPP_POW)
4439 self.putData(data=dataOut,mode = self.mode)
4439 self.putData(data=dataOut,mode = self.mode)
4440 ##### print("profIndex",self.__profIndex)
4440 ##### print("profIndex",self.__profIndex)
4441 if self.__profIndex == self.n:
4441 if self.__profIndex == self.n:
4442 data_360,n,data_p,data_e = self.pushData(data=dataOut)
4442 data_360,n,data_p,data_e = self.pushData(data=dataOut)
4443 self.__dataReady = True
4443 self.__dataReady = True
4444
4444
4445 return data_360,data_p,data_e
4445 return data_360,data_p,data_e
4446
4446
4447
4447
4448 def blockOp(self, dataOut, datatime= None):
4448 def blockOp(self, dataOut, datatime= None):
4449 if self.__initime == None:
4449 if self.__initime == None:
4450 self.__initime = datatime
4450 self.__initime = datatime
4451 data_360,data_p,data_e = self.byProfiles(dataOut)
4451 data_360,data_p,data_e = self.byProfiles(dataOut)
4452 self.__lastdatatime = datatime
4452 self.__lastdatatime = datatime
4453
4453
4454 if data_360 is None:
4454 if data_360 is None:
4455 return None, None,None,None
4455 return None, None,None,None
4456
4456
4457
4457
4458 avgdatatime = self.__initime
4458 avgdatatime = self.__initime
4459 if self.n==1:
4459 if self.n==1:
4460 avgdatatime = datatime
4460 avgdatatime = datatime
4461 deltatime = datatime - self.__lastdatatime
4461 deltatime = datatime - self.__lastdatatime
4462 self.__initime = datatime
4462 self.__initime = datatime
4463 #print(data_360.shape,avgdatatime,data_p.shape)
4463 #print(data_360.shape,avgdatatime,data_p.shape)
4464 return data_360,avgdatatime,data_p,data_e
4464 return data_360,avgdatatime,data_p,data_e
4465
4465
4466 def checkcase(self,data_ele):
4466 def checkcase(self,data_ele):
4467 start = data_ele[0]
4467 start = data_ele[0]
4468 end = data_ele[-1]
4468 end = data_ele[-1]
4469 diff_angle = (end-start)
4469 diff_angle = (end-start)
4470 len_ang=len(data_ele)
4470 len_ang=len(data_ele)
4471 print("start",start)
4471 print("start",start)
4472 print("end",end)
4472 print("end",end)
4473 print("number",diff_angle)
4473 print("number",diff_angle)
4474
4474
4475 print("len_ang",len_ang)
4475 print("len_ang",len_ang)
4476
4476
4477 aux = (data_ele<0).any(axis=0)
4477 aux = (data_ele<0).any(axis=0)
4478
4478
4479 #exit(1)
4479 #exit(1)
4480 if diff_angle<0 and aux!=1: #Bajada
4480 if diff_angle<0 and aux!=1: #Bajada
4481 return 1
4481 return 1
4482 elif diff_angle<0 and aux==1: #Bajada con angulos negativos
4482 elif diff_angle<0 and aux==1: #Bajada con angulos negativos
4483 return 0
4483 return 0
4484 elif diff_angle == 0: # This case happens when the angle reaches the max_angle if n = 2
4484 elif diff_angle == 0: # This case happens when the angle reaches the max_angle if n = 2
4485 self.flagEraseFirstData = 1
4485 self.flagEraseFirstData = 1
4486 print("ToDO this case")
4486 print("ToDO this case")
4487 exit(1)
4487 exit(1)
4488 elif diff_angle>0: #Subida
4488 elif diff_angle>0: #Subida
4489 return 0
4489 return 0
4490
4490
4491 def run(self, dataOut,n = None,mode=None,**kwargs):
4491 def run(self, dataOut,n = None,mode=None,**kwargs):
4492 #print("BLOCK 360 HERE WE GO MOMENTOS")
4492 #print("BLOCK 360 HERE WE GO MOMENTOS")
4493 print("Block 360")
4493 print("Block 360")
4494
4494
4495 #exit(1)
4495 #exit(1)
4496 if not self.isConfig:
4496 if not self.isConfig:
4497 if n == 1:
4497 if n == 1:
4498 print("*******************Min Value is 2. Setting n = 2*******************")
4498 print("*******************Min Value is 2. Setting n = 2*******************")
4499 n = 2
4499 n = 2
4500 #exit(1)
4500 #exit(1)
4501 print(n)
4501 print(n)
4502 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4502 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4503 ####self.index = 0
4503 ####self.index = 0
4504 #print("comova",self.isConfig)
4504 #print("comova",self.isConfig)
4505 self.isConfig = True
4505 self.isConfig = True
4506 ####if self.index==dataOut.azimuth.shape[0]:
4506 ####if self.index==dataOut.azimuth.shape[0]:
4507 #### self.index=0
4507 #### self.index=0
4508 data_360, avgdatatime,data_p,data_e = self.blockOp(dataOut, dataOut.utctime)
4508 data_360, avgdatatime,data_p,data_e = self.blockOp(dataOut, dataOut.utctime)
4509 dataOut.flagNoData = True
4509 dataOut.flagNoData = True
4510
4510
4511 if self.__dataReady:
4511 if self.__dataReady:
4512 dataOut.data_360 = data_360 # S
4512 dataOut.data_360 = data_360 # S
4513 #print("DATA 360")
4513 #print("DATA 360")
4514 #print(dataOut.data_360)
4514 #print(dataOut.data_360)
4515 #print("---------------------------------------------------------------------------------")
4515 #print("---------------------------------------------------------------------------------")
4516 print("---------------------------DATAREADY---------------------------------------------")
4516 print("---------------------------DATAREADY---------------------------------------------")
4517 #print("---------------------------------------------------------------------------------")
4517 #print("---------------------------------------------------------------------------------")
4518 #print("data_360",dataOut.data_360.shape)
4518 #print("data_360",dataOut.data_360.shape)
4519 dataOut.data_azi = data_p
4519 dataOut.data_azi = data_p
4520 dataOut.data_ele = data_e
4520 dataOut.data_ele = data_e
4521 ###print("azi: ",dataOut.data_azi)
4521 ###print("azi: ",dataOut.data_azi)
4522 #print("ele: ",dataOut.data_ele)
4522 #print("ele: ",dataOut.data_ele)
4523 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4523 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4524 dataOut.utctime = avgdatatime
4524 dataOut.utctime = avgdatatime
4525
4525
4526 dataOut.case_flag = self.checkcase(dataOut.data_ele)
4526 dataOut.case_flag = self.checkcase(dataOut.data_ele)
4527 if dataOut.case_flag: #Si estΓ‘ de bajada empieza a plotear
4527 if dataOut.case_flag: #Si estΓ‘ de bajada empieza a plotear
4528 print("INSIDE CASE FLAG BAJADA")
4528 print("INSIDE CASE FLAG BAJADA")
4529 dataOut.flagNoData = False
4529 dataOut.flagNoData = False
4530 else:
4530 else:
4531 print("CASE SUBIDA")
4531 print("CASE SUBIDA")
4532 dataOut.flagNoData = True
4532 dataOut.flagNoData = True
4533
4533
4534 #dataOut.flagNoData = False
4534 #dataOut.flagNoData = False
4535 return dataOut
4535 return dataOut
4536
4536
4537 class Block360_vRF2(Operation):
4537 class Block360_vRF2(Operation):
4538 '''
4538 '''
4539 '''
4539 '''
4540 isConfig = False
4540 isConfig = False
4541 __profIndex = 0
4541 __profIndex = 0
4542 __initime = None
4542 __initime = None
4543 __lastdatatime = None
4543 __lastdatatime = None
4544 __buffer = None
4544 __buffer = None
4545 __dataReady = False
4545 __dataReady = False
4546 n = None
4546 n = None
4547 __nch = 0
4547 __nch = 0
4548 __nHeis = 0
4548 __nHeis = 0
4549 index = 0
4549 index = 0
4550 mode = None
4550 mode = None
4551
4551
4552 def __init__(self,**kwargs):
4552 def __init__(self,**kwargs):
4553 Operation.__init__(self,**kwargs)
4553 Operation.__init__(self,**kwargs)
4554
4554
4555 def setup(self, dataOut, n = None, mode = None):
4555 def setup(self, dataOut, n = None, mode = None):
4556 '''
4556 '''
4557 n= Numero de PRF's de entrada
4557 n= Numero de PRF's de entrada
4558 '''
4558 '''
4559 self.__initime = None
4559 self.__initime = None
4560 self.__lastdatatime = 0
4560 self.__lastdatatime = 0
4561 self.__dataReady = False
4561 self.__dataReady = False
4562 self.__buffer = 0
4562 self.__buffer = 0
4563 self.__buffer_1D = 0
4563 self.__buffer_1D = 0
4564 #self.__profIndex = 0
4564 #self.__profIndex = 0
4565 self.index = 0
4565 self.index = 0
4566 self.__nch = dataOut.nChannels
4566 self.__nch = dataOut.nChannels
4567 self.__nHeis = dataOut.nHeights
4567 self.__nHeis = dataOut.nHeights
4568
4568
4569 self.mode = mode
4569 self.mode = mode
4570 #print("self.mode",self.mode)
4570 #print("self.mode",self.mode)
4571 #print("nHeights")
4571 #print("nHeights")
4572 self.__buffer = []
4572 self.__buffer = []
4573 self.__buffer2 = []
4573 self.__buffer2 = []
4574 self.__buffer3 = []
4574 self.__buffer3 = []
4575 self.__buffer4 = []
4575 self.__buffer4 = []
4576
4576
4577 def putData(self,data,mode):
4577 def putData(self,data,mode):
4578 '''
4578 '''
4579 Add a profile to he __buffer and increase in one the __profiel Index
4579 Add a profile to he __buffer and increase in one the __profiel Index
4580 '''
4580 '''
4581
4581
4582 if self.mode==0:
4582 if self.mode==0:
4583 self.__buffer.append(data.dataPP_POWER)# PRIMER MOMENTO
4583 self.__buffer.append(data.dataPP_POWER)# PRIMER MOMENTO
4584 if self.mode==1:
4584 if self.mode==1:
4585 self.__buffer.append(data.data_pow)
4585 self.__buffer.append(data.data_pow)
4586
4586
4587 self.__buffer4.append(data.dataPP_DOP)
4587 self.__buffer4.append(data.dataPP_DOP)
4588
4588
4589 self.__buffer2.append(data.azimuth)
4589 self.__buffer2.append(data.azimuth)
4590 self.__buffer3.append(data.elevation)
4590 self.__buffer3.append(data.elevation)
4591 self.__profIndex += 1
4591 self.__profIndex += 1
4592
4592
4593 return numpy.array(self.__buffer3) #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4593 return numpy.array(self.__buffer3) #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4594
4594
4595 def pushData(self,data):
4595 def pushData(self,data):
4596 '''
4596 '''
4597 Return the PULSEPAIR and the profiles used in the operation
4597 Return the PULSEPAIR and the profiles used in the operation
4598 Affected : self.__profileIndex
4598 Affected : self.__profileIndex
4599 '''
4599 '''
4600
4600
4601 data_360_Power = numpy.array(self.__buffer).transpose(1,0,2)
4601 data_360_Power = numpy.array(self.__buffer).transpose(1,0,2)
4602 data_360_Velocity = numpy.array(self.__buffer4).transpose(1,0,2)
4602 data_360_Velocity = numpy.array(self.__buffer4).transpose(1,0,2)
4603 data_p = numpy.array(self.__buffer2)
4603 data_p = numpy.array(self.__buffer2)
4604 data_e = numpy.array(self.__buffer3)
4604 data_e = numpy.array(self.__buffer3)
4605 n = self.__profIndex
4605 n = self.__profIndex
4606
4606
4607 self.__buffer = []
4607 self.__buffer = []
4608 self.__buffer4 = []
4608 self.__buffer4 = []
4609 self.__buffer2 = []
4609 self.__buffer2 = []
4610 self.__buffer3 = []
4610 self.__buffer3 = []
4611 self.__profIndex = 0
4611 self.__profIndex = 0
4612 return data_360_Power,data_360_Velocity,n,data_p,data_e
4612 return data_360_Power,data_360_Velocity,n,data_p,data_e
4613
4613
4614
4614
4615 def byProfiles(self,dataOut):
4615 def byProfiles(self,dataOut):
4616
4616
4617 self.__dataReady = False
4617 self.__dataReady = False
4618 data_360_Power = []
4618 data_360_Power = []
4619 data_360_Velocity = []
4619 data_360_Velocity = []
4620 data_p = None
4620 data_p = None
4621 data_e = None
4621 data_e = None
4622
4622
4623 elevations = self.putData(data=dataOut,mode = self.mode)
4623 elevations = self.putData(data=dataOut,mode = self.mode)
4624
4624
4625 if self.__profIndex > 1:
4625 if self.__profIndex > 1:
4626 case_flag = self.checkcase(elevations)
4626 case_flag = self.checkcase(elevations)
4627
4627
4628 if case_flag == 0: #Subida
4628 if case_flag == 0: #Subida
4629
4629
4630 if len(self.__buffer) == 2: #Cuando estΓ‘ de subida
4630 if len(self.__buffer) == 2: #Cuando estΓ‘ de subida
4631 #Se borra el dato anterior para liberar buffer y comparar el dato actual con el siguiente
4631 #Se borra el dato anterior para liberar buffer y comparar el dato actual con el siguiente
4632 self.__buffer.pop(0) #Erase first data
4632 self.__buffer.pop(0) #Erase first data
4633 self.__buffer2.pop(0)
4633 self.__buffer2.pop(0)
4634 self.__buffer3.pop(0)
4634 self.__buffer3.pop(0)
4635 self.__buffer4.pop(0)
4635 self.__buffer4.pop(0)
4636 self.__profIndex -= 1
4636 self.__profIndex -= 1
4637 else: #Cuando ha estado de bajada y ha vuelto a subir
4637 else: #Cuando ha estado de bajada y ha vuelto a subir
4638 #Se borra el ΓΊltimo dato
4638 #Se borra el ΓΊltimo dato
4639 self.__buffer.pop() #Erase last data
4639 self.__buffer.pop() #Erase last data
4640 self.__buffer2.pop()
4640 self.__buffer2.pop()
4641 self.__buffer3.pop()
4641 self.__buffer3.pop()
4642 self.__buffer4.pop()
4642 self.__buffer4.pop()
4643 data_360_Power,data_360_Velocity,n,data_p,data_e = self.pushData(data=dataOut)
4643 data_360_Power,data_360_Velocity,n,data_p,data_e = self.pushData(data=dataOut)
4644
4644
4645 self.__dataReady = True
4645 self.__dataReady = True
4646
4646
4647 return data_360_Power,data_360_Velocity,data_p,data_e
4647 return data_360_Power,data_360_Velocity,data_p,data_e
4648
4648
4649
4649
4650 def blockOp(self, dataOut, datatime= None):
4650 def blockOp(self, dataOut, datatime= None):
4651 if self.__initime == None:
4651 if self.__initime == None:
4652 self.__initime = datatime
4652 self.__initime = datatime
4653 data_360_Power,data_360_Velocity,data_p,data_e = self.byProfiles(dataOut)
4653 data_360_Power,data_360_Velocity,data_p,data_e = self.byProfiles(dataOut)
4654 self.__lastdatatime = datatime
4654 self.__lastdatatime = datatime
4655
4655
4656 avgdatatime = self.__initime
4656 avgdatatime = self.__initime
4657 if self.n==1:
4657 if self.n==1:
4658 avgdatatime = datatime
4658 avgdatatime = datatime
4659 deltatime = datatime - self.__lastdatatime
4659 deltatime = datatime - self.__lastdatatime
4660 self.__initime = datatime
4660 self.__initime = datatime
4661 return data_360_Power,data_360_Velocity,avgdatatime,data_p,data_e
4661 return data_360_Power,data_360_Velocity,avgdatatime,data_p,data_e
4662
4662
4663 def checkcase(self,data_ele):
4663 def checkcase(self,data_ele):
4664 #print(data_ele)
4664 #print(data_ele)
4665 start = data_ele[-2]
4665 start = data_ele[-2]
4666 end = data_ele[-1]
4666 end = data_ele[-1]
4667 diff_angle = (end-start)
4667 diff_angle = (end-start)
4668 len_ang=len(data_ele)
4668 len_ang=len(data_ele)
4669
4669
4670 if diff_angle > 0: #Subida
4670 if diff_angle > 0: #Subida
4671 return 0
4671 return 0
4672
4672
4673 def run(self, dataOut,mode='Power',**kwargs):
4673 def run(self, dataOut,mode='Power',**kwargs):
4674 #print("BLOCK 360 HERE WE GO MOMENTOS")
4674 #print("BLOCK 360 HERE WE GO MOMENTOS")
4675 #print("Block 360")
4675 #print("Block 360")
4676 dataOut.mode = mode
4676 dataOut.mode = mode
4677
4677
4678 if not self.isConfig:
4678 if not self.isConfig:
4679 self.setup(dataOut = dataOut ,mode= mode ,**kwargs)
4679 self.setup(dataOut = dataOut ,mode= mode ,**kwargs)
4680 self.isConfig = True
4680 self.isConfig = True
4681
4681
4682
4682
4683 data_360_Power, data_360_Velocity, avgdatatime,data_p,data_e = self.blockOp(dataOut, dataOut.utctime)
4683 data_360_Power, data_360_Velocity, avgdatatime,data_p,data_e = self.blockOp(dataOut, dataOut.utctime)
4684
4684
4685
4685
4686 dataOut.flagNoData = True
4686 dataOut.flagNoData = True
4687
4687
4688
4688
4689 if self.__dataReady:
4689 if self.__dataReady:
4690 dataOut.data_360_Power = data_360_Power # S
4690 dataOut.data_360_Power = data_360_Power # S
4691 dataOut.data_360_Velocity = data_360_Velocity
4691 dataOut.data_360_Velocity = data_360_Velocity
4692 dataOut.data_azi = data_p
4692 dataOut.data_azi = data_p
4693 dataOut.data_ele = data_e
4693 dataOut.data_ele = data_e
4694 dataOut.utctime = avgdatatime
4694 dataOut.utctime = avgdatatime
4695 dataOut.flagNoData = False
4695 dataOut.flagNoData = False
4696
4696
4697 return dataOut
4697 return dataOut
4698
4698
4699 class Block360_vRF3(Operation):
4699 class Block360_vRF3(Operation):
4700 '''
4700 '''
4701 '''
4701 '''
4702 isConfig = False
4702 isConfig = False
4703 __profIndex = 0
4703 __profIndex = 0
4704 __initime = None
4704 __initime = None
4705 __lastdatatime = None
4705 __lastdatatime = None
4706 __buffer = None
4706 __buffer = None
4707 __dataReady = False
4707 __dataReady = False
4708 n = None
4708 n = None
4709 __nch = 0
4709 __nch = 0
4710 __nHeis = 0
4710 __nHeis = 0
4711 index = 0
4711 index = 0
4712 mode = None
4712 mode = None
4713
4713
4714 def __init__(self,**kwargs):
4714 def __init__(self,**kwargs):
4715 Operation.__init__(self,**kwargs)
4715 Operation.__init__(self,**kwargs)
4716
4716
4717 def setup(self, dataOut, attr):
4717 def setup(self, dataOut, attr):
4718 '''
4718 '''
4719 n= Numero de PRF's de entrada
4719 n= Numero de PRF's de entrada
4720 '''
4720 '''
4721 self.__initime = None
4721 self.__initime = None
4722 self.__lastdatatime = 0
4722 self.__lastdatatime = 0
4723 self.__dataReady = False
4723 self.__dataReady = False
4724 self.__buffer = 0
4724 self.__buffer = 0
4725 self.__buffer_1D = 0
4725 self.__buffer_1D = 0
4726 self.index = 0
4726 self.index = 0
4727 self.__nch = dataOut.nChannels
4727 self.__nch = dataOut.nChannels
4728 self.__nHeis = dataOut.nHeights
4728 self.__nHeis = dataOut.nHeights
4729
4729
4730 self.attr = attr
4730 self.attr = attr
4731 #print("self.mode",self.mode)
4731 #print("self.mode",self.mode)
4732 #print("nHeights")
4732 #print("nHeights")
4733 self.__buffer = []
4733 self.__buffer = []
4734 self.__buffer2 = []
4734 self.__buffer2 = []
4735 self.__buffer3 = []
4735 self.__buffer3 = []
4736
4736
4737 def putData(self, data, attr):
4737 def putData(self, data, attr):
4738 '''
4738 '''
4739 Add a profile to he __buffer and increase in one the __profiel Index
4739 Add a profile to he __buffer and increase in one the __profiel Index
4740 '''
4740 '''
4741
4741
4742 self.__buffer.append(getattr(data, attr))
4742 self.__buffer.append(getattr(data, attr))
4743 self.__buffer2.append(data.azimuth)
4743 self.__buffer2.append(data.azimuth)
4744 self.__buffer3.append(data.elevation)
4744 self.__buffer3.append(data.elevation)
4745 self.__profIndex += 1
4745 self.__profIndex += 1
4746
4746
4747 return numpy.array(self.__buffer3)
4747 return numpy.array(self.__buffer3)
4748
4748
4749 def pushData(self, data):
4749 def pushData(self, data):
4750 '''
4750 '''
4751 Return the PULSEPAIR and the profiles used in the operation
4751 Return the PULSEPAIR and the profiles used in the operation
4752 Affected : self.__profileIndex
4752 Affected : self.__profileIndex
4753 '''
4753 '''
4754
4754
4755 data_360 = numpy.array(self.__buffer).transpose(1, 0, 2)
4755 data_360 = numpy.array(self.__buffer).transpose(1, 0, 2)
4756 data_p = numpy.array(self.__buffer2)
4756 data_p = numpy.array(self.__buffer2)
4757 data_e = numpy.array(self.__buffer3)
4757 data_e = numpy.array(self.__buffer3)
4758 n = self.__profIndex
4758 n = self.__profIndex
4759
4759
4760 self.__buffer = []
4760 self.__buffer = []
4761 self.__buffer2 = []
4761 self.__buffer2 = []
4762 self.__buffer3 = []
4762 self.__buffer3 = []
4763 self.__profIndex = 0
4763 self.__profIndex = 0
4764 return data_360, n, data_p, data_e
4764 return data_360, n, data_p, data_e
4765
4765
4766
4766
4767 def byProfiles(self,dataOut):
4767 def byProfiles(self,dataOut):
4768
4768
4769 self.__dataReady = False
4769 self.__dataReady = False
4770 data_360 = []
4770 data_360 = []
4771 data_p = None
4771 data_p = None
4772 data_e = None
4772 data_e = None
4773
4773
4774 elevations = self.putData(data=dataOut, attr = self.attr)
4774 elevations = self.putData(data=dataOut, attr = self.attr)
4775
4775
4776 if self.__profIndex > 1:
4776 if self.__profIndex > 1:
4777 case_flag = self.checkcase(elevations)
4777 case_flag = self.checkcase(elevations)
4778
4778
4779 if case_flag == 0: #Subida
4779 if case_flag == 0: #Subida
4780
4780
4781 if len(self.__buffer) == 2: #Cuando estΓ‘ de subida
4781 if len(self.__buffer) == 2: #Cuando estΓ‘ de subida
4782 #Se borra el dato anterior para liberar buffer y comparar el dato actual con el siguiente
4782 #Se borra el dato anterior para liberar buffer y comparar el dato actual con el siguiente
4783 self.__buffer.pop(0) #Erase first data
4783 self.__buffer.pop(0) #Erase first data
4784 self.__buffer2.pop(0)
4784 self.__buffer2.pop(0)
4785 self.__buffer3.pop(0)
4785 self.__buffer3.pop(0)
4786 self.__profIndex -= 1
4786 self.__profIndex -= 1
4787 else: #Cuando ha estado de bajada y ha vuelto a subir
4787 else: #Cuando ha estado de bajada y ha vuelto a subir
4788 #Se borra el ΓΊltimo dato
4788 #Se borra el ΓΊltimo dato
4789 self.__buffer.pop() #Erase last data
4789 self.__buffer.pop() #Erase last data
4790 self.__buffer2.pop()
4790 self.__buffer2.pop()
4791 self.__buffer3.pop()
4791 self.__buffer3.pop()
4792 data_360, n, data_p, data_e = self.pushData(data=dataOut)
4792 data_360, n, data_p, data_e = self.pushData(data=dataOut)
4793
4793
4794 self.__dataReady = True
4794 self.__dataReady = True
4795
4795
4796 return data_360, data_p, data_e
4796 return data_360, data_p, data_e
4797
4797
4798
4798
4799 def blockOp(self, dataOut, datatime= None):
4799 def blockOp(self, dataOut, datatime= None):
4800 if self.__initime == None:
4800 if self.__initime == None:
4801 self.__initime = datatime
4801 self.__initime = datatime
4802 data_360, data_p, data_e = self.byProfiles(dataOut)
4802 data_360, data_p, data_e = self.byProfiles(dataOut)
4803 self.__lastdatatime = datatime
4803 self.__lastdatatime = datatime
4804
4804
4805 avgdatatime = self.__initime
4805 avgdatatime = self.__initime
4806 if self.n==1:
4806 if self.n==1:
4807 avgdatatime = datatime
4807 avgdatatime = datatime
4808 deltatime = datatime - self.__lastdatatime
4808 deltatime = datatime - self.__lastdatatime
4809 self.__initime = datatime
4809 self.__initime = datatime
4810 return data_360, avgdatatime, data_p, data_e
4810 return data_360, avgdatatime, data_p, data_e
4811
4811
4812 def checkcase(self, data_ele):
4812 def checkcase(self, data_ele):
4813
4813
4814 start = data_ele[-2]
4814 start = data_ele[-2]
4815 end = data_ele[-1]
4815 end = data_ele[-1]
4816 diff_angle = (end-start)
4816 diff_angle = (end-start)
4817 len_ang=len(data_ele)
4817 len_ang=len(data_ele)
4818
4818
4819 if diff_angle > 0: #Subida
4819 if diff_angle > 0: #Subida
4820 return 0
4820 return 0
4821
4821
4822 def run(self, dataOut, attr_data='dataPP_POWER',**kwargs):
4822 def run(self, dataOut, attr_data='dataPP_POWER',**kwargs):
4823
4823
4824 dataOut.attr_data = attr_data
4824 dataOut.attr_data = attr_data
4825
4825
4826 if not self.isConfig:
4826 if not self.isConfig:
4827 self.setup(dataOut = dataOut, attr = attr_data ,**kwargs)
4827 self.setup(dataOut = dataOut, attr = attr_data ,**kwargs)
4828 self.isConfig = True
4828 self.isConfig = True
4829
4829
4830 data_360, avgdatatime, data_p, data_e = self.blockOp(dataOut, dataOut.utctime)
4830 data_360, avgdatatime, data_p, data_e = self.blockOp(dataOut, dataOut.utctime)
4831
4831
4832 dataOut.flagNoData = True
4832 dataOut.flagNoData = True
4833
4833
4834 if self.__dataReady:
4834 if self.__dataReady:
4835 setattr(dataOut, attr_data, data_360 )
4835 setattr(dataOut, attr_data, data_360 )
4836 dataOut.data_azi = data_p
4836 dataOut.data_azi = data_p
4837 dataOut.data_ele = data_e
4837 dataOut.data_ele = data_e
4838 dataOut.utctime = avgdatatime
4838 dataOut.utctime = avgdatatime
4839 dataOut.flagNoData = False
4839 dataOut.flagNoData = False
4840
4840
4841 return dataOut
4841 return dataOut
4842
4842
4843 class Block360_vRF4(Operation):
4843 class Block360_vRF4(Operation):
4844 '''
4844 '''
4845 '''
4845 '''
4846 isConfig = False
4846 isConfig = False
4847 __profIndex = 0
4847 __profIndex = 0
4848 __initime = None
4848 __initime = None
4849 __lastdatatime = None
4849 __lastdatatime = None
4850 __buffer = None
4850 __buffer = None
4851 __dataReady = False
4851 __dataReady = False
4852 n = None
4852 n = None
4853 __nch = 0
4853 __nch = 0
4854 __nHeis = 0
4854 __nHeis = 0
4855 index = 0
4855 index = 0
4856 mode = None
4856 mode = None
4857
4857
4858 def __init__(self,**kwargs):
4858 def __init__(self,**kwargs):
4859 Operation.__init__(self,**kwargs)
4859 Operation.__init__(self,**kwargs)
4860
4860
4861 def setup(self, dataOut, attr):
4861 def setup(self, dataOut, attr):
4862 '''
4862 '''
4863 n= Numero de PRF's de entrada
4863 n= Numero de PRF's de entrada
4864 '''
4864 '''
4865 self.__initime = None
4865 self.__initime = None
4866 self.__lastdatatime = 0
4866 self.__lastdatatime = 0
4867 self.__dataReady = False
4867 self.__dataReady = False
4868 self.__buffer = 0
4868 self.__buffer = 0
4869 self.__buffer_1D = 0
4869 self.__buffer_1D = 0
4870 self.index = 0
4870 self.index = 0
4871 self.__nch = dataOut.nChannels
4871 self.__nch = dataOut.nChannels
4872 self.__nHeis = dataOut.nHeights
4872 self.__nHeis = dataOut.nHeights
4873
4873
4874 self.attr = attr
4874 self.attr = attr
4875
4875
4876 self.__buffer = []
4876 self.__buffer = []
4877 self.__buffer2 = []
4877 self.__buffer2 = []
4878 self.__buffer3 = []
4878 self.__buffer3 = []
4879
4879
4880 def putData(self, data, attr, flagMode):
4880 def putData(self, data, attr, flagMode):
4881 '''
4881 '''
4882 Add a profile to he __buffer and increase in one the __profiel Index
4882 Add a profile to he __buffer and increase in one the __profiel Index
4883 '''
4883 '''
4884 tmp= getattr(data, attr)
4884 tmp= getattr(data, attr)
4885 if tmp.shape[0] is not 2:
4885 if tmp.shape[0] != 2:
4886 size_tmp= tmp.shape[0]
4886 size_tmp= tmp.shape[0]
4887 tmp=tmp.reshape(1,size_tmp)
4887 tmp=tmp.reshape(1,size_tmp)
4888
4888
4889 self.__buffer.append(tmp)
4889 self.__buffer.append(tmp)
4890 self.__buffer2.append(data.azimuth)
4890 self.__buffer2.append(data.azimuth)
4891 self.__buffer3.append(data.elevation)
4891 self.__buffer3.append(data.elevation)
4892 self.__profIndex += 1
4892 self.__profIndex += 1
4893
4893
4894 if flagMode == 1: #'AZI'
4894 if flagMode == 1: #'AZI'
4895 return numpy.array(self.__buffer2)
4895 return numpy.array(self.__buffer2)
4896 elif flagMode == 0: #'ELE'
4896 elif flagMode == 0: #'ELE'
4897 return numpy.array(self.__buffer3)
4897 return numpy.array(self.__buffer3)
4898
4898
4899 def pushData(self, data,flagMode,case_flag):
4899 def pushData(self, data,flagMode,case_flag):
4900 '''
4900 '''
4901 Return the PULSEPAIR and the profiles used in the operation
4901 Return the PULSEPAIR and the profiles used in the operation
4902 Affected : self.__profileIndex
4902 Affected : self.__profileIndex
4903 '''
4903 '''
4904
4904
4905 data_360 = numpy.array(self.__buffer).transpose(1, 0, 2)
4905 data_360 = numpy.array(self.__buffer).transpose(1, 0, 2)
4906 data_p = numpy.array(self.__buffer2)
4906 data_p = numpy.array(self.__buffer2)
4907 data_e = numpy.array(self.__buffer3)
4907 data_e = numpy.array(self.__buffer3)
4908 n = self.__profIndex
4908 n = self.__profIndex
4909
4909
4910 self.__buffer = []
4910 self.__buffer = []
4911 self.__buffer2 = []
4911 self.__buffer2 = []
4912 self.__buffer3 = []
4912 self.__buffer3 = []
4913 self.__profIndex = 0
4913 self.__profIndex = 0
4914
4914
4915 if flagMode == 1 and case_flag == 0: #'AZI' y ha girado
4915 if flagMode == 1 and case_flag == 0: #'AZI' y ha girado
4916 self.putData(data=data, attr = self.attr, flagMode=flagMode)
4916 self.putData(data=data, attr = self.attr, flagMode=flagMode)
4917
4917
4918 return data_360, n, data_p, data_e
4918 return data_360, n, data_p, data_e
4919
4919
4920
4920
4921 def byProfiles(self,dataOut,flagMode):
4921 def byProfiles(self,dataOut,flagMode):
4922
4922
4923 self.__dataReady = False
4923 self.__dataReady = False
4924 data_360 = []
4924 data_360 = []
4925 data_p = None
4925 data_p = None
4926 data_e = None
4926 data_e = None
4927
4927
4928 angles = self.putData(data=dataOut, attr = self.attr, flagMode=flagMode)
4928 angles = self.putData(data=dataOut, attr = self.attr, flagMode=flagMode)
4929 #print(angles)
4929 #print(angles)
4930 if self.__profIndex > 1:
4930 if self.__profIndex > 1:
4931 case_flag = self.checkcase(angles,flagMode)
4931 case_flag = self.checkcase(angles,flagMode)
4932
4932
4933 if flagMode == 1: #'AZI':
4933 if flagMode == 1: #'AZI':
4934 if case_flag == 0: #Ya girΓ³
4934 if case_flag == 0: #Ya girΓ³
4935 self.__buffer.pop() #Erase last data
4935 self.__buffer.pop() #Erase last data
4936 self.__buffer2.pop()
4936 self.__buffer2.pop()
4937 self.__buffer3.pop()
4937 self.__buffer3.pop()
4938 data_360,n,data_p,data_e = self.pushData(data=dataOut,flagMode=flagMode,case_flag=case_flag)
4938 data_360,n,data_p,data_e = self.pushData(data=dataOut,flagMode=flagMode,case_flag=case_flag)
4939
4939
4940 self.__dataReady = True
4940 self.__dataReady = True
4941
4941
4942 elif flagMode == 0: #'ELE'
4942 elif flagMode == 0: #'ELE'
4943
4943
4944 if case_flag == 0: #Subida
4944 if case_flag == 0: #Subida
4945
4945
4946 if len(self.__buffer) == 2: #Cuando estΓ‘ de subida
4946 if len(self.__buffer) == 2: #Cuando estΓ‘ de subida
4947 #Se borra el dato anterior para liberar buffer y comparar el dato actual con el siguiente
4947 #Se borra el dato anterior para liberar buffer y comparar el dato actual con el siguiente
4948 self.__buffer.pop(0) #Erase first data
4948 self.__buffer.pop(0) #Erase first data
4949 self.__buffer2.pop(0)
4949 self.__buffer2.pop(0)
4950 self.__buffer3.pop(0)
4950 self.__buffer3.pop(0)
4951 self.__profIndex -= 1
4951 self.__profIndex -= 1
4952 else: #Cuando ha estado de bajada y ha vuelto a subir
4952 else: #Cuando ha estado de bajada y ha vuelto a subir
4953 #Se borra el ΓΊltimo dato
4953 #Se borra el ΓΊltimo dato
4954 self.__buffer.pop() #Erase last data
4954 self.__buffer.pop() #Erase last data
4955 self.__buffer2.pop()
4955 self.__buffer2.pop()
4956 self.__buffer3.pop()
4956 self.__buffer3.pop()
4957 data_360, n, data_p, data_e = self.pushData(data=dataOut,flagMode=flagMode,case_flag=case_flag)
4957 data_360, n, data_p, data_e = self.pushData(data=dataOut,flagMode=flagMode,case_flag=case_flag)
4958
4958
4959 self.__dataReady = True
4959 self.__dataReady = True
4960
4960
4961 return data_360, data_p, data_e
4961 return data_360, data_p, data_e
4962
4962
4963
4963
4964 def blockOp(self, dataOut, flagMode, datatime= None):
4964 def blockOp(self, dataOut, flagMode, datatime= None):
4965 if self.__initime == None:
4965 if self.__initime == None:
4966 self.__initime = datatime
4966 self.__initime = datatime
4967 data_360, data_p, data_e = self.byProfiles(dataOut,flagMode)
4967 data_360, data_p, data_e = self.byProfiles(dataOut,flagMode)
4968 self.__lastdatatime = datatime
4968 self.__lastdatatime = datatime
4969
4969
4970 avgdatatime = self.__initime
4970 avgdatatime = self.__initime
4971 if self.n==1:
4971 if self.n==1:
4972 avgdatatime = datatime
4972 avgdatatime = datatime
4973 deltatime = datatime - self.__lastdatatime
4973 deltatime = datatime - self.__lastdatatime
4974 self.__initime = datatime
4974 self.__initime = datatime
4975 return data_360, avgdatatime, data_p, data_e
4975 return data_360, avgdatatime, data_p, data_e
4976
4976
4977 def checkcase(self, angles, flagMode):
4977 def checkcase(self, angles, flagMode):
4978
4978
4979 if flagMode == 1: #'AZI'
4979 if flagMode == 1: #'AZI'
4980 start = angles[-2]
4980 start = angles[-2]
4981 end = angles[-1]
4981 end = angles[-1]
4982 diff_angle = (end-start)
4982 diff_angle = (end-start)
4983
4983
4984 if diff_angle < 0: #Ya girΓ³
4984 if diff_angle < 0: #Ya girΓ³
4985 return 0
4985 return 0
4986
4986
4987 elif flagMode == 0: #'ELE'
4987 elif flagMode == 0: #'ELE'
4988
4988
4989 start = angles[-2]
4989 start = angles[-2]
4990 end = angles[-1]
4990 end = angles[-1]
4991 diff_angle = (end-start)
4991 diff_angle = (end-start)
4992
4992
4993 if diff_angle > 0: #Subida
4993 if diff_angle > 0: #Subida
4994 return 0
4994 return 0
4995
4995
4996 def run(self, dataOut, attr_data='dataPP_POWER', axis=None,**kwargs):
4996 def run(self, dataOut, attr_data='dataPP_POWER', axis=None, runNextOp = False,**kwargs):
4997
4997
4998 dataOut.attr_data = attr_data
4998 dataOut.attr_data = attr_data
4999 dataOut.runNextOp = runNextOp
4999
5000
5000 dataOut.flagMode = axis[0] #Provisional, deberΓ­a venir del header
5001 dataOut.flagMode = axis[0] #Provisional, deberΓ­a venir del header
5001
5002
5002 if not self.isConfig:
5003 if not self.isConfig:
5003 self.setup(dataOut = dataOut, attr = attr_data ,**kwargs)
5004 self.setup(dataOut = dataOut, attr = attr_data ,**kwargs)
5004 self.isConfig = True
5005 self.isConfig = True
5005
5006
5006 data_360, avgdatatime, data_p, data_e = self.blockOp(dataOut, dataOut.flagMode, dataOut.utctime)
5007 data_360, avgdatatime, data_p, data_e = self.blockOp(dataOut, dataOut.flagMode, dataOut.utctime)
5007
5008
5008 dataOut.flagNoData = True
5009 dataOut.flagNoData = True
5009
5010
5010 if self.__dataReady:
5011 if self.__dataReady:
5011 setattr(dataOut, attr_data, data_360 )
5012 setattr(dataOut, attr_data, data_360 )
5012 dataOut.data_azi = data_p
5013 dataOut.data_azi = data_p
5013 dataOut.data_ele = data_e
5014 dataOut.data_ele = data_e
5014 dataOut.utctime = avgdatatime
5015 dataOut.utctime = avgdatatime
5015 dataOut.flagNoData = False
5016 dataOut.flagNoData = False
5016 print("********************attr_data********************",attr_data)
5017 #print("********************attr_data********************",attr_data)
5017 #print(data_360.shape)
5018 #print(data_360.shape)
5018 #print(dataOut.heightList)
5019 #print(dataOut.heightList)
5019
5020
5020 return dataOut
5021 return dataOut
5021
5022
5022 class MergeProc(ProcessingUnit):
5023 class MergeProc(ProcessingUnit):
5023
5024
5024 def __init__(self):
5025 def __init__(self):
5025 ProcessingUnit.__init__(self)
5026 ProcessingUnit.__init__(self)
5026
5027
5027 def run(self, attr_data, mode=0):
5028 def run(self, attr_data, mode=0):
5028
5029
5029 #exit(1)
5030 #exit(1)
5030 self.dataOut = getattr(self, self.inputs[0])
5031 self.dataOut = getattr(self, self.inputs[0])
5031 data_inputs = [getattr(self, attr) for attr in self.inputs]
5032 data_inputs = [getattr(self, attr) for attr in self.inputs]
5032 #print(data_inputs)
5033 #print(data_inputs)
5033 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
5034 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
5034 #exit(1)
5035 #exit(1)
5035 if mode==0:
5036 if mode==0:
5036 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
5037 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
5037 setattr(self.dataOut, attr_data, data)
5038 setattr(self.dataOut, attr_data, data)
5038
5039
5039 if mode==1: #Hybrid
5040 if mode==1: #Hybrid
5040 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
5041 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
5041 #setattr(self.dataOut, attr_data, data)
5042 #setattr(self.dataOut, attr_data, data)
5042 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
5043 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
5043 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
5044 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
5044 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
5045 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
5045 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
5046 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
5046 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
5047 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
5047 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
5048 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
5048 '''
5049 '''
5049 print(self.dataOut.dataLag_spc_LP.shape)
5050 print(self.dataOut.dataLag_spc_LP.shape)
5050 print(self.dataOut.dataLag_cspc_LP.shape)
5051 print(self.dataOut.dataLag_cspc_LP.shape)
5051 exit(1)
5052 exit(1)
5052 '''
5053 '''
5053
5054
5054 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
5055 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
5055 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
5056 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
5056 '''
5057 '''
5057 print("Merge")
5058 print("Merge")
5058 print(numpy.shape(self.dataOut.dataLag_spc))
5059 print(numpy.shape(self.dataOut.dataLag_spc))
5059 print(numpy.shape(self.dataOut.dataLag_spc_LP))
5060 print(numpy.shape(self.dataOut.dataLag_spc_LP))
5060 print(numpy.shape(self.dataOut.dataLag_cspc))
5061 print(numpy.shape(self.dataOut.dataLag_cspc))
5061 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
5062 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
5062 exit(1)
5063 exit(1)
5063 '''
5064 '''
5064 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
5065 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
5065 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
5066 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
5066 #exit(1)
5067 #exit(1)
5067 #print(self.dataOut.NDP)
5068 #print(self.dataOut.NDP)
5068 #print(self.dataOut.nNoiseProfiles)
5069 #print(self.dataOut.nNoiseProfiles)
5069
5070
5070 #self.dataOut.nIncohInt_LP = 128
5071 #self.dataOut.nIncohInt_LP = 128
5071 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
5072 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
5072 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
5073 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
5073 self.dataOut.NLAG = 16
5074 self.dataOut.NLAG = 16
5074 self.dataOut.NRANGE = 200
5075 self.dataOut.NRANGE = 200
5075 self.dataOut.NSCAN = 128
5076 self.dataOut.NSCAN = 128
5076 #print(numpy.shape(self.dataOut.data_spc))
5077 #print(numpy.shape(self.dataOut.data_spc))
5077
5078
5078 #exit(1)
5079 #exit(1)
5079
5080
5080 if mode==2: #HAE 2022
5081 if mode==2: #HAE 2022
5081 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
5082 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
5082 setattr(self.dataOut, attr_data, data)
5083 setattr(self.dataOut, attr_data, data)
5083
5084
5084 self.dataOut.nIncohInt *= 2
5085 self.dataOut.nIncohInt *= 2
5085 #meta = self.dataOut.getFreqRange(1)/1000.
5086 #meta = self.dataOut.getFreqRange(1)/1000.
5086 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
5087 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
5087
5088
5088 #exit(1)
5089 #exit(1)
5089
5090
5090 if mode==7: #RM
5091 if mode==7: #RM
5091
5092
5092 f = [getattr(data, attr_data) for data in data_inputs][0]
5093 f = [getattr(data, attr_data) for data in data_inputs][0]
5093 g = [getattr(data, attr_data) for data in data_inputs][1]
5094 g = [getattr(data, attr_data) for data in data_inputs][1]
5094
5095
5095 data = numpy.concatenate((f,g),axis=2)
5096 data = numpy.concatenate((f,g),axis=2)
5096 #print(data)
5097 #print(data)
5097 setattr(self.dataOut, attr_data, data)
5098 setattr(self.dataOut, attr_data, data)
5098 #print(self.dataOut.dataPP_POWER.shape)
5099 #print(self.dataOut.dataPP_POWER.shape)
5099 #CONSTRUIR NUEVA ALTURAS
5100 #CONSTRUIR NUEVA ALTURAS
5100 #print("hei_merge",self.dataOut.heightList)
5101 #print("hei_merge",self.dataOut.heightList)
5101 dh = self.dataOut.heightList[1]-self.dataOut.heightList[0]
5102 dh = self.dataOut.heightList[1]-self.dataOut.heightList[0]
5102 heightList_2 = (self.dataOut.heightList[-1]+dh) + numpy.arange(g.shape[-1], dtype=numpy.float) * dh
5103 heightList_2 = (self.dataOut.heightList[-1]+dh) + numpy.arange(g.shape[-1], dtype=numpy.float) * dh
5103
5104
5104 self.dataOut.heightList = numpy.concatenate((self.dataOut.heightList,heightList_2))
5105 self.dataOut.heightList = numpy.concatenate((self.dataOut.heightList,heightList_2))
5105 #print("hei_merge_total",self.dataOut.heightList)
5106 #print("hei_merge_total",self.dataOut.heightList)
5106 #exit(1)
5107 #exit(1)
@@ -1,1860 +1,1861
1 import sys
1 import sys
2 import numpy,math
2 import numpy,math
3 from scipy import interpolate
3 from scipy import interpolate
4 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
4 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
5 from schainpy.model.data.jrodata import Voltage,hildebrand_sekhon
5 from schainpy.model.data.jrodata import Voltage,hildebrand_sekhon
6 from schainpy.utils import log
6 from schainpy.utils import log
7 from time import time
7 from time import time
8
8
9
9
10
10
11 class VoltageProc(ProcessingUnit):
11 class VoltageProc(ProcessingUnit):
12
12
13 def __init__(self):
13 def __init__(self):
14
14
15 ProcessingUnit.__init__(self)
15 ProcessingUnit.__init__(self)
16
16
17 self.dataOut = Voltage()
17 self.dataOut = Voltage()
18 self.flip = 1
18 self.flip = 1
19 self.setupReq = False
19 self.setupReq = False
20
20
21 def run(self):
21 def run(self):
22
22
23 if self.dataIn.type == 'AMISR':
23 if self.dataIn.type == 'AMISR':
24 self.__updateObjFromAmisrInput()
24 self.__updateObjFromAmisrInput()
25
25
26 if self.dataIn.type == 'Voltage':
26 if self.dataIn.type == 'Voltage':
27 self.dataOut.copy(self.dataIn)
27 self.dataOut.copy(self.dataIn)
28
28
29 def __updateObjFromAmisrInput(self):
29 def __updateObjFromAmisrInput(self):
30
30
31 self.dataOut.timeZone = self.dataIn.timeZone
31 self.dataOut.timeZone = self.dataIn.timeZone
32 self.dataOut.dstFlag = self.dataIn.dstFlag
32 self.dataOut.dstFlag = self.dataIn.dstFlag
33 self.dataOut.errorCount = self.dataIn.errorCount
33 self.dataOut.errorCount = self.dataIn.errorCount
34 self.dataOut.useLocalTime = self.dataIn.useLocalTime
34 self.dataOut.useLocalTime = self.dataIn.useLocalTime
35
35
36 self.dataOut.flagNoData = self.dataIn.flagNoData
36 self.dataOut.flagNoData = self.dataIn.flagNoData
37 self.dataOut.data = self.dataIn.data
37 self.dataOut.data = self.dataIn.data
38 self.dataOut.utctime = self.dataIn.utctime
38 self.dataOut.utctime = self.dataIn.utctime
39 self.dataOut.channelList = self.dataIn.channelList
39 self.dataOut.channelList = self.dataIn.channelList
40 #self.dataOut.timeInterval = self.dataIn.timeInterval
40 #self.dataOut.timeInterval = self.dataIn.timeInterval
41 self.dataOut.heightList = self.dataIn.heightList
41 self.dataOut.heightList = self.dataIn.heightList
42 self.dataOut.nProfiles = self.dataIn.nProfiles
42 self.dataOut.nProfiles = self.dataIn.nProfiles
43
43
44 self.dataOut.nCohInt = self.dataIn.nCohInt
44 self.dataOut.nCohInt = self.dataIn.nCohInt
45 self.dataOut.ippSeconds = self.dataIn.ippSeconds
45 self.dataOut.ippSeconds = self.dataIn.ippSeconds
46 self.dataOut.frequency = self.dataIn.frequency
46 self.dataOut.frequency = self.dataIn.frequency
47
47
48 self.dataOut.azimuth = self.dataIn.azimuth
48 self.dataOut.azimuth = self.dataIn.azimuth
49 self.dataOut.zenith = self.dataIn.zenith
49 self.dataOut.zenith = self.dataIn.zenith
50
50
51 self.dataOut.beam.codeList = self.dataIn.beam.codeList
51 self.dataOut.beam.codeList = self.dataIn.beam.codeList
52 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
52 self.dataOut.beam.azimuthList = self.dataIn.beam.azimuthList
53 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
53 self.dataOut.beam.zenithList = self.dataIn.beam.zenithList
54
54
55
55
56 class selectChannels(Operation):
56 class selectChannels(Operation):
57
57
58 def run(self, dataOut, channelList):
58 def run(self, dataOut, channelList):
59
59
60 channelIndexList = []
60 channelIndexList = []
61 self.dataOut = dataOut
61 self.dataOut = dataOut
62 for channel in channelList:
62 for channel in channelList:
63 if channel not in self.dataOut.channelList:
63 if channel not in self.dataOut.channelList:
64 raise ValueError("Channel %d is not in %s" %(channel, str(self.dataOut.channelList)))
64 raise ValueError("Channel %d is not in %s" %(channel, str(self.dataOut.channelList)))
65
65
66 index = self.dataOut.channelList.index(channel)
66 index = self.dataOut.channelList.index(channel)
67 channelIndexList.append(index)
67 channelIndexList.append(index)
68 self.selectChannelsByIndex(channelIndexList)
68 self.selectChannelsByIndex(channelIndexList)
69 return self.dataOut
69 return self.dataOut
70
70
71 def selectChannelsByIndex(self, channelIndexList):
71 def selectChannelsByIndex(self, channelIndexList):
72 """
72 """
73 Selecciona un bloque de datos en base a canales segun el channelIndexList
73 Selecciona un bloque de datos en base a canales segun el channelIndexList
74
74
75 Input:
75 Input:
76 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
76 channelIndexList : lista sencilla de canales a seleccionar por ej. [2,3,7]
77
77
78 Affected:
78 Affected:
79 self.dataOut.data
79 self.dataOut.data
80 self.dataOut.channelIndexList
80 self.dataOut.channelIndexList
81 self.dataOut.nChannels
81 self.dataOut.nChannels
82 self.dataOut.m_ProcessingHeader.totalSpectra
82 self.dataOut.m_ProcessingHeader.totalSpectra
83 self.dataOut.systemHeaderObj.numChannels
83 self.dataOut.systemHeaderObj.numChannels
84 self.dataOut.m_ProcessingHeader.blockSize
84 self.dataOut.m_ProcessingHeader.blockSize
85
85
86 Return:
86 Return:
87 None
87 None
88 """
88 """
89
89
90 for channelIndex in channelIndexList:
90 for channelIndex in channelIndexList:
91 if channelIndex not in self.dataOut.channelIndexList:
91 if channelIndex not in self.dataOut.channelIndexList:
92 raise ValueError("The value %d in channelIndexList is not valid" %channelIndex)
92 raise ValueError("The value %d in channelIndexList is not valid" %channelIndex)
93
93
94 if self.dataOut.type == 'Voltage':
94 if self.dataOut.type == 'Voltage':
95 if self.dataOut.flagDataAsBlock:
95 if self.dataOut.flagDataAsBlock:
96 """
96 """
97 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
97 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
98 """
98 """
99 data = self.dataOut.data[channelIndexList,:,:]
99 data = self.dataOut.data[channelIndexList,:,:]
100 else:
100 else:
101 data = self.dataOut.data[channelIndexList,:]
101 data = self.dataOut.data[channelIndexList,:]
102
102
103 self.dataOut.data = data
103 self.dataOut.data = data
104 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
104 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
105 self.dataOut.channelList = range(len(channelIndexList))
105 self.dataOut.channelList = range(len(channelIndexList))
106
106
107 elif self.dataOut.type == 'Spectra':
107 elif self.dataOut.type == 'Spectra':
108 data_spc = self.dataOut.data_spc[channelIndexList, :]
108 data_spc = self.dataOut.data_spc[channelIndexList, :]
109 data_dc = self.dataOut.data_dc[channelIndexList, :]
109 data_dc = self.dataOut.data_dc[channelIndexList, :]
110
110
111 self.dataOut.data_spc = data_spc
111 self.dataOut.data_spc = data_spc
112 self.dataOut.data_dc = data_dc
112 self.dataOut.data_dc = data_dc
113
113
114 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
114 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
115 self.dataOut.channelList = range(len(channelIndexList))
115 self.dataOut.channelList = range(len(channelIndexList))
116 self.__selectPairsByChannel(channelIndexList)
116 self.__selectPairsByChannel(channelIndexList)
117
117
118 return 1
118 return 1
119
119
120 def __selectPairsByChannel(self, channelList=None):
120 def __selectPairsByChannel(self, channelList=None):
121
121
122 if channelList == None:
122 if channelList == None:
123 return
123 return
124
124
125 pairsIndexListSelected = []
125 pairsIndexListSelected = []
126 for pairIndex in self.dataOut.pairsIndexList:
126 for pairIndex in self.dataOut.pairsIndexList:
127 # First pair
127 # First pair
128 if self.dataOut.pairsList[pairIndex][0] not in channelList:
128 if self.dataOut.pairsList[pairIndex][0] not in channelList:
129 continue
129 continue
130 # Second pair
130 # Second pair
131 if self.dataOut.pairsList[pairIndex][1] not in channelList:
131 if self.dataOut.pairsList[pairIndex][1] not in channelList:
132 continue
132 continue
133
133
134 pairsIndexListSelected.append(pairIndex)
134 pairsIndexListSelected.append(pairIndex)
135
135
136 if not pairsIndexListSelected:
136 if not pairsIndexListSelected:
137 self.dataOut.data_cspc = None
137 self.dataOut.data_cspc = None
138 self.dataOut.pairsList = []
138 self.dataOut.pairsList = []
139 return
139 return
140
140
141 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
141 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndexListSelected]
142 self.dataOut.pairsList = [self.dataOut.pairsList[i]
142 self.dataOut.pairsList = [self.dataOut.pairsList[i]
143 for i in pairsIndexListSelected]
143 for i in pairsIndexListSelected]
144
144
145 return
145 return
146
146
147 class selectHeights(Operation):
147 class selectHeights(Operation):
148
148
149 def run(self, dataOut, minHei=None, maxHei=None, minIndex=None, maxIndex=None):
149 def run(self, dataOut, minHei=None, maxHei=None, minIndex=None, maxIndex=None):
150 """
150 """
151 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
151 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
152 minHei <= height <= maxHei
152 minHei <= height <= maxHei
153
153
154 Input:
154 Input:
155 minHei : valor minimo de altura a considerar
155 minHei : valor minimo de altura a considerar
156 maxHei : valor maximo de altura a considerar
156 maxHei : valor maximo de altura a considerar
157
157
158 Affected:
158 Affected:
159 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
159 Indirectamente son cambiados varios valores a travez del metodo selectHeightsByIndex
160
160
161 Return:
161 Return:
162 1 si el metodo se ejecuto con exito caso contrario devuelve 0
162 1 si el metodo se ejecuto con exito caso contrario devuelve 0
163 """
163 """
164
164
165 self.dataOut = dataOut
165 self.dataOut = dataOut
166
166
167 if minHei and maxHei:
167 if minHei and maxHei:
168
168
169 if (minHei < self.dataOut.heightList[0]):
169 if (minHei < self.dataOut.heightList[0]):
170 minHei = self.dataOut.heightList[0]
170 minHei = self.dataOut.heightList[0]
171
171
172 if (maxHei > self.dataOut.heightList[-1]):
172 if (maxHei > self.dataOut.heightList[-1]):
173 maxHei = self.dataOut.heightList[-1]
173 maxHei = self.dataOut.heightList[-1]
174
174
175 minIndex = 0
175 minIndex = 0
176 maxIndex = 0
176 maxIndex = 0
177 heights = self.dataOut.heightList
177 heights = self.dataOut.heightList
178
178
179 inda = numpy.where(heights >= minHei)
179 inda = numpy.where(heights >= minHei)
180 indb = numpy.where(heights <= maxHei)
180 indb = numpy.where(heights <= maxHei)
181
181
182 try:
182 try:
183 minIndex = inda[0][0]
183 minIndex = inda[0][0]
184 except:
184 except:
185 minIndex = 0
185 minIndex = 0
186
186
187 try:
187 try:
188 maxIndex = indb[0][-1]
188 maxIndex = indb[0][-1]
189 except:
189 except:
190 maxIndex = len(heights)
190 maxIndex = len(heights)
191
191
192 self.selectHeightsByIndex(minIndex, maxIndex)
192 self.selectHeightsByIndex(minIndex, maxIndex)
193
193
194 return self.dataOut
194 return self.dataOut
195
195
196 def selectHeightsByIndex(self, minIndex, maxIndex):
196 def selectHeightsByIndex(self, minIndex, maxIndex):
197 """
197 """
198 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
198 Selecciona un bloque de datos en base a un grupo indices de alturas segun el rango
199 minIndex <= index <= maxIndex
199 minIndex <= index <= maxIndex
200
200
201 Input:
201 Input:
202 minIndex : valor de indice minimo de altura a considerar
202 minIndex : valor de indice minimo de altura a considerar
203 maxIndex : valor de indice maximo de altura a considerar
203 maxIndex : valor de indice maximo de altura a considerar
204
204
205 Affected:
205 Affected:
206 self.dataOut.data
206 self.dataOut.data
207 self.dataOut.heightList
207 self.dataOut.heightList
208
208
209 Return:
209 Return:
210 1 si el metodo se ejecuto con exito caso contrario devuelve 0
210 1 si el metodo se ejecuto con exito caso contrario devuelve 0
211 """
211 """
212
212
213 if self.dataOut.type == 'Voltage':
213 if self.dataOut.type == 'Voltage':
214 if (minIndex < 0) or (minIndex > maxIndex):
214 if (minIndex < 0) or (minIndex > maxIndex):
215 raise ValueError("Height index range (%d,%d) is not valid" % (minIndex, maxIndex))
215 raise ValueError("Height index range (%d,%d) is not valid" % (minIndex, maxIndex))
216
216
217 if (maxIndex >= self.dataOut.nHeights):
217 if (maxIndex >= self.dataOut.nHeights):
218 maxIndex = self.dataOut.nHeights
218 maxIndex = self.dataOut.nHeights
219 #print("shapeeee",self.dataOut.data.shape)
219 #print("shapeeee",self.dataOut.data.shape)
220 #voltage
220 #voltage
221 if self.dataOut.flagDataAsBlock:
221 if self.dataOut.flagDataAsBlock:
222 """
222 """
223 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
223 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
224 """
224 """
225 data = self.dataOut.data[:,:, minIndex:maxIndex]
225 data = self.dataOut.data[:,:, minIndex:maxIndex]
226 else:
226 else:
227 data = self.dataOut.data[:, minIndex:maxIndex]
227 data = self.dataOut.data[:, minIndex:maxIndex]
228
228
229 # firstHeight = self.dataOut.heightList[minIndex]
229 # firstHeight = self.dataOut.heightList[minIndex]
230
230
231 self.dataOut.data = data
231 self.dataOut.data = data
232 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
232 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex]
233
233
234 if self.dataOut.nHeights <= 1:
234 if self.dataOut.nHeights <= 1:
235 raise ValueError("selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights))
235 raise ValueError("selectHeights: Too few heights. Current number of heights is %d" %(self.dataOut.nHeights))
236 elif self.dataOut.type == 'Spectra':
236 elif self.dataOut.type == 'Spectra':
237 if (minIndex < 0) or (minIndex > maxIndex):
237 if (minIndex < 0) or (minIndex > maxIndex):
238 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (
238 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (
239 minIndex, maxIndex))
239 minIndex, maxIndex))
240
240
241 if (maxIndex >= self.dataOut.nHeights):
241 if (maxIndex >= self.dataOut.nHeights):
242 maxIndex = self.dataOut.nHeights - 1
242 maxIndex = self.dataOut.nHeights - 1
243
243
244 # Spectra
244 # Spectra
245 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
245 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
246
246
247 data_cspc = None
247 data_cspc = None
248 if self.dataOut.data_cspc is not None:
248 if self.dataOut.data_cspc is not None:
249 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
249 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
250
250
251 data_dc = None
251 data_dc = None
252 if self.dataOut.data_dc is not None:
252 if self.dataOut.data_dc is not None:
253 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
253 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
254
254
255 self.dataOut.data_spc = data_spc
255 self.dataOut.data_spc = data_spc
256 self.dataOut.data_cspc = data_cspc
256 self.dataOut.data_cspc = data_cspc
257 self.dataOut.data_dc = data_dc
257 self.dataOut.data_dc = data_dc
258
258
259 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
259 self.dataOut.heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
260
260
261 return 1
261 return 1
262
262
263
263
264 class filterByHeights(Operation):
264 class filterByHeights(Operation):
265
265
266 def run(self, dataOut, window):
266 def run(self, dataOut, window):
267
267
268 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
268 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
269
269
270 if window == None:
270 if window == None:
271 window = (dataOut.radarControllerHeaderObj.txA/dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
271 window = (dataOut.radarControllerHeaderObj.txA/dataOut.radarControllerHeaderObj.nBaud) / deltaHeight
272
272
273 newdelta = deltaHeight * window
273 newdelta = deltaHeight * window
274 r = dataOut.nHeights % window
274 r = dataOut.nHeights % window
275 newheights = (dataOut.nHeights-r)/window
275 newheights = (dataOut.nHeights-r)/window
276
276
277 if newheights <= 1:
277 if newheights <= 1:
278 raise ValueError("filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(dataOut.nHeights, window))
278 raise ValueError("filterByHeights: Too few heights. Current number of heights is %d and window is %d" %(dataOut.nHeights, window))
279
279
280 if dataOut.flagDataAsBlock:
280 if dataOut.flagDataAsBlock:
281 """
281 """
282 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
282 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
283 """
283 """
284 buffer = dataOut.data[:, :, 0:int(dataOut.nHeights-r)]
284 buffer = dataOut.data[:, :, 0:int(dataOut.nHeights-r)]
285 buffer = buffer.reshape(dataOut.nChannels, dataOut.nProfiles, int(dataOut.nHeights/window), window)
285 buffer = buffer.reshape(dataOut.nChannels, dataOut.nProfiles, int(dataOut.nHeights/window), window)
286 buffer = numpy.sum(buffer,3)
286 buffer = numpy.sum(buffer,3)
287
287
288 else:
288 else:
289 buffer = dataOut.data[:,0:int(dataOut.nHeights-r)]
289 buffer = dataOut.data[:,0:int(dataOut.nHeights-r)]
290 buffer = buffer.reshape(dataOut.nChannels,int(dataOut.nHeights/window),int(window))
290 buffer = buffer.reshape(dataOut.nChannels,int(dataOut.nHeights/window),int(window))
291 buffer = numpy.sum(buffer,2)
291 buffer = numpy.sum(buffer,2)
292
292
293 dataOut.data = buffer
293 dataOut.data = buffer
294 dataOut.heightList = dataOut.heightList[0] + numpy.arange( newheights )*newdelta
294 dataOut.heightList = dataOut.heightList[0] + numpy.arange( newheights )*newdelta
295 dataOut.windowOfFilter = window
295 dataOut.windowOfFilter = window
296
296
297 return dataOut
297 return dataOut
298
298
299
299
300 class setH0(Operation):
300 class setH0(Operation):
301
301
302 def run(self, dataOut, h0, deltaHeight = None):
302 def run(self, dataOut, h0, deltaHeight = None):
303
303
304 if not deltaHeight:
304 if not deltaHeight:
305 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
305 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
306
306
307 nHeights = dataOut.nHeights
307 nHeights = dataOut.nHeights
308
308
309 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
309 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
310
310
311 dataOut.heightList = newHeiRange
311 dataOut.heightList = newHeiRange
312
312
313 return dataOut
313 return dataOut
314
314
315
315
316 class deFlip(Operation):
316 class deFlip(Operation):
317
317
318 def run(self, dataOut, channelList = []):
318 def run(self, dataOut, channelList = []):
319
319
320 data = dataOut.data.copy()
320 data = dataOut.data.copy()
321
321
322 if dataOut.flagDataAsBlock:
322 if dataOut.flagDataAsBlock:
323 flip = self.flip
323 flip = self.flip
324 profileList = list(range(dataOut.nProfiles))
324 profileList = list(range(dataOut.nProfiles))
325
325
326 if not channelList:
326 if not channelList:
327 for thisProfile in profileList:
327 for thisProfile in profileList:
328 data[:,thisProfile,:] = data[:,thisProfile,:]*flip
328 data[:,thisProfile,:] = data[:,thisProfile,:]*flip
329 flip *= -1.0
329 flip *= -1.0
330 else:
330 else:
331 for thisChannel in channelList:
331 for thisChannel in channelList:
332 if thisChannel not in dataOut.channelList:
332 if thisChannel not in dataOut.channelList:
333 continue
333 continue
334
334
335 for thisProfile in profileList:
335 for thisProfile in profileList:
336 data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip
336 data[thisChannel,thisProfile,:] = data[thisChannel,thisProfile,:]*flip
337 flip *= -1.0
337 flip *= -1.0
338
338
339 self.flip = flip
339 self.flip = flip
340
340
341 else:
341 else:
342 if not channelList:
342 if not channelList:
343 data[:,:] = data[:,:]*self.flip
343 data[:,:] = data[:,:]*self.flip
344 else:
344 else:
345 for thisChannel in channelList:
345 for thisChannel in channelList:
346 if thisChannel not in dataOut.channelList:
346 if thisChannel not in dataOut.channelList:
347 continue
347 continue
348
348
349 data[thisChannel,:] = data[thisChannel,:]*self.flip
349 data[thisChannel,:] = data[thisChannel,:]*self.flip
350
350
351 self.flip *= -1.
351 self.flip *= -1.
352
352
353 dataOut.data = data
353 dataOut.data = data
354
354
355 return dataOut
355 return dataOut
356
356
357
357
358 class setAttribute(Operation):
358 class setAttribute(Operation):
359 '''
359 '''
360 Set an arbitrary attribute(s) to dataOut
360 Set an arbitrary attribute(s) to dataOut
361 '''
361 '''
362
362
363 def __init__(self):
363 def __init__(self):
364
364
365 Operation.__init__(self)
365 Operation.__init__(self)
366 self._ready = False
366 self._ready = False
367
367
368 def run(self, dataOut, **kwargs):
368 def run(self, dataOut, **kwargs):
369
369
370 for key, value in kwargs.items():
370 for key, value in kwargs.items():
371 setattr(dataOut, key, value)
371 setattr(dataOut, key, value)
372
372
373 return dataOut
373 return dataOut
374
374
375
375
376 @MPDecorator
376 @MPDecorator
377 class printAttribute(Operation):
377 class printAttribute(Operation):
378 '''
378 '''
379 Print an arbitrary attribute of dataOut
379 Print an arbitrary attribute of dataOut
380 '''
380 '''
381
381
382 def __init__(self):
382 def __init__(self):
383
383
384 Operation.__init__(self)
384 Operation.__init__(self)
385
385
386 def run(self, dataOut, attributes):
386 def run(self, dataOut, attributes):
387
387
388 if isinstance(attributes, str):
388 if isinstance(attributes, str):
389 attributes = [attributes]
389 attributes = [attributes]
390 for attr in attributes:
390 for attr in attributes:
391 if hasattr(dataOut, attr):
391 if hasattr(dataOut, attr):
392 log.log(getattr(dataOut, attr), attr)
392 log.log(getattr(dataOut, attr), attr)
393
393
394
394
395 class interpolateHeights(Operation):
395 class interpolateHeights(Operation):
396
396
397 def run(self, dataOut, topLim, botLim):
397 def run(self, dataOut, topLim, botLim):
398 #69 al 72 para julia
398 #69 al 72 para julia
399 #82-84 para meteoros
399 #82-84 para meteoros
400 if len(numpy.shape(dataOut.data))==2:
400 if len(numpy.shape(dataOut.data))==2:
401 sampInterp = (dataOut.data[:,botLim-1] + dataOut.data[:,topLim+1])/2
401 sampInterp = (dataOut.data[:,botLim-1] + dataOut.data[:,topLim+1])/2
402 sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1)))
402 sampInterp = numpy.transpose(numpy.tile(sampInterp,(topLim-botLim + 1,1)))
403 #dataOut.data[:,botLim:limSup+1] = sampInterp
403 #dataOut.data[:,botLim:limSup+1] = sampInterp
404 dataOut.data[:,botLim:topLim+1] = sampInterp
404 dataOut.data[:,botLim:topLim+1] = sampInterp
405 else:
405 else:
406 nHeights = dataOut.data.shape[2]
406 nHeights = dataOut.data.shape[2]
407 x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights)))
407 x = numpy.hstack((numpy.arange(botLim),numpy.arange(topLim+1,nHeights)))
408 y = dataOut.data[:,:,list(range(botLim))+list(range(topLim+1,nHeights))]
408 y = dataOut.data[:,:,list(range(botLim))+list(range(topLim+1,nHeights))]
409 f = interpolate.interp1d(x, y, axis = 2)
409 f = interpolate.interp1d(x, y, axis = 2)
410 xnew = numpy.arange(botLim,topLim+1)
410 xnew = numpy.arange(botLim,topLim+1)
411 ynew = f(xnew)
411 ynew = f(xnew)
412 dataOut.data[:,:,botLim:topLim+1] = ynew
412 dataOut.data[:,:,botLim:topLim+1] = ynew
413
413
414 return dataOut
414 return dataOut
415
415
416
416
417 class CohInt(Operation):
417 class CohInt(Operation):
418
418
419 isConfig = False
419 isConfig = False
420 __profIndex = 0
420 __profIndex = 0
421 __byTime = False
421 __byTime = False
422 __initime = None
422 __initime = None
423 __lastdatatime = None
423 __lastdatatime = None
424 __integrationtime = None
424 __integrationtime = None
425 __buffer = None
425 __buffer = None
426 __bufferStride = []
426 __bufferStride = []
427 __dataReady = False
427 __dataReady = False
428 __profIndexStride = 0
428 __profIndexStride = 0
429 __dataToPutStride = False
429 __dataToPutStride = False
430 n = None
430 n = None
431
431
432 def __init__(self, **kwargs):
432 def __init__(self, **kwargs):
433
433
434 Operation.__init__(self, **kwargs)
434 Operation.__init__(self, **kwargs)
435
435
436 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
436 def setup(self, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False):
437 """
437 """
438 Set the parameters of the integration class.
438 Set the parameters of the integration class.
439
439
440 Inputs:
440 Inputs:
441
441
442 n : Number of coherent integrations
442 n : Number of coherent integrations
443 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
443 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
444 overlapping :
444 overlapping :
445 """
445 """
446
446
447 self.__initime = None
447 self.__initime = None
448 self.__lastdatatime = 0
448 self.__lastdatatime = 0
449 self.__buffer = None
449 self.__buffer = None
450 self.__dataReady = False
450 self.__dataReady = False
451 self.byblock = byblock
451 self.byblock = byblock
452 self.stride = stride
452 self.stride = stride
453
453
454 if n == None and timeInterval == None:
454 if n == None and timeInterval == None:
455 raise ValueError("n or timeInterval should be specified ...")
455 raise ValueError("n or timeInterval should be specified ...")
456
456
457 if n != None:
457 if n != None:
458 self.n = n
458 self.n = n
459 self.__byTime = False
459 self.__byTime = False
460 else:
460 else:
461 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
461 self.__integrationtime = timeInterval #* 60. #if (type(timeInterval)!=integer) -> change this line
462 self.n = 9999
462 self.n = 9999
463 self.__byTime = True
463 self.__byTime = True
464
464
465 if overlapping:
465 if overlapping:
466 self.__withOverlapping = True
466 self.__withOverlapping = True
467 self.__buffer = None
467 self.__buffer = None
468 else:
468 else:
469 self.__withOverlapping = False
469 self.__withOverlapping = False
470 self.__buffer = 0
470 self.__buffer = 0
471
471
472 self.__profIndex = 0
472 self.__profIndex = 0
473
473
474 def putData(self, data):
474 def putData(self, data):
475
475
476 """
476 """
477 Add a profile to the __buffer and increase in one the __profileIndex
477 Add a profile to the __buffer and increase in one the __profileIndex
478
478
479 """
479 """
480
480
481 if not self.__withOverlapping:
481 if not self.__withOverlapping:
482 self.__buffer += data.copy()
482 self.__buffer += data.copy()
483 self.__profIndex += 1
483 self.__profIndex += 1
484 return
484 return
485
485
486 #Overlapping data
486 #Overlapping data
487 nChannels, nHeis = data.shape
487 nChannels, nHeis = data.shape
488 data = numpy.reshape(data, (1, nChannels, nHeis))
488 data = numpy.reshape(data, (1, nChannels, nHeis))
489
489
490 #If the buffer is empty then it takes the data value
490 #If the buffer is empty then it takes the data value
491 if self.__buffer is None:
491 if self.__buffer is None:
492 self.__buffer = data
492 self.__buffer = data
493 self.__profIndex += 1
493 self.__profIndex += 1
494 return
494 return
495
495
496 #If the buffer length is lower than n then stakcing the data value
496 #If the buffer length is lower than n then stakcing the data value
497 if self.__profIndex < self.n:
497 if self.__profIndex < self.n:
498 self.__buffer = numpy.vstack((self.__buffer, data))
498 self.__buffer = numpy.vstack((self.__buffer, data))
499 self.__profIndex += 1
499 self.__profIndex += 1
500 return
500 return
501
501
502 #If the buffer length is equal to n then replacing the last buffer value with the data value
502 #If the buffer length is equal to n then replacing the last buffer value with the data value
503 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
503 self.__buffer = numpy.roll(self.__buffer, -1, axis=0)
504 self.__buffer[self.n-1] = data
504 self.__buffer[self.n-1] = data
505 self.__profIndex = self.n
505 self.__profIndex = self.n
506 return
506 return
507
507
508
508
509 def pushData(self):
509 def pushData(self):
510 """
510 """
511 Return the sum of the last profiles and the profiles used in the sum.
511 Return the sum of the last profiles and the profiles used in the sum.
512
512
513 Affected:
513 Affected:
514
514
515 self.__profileIndex
515 self.__profileIndex
516
516
517 """
517 """
518
518
519 if not self.__withOverlapping:
519 if not self.__withOverlapping:
520 data = self.__buffer
520 data = self.__buffer
521 n = self.__profIndex
521 n = self.__profIndex
522
522
523 self.__buffer = 0
523 self.__buffer = 0
524 self.__profIndex = 0
524 self.__profIndex = 0
525
525
526 return data, n
526 return data, n
527
527
528 #Integration with Overlapping
528 #Integration with Overlapping
529 data = numpy.sum(self.__buffer, axis=0)
529 data = numpy.sum(self.__buffer, axis=0)
530 # print data
530 # print data
531 # raise
531 # raise
532 n = self.__profIndex
532 n = self.__profIndex
533
533
534 return data, n
534 return data, n
535
535
536 def byProfiles(self, data):
536 def byProfiles(self, data):
537
537
538 self.__dataReady = False
538 self.__dataReady = False
539 avgdata = None
539 avgdata = None
540 # n = None
540 # n = None
541 # print data
541 # print data
542 # raise
542 # raise
543 self.putData(data)
543 self.putData(data)
544
544
545 if self.__profIndex == self.n:
545 if self.__profIndex == self.n:
546 avgdata, n = self.pushData()
546 avgdata, n = self.pushData()
547 self.__dataReady = True
547 self.__dataReady = True
548
548
549 return avgdata
549 return avgdata
550
550
551 def byTime(self, data, datatime):
551 def byTime(self, data, datatime):
552
552
553 self.__dataReady = False
553 self.__dataReady = False
554 avgdata = None
554 avgdata = None
555 n = None
555 n = None
556
556
557 self.putData(data)
557 self.putData(data)
558
558
559 if (datatime - self.__initime) >= self.__integrationtime:
559 if (datatime - self.__initime) >= self.__integrationtime:
560 avgdata, n = self.pushData()
560 avgdata, n = self.pushData()
561 self.n = n
561 self.n = n
562 self.__dataReady = True
562 self.__dataReady = True
563
563
564 return avgdata
564 return avgdata
565
565
566 def integrateByStride(self, data, datatime):
566 def integrateByStride(self, data, datatime):
567 # print data
567 # print data
568 if self.__profIndex == 0:
568 if self.__profIndex == 0:
569 self.__buffer = [[data.copy(), datatime]]
569 self.__buffer = [[data.copy(), datatime]]
570 else:
570 else:
571 self.__buffer.append([data.copy(),datatime])
571 self.__buffer.append([data.copy(),datatime])
572 self.__profIndex += 1
572 self.__profIndex += 1
573 self.__dataReady = False
573 self.__dataReady = False
574
574
575 if self.__profIndex == self.n * self.stride :
575 if self.__profIndex == self.n * self.stride :
576 self.__dataToPutStride = True
576 self.__dataToPutStride = True
577 self.__profIndexStride = 0
577 self.__profIndexStride = 0
578 self.__profIndex = 0
578 self.__profIndex = 0
579 self.__bufferStride = []
579 self.__bufferStride = []
580 for i in range(self.stride):
580 for i in range(self.stride):
581 current = self.__buffer[i::self.stride]
581 current = self.__buffer[i::self.stride]
582 data = numpy.sum([t[0] for t in current], axis=0)
582 data = numpy.sum([t[0] for t in current], axis=0)
583 avgdatatime = numpy.average([t[1] for t in current])
583 avgdatatime = numpy.average([t[1] for t in current])
584 # print data
584 # print data
585 self.__bufferStride.append((data, avgdatatime))
585 self.__bufferStride.append((data, avgdatatime))
586
586
587 if self.__dataToPutStride:
587 if self.__dataToPutStride:
588 self.__dataReady = True
588 self.__dataReady = True
589 self.__profIndexStride += 1
589 self.__profIndexStride += 1
590 if self.__profIndexStride == self.stride:
590 if self.__profIndexStride == self.stride:
591 self.__dataToPutStride = False
591 self.__dataToPutStride = False
592 # print self.__bufferStride[self.__profIndexStride - 1]
592 # print self.__bufferStride[self.__profIndexStride - 1]
593 # raise
593 # raise
594 return self.__bufferStride[self.__profIndexStride - 1]
594 return self.__bufferStride[self.__profIndexStride - 1]
595
595
596
596
597 return None, None
597 return None, None
598
598
599 def integrate(self, data, datatime=None):
599 def integrate(self, data, datatime=None):
600
600
601 if self.__initime == None:
601 if self.__initime == None:
602 self.__initime = datatime
602 self.__initime = datatime
603
603
604 if self.__byTime:
604 if self.__byTime:
605 avgdata = self.byTime(data, datatime)
605 avgdata = self.byTime(data, datatime)
606 else:
606 else:
607 avgdata = self.byProfiles(data)
607 avgdata = self.byProfiles(data)
608
608
609
609
610 self.__lastdatatime = datatime
610 self.__lastdatatime = datatime
611
611
612 if avgdata is None:
612 if avgdata is None:
613 return None, None
613 return None, None
614
614
615 avgdatatime = self.__initime
615 avgdatatime = self.__initime
616
616
617 deltatime = datatime - self.__lastdatatime
617 deltatime = datatime - self.__lastdatatime
618
618
619 if not self.__withOverlapping:
619 if not self.__withOverlapping:
620 self.__initime = datatime
620 self.__initime = datatime
621 else:
621 else:
622 self.__initime += deltatime
622 self.__initime += deltatime
623
623
624 return avgdata, avgdatatime
624 return avgdata, avgdatatime
625
625
626 def integrateByBlock(self, dataOut):
626 def integrateByBlock(self, dataOut):
627
627
628 times = int(dataOut.data.shape[1]/self.n)
628 times = int(dataOut.data.shape[1]/self.n)
629 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
629 avgdata = numpy.zeros((dataOut.nChannels, times, dataOut.nHeights), dtype=numpy.complex)
630
630
631 id_min = 0
631 id_min = 0
632 id_max = self.n
632 id_max = self.n
633
633
634 for i in range(times):
634 for i in range(times):
635 junk = dataOut.data[:,id_min:id_max,:]
635 junk = dataOut.data[:,id_min:id_max,:]
636 avgdata[:,i,:] = junk.sum(axis=1)
636 avgdata[:,i,:] = junk.sum(axis=1)
637 id_min += self.n
637 id_min += self.n
638 id_max += self.n
638 id_max += self.n
639
639
640 timeInterval = dataOut.ippSeconds*self.n
640 timeInterval = dataOut.ippSeconds*self.n
641 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
641 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
642 self.__dataReady = True
642 self.__dataReady = True
643 return avgdata, avgdatatime
643 return avgdata, avgdatatime
644
644
645 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
645 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
646
646
647 if not self.isConfig:
647 if not self.isConfig:
648 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
648 self.setup(n=n, stride=stride, timeInterval=timeInterval, overlapping=overlapping, byblock=byblock, **kwargs)
649 self.isConfig = True
649 self.isConfig = True
650
650
651 if dataOut.flagDataAsBlock:
651 if dataOut.flagDataAsBlock:
652 """
652 """
653 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
653 Si la data es leida por bloques, dimension = [nChannels, nProfiles, nHeis]
654 """
654 """
655 avgdata, avgdatatime = self.integrateByBlock(dataOut)
655 avgdata, avgdatatime = self.integrateByBlock(dataOut)
656 dataOut.nProfiles /= self.n
656 dataOut.nProfiles /= self.n
657 else:
657 else:
658 if stride is None:
658 if stride is None:
659 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
659 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
660 else:
660 else:
661 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
661 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
662
662
663
663
664 # dataOut.timeInterval *= n
664 # dataOut.timeInterval *= n
665 dataOut.flagNoData = True
665 dataOut.flagNoData = True
666
666
667 if self.__dataReady:
667 if self.__dataReady:
668 dataOut.data = avgdata
668 dataOut.data = avgdata
669 if not dataOut.flagCohInt:
669 if not dataOut.flagCohInt:
670 dataOut.nCohInt *= self.n
670 dataOut.nCohInt *= self.n
671 dataOut.flagCohInt = True
671 dataOut.flagCohInt = True
672 dataOut.utctime = avgdatatime
672 ####################################dataOut.utctime = avgdatatime
673 # print avgdata, avgdatatime
673 # print avgdata, avgdatatime
674 # raise
674 # raise
675 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
675 # dataOut.timeInterval = dataOut.ippSeconds * dataOut.nCohInt
676 dataOut.flagNoData = False
676 dataOut.flagNoData = False
677 return dataOut
677 return dataOut
678
678
679 class Decoder(Operation):
679 class Decoder(Operation):
680
680
681 isConfig = False
681 isConfig = False
682 __profIndex = 0
682 __profIndex = 0
683
683
684 code = None
684 code = None
685
685
686 nCode = None
686 nCode = None
687 nBaud = None
687 nBaud = None
688
688
689 def __init__(self, **kwargs):
689 def __init__(self, **kwargs):
690
690
691 Operation.__init__(self, **kwargs)
691 Operation.__init__(self, **kwargs)
692
692
693 self.times = None
693 self.times = None
694 self.osamp = None
694 self.osamp = None
695 # self.__setValues = False
695 # self.__setValues = False
696 self.isConfig = False
696 self.isConfig = False
697 self.setupReq = False
697 self.setupReq = False
698 def setup(self, code, osamp, dataOut):
698 def setup(self, code, osamp, dataOut):
699
699
700 self.__profIndex = 0
700 self.__profIndex = 0
701
701
702 self.code = code
702 self.code = code
703
703
704 self.nCode = len(code)
704 self.nCode = len(code)
705 self.nBaud = len(code[0])
705 self.nBaud = len(code[0])
706
706
707 if (osamp != None) and (osamp >1):
707 if (osamp != None) and (osamp >1):
708 self.osamp = osamp
708 self.osamp = osamp
709 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
709 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
710 self.nBaud = self.nBaud*self.osamp
710 self.nBaud = self.nBaud*self.osamp
711
711
712 self.__nChannels = dataOut.nChannels
712 self.__nChannels = dataOut.nChannels
713 self.__nProfiles = dataOut.nProfiles
713 self.__nProfiles = dataOut.nProfiles
714 self.__nHeis = dataOut.nHeights
714 self.__nHeis = dataOut.nHeights
715
715
716 if self.__nHeis < self.nBaud:
716 if self.__nHeis < self.nBaud:
717 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
717 raise ValueError('Number of heights (%d) should be greater than number of bauds (%d)' %(self.__nHeis, self.nBaud))
718
718
719 #Frequency
719 #Frequency
720 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
720 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
721
721
722 __codeBuffer[:,0:self.nBaud] = self.code
722 __codeBuffer[:,0:self.nBaud] = self.code
723
723
724 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
724 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
725
725
726 if dataOut.flagDataAsBlock:
726 if dataOut.flagDataAsBlock:
727
727
728 self.ndatadec = self.__nHeis #- self.nBaud + 1
728 self.ndatadec = self.__nHeis #- self.nBaud + 1
729
729
730 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
730 self.datadecTime = numpy.zeros((self.__nChannels, self.__nProfiles, self.ndatadec), dtype=numpy.complex)
731
731
732 else:
732 else:
733
733
734 #Time
734 #Time
735 self.ndatadec = self.__nHeis #- self.nBaud + 1
735 self.ndatadec = self.__nHeis #- self.nBaud + 1
736
736
737 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
737 self.datadecTime = numpy.zeros((self.__nChannels, self.ndatadec), dtype=numpy.complex)
738
738
739 def __convolutionInFreq(self, data):
739 def __convolutionInFreq(self, data):
740
740
741 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
741 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
742
742
743 fft_data = numpy.fft.fft(data, axis=1)
743 fft_data = numpy.fft.fft(data, axis=1)
744
744
745 conv = fft_data*fft_code
745 conv = fft_data*fft_code
746
746
747 data = numpy.fft.ifft(conv,axis=1)
747 data = numpy.fft.ifft(conv,axis=1)
748
748
749 return data
749 return data
750
750
751 def __convolutionInFreqOpt(self, data):
751 def __convolutionInFreqOpt(self, data):
752
752
753 raise NotImplementedError
753 raise NotImplementedError
754
754
755 def __convolutionInTime(self, data):
755 def __convolutionInTime(self, data):
756
756
757 code = self.code[self.__profIndex]
757 code = self.code[self.__profIndex]
758 for i in range(self.__nChannels):
758 for i in range(self.__nChannels):
759 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
759 self.datadecTime[i,:] = numpy.correlate(data[i,:], code, mode='full')[self.nBaud-1:]
760
760
761 return self.datadecTime
761 return self.datadecTime
762
762
763 def __convolutionByBlockInTime(self, data):
763 def __convolutionByBlockInTime(self, data):
764
764
765 repetitions = int(self.__nProfiles / self.nCode)
765 repetitions = int(self.__nProfiles / self.nCode)
766 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
766 junk = numpy.lib.stride_tricks.as_strided(self.code, (repetitions, self.code.size), (0, self.code.itemsize))
767 junk = junk.flatten()
767 junk = junk.flatten()
768 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
768 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
769 profilesList = range(self.__nProfiles)
769 profilesList = range(self.__nProfiles)
770
770
771 for i in range(self.__nChannels):
771 for i in range(self.__nChannels):
772 for j in profilesList:
772 for j in profilesList:
773 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
773 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
774 return self.datadecTime
774 return self.datadecTime
775
775
776 def __convolutionByBlockInFreq(self, data):
776 def __convolutionByBlockInFreq(self, data):
777
777
778 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
778 raise NotImplementedError("Decoder by frequency fro Blocks not implemented")
779
779
780
780
781 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
781 fft_code = self.fft_code[self.__profIndex].reshape(1,-1)
782
782
783 fft_data = numpy.fft.fft(data, axis=2)
783 fft_data = numpy.fft.fft(data, axis=2)
784
784
785 conv = fft_data*fft_code
785 conv = fft_data*fft_code
786
786
787 data = numpy.fft.ifft(conv,axis=2)
787 data = numpy.fft.ifft(conv,axis=2)
788
788
789 return data
789 return data
790
790
791
791
792 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
792 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
793
793
794 if dataOut.flagDecodeData:
794 if dataOut.flagDecodeData:
795 print("This data is already decoded, recoding again ...")
795 print("This data is already decoded, recoding again ...")
796
796
797 if not self.isConfig:
797 if not self.isConfig:
798
798
799 if code is None:
799 if code is None:
800 if dataOut.code is None:
800 if dataOut.code is None:
801 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
801 raise ValueError("Code could not be read from %s instance. Enter a value in Code parameter" %dataOut.type)
802
802
803 code = dataOut.code
803 code = dataOut.code
804 else:
804 else:
805 code = numpy.array(code).reshape(nCode,nBaud)
805 code = numpy.array(code).reshape(nCode,nBaud)
806 self.setup(code, osamp, dataOut)
806 self.setup(code, osamp, dataOut)
807
807
808 self.isConfig = True
808 self.isConfig = True
809
809
810 if mode == 3:
810 if mode == 3:
811 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
811 sys.stderr.write("Decoder Warning: mode=%d is not valid, using mode=0\n" %mode)
812
812
813 if times != None:
813 if times != None:
814 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
814 sys.stderr.write("Decoder Warning: Argument 'times' in not used anymore\n")
815
815
816 if self.code is None:
816 if self.code is None:
817 print("Fail decoding: Code is not defined.")
817 print("Fail decoding: Code is not defined.")
818 return
818 return
819
819
820 self.__nProfiles = dataOut.nProfiles
820 self.__nProfiles = dataOut.nProfiles
821 datadec = None
821 datadec = None
822
822
823 if mode == 3:
823 if mode == 3:
824 mode = 0
824 mode = 0
825
825
826 if dataOut.flagDataAsBlock:
826 if dataOut.flagDataAsBlock:
827 """
827 """
828 Decoding when data have been read as block,
828 Decoding when data have been read as block,
829 """
829 """
830
830
831 if mode == 0:
831 if mode == 0:
832 datadec = self.__convolutionByBlockInTime(dataOut.data)
832 datadec = self.__convolutionByBlockInTime(dataOut.data)
833 if mode == 1:
833 if mode == 1:
834 datadec = self.__convolutionByBlockInFreq(dataOut.data)
834 datadec = self.__convolutionByBlockInFreq(dataOut.data)
835 else:
835 else:
836 """
836 """
837 Decoding when data have been read profile by profile
837 Decoding when data have been read profile by profile
838 """
838 """
839 if mode == 0:
839 if mode == 0:
840 datadec = self.__convolutionInTime(dataOut.data)
840 datadec = self.__convolutionInTime(dataOut.data)
841
841
842 if mode == 1:
842 if mode == 1:
843 datadec = self.__convolutionInFreq(dataOut.data)
843 datadec = self.__convolutionInFreq(dataOut.data)
844
844
845 if mode == 2:
845 if mode == 2:
846 datadec = self.__convolutionInFreqOpt(dataOut.data)
846 datadec = self.__convolutionInFreqOpt(dataOut.data)
847
847
848 if datadec is None:
848 if datadec is None:
849 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
849 raise ValueError("Codification mode selected is not valid: mode=%d. Try selecting 0 or 1" %mode)
850
850
851 dataOut.code = self.code
851 dataOut.code = self.code
852 dataOut.nCode = self.nCode
852 dataOut.nCode = self.nCode
853 dataOut.nBaud = self.nBaud
853 dataOut.nBaud = self.nBaud
854
854
855 dataOut.data = datadec
855 dataOut.data = datadec
856
856
857 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
857 dataOut.heightList = dataOut.heightList[0:datadec.shape[-1]]
858
858
859 dataOut.flagDecodeData = True #asumo q la data esta decodificada
859 dataOut.flagDecodeData = True #asumo q la data esta decodificada
860
860
861 if self.__profIndex == self.nCode-1:
861 if self.__profIndex == self.nCode-1:
862 self.__profIndex = 0
862 self.__profIndex = 0
863 return dataOut
863 return dataOut
864
864
865 self.__profIndex += 1
865 self.__profIndex += 1
866
866
867 return dataOut
867 return dataOut
868 # dataOut.flagDeflipData = True #asumo q la data no esta sin flip
868 # dataOut.flagDeflipData = True #asumo q la data no esta sin flip
869
869
870
870
871 class ProfileConcat(Operation):
871 class ProfileConcat(Operation):
872
872
873 isConfig = False
873 isConfig = False
874 buffer = None
874 buffer = None
875
875
876 def __init__(self, **kwargs):
876 def __init__(self, **kwargs):
877
877
878 Operation.__init__(self, **kwargs)
878 Operation.__init__(self, **kwargs)
879 self.profileIndex = 0
879 self.profileIndex = 0
880
880
881 def reset(self):
881 def reset(self):
882 self.buffer = numpy.zeros_like(self.buffer)
882 self.buffer = numpy.zeros_like(self.buffer)
883 self.start_index = 0
883 self.start_index = 0
884 self.times = 1
884 self.times = 1
885
885
886 def setup(self, data, m, n=1):
886 def setup(self, data, m, n=1):
887 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
887 self.buffer = numpy.zeros((data.shape[0],data.shape[1]*m),dtype=type(data[0,0]))
888 self.nHeights = data.shape[1]#.nHeights
888 self.nHeights = data.shape[1]#.nHeights
889 self.start_index = 0
889 self.start_index = 0
890 self.times = 1
890 self.times = 1
891
891
892 def concat(self, data):
892 def concat(self, data):
893
893
894 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
894 self.buffer[:,self.start_index:self.nHeights*self.times] = data.copy()
895 self.start_index = self.start_index + self.nHeights
895 self.start_index = self.start_index + self.nHeights
896
896
897 def run(self, dataOut, m):
897 def run(self, dataOut, m):
898 dataOut.flagNoData = True
898 dataOut.flagNoData = True
899
899
900 if not self.isConfig:
900 if not self.isConfig:
901 self.setup(dataOut.data, m, 1)
901 self.setup(dataOut.data, m, 1)
902 self.isConfig = True
902 self.isConfig = True
903
903
904 if dataOut.flagDataAsBlock:
904 if dataOut.flagDataAsBlock:
905 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
905 raise ValueError("ProfileConcat can only be used when voltage have been read profile by profile, getBlock = False")
906
906
907 else:
907 else:
908 self.concat(dataOut.data)
908 self.concat(dataOut.data)
909 self.times += 1
909 self.times += 1
910 if self.times > m:
910 if self.times > m:
911 dataOut.data = self.buffer
911 dataOut.data = self.buffer
912 self.reset()
912 self.reset()
913 dataOut.flagNoData = False
913 dataOut.flagNoData = False
914 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
914 # se deben actualizar mas propiedades del header y del objeto dataOut, por ejemplo, las alturas
915 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
915 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
916 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
916 xf = dataOut.heightList[0] + dataOut.nHeights * deltaHeight * m
917 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
917 dataOut.heightList = numpy.arange(dataOut.heightList[0], xf, deltaHeight)
918 dataOut.ippSeconds *= m
918 dataOut.ippSeconds *= m
919 return dataOut
919 return dataOut
920
920
921 class ProfileSelector(Operation):
921 class ProfileSelector(Operation):
922
922
923 profileIndex = None
923 profileIndex = None
924 # Tamanho total de los perfiles
924 # Tamanho total de los perfiles
925 nProfiles = None
925 nProfiles = None
926
926
927 def __init__(self, **kwargs):
927 def __init__(self, **kwargs):
928
928
929 Operation.__init__(self, **kwargs)
929 Operation.__init__(self, **kwargs)
930 self.profileIndex = 0
930 self.profileIndex = 0
931
931
932 def incProfileIndex(self):
932 def incProfileIndex(self):
933
933
934 self.profileIndex += 1
934 self.profileIndex += 1
935
935
936 if self.profileIndex >= self.nProfiles:
936 if self.profileIndex >= self.nProfiles:
937 self.profileIndex = 0
937 self.profileIndex = 0
938
938
939 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
939 def isThisProfileInRange(self, profileIndex, minIndex, maxIndex):
940
940
941 if profileIndex < minIndex:
941 if profileIndex < minIndex:
942 return False
942 return False
943
943
944 if profileIndex > maxIndex:
944 if profileIndex > maxIndex:
945 return False
945 return False
946
946
947 return True
947 return True
948
948
949 def isThisProfileInList(self, profileIndex, profileList):
949 def isThisProfileInList(self, profileIndex, profileList):
950
950
951 if profileIndex not in profileList:
951 if profileIndex not in profileList:
952 return False
952 return False
953
953
954 return True
954 return True
955
955
956 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
956 def run(self, dataOut, profileList=None, profileRangeList=None, beam=None, byblock=False, rangeList = None, nProfiles=None):
957 #print("before",dataOut.data.shape)
957 #print("before",dataOut.data.shape)
958 """
958 """
959 ProfileSelector:
959 ProfileSelector:
960
960
961 Inputs:
961 Inputs:
962 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
962 profileList : Index of profiles selected. Example: profileList = (0,1,2,7,8)
963
963
964 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
964 profileRangeList : Minimum and maximum profile indexes. Example: profileRangeList = (4, 30)
965
965
966 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
966 rangeList : List of profile ranges. Example: rangeList = ((4, 30), (32, 64), (128, 256))
967
967
968 """
968 """
969
969
970 if rangeList is not None:
970 if rangeList is not None:
971 if type(rangeList[0]) not in (tuple, list):
971 if type(rangeList[0]) not in (tuple, list):
972 rangeList = [rangeList]
972 rangeList = [rangeList]
973
973
974 dataOut.flagNoData = True
974 dataOut.flagNoData = True
975
975
976 if dataOut.flagDataAsBlock:
976 if dataOut.flagDataAsBlock:
977 """
977 """
978 data dimension = [nChannels, nProfiles, nHeis]
978 data dimension = [nChannels, nProfiles, nHeis]
979 """
979 """
980 if profileList != None:
980 if profileList != None:
981 dataOut.data = dataOut.data[:,profileList,:]
981 dataOut.data = dataOut.data[:,profileList,:]
982
982
983 if profileRangeList != None:
983 if profileRangeList != None:
984 minIndex = profileRangeList[0]
984 minIndex = profileRangeList[0]
985 maxIndex = profileRangeList[1]
985 maxIndex = profileRangeList[1]
986 profileList = list(range(minIndex, maxIndex+1))
986 profileList = list(range(minIndex, maxIndex+1))
987
987
988 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
988 dataOut.data = dataOut.data[:,minIndex:maxIndex+1,:]
989
989
990 if rangeList != None:
990 if rangeList != None:
991
991
992 profileList = []
992 profileList = []
993
993
994 for thisRange in rangeList:
994 for thisRange in rangeList:
995 minIndex = thisRange[0]
995 minIndex = thisRange[0]
996 maxIndex = thisRange[1]
996 maxIndex = thisRange[1]
997
997
998 profileList.extend(list(range(minIndex, maxIndex+1)))
998 profileList.extend(list(range(minIndex, maxIndex+1)))
999
999
1000 dataOut.data = dataOut.data[:,profileList,:]
1000 dataOut.data = dataOut.data[:,profileList,:]
1001
1001
1002 dataOut.nProfiles = len(profileList)
1002 dataOut.nProfiles = len(profileList)
1003 dataOut.profileIndex = dataOut.nProfiles - 1
1003 dataOut.profileIndex = dataOut.nProfiles - 1
1004 dataOut.flagNoData = False
1004 dataOut.flagNoData = False
1005 #print(dataOut.data.shape)
1005 #print(dataOut.data.shape)
1006 return dataOut
1006 return dataOut
1007
1007
1008 """
1008 """
1009 data dimension = [nChannels, nHeis]
1009 data dimension = [nChannels, nHeis]
1010 """
1010 """
1011
1011
1012 if profileList != None:
1012 if profileList != None:
1013
1013
1014 if self.isThisProfileInList(dataOut.profileIndex, profileList):
1014 if self.isThisProfileInList(dataOut.profileIndex, profileList):
1015
1015
1016 self.nProfiles = len(profileList)
1016 self.nProfiles = len(profileList)
1017 dataOut.nProfiles = self.nProfiles
1017 dataOut.nProfiles = self.nProfiles
1018 dataOut.profileIndex = self.profileIndex
1018 dataOut.profileIndex = self.profileIndex
1019 dataOut.flagNoData = False
1019 dataOut.flagNoData = False
1020
1020
1021 self.incProfileIndex()
1021 self.incProfileIndex()
1022 return dataOut
1022 return dataOut
1023
1023
1024 if profileRangeList != None:
1024 if profileRangeList != None:
1025
1025
1026 minIndex = profileRangeList[0]
1026 minIndex = profileRangeList[0]
1027 maxIndex = profileRangeList[1]
1027 maxIndex = profileRangeList[1]
1028
1028
1029 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1029 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1030
1030
1031 self.nProfiles = maxIndex - minIndex + 1
1031 self.nProfiles = maxIndex - minIndex + 1
1032 dataOut.nProfiles = self.nProfiles
1032 dataOut.nProfiles = self.nProfiles
1033 dataOut.profileIndex = self.profileIndex
1033 dataOut.profileIndex = self.profileIndex
1034 dataOut.flagNoData = False
1034 dataOut.flagNoData = False
1035
1035
1036 self.incProfileIndex()
1036 self.incProfileIndex()
1037 return dataOut
1037 return dataOut
1038
1038
1039 if rangeList != None:
1039 if rangeList != None:
1040
1040
1041 nProfiles = 0
1041 nProfiles = 0
1042
1042
1043 for thisRange in rangeList:
1043 for thisRange in rangeList:
1044 minIndex = thisRange[0]
1044 minIndex = thisRange[0]
1045 maxIndex = thisRange[1]
1045 maxIndex = thisRange[1]
1046
1046
1047 nProfiles += maxIndex - minIndex + 1
1047 nProfiles += maxIndex - minIndex + 1
1048
1048
1049 for thisRange in rangeList:
1049 for thisRange in rangeList:
1050
1050
1051 minIndex = thisRange[0]
1051 minIndex = thisRange[0]
1052 maxIndex = thisRange[1]
1052 maxIndex = thisRange[1]
1053
1053
1054 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1054 if self.isThisProfileInRange(dataOut.profileIndex, minIndex, maxIndex):
1055
1055
1056 self.nProfiles = nProfiles
1056 self.nProfiles = nProfiles
1057 dataOut.nProfiles = self.nProfiles
1057 dataOut.nProfiles = self.nProfiles
1058 dataOut.profileIndex = self.profileIndex
1058 dataOut.profileIndex = self.profileIndex
1059 dataOut.flagNoData = False
1059 dataOut.flagNoData = False
1060
1060
1061 self.incProfileIndex()
1061 self.incProfileIndex()
1062
1062
1063 break
1063 break
1064
1064
1065 return dataOut
1065 return dataOut
1066
1066
1067
1067
1068 if beam != None: #beam is only for AMISR data
1068 if beam != None: #beam is only for AMISR data
1069 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
1069 if self.isThisProfileInList(dataOut.profileIndex, dataOut.beamRangeDict[beam]):
1070 dataOut.flagNoData = False
1070 dataOut.flagNoData = False
1071 dataOut.profileIndex = self.profileIndex
1071 dataOut.profileIndex = self.profileIndex
1072
1072
1073 self.incProfileIndex()
1073 self.incProfileIndex()
1074
1074
1075 return dataOut
1075 return dataOut
1076
1076
1077 raise ValueError("ProfileSelector needs profileList, profileRangeList or rangeList parameter")
1077 raise ValueError("ProfileSelector needs profileList, profileRangeList or rangeList parameter")
1078
1078
1079
1079
1080 class Reshaper(Operation):
1080 class Reshaper(Operation):
1081
1081
1082 def __init__(self, **kwargs):
1082 def __init__(self, **kwargs):
1083
1083
1084 Operation.__init__(self, **kwargs)
1084 Operation.__init__(self, **kwargs)
1085
1085
1086 self.__buffer = None
1086 self.__buffer = None
1087 self.__nitems = 0
1087 self.__nitems = 0
1088
1088
1089 def __appendProfile(self, dataOut, nTxs):
1089 def __appendProfile(self, dataOut, nTxs):
1090
1090
1091 if self.__buffer is None:
1091 if self.__buffer is None:
1092 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
1092 shape = (dataOut.nChannels, int(dataOut.nHeights/nTxs) )
1093 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
1093 self.__buffer = numpy.empty(shape, dtype = dataOut.data.dtype)
1094
1094
1095 ini = dataOut.nHeights * self.__nitems
1095 ini = dataOut.nHeights * self.__nitems
1096 end = ini + dataOut.nHeights
1096 end = ini + dataOut.nHeights
1097
1097
1098 self.__buffer[:, ini:end] = dataOut.data
1098 self.__buffer[:, ini:end] = dataOut.data
1099
1099
1100 self.__nitems += 1
1100 self.__nitems += 1
1101
1101
1102 return int(self.__nitems*nTxs)
1102 return int(self.__nitems*nTxs)
1103
1103
1104 def __getBuffer(self):
1104 def __getBuffer(self):
1105
1105
1106 if self.__nitems == int(1./self.__nTxs):
1106 if self.__nitems == int(1./self.__nTxs):
1107
1107
1108 self.__nitems = 0
1108 self.__nitems = 0
1109
1109
1110 return self.__buffer.copy()
1110 return self.__buffer.copy()
1111
1111
1112 return None
1112 return None
1113
1113
1114 def __checkInputs(self, dataOut, shape, nTxs):
1114 def __checkInputs(self, dataOut, shape, nTxs):
1115
1115
1116 if shape is None and nTxs is None:
1116 if shape is None and nTxs is None:
1117 raise ValueError("Reshaper: shape of factor should be defined")
1117 raise ValueError("Reshaper: shape of factor should be defined")
1118
1118
1119 if nTxs:
1119 if nTxs:
1120 if nTxs < 0:
1120 if nTxs < 0:
1121 raise ValueError("nTxs should be greater than 0")
1121 raise ValueError("nTxs should be greater than 0")
1122
1122
1123 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
1123 if nTxs < 1 and dataOut.nProfiles % (1./nTxs) != 0:
1124 raise ValueError("nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)))
1124 raise ValueError("nProfiles= %d is not divisibled by (1./nTxs) = %f" %(dataOut.nProfiles, (1./nTxs)))
1125
1125
1126 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
1126 shape = [dataOut.nChannels, dataOut.nProfiles*nTxs, dataOut.nHeights/nTxs]
1127
1127
1128 return shape, nTxs
1128 return shape, nTxs
1129
1129
1130 if len(shape) != 2 and len(shape) != 3:
1130 if len(shape) != 2 and len(shape) != 3:
1131 raise ValueError("shape dimension should be equal to 2 or 3. shape = (nProfiles, nHeis) or (nChannels, nProfiles, nHeis). Actually shape = (%d, %d, %d)" %(dataOut.nChannels, dataOut.nProfiles, dataOut.nHeights))
1131 raise ValueError("shape dimension should be equal to 2 or 3. shape = (nProfiles, nHeis) or (nChannels, nProfiles, nHeis). Actually shape = (%d, %d, %d)" %(dataOut.nChannels, dataOut.nProfiles, dataOut.nHeights))
1132
1132
1133 if len(shape) == 2:
1133 if len(shape) == 2:
1134 shape_tuple = [dataOut.nChannels]
1134 shape_tuple = [dataOut.nChannels]
1135 shape_tuple.extend(shape)
1135 shape_tuple.extend(shape)
1136 else:
1136 else:
1137 shape_tuple = list(shape)
1137 shape_tuple = list(shape)
1138
1138
1139 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
1139 nTxs = 1.0*shape_tuple[1]/dataOut.nProfiles
1140
1140
1141 return shape_tuple, nTxs
1141 return shape_tuple, nTxs
1142
1142
1143 def run(self, dataOut, shape=None, nTxs=None):
1143 def run(self, dataOut, shape=None, nTxs=None):
1144
1144
1145 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
1145 shape_tuple, self.__nTxs = self.__checkInputs(dataOut, shape, nTxs)
1146
1146
1147 dataOut.flagNoData = True
1147 dataOut.flagNoData = True
1148 profileIndex = None
1148 profileIndex = None
1149
1149
1150 if dataOut.flagDataAsBlock:
1150 if dataOut.flagDataAsBlock:
1151
1151
1152 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
1152 dataOut.data = numpy.reshape(dataOut.data, shape_tuple)
1153 dataOut.flagNoData = False
1153 dataOut.flagNoData = False
1154
1154
1155 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
1155 profileIndex = int(dataOut.nProfiles*self.__nTxs) - 1
1156
1156
1157 else:
1157 else:
1158
1158
1159 if self.__nTxs < 1:
1159 if self.__nTxs < 1:
1160
1160
1161 self.__appendProfile(dataOut, self.__nTxs)
1161 self.__appendProfile(dataOut, self.__nTxs)
1162 new_data = self.__getBuffer()
1162 new_data = self.__getBuffer()
1163
1163
1164 if new_data is not None:
1164 if new_data is not None:
1165 dataOut.data = new_data
1165 dataOut.data = new_data
1166 dataOut.flagNoData = False
1166 dataOut.flagNoData = False
1167
1167
1168 profileIndex = dataOut.profileIndex*nTxs
1168 profileIndex = dataOut.profileIndex*nTxs
1169
1169
1170 else:
1170 else:
1171 raise ValueError("nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)")
1171 raise ValueError("nTxs should be greater than 0 and lower than 1, or use VoltageReader(..., getblock=True)")
1172
1172
1173 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1173 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1174
1174
1175 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
1175 dataOut.heightList = numpy.arange(dataOut.nHeights/self.__nTxs) * deltaHeight + dataOut.heightList[0]
1176
1176
1177 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
1177 dataOut.nProfiles = int(dataOut.nProfiles*self.__nTxs)
1178
1178
1179 dataOut.profileIndex = profileIndex
1179 dataOut.profileIndex = profileIndex
1180
1180
1181 dataOut.ippSeconds /= self.__nTxs
1181 dataOut.ippSeconds /= self.__nTxs
1182
1182
1183 return dataOut
1183 return dataOut
1184
1184
1185 class SplitProfiles(Operation):
1185 class SplitProfiles(Operation):
1186
1186
1187 def __init__(self, **kwargs):
1187 def __init__(self, **kwargs):
1188
1188
1189 Operation.__init__(self, **kwargs)
1189 Operation.__init__(self, **kwargs)
1190
1190
1191 def run(self, dataOut, n):
1191 def run(self, dataOut, n):
1192
1192
1193 dataOut.flagNoData = True
1193 dataOut.flagNoData = True
1194 profileIndex = None
1194 profileIndex = None
1195
1195
1196 if dataOut.flagDataAsBlock:
1196 if dataOut.flagDataAsBlock:
1197
1197
1198 #nchannels, nprofiles, nsamples
1198 #nchannels, nprofiles, nsamples
1199 shape = dataOut.data.shape
1199 shape = dataOut.data.shape
1200
1200
1201 if shape[2] % n != 0:
1201 if shape[2] % n != 0:
1202 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
1202 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
1203
1203
1204 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
1204 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
1205
1205
1206 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1206 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1207 dataOut.flagNoData = False
1207 dataOut.flagNoData = False
1208
1208
1209 profileIndex = int(dataOut.nProfiles/n) - 1
1209 profileIndex = int(dataOut.nProfiles/n) - 1
1210
1210
1211 else:
1211 else:
1212
1212
1213 raise ValueError("Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)")
1213 raise ValueError("Could not split the data when is read Profile by Profile. Use VoltageReader(..., getblock=True)")
1214
1214
1215 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1215 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1216
1216
1217 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
1217 dataOut.heightList = numpy.arange(dataOut.nHeights/n) * deltaHeight + dataOut.heightList[0]
1218
1218
1219 dataOut.nProfiles = int(dataOut.nProfiles*n)
1219 dataOut.nProfiles = int(dataOut.nProfiles*n)
1220
1220
1221 dataOut.profileIndex = profileIndex
1221 dataOut.profileIndex = profileIndex
1222
1222
1223 dataOut.ippSeconds /= n
1223 dataOut.ippSeconds /= n
1224
1224
1225 return dataOut
1225 return dataOut
1226
1226
1227 class CombineProfiles(Operation):
1227 class CombineProfiles(Operation):
1228 def __init__(self, **kwargs):
1228 def __init__(self, **kwargs):
1229
1229
1230 Operation.__init__(self, **kwargs)
1230 Operation.__init__(self, **kwargs)
1231
1231
1232 self.__remData = None
1232 self.__remData = None
1233 self.__profileIndex = 0
1233 self.__profileIndex = 0
1234
1234
1235 def run(self, dataOut, n):
1235 def run(self, dataOut, n):
1236
1236
1237 dataOut.flagNoData = True
1237 dataOut.flagNoData = True
1238 profileIndex = None
1238 profileIndex = None
1239
1239
1240 if dataOut.flagDataAsBlock:
1240 if dataOut.flagDataAsBlock:
1241
1241
1242 #nchannels, nprofiles, nsamples
1242 #nchannels, nprofiles, nsamples
1243 shape = dataOut.data.shape
1243 shape = dataOut.data.shape
1244 new_shape = shape[0], shape[1]/n, shape[2]*n
1244 new_shape = shape[0], shape[1]/n, shape[2]*n
1245
1245
1246 if shape[1] % n != 0:
1246 if shape[1] % n != 0:
1247 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]))
1247 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[1]))
1248
1248
1249 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1249 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1250 dataOut.flagNoData = False
1250 dataOut.flagNoData = False
1251
1251
1252 profileIndex = int(dataOut.nProfiles*n) - 1
1252 profileIndex = int(dataOut.nProfiles*n) - 1
1253
1253
1254 else:
1254 else:
1255
1255
1256 #nchannels, nsamples
1256 #nchannels, nsamples
1257 if self.__remData is None:
1257 if self.__remData is None:
1258 newData = dataOut.data
1258 newData = dataOut.data
1259 else:
1259 else:
1260 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
1260 newData = numpy.concatenate((self.__remData, dataOut.data), axis=1)
1261
1261
1262 self.__profileIndex += 1
1262 self.__profileIndex += 1
1263
1263
1264 if self.__profileIndex < n:
1264 if self.__profileIndex < n:
1265 self.__remData = newData
1265 self.__remData = newData
1266 #continue
1266 #continue
1267 return
1267 return
1268
1268
1269 self.__profileIndex = 0
1269 self.__profileIndex = 0
1270 self.__remData = None
1270 self.__remData = None
1271
1271
1272 dataOut.data = newData
1272 dataOut.data = newData
1273 dataOut.flagNoData = False
1273 dataOut.flagNoData = False
1274
1274
1275 profileIndex = dataOut.profileIndex/n
1275 profileIndex = dataOut.profileIndex/n
1276
1276
1277
1277
1278 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1278 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1279
1279
1280 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
1280 dataOut.heightList = numpy.arange(dataOut.nHeights*n) * deltaHeight + dataOut.heightList[0]
1281
1281
1282 dataOut.nProfiles = int(dataOut.nProfiles/n)
1282 dataOut.nProfiles = int(dataOut.nProfiles/n)
1283
1283
1284 dataOut.profileIndex = profileIndex
1284 dataOut.profileIndex = profileIndex
1285
1285
1286 dataOut.ippSeconds *= n
1286 dataOut.ippSeconds *= n
1287
1287
1288 return dataOut
1288 return dataOut
1289
1289
1290 class PulsePair(Operation):
1290 class PulsePair(Operation):
1291 '''
1291 '''
1292 Function PulsePair(Signal Power, Velocity)
1292 Function PulsePair(Signal Power, Velocity)
1293 The real component of Lag[0] provides Intensity Information
1293 The real component of Lag[0] provides Intensity Information
1294 The imag component of Lag[1] Phase provides Velocity Information
1294 The imag component of Lag[1] Phase provides Velocity Information
1295
1295
1296 Configuration Parameters:
1296 Configuration Parameters:
1297 nPRF = Number of Several PRF
1297 nPRF = Number of Several PRF
1298 theta = Degree Azimuth angel Boundaries
1298 theta = Degree Azimuth angel Boundaries
1299
1299
1300 Input:
1300 Input:
1301 self.dataOut
1301 self.dataOut
1302 lag[N]
1302 lag[N]
1303 Affected:
1303 Affected:
1304 self.dataOut.spc
1304 self.dataOut.spc
1305 '''
1305 '''
1306 isConfig = False
1306 isConfig = False
1307 __profIndex = 0
1307 __profIndex = 0
1308 __initime = None
1308 __initime = None
1309 __lastdatatime = None
1309 __lastdatatime = None
1310 __buffer = None
1310 __buffer = None
1311 noise = None
1311 noise = None
1312 __dataReady = False
1312 __dataReady = False
1313 n = None
1313 n = None
1314 __nch = 0
1314 __nch = 0
1315 __nHeis = 0
1315 __nHeis = 0
1316 removeDC = False
1316 removeDC = False
1317 ipp = None
1317 ipp = None
1318 lambda_ = 0
1318 lambda_ = 0
1319
1319
1320 def __init__(self,**kwargs):
1320 def __init__(self,**kwargs):
1321 Operation.__init__(self,**kwargs)
1321 Operation.__init__(self,**kwargs)
1322
1322
1323 def setup(self, dataOut, n = None, removeDC=False):
1323 def setup(self, dataOut, n = None, removeDC=False):
1324 '''
1324 '''
1325 n= Numero de PRF's de entrada
1325 n= Numero de PRF's de entrada
1326 '''
1326 '''
1327 self.__initime = None
1327 self.__initime = None
1328 ####print("[INICIO]-setup del METODO PULSE PAIR")
1328 ####print("[INICIO]-setup del METODO PULSE PAIR")
1329 self.__lastdatatime = 0
1329 self.__lastdatatime = 0
1330 self.__dataReady = False
1330 self.__dataReady = False
1331 self.__buffer = 0
1331 self.__buffer = 0
1332 self.__profIndex = 0
1332 self.__profIndex = 0
1333 self.noise = None
1333 self.noise = None
1334 self.__nch = dataOut.nChannels
1334 self.__nch = dataOut.nChannels
1335 self.__nHeis = dataOut.nHeights
1335 self.__nHeis = dataOut.nHeights
1336 self.removeDC = removeDC
1336 self.removeDC = removeDC
1337 self.lambda_ = 3.0e8/(9345.0e6)
1337 self.lambda_ = 3.0e8/(9345.0e6)
1338 self.ippSec = dataOut.ippSeconds
1338 self.ippSec = dataOut.ippSeconds
1339 self.nCohInt = dataOut.nCohInt
1339 self.nCohInt = dataOut.nCohInt
1340 ####print("IPPseconds",dataOut.ippSeconds)
1340 ####print("IPPseconds",dataOut.ippSeconds)
1341 ####print("ELVALOR DE n es:", n)
1341 ####print("ELVALOR DE n es:", n)
1342 if n == None:
1342 if n == None:
1343 raise ValueError("n should be specified.")
1343 raise ValueError("n should be specified.")
1344
1344
1345 if n != None:
1345 if n != None:
1346 if n<2:
1346 if n<2:
1347 raise ValueError("n should be greater than 2")
1347 raise ValueError("n should be greater than 2")
1348
1348
1349 self.n = n
1349 self.n = n
1350 self.__nProf = n
1350 self.__nProf = n
1351
1351
1352 self.__buffer = numpy.zeros((dataOut.nChannels,
1352 self.__buffer = numpy.zeros((dataOut.nChannels,
1353 n,
1353 n,
1354 dataOut.nHeights),
1354 dataOut.nHeights),
1355 dtype='complex')
1355 dtype='complex')
1356
1356
1357 def putData(self,data):
1357 def putData(self,data):
1358 '''
1358 '''
1359 Add a profile to he __buffer and increase in one the __profiel Index
1359 Add a profile to he __buffer and increase in one the __profiel Index
1360 '''
1360 '''
1361 self.__buffer[:,self.__profIndex,:]= data
1361 self.__buffer[:,self.__profIndex,:]= data
1362 self.__profIndex += 1
1362 self.__profIndex += 1
1363 return
1363 return
1364
1364
1365 def pushData(self,dataOut):
1365 def pushData(self,dataOut):
1366 '''
1366 '''
1367 Return the PULSEPAIR and the profiles used in the operation
1367 Return the PULSEPAIR and the profiles used in the operation
1368 Affected : self.__profileIndex
1368 Affected : self.__profileIndex
1369 '''
1369 '''
1370 #----------------- Remove DC-----------------------------------
1370 #----------------- Remove DC-----------------------------------
1371 if self.removeDC==True:
1371 if self.removeDC==True:
1372 mean = numpy.mean(self.__buffer,1)
1372 mean = numpy.mean(self.__buffer,1)
1373 tmp = mean.reshape(self.__nch,1,self.__nHeis)
1373 tmp = mean.reshape(self.__nch,1,self.__nHeis)
1374 dc= numpy.tile(tmp,[1,self.__nProf,1])
1374 dc= numpy.tile(tmp,[1,self.__nProf,1])
1375 self.__buffer = self.__buffer - dc
1375 self.__buffer = self.__buffer - dc
1376 #------------------Calculo de Potencia ------------------------
1376 #------------------Calculo de Potencia ------------------------
1377 pair0 = self.__buffer*numpy.conj(self.__buffer)
1377 pair0 = self.__buffer*numpy.conj(self.__buffer)
1378 pair0 = pair0.real
1378 pair0 = pair0.real
1379 lag_0 = numpy.sum(pair0,1)
1379 lag_0 = numpy.sum(pair0,1)
1380 #-----------------Calculo de Cscp------------------------------ New
1380 #-----------------Calculo de Cscp------------------------------ New
1381 cspc_pair01 = self.__buffer[0]*self.__buffer[1]
1381 cspc_pair01 = self.__buffer[0]*self.__buffer[1]
1382 #------------------Calculo de Ruido x canal--------------------
1382 #------------------Calculo de Ruido x canal--------------------
1383 self.noise = numpy.zeros(self.__nch)
1383 self.noise = numpy.zeros(self.__nch)
1384 for i in range(self.__nch):
1384 for i in range(self.__nch):
1385 daux = numpy.sort(pair0[i,:,:],axis= None)
1385 daux = numpy.sort(pair0[i,:,:],axis= None)
1386 self.noise[i]=hildebrand_sekhon( daux ,self.nCohInt)
1386 self.noise[i]=hildebrand_sekhon( daux ,self.nCohInt)
1387
1387
1388 self.noise = self.noise.reshape(self.__nch,1)
1388 self.noise = self.noise.reshape(self.__nch,1)
1389 self.noise = numpy.tile(self.noise,[1,self.__nHeis])
1389 self.noise = numpy.tile(self.noise,[1,self.__nHeis])
1390 noise_buffer = self.noise.reshape(self.__nch,1,self.__nHeis)
1390 noise_buffer = self.noise.reshape(self.__nch,1,self.__nHeis)
1391 noise_buffer = numpy.tile(noise_buffer,[1,self.__nProf,1])
1391 noise_buffer = numpy.tile(noise_buffer,[1,self.__nProf,1])
1392 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
1392 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
1393 #------------------ P= S+N ,P=lag_0/N ---------------------------------
1393 #------------------ P= S+N ,P=lag_0/N ---------------------------------
1394 #-------------------- Power --------------------------------------------------
1394 #-------------------- Power --------------------------------------------------
1395 data_power = lag_0/(self.n*self.nCohInt)
1395 data_power = lag_0/(self.n*self.nCohInt)
1396 #--------------------CCF------------------------------------------------------
1396 #--------------------CCF------------------------------------------------------
1397 data_ccf =numpy.sum(cspc_pair01,axis=0)/(self.n*self.nCohInt)
1397 data_ccf =numpy.sum(cspc_pair01,axis=0)/(self.n*self.nCohInt)
1398 #------------------ Senal --------------------------------------------------
1398 #------------------ Senal --------------------------------------------------
1399 data_intensity = pair0 - noise_buffer
1399 data_intensity = pair0 - noise_buffer
1400 data_intensity = numpy.sum(data_intensity,axis=1)*(self.n*self.nCohInt)#*self.nCohInt)
1400 data_intensity = numpy.sum(data_intensity,axis=1)*(self.n*self.nCohInt)#*self.nCohInt)
1401 #data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
1401 #data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
1402 for i in range(self.__nch):
1402 for i in range(self.__nch):
1403 for j in range(self.__nHeis):
1403 for j in range(self.__nHeis):
1404 if data_intensity[i][j] < 0:
1404 if data_intensity[i][j] < 0:
1405 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
1405 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
1406
1406
1407 #----------------- Calculo de Frecuencia y Velocidad doppler--------
1407 #----------------- Calculo de Frecuencia y Velocidad doppler--------
1408 pair1 = self.__buffer[:,:-1,:]*numpy.conjugate(self.__buffer[:,1:,:])
1408 pair1 = self.__buffer[:,:-1,:]*numpy.conjugate(self.__buffer[:,1:,:])
1409 lag_1 = numpy.sum(pair1,1)
1409 lag_1 = numpy.sum(pair1,1)
1410 data_freq = (-1/(2.0*math.pi*self.ippSec*self.nCohInt))*numpy.angle(lag_1)
1410 data_freq = (-1/(2.0*math.pi*self.ippSec*self.nCohInt))*numpy.angle(lag_1)
1411 data_velocity = (self.lambda_/2.0)*data_freq
1411 data_velocity = (self.lambda_/2.0)*data_freq
1412
1412
1413 #---------------- Potencia promedio estimada de la Senal-----------
1413 #---------------- Potencia promedio estimada de la Senal-----------
1414 lag_0 = lag_0/self.n
1414 lag_0 = lag_0/self.n
1415 S = lag_0-self.noise
1415 S = lag_0-self.noise
1416
1416
1417 #---------------- Frecuencia Doppler promedio ---------------------
1417 #---------------- Frecuencia Doppler promedio ---------------------
1418 lag_1 = lag_1/(self.n-1)
1418 lag_1 = lag_1/(self.n-1)
1419 R1 = numpy.abs(lag_1)
1419 R1 = numpy.abs(lag_1)
1420
1420
1421 #---------------- Calculo del SNR----------------------------------
1421 #---------------- Calculo del SNR----------------------------------
1422 data_snrPP = S/self.noise
1422 data_snrPP = S/self.noise
1423 for i in range(self.__nch):
1423 for i in range(self.__nch):
1424 for j in range(self.__nHeis):
1424 for j in range(self.__nHeis):
1425 if data_snrPP[i][j] < 1.e-20:
1425 if data_snrPP[i][j] < 1.e-20:
1426 data_snrPP[i][j] = 1.e-20
1426 data_snrPP[i][j] = 1.e-20
1427
1427
1428 #----------------- Calculo del ancho espectral ----------------------
1428 #----------------- Calculo del ancho espectral ----------------------
1429 L = S/R1
1429 L = S/R1
1430 L = numpy.where(L<0,1,L)
1430 L = numpy.where(L<0,1,L)
1431 L = numpy.log(L)
1431 L = numpy.log(L)
1432 tmp = numpy.sqrt(numpy.absolute(L))
1432 tmp = numpy.sqrt(numpy.absolute(L))
1433 data_specwidth = (self.lambda_/(2*math.sqrt(2)*math.pi*self.ippSec*self.nCohInt))*tmp*numpy.sign(L)
1433 data_specwidth = (self.lambda_/(2*math.sqrt(2)*math.pi*self.ippSec*self.nCohInt))*tmp*numpy.sign(L)
1434 n = self.__profIndex
1434 n = self.__profIndex
1435
1435
1436 self.__buffer = numpy.zeros((self.__nch, self.__nProf,self.__nHeis), dtype='complex')
1436 self.__buffer = numpy.zeros((self.__nch, self.__nProf,self.__nHeis), dtype='complex')
1437 self.__profIndex = 0
1437 self.__profIndex = 0
1438 return data_power,data_intensity,data_velocity,data_snrPP,data_specwidth,data_ccf,n
1438 return data_power,data_intensity,data_velocity,data_snrPP,data_specwidth,data_ccf,n
1439
1439
1440
1440
1441 def pulsePairbyProfiles(self,dataOut):
1441 def pulsePairbyProfiles(self,dataOut):
1442
1442
1443 self.__dataReady = False
1443 self.__dataReady = False
1444 data_power = None
1444 data_power = None
1445 data_intensity = None
1445 data_intensity = None
1446 data_velocity = None
1446 data_velocity = None
1447 data_specwidth = None
1447 data_specwidth = None
1448 data_snrPP = None
1448 data_snrPP = None
1449 data_ccf = None
1449 data_ccf = None
1450 self.putData(data=dataOut.data)
1450 self.putData(data=dataOut.data)
1451 if self.__profIndex == self.n:
1451 if self.__profIndex == self.n:
1452 data_power,data_intensity, data_velocity,data_snrPP,data_specwidth,data_ccf, n = self.pushData(dataOut=dataOut)
1452 data_power,data_intensity, data_velocity,data_snrPP,data_specwidth,data_ccf, n = self.pushData(dataOut=dataOut)
1453 self.__dataReady = True
1453 self.__dataReady = True
1454
1454
1455 return data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf
1455 return data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf
1456
1456
1457
1457
1458 def pulsePairOp(self, dataOut, datatime= None):
1458 def pulsePairOp(self, dataOut, datatime= None):
1459
1459
1460 if self.__initime == None:
1460 if self.__initime == None:
1461 self.__initime = datatime
1461 self.__initime = datatime
1462 data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf = self.pulsePairbyProfiles(dataOut)
1462 data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf = self.pulsePairbyProfiles(dataOut)
1463 self.__lastdatatime = datatime
1463 self.__lastdatatime = datatime
1464
1464
1465 if data_power is None:
1465 if data_power is None:
1466 return None, None, None,None,None,None,None
1466 return None, None, None,None,None,None,None
1467
1467
1468 avgdatatime = self.__initime
1468 avgdatatime = self.__initime
1469 deltatime = datatime - self.__lastdatatime
1469 deltatime = datatime - self.__lastdatatime
1470 self.__initime = datatime
1470 self.__initime = datatime
1471
1471
1472 return data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf, avgdatatime
1472 return data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf, avgdatatime
1473
1473
1474 def run(self, dataOut,n = None,removeDC= False, overlapping= False,**kwargs):
1474 def run(self, dataOut,n = None,removeDC= False, overlapping= False,**kwargs):
1475 #print("hey")
1475 #print("hey")
1476 #print(dataOut.data.shape)
1476 #print(dataOut.data.shape)
1477 #exit(1)
1477 #exit(1)
1478 #print(self.__profIndex)
1478 #print(self.__profIndex)
1479 if not self.isConfig:
1479 if not self.isConfig:
1480 self.setup(dataOut = dataOut, n = n , removeDC=removeDC , **kwargs)
1480 self.setup(dataOut = dataOut, n = n , removeDC=removeDC , **kwargs)
1481 self.isConfig = True
1481 self.isConfig = True
1482 data_power, data_intensity, data_velocity,data_snrPP,data_specwidth,data_ccf, avgdatatime = self.pulsePairOp(dataOut, dataOut.utctime)
1482 data_power, data_intensity, data_velocity,data_snrPP,data_specwidth,data_ccf, avgdatatime = self.pulsePairOp(dataOut, dataOut.utctime)
1483 dataOut.flagNoData = True
1483 dataOut.flagNoData = True
1484
1484
1485 if self.__dataReady:
1485 if self.__dataReady:
1486 ###print("READY ----------------------------------")
1486 ###print("READY ----------------------------------")
1487 dataOut.nCohInt *= self.n
1487 dataOut.nCohInt *= self.n
1488 dataOut.dataPP_POW = data_intensity # S
1488 dataOut.dataPP_POW = data_intensity # S
1489 dataOut.dataPP_POWER = data_power # P valor que corresponde a POTENCIA MOMENTO
1489 dataOut.dataPP_POWER = data_power # P valor que corresponde a POTENCIA MOMENTO
1490 dataOut.dataPP_DOP = data_velocity
1490 dataOut.dataPP_DOP = data_velocity
1491 dataOut.dataPP_SNR = data_snrPP
1491 dataOut.dataPP_SNR = data_snrPP
1492 dataOut.dataPP_WIDTH = data_specwidth
1492 dataOut.dataPP_WIDTH = data_specwidth
1493 dataOut.dataPP_CCF = data_ccf
1493 dataOut.dataPP_CCF = data_ccf
1494 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1494 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1495 dataOut.nProfiles = int(dataOut.nProfiles/n)
1495 dataOut.nProfiles = int(dataOut.nProfiles/n)
1496 dataOut.utctime = avgdatatime
1496 dataOut.utctime = avgdatatime
1497 dataOut.flagNoData = False
1497 dataOut.flagNoData = False
1498 return dataOut
1498 return dataOut
1499
1499
1500 class PulsePair_vRF(Operation):
1500 class PulsePair_vRF(Operation):
1501 '''
1501 '''
1502 Function PulsePair(Signal Power, Velocity)
1502 Function PulsePair(Signal Power, Velocity)
1503 The real component of Lag[0] provides Intensity Information
1503 The real component of Lag[0] provides Intensity Information
1504 The imag component of Lag[1] Phase provides Velocity Information
1504 The imag component of Lag[1] Phase provides Velocity Information
1505
1505
1506 Configuration Parameters:
1506 Configuration Parameters:
1507 nPRF = Number of Several PRF
1507 nPRF = Number of Several PRF
1508 theta = Degree Azimuth angel Boundaries
1508 theta = Degree Azimuth angel Boundaries
1509
1509
1510 Input:
1510 Input:
1511 self.dataOut
1511 self.dataOut
1512 lag[N]
1512 lag[N]
1513 Affected:
1513 Affected:
1514 self.dataOut.spc
1514 self.dataOut.spc
1515 '''
1515 '''
1516 isConfig = False
1516 isConfig = False
1517 __profIndex = 0
1517 __profIndex = 0
1518 __initime = None
1518 __initime = None
1519 __lastdatatime = None
1519 __lastdatatime = None
1520 __buffer = None
1520 __buffer = None
1521 noise = None
1521 noise = None
1522 __dataReady = False
1522 __dataReady = False
1523 n = None
1523 n = None
1524 __nch = 0
1524 __nch = 0
1525 __nHeis = 0
1525 __nHeis = 0
1526 removeDC = False
1526 removeDC = False
1527 ipp = None
1527 ipp = None
1528 lambda_ = 0
1528 lambda_ = 0
1529
1529
1530 def __init__(self,**kwargs):
1530 def __init__(self,**kwargs):
1531 Operation.__init__(self,**kwargs)
1531 Operation.__init__(self,**kwargs)
1532
1532
1533 def setup(self, dataOut, n = None, removeDC=False):
1533 def setup(self, dataOut, n = None, removeDC=False):
1534 '''
1534 '''
1535 n= Numero de PRF's de entrada
1535 n= Numero de PRF's de entrada
1536 '''
1536 '''
1537 self.__initime = None
1537 self.__initime = None
1538 ####print("[INICIO]-setup del METODO PULSE PAIR")
1538 ####print("[INICIO]-setup del METODO PULSE PAIR")
1539 self.__lastdatatime = 0
1539 self.__lastdatatime = 0
1540 self.__dataReady = False
1540 self.__dataReady = False
1541 self.__buffer = 0
1541 self.__buffer = 0
1542 self.__profIndex = 0
1542 self.__profIndex = 0
1543 self.noise = None
1543 self.noise = None
1544 self.__nch = dataOut.nChannels
1544 self.__nch = dataOut.nChannels
1545 self.__nHeis = dataOut.nHeights
1545 self.__nHeis = dataOut.nHeights
1546 self.removeDC = removeDC
1546 self.removeDC = removeDC
1547 self.lambda_ = 3.0e8/(9345.0e6)
1547 self.lambda_ = 3.0e8/(9345.0e6)
1548 self.ippSec = dataOut.ippSeconds
1548 self.ippSec = dataOut.ippSeconds
1549 self.nCohInt = dataOut.nCohInt
1549 self.nCohInt = dataOut.nCohInt
1550 ####print("IPPseconds",dataOut.ippSeconds)
1550 ####print("IPPseconds",dataOut.ippSeconds)
1551 ####print("ELVALOR DE n es:", n)
1551 ####print("ELVALOR DE n es:", n)
1552 if n == None:
1552 if n == None:
1553 raise ValueError("n should be specified.")
1553 raise ValueError("n should be specified.")
1554
1554
1555 if n != None:
1555 if n != None:
1556 if n<2:
1556 if n<2:
1557 raise ValueError("n should be greater than 2")
1557 raise ValueError("n should be greater than 2")
1558
1558
1559 self.n = n
1559 self.n = n
1560 self.__nProf = n
1560 self.__nProf = n
1561
1561
1562 self.__buffer = numpy.zeros((dataOut.nChannels,
1562 self.__buffer = numpy.zeros((dataOut.nChannels,
1563 n,
1563 n,
1564 dataOut.nHeights),
1564 dataOut.nHeights),
1565 dtype='complex')
1565 dtype='complex')
1566
1566
1567 def putData(self,data):
1567 def putData(self,data):
1568 '''
1568 '''
1569 Add a profile to he __buffer and increase in one the __profiel Index
1569 Add a profile to he __buffer and increase in one the __profiel Index
1570 '''
1570 '''
1571 self.__buffer[:,self.__profIndex,:]= data
1571 self.__buffer[:,self.__profIndex,:]= data
1572 self.__profIndex += 1
1572 self.__profIndex += 1
1573 return
1573 return
1574
1574
1575 def putDataByBlock(self,data,n):
1575 def putDataByBlock(self,data,n):
1576 '''
1576 '''
1577 Add a profile to he __buffer and increase in one the __profiel Index
1577 Add a profile to he __buffer and increase in one the __profiel Index
1578 '''
1578 '''
1579 self.__buffer[:]= data
1579 self.__buffer[:]= data
1580 self.__profIndex = n
1580 self.__profIndex = n
1581 return
1581 return
1582
1582
1583 def pushData(self,dataOut):
1583 def pushData(self,dataOut):
1584 '''
1584 '''
1585 Return the PULSEPAIR and the profiles used in the operation
1585 Return the PULSEPAIR and the profiles used in the operation
1586 Affected : self.__profileIndex
1586 Affected : self.__profileIndex
1587 '''
1587 '''
1588 #----------------- Remove DC-----------------------------------
1588 #----------------- Remove DC-----------------------------------
1589 if self.removeDC==True:
1589 if self.removeDC==True:
1590 mean = numpy.mean(self.__buffer,1)
1590 mean = numpy.mean(self.__buffer,1)
1591 tmp = mean.reshape(self.__nch,1,self.__nHeis)
1591 tmp = mean.reshape(self.__nch,1,self.__nHeis)
1592 dc= numpy.tile(tmp,[1,self.__nProf,1])
1592 dc= numpy.tile(tmp,[1,self.__nProf,1])
1593 self.__buffer = self.__buffer - dc
1593 self.__buffer = self.__buffer - dc
1594 #------------------Calculo de Potencia ------------------------
1594 #------------------Calculo de Potencia ------------------------
1595 pair0 = self.__buffer*numpy.conj(self.__buffer)
1595 pair0 = self.__buffer*numpy.conj(self.__buffer)
1596 pair0 = pair0.real
1596 pair0 = pair0.real
1597 lag_0 = numpy.sum(pair0,1)
1597 lag_0 = numpy.sum(pair0,1)
1598 #-----------------Calculo de Cscp------------------------------ New
1598 #-----------------Calculo de Cscp------------------------------ New
1599 cspc_pair01 = self.__buffer[0]*self.__buffer[1]
1599 cspc_pair01 = self.__buffer[0]*self.__buffer[1]
1600 #------------------Calculo de Ruido x canal--------------------
1600 #------------------Calculo de Ruido x canal--------------------
1601 self.noise = numpy.zeros(self.__nch)
1601 self.noise = numpy.zeros(self.__nch)
1602 for i in range(self.__nch):
1602 for i in range(self.__nch):
1603 daux = numpy.sort(pair0[i,:,:],axis= None)
1603 daux = numpy.sort(pair0[i,:,:],axis= None)
1604 self.noise[i]=hildebrand_sekhon( daux ,self.nCohInt)
1604 self.noise[i]=hildebrand_sekhon( daux ,self.nCohInt)
1605
1605
1606 self.noise = self.noise.reshape(self.__nch,1)
1606 self.noise = self.noise.reshape(self.__nch,1)
1607 self.noise = numpy.tile(self.noise,[1,self.__nHeis])
1607 self.noise = numpy.tile(self.noise,[1,self.__nHeis])
1608 noise_buffer = self.noise.reshape(self.__nch,1,self.__nHeis)
1608 noise_buffer = self.noise.reshape(self.__nch,1,self.__nHeis)
1609 noise_buffer = numpy.tile(noise_buffer,[1,self.__nProf,1])
1609 noise_buffer = numpy.tile(noise_buffer,[1,self.__nProf,1])
1610 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
1610 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
1611 #------------------ P= S+N ,P=lag_0/N ---------------------------------
1611 #------------------ P= S+N ,P=lag_0/N ---------------------------------
1612 #-------------------- Power --------------------------------------------------
1612 #-------------------- Power --------------------------------------------------
1613 data_power = lag_0/(self.n*self.nCohInt)
1613 data_power = lag_0/(self.n*self.nCohInt)
1614 #--------------------CCF------------------------------------------------------
1614 #--------------------CCF------------------------------------------------------
1615 data_ccf =numpy.sum(cspc_pair01,axis=0)/(self.n*self.nCohInt)
1615 data_ccf =numpy.sum(cspc_pair01,axis=0)/(self.n*self.nCohInt)
1616 #------------------ Senal --------------------------------------------------
1616 #------------------ Senal --------------------------------------------------
1617 data_intensity = pair0 - noise_buffer
1617 data_intensity = pair0 - noise_buffer
1618 data_intensity = numpy.sum(data_intensity,axis=1)*(self.n*self.nCohInt)#*self.nCohInt)
1618 data_intensity = numpy.sum(data_intensity,axis=1)*(self.n*self.nCohInt)#*self.nCohInt)
1619 #data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
1619 #data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
1620 for i in range(self.__nch):
1620 for i in range(self.__nch):
1621 for j in range(self.__nHeis):
1621 for j in range(self.__nHeis):
1622 if data_intensity[i][j] < 0:
1622 if data_intensity[i][j] < 0:
1623 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
1623 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
1624
1624
1625 #----------------- Calculo de Frecuencia y Velocidad doppler--------
1625 #----------------- Calculo de Frecuencia y Velocidad doppler--------
1626 pair1 = self.__buffer[:,:-1,:]*numpy.conjugate(self.__buffer[:,1:,:])
1626 pair1 = self.__buffer[:,:-1,:]*numpy.conjugate(self.__buffer[:,1:,:])
1627 lag_1 = numpy.sum(pair1,1)
1627 lag_1 = numpy.sum(pair1,1)
1628 data_freq = (-1/(2.0*math.pi*self.ippSec*self.nCohInt))*numpy.angle(lag_1)
1628 data_freq = (-1/(2.0*math.pi*self.ippSec*self.nCohInt))*numpy.angle(lag_1)
1629 data_velocity = (self.lambda_/2.0)*data_freq
1629 data_velocity = (self.lambda_/2.0)*data_freq
1630
1630
1631 #---------------- Potencia promedio estimada de la Senal-----------
1631 #---------------- Potencia promedio estimada de la Senal-----------
1632 lag_0 = lag_0/self.n
1632 lag_0 = lag_0/self.n
1633 S = lag_0-self.noise
1633 S = lag_0-self.noise
1634
1634
1635 #---------------- Frecuencia Doppler promedio ---------------------
1635 #---------------- Frecuencia Doppler promedio ---------------------
1636 lag_1 = lag_1/(self.n-1)
1636 lag_1 = lag_1/(self.n-1)
1637 R1 = numpy.abs(lag_1)
1637 R1 = numpy.abs(lag_1)
1638
1638
1639 #---------------- Calculo del SNR----------------------------------
1639 #---------------- Calculo del SNR----------------------------------
1640 data_snrPP = S/self.noise
1640 data_snrPP = S/self.noise
1641 for i in range(self.__nch):
1641 for i in range(self.__nch):
1642 for j in range(self.__nHeis):
1642 for j in range(self.__nHeis):
1643 if data_snrPP[i][j] < 1.e-20:
1643 if data_snrPP[i][j] < 1.e-20:
1644 data_snrPP[i][j] = 1.e-20
1644 data_snrPP[i][j] = 1.e-20
1645
1645
1646 #----------------- Calculo del ancho espectral ----------------------
1646 #----------------- Calculo del ancho espectral ----------------------
1647 L = S/R1
1647 L = S/R1
1648 L = numpy.where(L<0,1,L)
1648 L = numpy.where(L<0,1,L)
1649 L = numpy.log(L)
1649 L = numpy.log(L)
1650 tmp = numpy.sqrt(numpy.absolute(L))
1650 tmp = numpy.sqrt(numpy.absolute(L))
1651 data_specwidth = (self.lambda_/(2*math.sqrt(2)*math.pi*self.ippSec*self.nCohInt))*tmp*numpy.sign(L)
1651 data_specwidth = (self.lambda_/(2*math.sqrt(2)*math.pi*self.ippSec*self.nCohInt))*tmp*numpy.sign(L)
1652 n = self.__profIndex
1652 n = self.__profIndex
1653
1653
1654 self.__buffer = numpy.zeros((self.__nch, self.__nProf,self.__nHeis), dtype='complex')
1654 self.__buffer = numpy.zeros((self.__nch, self.__nProf,self.__nHeis), dtype='complex')
1655 self.__profIndex = 0
1655 self.__profIndex = 0
1656 return data_power,data_intensity,data_velocity,data_snrPP,data_specwidth,data_ccf,n
1656 return data_power,data_intensity,data_velocity,data_snrPP,data_specwidth,data_ccf,n
1657
1657
1658
1658
1659 def pulsePairbyProfiles(self,dataOut,n):
1659 def pulsePairbyProfiles(self,dataOut,n):
1660
1660
1661 self.__dataReady = False
1661 self.__dataReady = False
1662 data_power = None
1662 data_power = None
1663 data_intensity = None
1663 data_intensity = None
1664 data_velocity = None
1664 data_velocity = None
1665 data_specwidth = None
1665 data_specwidth = None
1666 data_snrPP = None
1666 data_snrPP = None
1667 data_ccf = None
1667 data_ccf = None
1668
1668
1669 if dataOut.flagDataAsBlock:
1669 if dataOut.flagDataAsBlock:
1670 self.putDataByBlock(data=dataOut.data,n=n)
1670 self.putDataByBlock(data=dataOut.data,n=n)
1671 else:
1671 else:
1672 self.putData(data=dataOut.data)
1672 self.putData(data=dataOut.data)
1673 if self.__profIndex == self.n:
1673 if self.__profIndex == self.n:
1674 data_power,data_intensity, data_velocity,data_snrPP,data_specwidth,data_ccf, n = self.pushData(dataOut=dataOut)
1674 data_power,data_intensity, data_velocity,data_snrPP,data_specwidth,data_ccf, n = self.pushData(dataOut=dataOut)
1675 self.__dataReady = True
1675 self.__dataReady = True
1676
1676
1677 return data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf
1677 return data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf
1678
1678
1679
1679
1680 def pulsePairOp(self, dataOut, n, datatime= None):
1680 def pulsePairOp(self, dataOut, n, datatime= None):
1681
1681
1682 if self.__initime == None:
1682 if self.__initime == None:
1683 self.__initime = datatime
1683 self.__initime = datatime
1684 data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf = self.pulsePairbyProfiles(dataOut,n)
1684 data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf = self.pulsePairbyProfiles(dataOut,n)
1685 self.__lastdatatime = datatime
1685 self.__lastdatatime = datatime
1686
1686
1687 if data_power is None:
1687 if data_power is None:
1688 return None, None, None,None,None,None,None
1688 return None, None, None,None,None,None,None
1689
1689
1690 avgdatatime = self.__initime
1690 avgdatatime = self.__initime
1691 deltatime = datatime - self.__lastdatatime
1691 deltatime = datatime - self.__lastdatatime
1692 self.__initime = datatime
1692 self.__initime = datatime
1693
1693
1694 return data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf, avgdatatime
1694 return data_power, data_intensity, data_velocity, data_snrPP,data_specwidth,data_ccf, avgdatatime
1695
1695
1696 def run(self, dataOut,n = None,removeDC= False, overlapping= False,**kwargs):
1696 def run(self, dataOut,n = None,removeDC= False, overlapping= False,**kwargs):
1697
1697
1698 if dataOut.flagDataAsBlock:
1698 if dataOut.flagDataAsBlock:
1699 n = dataOut.nProfiles
1699 n = int(dataOut.nProfiles)
1700 #print("n",n)
1700
1701
1701 if not self.isConfig:
1702 if not self.isConfig:
1702 self.setup(dataOut = dataOut, n = n , removeDC=removeDC , **kwargs)
1703 self.setup(dataOut = dataOut, n = n , removeDC=removeDC , **kwargs)
1703 self.isConfig = True
1704 self.isConfig = True
1704
1705
1705
1706
1706 data_power, data_intensity, data_velocity,data_snrPP,data_specwidth,data_ccf, avgdatatime = self.pulsePairOp(dataOut, n, dataOut.utctime)
1707 data_power, data_intensity, data_velocity,data_snrPP,data_specwidth,data_ccf, avgdatatime = self.pulsePairOp(dataOut, n, dataOut.utctime)
1707
1708
1708
1709
1709 dataOut.flagNoData = True
1710 dataOut.flagNoData = True
1710
1711
1711 if self.__dataReady:
1712 if self.__dataReady:
1712 ###print("READY ----------------------------------")
1713 ###print("READY ----------------------------------")
1713 dataOut.nCohInt *= self.n
1714 dataOut.nCohInt *= self.n
1714 dataOut.dataPP_POW = data_intensity # S
1715 dataOut.dataPP_POW = data_intensity # S
1715 dataOut.dataPP_POWER = data_power # P valor que corresponde a POTENCIA MOMENTO
1716 dataOut.dataPP_POWER = data_power # P valor que corresponde a POTENCIA MOMENTO
1716 dataOut.dataPP_DOP = data_velocity
1717 dataOut.dataPP_DOP = data_velocity
1717 dataOut.dataPP_SNR = data_snrPP
1718 dataOut.dataPP_SNR = data_snrPP
1718 dataOut.dataPP_WIDTH = data_specwidth
1719 dataOut.dataPP_WIDTH = data_specwidth
1719 dataOut.dataPP_CCF = data_ccf
1720 dataOut.dataPP_CCF = data_ccf
1720 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1721 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1721 dataOut.nProfiles = int(dataOut.nProfiles/n)
1722 dataOut.nProfiles = int(dataOut.nProfiles/n)
1722 dataOut.utctime = avgdatatime
1723 dataOut.utctime = avgdatatime
1723 dataOut.flagNoData = False
1724 dataOut.flagNoData = False
1724 return dataOut
1725 return dataOut
1725
1726
1726 # import collections
1727 # import collections
1727 # from scipy.stats import mode
1728 # from scipy.stats import mode
1728 #
1729 #
1729 # class Synchronize(Operation):
1730 # class Synchronize(Operation):
1730 #
1731 #
1731 # isConfig = False
1732 # isConfig = False
1732 # __profIndex = 0
1733 # __profIndex = 0
1733 #
1734 #
1734 # def __init__(self, **kwargs):
1735 # def __init__(self, **kwargs):
1735 #
1736 #
1736 # Operation.__init__(self, **kwargs)
1737 # Operation.__init__(self, **kwargs)
1737 # # self.isConfig = False
1738 # # self.isConfig = False
1738 # self.__powBuffer = None
1739 # self.__powBuffer = None
1739 # self.__startIndex = 0
1740 # self.__startIndex = 0
1740 # self.__pulseFound = False
1741 # self.__pulseFound = False
1741 #
1742 #
1742 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1743 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1743 #
1744 #
1744 # #Read data
1745 # #Read data
1745 #
1746 #
1746 # powerdB = dataOut.getPower(channel = channel)
1747 # powerdB = dataOut.getPower(channel = channel)
1747 # noisedB = dataOut.getNoise(channel = channel)[0]
1748 # noisedB = dataOut.getNoise(channel = channel)[0]
1748 #
1749 #
1749 # self.__powBuffer.extend(powerdB.flatten())
1750 # self.__powBuffer.extend(powerdB.flatten())
1750 #
1751 #
1751 # dataArray = numpy.array(self.__powBuffer)
1752 # dataArray = numpy.array(self.__powBuffer)
1752 #
1753 #
1753 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1754 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1754 #
1755 #
1755 # maxValue = numpy.nanmax(filteredPower)
1756 # maxValue = numpy.nanmax(filteredPower)
1756 #
1757 #
1757 # if maxValue < noisedB + 10:
1758 # if maxValue < noisedB + 10:
1758 # #No se encuentra ningun pulso de transmision
1759 # #No se encuentra ningun pulso de transmision
1759 # return None
1760 # return None
1760 #
1761 #
1761 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1762 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1762 #
1763 #
1763 # if len(maxValuesIndex) < 2:
1764 # if len(maxValuesIndex) < 2:
1764 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1765 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1765 # return None
1766 # return None
1766 #
1767 #
1767 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1768 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1768 #
1769 #
1769 # #Seleccionar solo valores con un espaciamiento de nSamples
1770 # #Seleccionar solo valores con un espaciamiento de nSamples
1770 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1771 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1771 #
1772 #
1772 # if len(pulseIndex) < 2:
1773 # if len(pulseIndex) < 2:
1773 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1774 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1774 # return None
1775 # return None
1775 #
1776 #
1776 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1777 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1777 #
1778 #
1778 # #remover senales que se distancien menos de 10 unidades o muestras
1779 # #remover senales que se distancien menos de 10 unidades o muestras
1779 # #(No deberian existir IPP menor a 10 unidades)
1780 # #(No deberian existir IPP menor a 10 unidades)
1780 #
1781 #
1781 # realIndex = numpy.where(spacing > 10 )[0]
1782 # realIndex = numpy.where(spacing > 10 )[0]
1782 #
1783 #
1783 # if len(realIndex) < 2:
1784 # if len(realIndex) < 2:
1784 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1785 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1785 # return None
1786 # return None
1786 #
1787 #
1787 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1788 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1788 # realPulseIndex = pulseIndex[realIndex]
1789 # realPulseIndex = pulseIndex[realIndex]
1789 #
1790 #
1790 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1791 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1791 #
1792 #
1792 # print "IPP = %d samples" %period
1793 # print "IPP = %d samples" %period
1793 #
1794 #
1794 # self.__newNSamples = dataOut.nHeights #int(period)
1795 # self.__newNSamples = dataOut.nHeights #int(period)
1795 # self.__startIndex = int(realPulseIndex[0])
1796 # self.__startIndex = int(realPulseIndex[0])
1796 #
1797 #
1797 # return 1
1798 # return 1
1798 #
1799 #
1799 #
1800 #
1800 # def setup(self, nSamples, nChannels, buffer_size = 4):
1801 # def setup(self, nSamples, nChannels, buffer_size = 4):
1801 #
1802 #
1802 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1803 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1803 # maxlen = buffer_size*nSamples)
1804 # maxlen = buffer_size*nSamples)
1804 #
1805 #
1805 # bufferList = []
1806 # bufferList = []
1806 #
1807 #
1807 # for i in range(nChannels):
1808 # for i in range(nChannels):
1808 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1809 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1809 # maxlen = buffer_size*nSamples)
1810 # maxlen = buffer_size*nSamples)
1810 #
1811 #
1811 # bufferList.append(bufferByChannel)
1812 # bufferList.append(bufferByChannel)
1812 #
1813 #
1813 # self.__nSamples = nSamples
1814 # self.__nSamples = nSamples
1814 # self.__nChannels = nChannels
1815 # self.__nChannels = nChannels
1815 # self.__bufferList = bufferList
1816 # self.__bufferList = bufferList
1816 #
1817 #
1817 # def run(self, dataOut, channel = 0):
1818 # def run(self, dataOut, channel = 0):
1818 #
1819 #
1819 # if not self.isConfig:
1820 # if not self.isConfig:
1820 # nSamples = dataOut.nHeights
1821 # nSamples = dataOut.nHeights
1821 # nChannels = dataOut.nChannels
1822 # nChannels = dataOut.nChannels
1822 # self.setup(nSamples, nChannels)
1823 # self.setup(nSamples, nChannels)
1823 # self.isConfig = True
1824 # self.isConfig = True
1824 #
1825 #
1825 # #Append new data to internal buffer
1826 # #Append new data to internal buffer
1826 # for thisChannel in range(self.__nChannels):
1827 # for thisChannel in range(self.__nChannels):
1827 # bufferByChannel = self.__bufferList[thisChannel]
1828 # bufferByChannel = self.__bufferList[thisChannel]
1828 # bufferByChannel.extend(dataOut.data[thisChannel])
1829 # bufferByChannel.extend(dataOut.data[thisChannel])
1829 #
1830 #
1830 # if self.__pulseFound:
1831 # if self.__pulseFound:
1831 # self.__startIndex -= self.__nSamples
1832 # self.__startIndex -= self.__nSamples
1832 #
1833 #
1833 # #Finding Tx Pulse
1834 # #Finding Tx Pulse
1834 # if not self.__pulseFound:
1835 # if not self.__pulseFound:
1835 # indexFound = self.__findTxPulse(dataOut, channel)
1836 # indexFound = self.__findTxPulse(dataOut, channel)
1836 #
1837 #
1837 # if indexFound == None:
1838 # if indexFound == None:
1838 # dataOut.flagNoData = True
1839 # dataOut.flagNoData = True
1839 # return
1840 # return
1840 #
1841 #
1841 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1842 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1842 # self.__pulseFound = True
1843 # self.__pulseFound = True
1843 # self.__startIndex = indexFound
1844 # self.__startIndex = indexFound
1844 #
1845 #
1845 # #If pulse was found ...
1846 # #If pulse was found ...
1846 # for thisChannel in range(self.__nChannels):
1847 # for thisChannel in range(self.__nChannels):
1847 # bufferByChannel = self.__bufferList[thisChannel]
1848 # bufferByChannel = self.__bufferList[thisChannel]
1848 # #print self.__startIndex
1849 # #print self.__startIndex
1849 # x = numpy.array(bufferByChannel)
1850 # x = numpy.array(bufferByChannel)
1850 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1851 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1851 #
1852 #
1852 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1853 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1853 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1854 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1854 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1855 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1855 #
1856 #
1856 # dataOut.data = self.__arrayBuffer
1857 # dataOut.data = self.__arrayBuffer
1857 #
1858 #
1858 # self.__startIndex += self.__newNSamples
1859 # self.__startIndex += self.__newNSamples
1859 #
1860 #
1860 # return
1861 # return
General Comments 0
You need to be logged in to leave comments. Login now