##// END OF EJS Templates
last debbug fix pulsepair and spectralmoment
avaldez -
r1395:e5714b82613d
parent child
Show More
@@ -1,517 +1,517
1 import os
1 import os
2 import datetime
2 import datetime
3 import numpy
3 import numpy
4
4
5 from schainpy.model.graphics.jroplot_base import Plot, plt
5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
7 from schainpy.utils import log
7 from schainpy.utils import log
8 # libreria wradlib
8 # libreria wradlib
9 import wradlib as wrl
9 import wradlib as wrl
10
10
11 EARTH_RADIUS = 6.3710e3
11 EARTH_RADIUS = 6.3710e3
12
12
13
13
14 def ll2xy(lat1, lon1, lat2, lon2):
14 def ll2xy(lat1, lon1, lat2, lon2):
15
15
16 p = 0.017453292519943295
16 p = 0.017453292519943295
17 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
17 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
18 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
18 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
19 r = 12742 * numpy.arcsin(numpy.sqrt(a))
19 r = 12742 * numpy.arcsin(numpy.sqrt(a))
20 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
20 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
21 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
21 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
22 theta = -theta + numpy.pi/2
22 theta = -theta + numpy.pi/2
23 return r*numpy.cos(theta), r*numpy.sin(theta)
23 return r*numpy.cos(theta), r*numpy.sin(theta)
24
24
25
25
26 def km2deg(km):
26 def km2deg(km):
27 '''
27 '''
28 Convert distance in km to degrees
28 Convert distance in km to degrees
29 '''
29 '''
30
30
31 return numpy.rad2deg(km/EARTH_RADIUS)
31 return numpy.rad2deg(km/EARTH_RADIUS)
32
32
33
33
34
34
35 class SpectralMomentsPlot(SpectraPlot):
35 class SpectralMomentsPlot(SpectraPlot):
36 '''
36 '''
37 Plot for Spectral Moments
37 Plot for Spectral Moments
38 '''
38 '''
39 CODE = 'spc_moments'
39 CODE = 'spc_moments'
40 # colormap = 'jet'
40 # colormap = 'jet'
41 # plot_type = 'pcolor'
41 # plot_type = 'pcolor'
42
42
43 class DobleGaussianPlot(SpectraPlot):
43 class DobleGaussianPlot(SpectraPlot):
44 '''
44 '''
45 Plot for Double Gaussian Plot
45 Plot for Double Gaussian Plot
46 '''
46 '''
47 CODE = 'gaussian_fit'
47 CODE = 'gaussian_fit'
48 # colormap = 'jet'
48 # colormap = 'jet'
49 # plot_type = 'pcolor'
49 # plot_type = 'pcolor'
50
50
51 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
51 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
52 '''
52 '''
53 Plot SpectraCut with Double Gaussian Fit
53 Plot SpectraCut with Double Gaussian Fit
54 '''
54 '''
55 CODE = 'cut_gaussian_fit'
55 CODE = 'cut_gaussian_fit'
56
56
57 class SnrPlot(RTIPlot):
57 class SnrPlot(RTIPlot):
58 '''
58 '''
59 Plot for SNR Data
59 Plot for SNR Data
60 '''
60 '''
61
61
62 CODE = 'snr'
62 CODE = 'snr'
63 colormap = 'jet'
63 colormap = 'jet'
64
64
65 def update(self, dataOut):
65 def update(self, dataOut):
66
66
67 data = {
67 data = {
68 'snr': 10*numpy.log10(dataOut.data_snr)
68 'snr': 10*numpy.log10(dataOut.data_snr)
69 }
69 }
70
70
71 return data, {}
71 return data, {}
72
72
73 class DopplerPlot(RTIPlot):
73 class DopplerPlot(RTIPlot):
74 '''
74 '''
75 Plot for DOPPLER Data (1st moment)
75 Plot for DOPPLER Data (1st moment)
76 '''
76 '''
77
77
78 CODE = 'dop'
78 CODE = 'dop'
79 colormap = 'jet'
79 colormap = 'jet'
80
80
81 def update(self, dataOut):
81 def update(self, dataOut):
82
82
83 data = {
83 data = {
84 'dop': 10*numpy.log10(dataOut.data_dop)
84 'dop': 10*numpy.log10(dataOut.data_dop)
85 }
85 }
86
86
87 return data, {}
87 return data, {}
88
88
89 class PowerPlot(RTIPlot):
89 class PowerPlot(RTIPlot):
90 '''
90 '''
91 Plot for Power Data (0 moment)
91 Plot for Power Data (0 moment)
92 '''
92 '''
93
93
94 CODE = 'pow'
94 CODE = 'pow'
95 colormap = 'jet'
95 colormap = 'jet'
96
96
97 def update(self, dataOut):
97 def update(self, dataOut):
98 data = {
98 data = {
99 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
99 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
100 }
100 }
101 return data, {}
101 return data, {}
102
102
103 class SpectralWidthPlot(RTIPlot):
103 class SpectralWidthPlot(RTIPlot):
104 '''
104 '''
105 Plot for Spectral Width Data (2nd moment)
105 Plot for Spectral Width Data (2nd moment)
106 '''
106 '''
107
107
108 CODE = 'width'
108 CODE = 'width'
109 colormap = 'jet'
109 colormap = 'jet'
110
110
111 def update(self, dataOut):
111 def update(self, dataOut):
112
112
113 data = {
113 data = {
114 'width': dataOut.data_width
114 'width': dataOut.data_width
115 }
115 }
116
116
117 return data, {}
117 return data, {}
118
118
119 class SkyMapPlot(Plot):
119 class SkyMapPlot(Plot):
120 '''
120 '''
121 Plot for meteors detection data
121 Plot for meteors detection data
122 '''
122 '''
123
123
124 CODE = 'param'
124 CODE = 'param'
125
125
126 def setup(self):
126 def setup(self):
127
127
128 self.ncols = 1
128 self.ncols = 1
129 self.nrows = 1
129 self.nrows = 1
130 self.width = 7.2
130 self.width = 7.2
131 self.height = 7.2
131 self.height = 7.2
132 self.nplots = 1
132 self.nplots = 1
133 self.xlabel = 'Zonal Zenith Angle (deg)'
133 self.xlabel = 'Zonal Zenith Angle (deg)'
134 self.ylabel = 'Meridional Zenith Angle (deg)'
134 self.ylabel = 'Meridional Zenith Angle (deg)'
135 self.polar = True
135 self.polar = True
136 self.ymin = -180
136 self.ymin = -180
137 self.ymax = 180
137 self.ymax = 180
138 self.colorbar = False
138 self.colorbar = False
139
139
140 def plot(self):
140 def plot(self):
141
141
142 arrayParameters = numpy.concatenate(self.data['param'])
142 arrayParameters = numpy.concatenate(self.data['param'])
143 error = arrayParameters[:, -1]
143 error = arrayParameters[:, -1]
144 indValid = numpy.where(error == 0)[0]
144 indValid = numpy.where(error == 0)[0]
145 finalMeteor = arrayParameters[indValid, :]
145 finalMeteor = arrayParameters[indValid, :]
146 finalAzimuth = finalMeteor[:, 3]
146 finalAzimuth = finalMeteor[:, 3]
147 finalZenith = finalMeteor[:, 4]
147 finalZenith = finalMeteor[:, 4]
148
148
149 x = finalAzimuth * numpy.pi / 180
149 x = finalAzimuth * numpy.pi / 180
150 y = finalZenith
150 y = finalZenith
151
151
152 ax = self.axes[0]
152 ax = self.axes[0]
153
153
154 if ax.firsttime:
154 if ax.firsttime:
155 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
155 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
156 else:
156 else:
157 ax.plot.set_data(x, y)
157 ax.plot.set_data(x, y)
158
158
159 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
159 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
160 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
160 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
161 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
161 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
162 dt2,
162 dt2,
163 len(x))
163 len(x))
164 self.titles[0] = title
164 self.titles[0] = title
165
165
166
166
167 class GenericRTIPlot(Plot):
167 class GenericRTIPlot(Plot):
168 '''
168 '''
169 Plot for data_xxxx object
169 Plot for data_xxxx object
170 '''
170 '''
171
171
172 CODE = 'param'
172 CODE = 'param'
173 colormap = 'viridis'
173 colormap = 'viridis'
174 plot_type = 'pcolorbuffer'
174 plot_type = 'pcolorbuffer'
175
175
176 def setup(self):
176 def setup(self):
177 self.xaxis = 'time'
177 self.xaxis = 'time'
178 self.ncols = 1
178 self.ncols = 1
179 self.nrows = self.data.shape('param')[0]
179 self.nrows = self.data.shape('param')[0]
180 self.nplots = self.nrows
180 self.nplots = self.nrows
181 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
181 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
182
182
183 if not self.xlabel:
183 if not self.xlabel:
184 self.xlabel = 'Time'
184 self.xlabel = 'Time'
185
185
186 self.ylabel = 'Range [km]'
186 self.ylabel = 'Range [km]'
187 if not self.titles:
187 if not self.titles:
188 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
188 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
189
189
190 def update(self, dataOut):
190 def update(self, dataOut):
191
191
192 data = {
192 data = {
193 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
193 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
194 }
194 }
195
195
196 meta = {}
196 meta = {}
197
197
198 return data, meta
198 return data, meta
199
199
200 def plot(self):
200 def plot(self):
201 # self.data.normalize_heights()
201 # self.data.normalize_heights()
202 self.x = self.data.times
202 self.x = self.data.times
203 self.y = self.data.yrange
203 self.y = self.data.yrange
204 self.z = self.data['param']
204 self.z = self.data['param']
205 self.z = 10*numpy.log10(self.z)
205 self.z = 10*numpy.log10(self.z)
206 self.z = numpy.ma.masked_invalid(self.z)
206 self.z = numpy.ma.masked_invalid(self.z)
207
207
208 if self.decimation is None:
208 if self.decimation is None:
209 x, y, z = self.fill_gaps(self.x, self.y, self.z)
209 x, y, z = self.fill_gaps(self.x, self.y, self.z)
210 else:
210 else:
211 x, y, z = self.fill_gaps(*self.decimate())
211 x, y, z = self.fill_gaps(*self.decimate())
212
212
213 for n, ax in enumerate(self.axes):
213 for n, ax in enumerate(self.axes):
214
214
215 self.zmax = self.zmax if self.zmax is not None else numpy.max(
215 self.zmax = self.zmax if self.zmax is not None else numpy.max(
216 self.z[n])
216 self.z[n])
217 self.zmin = self.zmin if self.zmin is not None else numpy.min(
217 self.zmin = self.zmin if self.zmin is not None else numpy.min(
218 self.z[n])
218 self.z[n])
219
219
220 if ax.firsttime:
220 if ax.firsttime:
221 if self.zlimits is not None:
221 if self.zlimits is not None:
222 self.zmin, self.zmax = self.zlimits[n]
222 self.zmin, self.zmax = self.zlimits[n]
223
223
224 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
224 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
225 vmin=self.zmin,
225 vmin=self.zmin,
226 vmax=self.zmax,
226 vmax=self.zmax,
227 cmap=self.cmaps[n]
227 cmap=self.cmaps[n]
228 )
228 )
229 else:
229 else:
230 if self.zlimits is not None:
230 if self.zlimits is not None:
231 self.zmin, self.zmax = self.zlimits[n]
231 self.zmin, self.zmax = self.zlimits[n]
232 ax.collections.remove(ax.collections[0])
232 ax.collections.remove(ax.collections[0])
233 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
233 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
234 vmin=self.zmin,
234 vmin=self.zmin,
235 vmax=self.zmax,
235 vmax=self.zmax,
236 cmap=self.cmaps[n]
236 cmap=self.cmaps[n]
237 )
237 )
238
238
239
239
240 class PolarMapPlot(Plot):
240 class PolarMapPlot(Plot):
241 '''
241 '''
242 Plot for weather radar
242 Plot for weather radar
243 '''
243 '''
244
244
245 CODE = 'param'
245 CODE = 'param'
246 colormap = 'seismic'
246 colormap = 'seismic'
247
247
248 def setup(self):
248 def setup(self):
249 self.ncols = 1
249 self.ncols = 1
250 self.nrows = 1
250 self.nrows = 1
251 self.width = 9
251 self.width = 9
252 self.height = 8
252 self.height = 8
253 self.mode = self.data.meta['mode']
253 self.mode = self.data.meta['mode']
254 if self.channels is not None:
254 if self.channels is not None:
255 self.nplots = len(self.channels)
255 self.nplots = len(self.channels)
256 self.nrows = len(self.channels)
256 self.nrows = len(self.channels)
257 else:
257 else:
258 self.nplots = self.data.shape(self.CODE)[0]
258 self.nplots = self.data.shape(self.CODE)[0]
259 self.nrows = self.nplots
259 self.nrows = self.nplots
260 self.channels = list(range(self.nplots))
260 self.channels = list(range(self.nplots))
261 if self.mode == 'E':
261 if self.mode == 'E':
262 self.xlabel = 'Longitude'
262 self.xlabel = 'Longitude'
263 self.ylabel = 'Latitude'
263 self.ylabel = 'Latitude'
264 else:
264 else:
265 self.xlabel = 'Range (km)'
265 self.xlabel = 'Range (km)'
266 self.ylabel = 'Height (km)'
266 self.ylabel = 'Height (km)'
267 self.bgcolor = 'white'
267 self.bgcolor = 'white'
268 self.cb_labels = self.data.meta['units']
268 self.cb_labels = self.data.meta['units']
269 self.lat = self.data.meta['latitude']
269 self.lat = self.data.meta['latitude']
270 self.lon = self.data.meta['longitude']
270 self.lon = self.data.meta['longitude']
271 self.xmin, self.xmax = float(
271 self.xmin, self.xmax = float(
272 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
272 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
273 self.ymin, self.ymax = float(
273 self.ymin, self.ymax = float(
274 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
274 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
275 # self.polar = True
275 # self.polar = True
276
276
277 def plot(self):
277 def plot(self):
278
278
279 for n, ax in enumerate(self.axes):
279 for n, ax in enumerate(self.axes):
280 data = self.data['param'][self.channels[n]]
280 data = self.data['param'][self.channels[n]]
281
281
282 zeniths = numpy.linspace(
282 zeniths = numpy.linspace(
283 0, self.data.meta['max_range'], data.shape[1])
283 0, self.data.meta['max_range'], data.shape[1])
284 if self.mode == 'E':
284 if self.mode == 'E':
285 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
285 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
286 r, theta = numpy.meshgrid(zeniths, azimuths)
286 r, theta = numpy.meshgrid(zeniths, azimuths)
287 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
287 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
288 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
288 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
289 x = km2deg(x) + self.lon
289 x = km2deg(x) + self.lon
290 y = km2deg(y) + self.lat
290 y = km2deg(y) + self.lat
291 else:
291 else:
292 azimuths = numpy.radians(self.data.yrange)
292 azimuths = numpy.radians(self.data.yrange)
293 r, theta = numpy.meshgrid(zeniths, azimuths)
293 r, theta = numpy.meshgrid(zeniths, azimuths)
294 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
294 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
295 self.y = zeniths
295 self.y = zeniths
296
296
297 if ax.firsttime:
297 if ax.firsttime:
298 if self.zlimits is not None:
298 if self.zlimits is not None:
299 self.zmin, self.zmax = self.zlimits[n]
299 self.zmin, self.zmax = self.zlimits[n]
300 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
300 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
301 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
301 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
302 vmin=self.zmin,
302 vmin=self.zmin,
303 vmax=self.zmax,
303 vmax=self.zmax,
304 cmap=self.cmaps[n])
304 cmap=self.cmaps[n])
305 else:
305 else:
306 if self.zlimits is not None:
306 if self.zlimits is not None:
307 self.zmin, self.zmax = self.zlimits[n]
307 self.zmin, self.zmax = self.zlimits[n]
308 ax.collections.remove(ax.collections[0])
308 ax.collections.remove(ax.collections[0])
309 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
309 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
310 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
310 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
311 vmin=self.zmin,
311 vmin=self.zmin,
312 vmax=self.zmax,
312 vmax=self.zmax,
313 cmap=self.cmaps[n])
313 cmap=self.cmaps[n])
314
314
315 if self.mode == 'A':
315 if self.mode == 'A':
316 continue
316 continue
317
317
318 # plot district names
318 # plot district names
319 f = open('/data/workspace/schain_scripts/distrito.csv')
319 f = open('/data/workspace/schain_scripts/distrito.csv')
320 for line in f:
320 for line in f:
321 label, lon, lat = [s.strip() for s in line.split(',') if s]
321 label, lon, lat = [s.strip() for s in line.split(',') if s]
322 lat = float(lat)
322 lat = float(lat)
323 lon = float(lon)
323 lon = float(lon)
324 # ax.plot(lon, lat, '.b', ms=2)
324 # ax.plot(lon, lat, '.b', ms=2)
325 ax.text(lon, lat, label.decode('utf8'), ha='center',
325 ax.text(lon, lat, label.decode('utf8'), ha='center',
326 va='bottom', size='8', color='black')
326 va='bottom', size='8', color='black')
327
327
328 # plot limites
328 # plot limites
329 limites = []
329 limites = []
330 tmp = []
330 tmp = []
331 for line in open('/data/workspace/schain_scripts/lima.csv'):
331 for line in open('/data/workspace/schain_scripts/lima.csv'):
332 if '#' in line:
332 if '#' in line:
333 if tmp:
333 if tmp:
334 limites.append(tmp)
334 limites.append(tmp)
335 tmp = []
335 tmp = []
336 continue
336 continue
337 values = line.strip().split(',')
337 values = line.strip().split(',')
338 tmp.append((float(values[0]), float(values[1])))
338 tmp.append((float(values[0]), float(values[1])))
339 for points in limites:
339 for points in limites:
340 ax.add_patch(
340 ax.add_patch(
341 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
341 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
342
342
343 # plot Cuencas
343 # plot Cuencas
344 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
344 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
345 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
345 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
346 values = [line.strip().split(',') for line in f]
346 values = [line.strip().split(',') for line in f]
347 points = [(float(s[0]), float(s[1])) for s in values]
347 points = [(float(s[0]), float(s[1])) for s in values]
348 ax.add_patch(Polygon(points, ec='b', fc='none'))
348 ax.add_patch(Polygon(points, ec='b', fc='none'))
349
349
350 # plot grid
350 # plot grid
351 for r in (15, 30, 45, 60):
351 for r in (15, 30, 45, 60):
352 ax.add_artist(plt.Circle((self.lon, self.lat),
352 ax.add_artist(plt.Circle((self.lon, self.lat),
353 km2deg(r), color='0.6', fill=False, lw=0.2))
353 km2deg(r), color='0.6', fill=False, lw=0.2))
354 ax.text(
354 ax.text(
355 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
355 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
356 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
356 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
357 '{}km'.format(r),
357 '{}km'.format(r),
358 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
358 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
359
359
360 if self.mode == 'E':
360 if self.mode == 'E':
361 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
361 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
362 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
362 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
363 else:
363 else:
364 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
364 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
365 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
365 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
366
366
367 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
367 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
368 self.titles = ['{} {}'.format(
368 self.titles = ['{} {}'.format(
369 self.data.parameters[x], title) for x in self.channels]
369 self.data.parameters[x], title) for x in self.channels]
370
370
371 class WeatherPlot(Plot):
371 class WeatherPlot(Plot):
372 CODE = 'weather'
372 CODE = 'weather'
373 plot_name = 'weather'
373 plot_name = 'weather'
374 plot_type = 'ppistyle'
374 plot_type = 'ppistyle'
375 buffering = False
375 buffering = False
376
376
377 def setup(self):
377 def setup(self):
378 self.ncols = 1
378 self.ncols = 1
379 self.nrows = 1
379 self.nrows = 1
380 self.nplots= 1
380 self.nplots= 1
381 self.ylabel= 'Range [Km]'
381 self.ylabel= 'Range [Km]'
382 self.titles= ['Weather']
382 self.titles= ['Weather']
383 self.colorbar=False
383 self.colorbar=False
384 self.width =8
384 self.width =8
385 self.height =8
385 self.height =8
386 self.ini =0
386 self.ini =0
387 self.len_azi =0
387 self.len_azi =0
388 self.buffer_ini = None
388 self.buffer_ini = None
389 self.buffer_azi = None
389 self.buffer_azi = None
390 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
390 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
391 self.flag =0
391 self.flag =0
392 self.indicador= 0
392 self.indicador= 0
393
393
394 def update(self, dataOut):
394 def update(self, dataOut):
395
395
396 data = {}
396 data = {}
397 meta = {}
397 meta = {}
398 if hasattr(dataOut, 'dataPP_POWER'):
398 if hasattr(dataOut, 'dataPP_POWER'):
399 factor = 1
399 factor = 1
400
400
401 if hasattr(dataOut, 'nFFTPoints'):
401 if hasattr(dataOut, 'nFFTPoints'):
402 factor = dataOut.normFactor
402 factor = dataOut.normFactor
403
403
404 print("factor",factor)
404 ####print("factor",factor)
405 data['weather'] = 10*numpy.log10(dataOut.data_360[0]/(factor))
405 data['weather'] = 10*numpy.log10(dataOut.data_360[0]/(factor))
406 print("weather",data['weather'])
406 print("weather",data['weather'])
407 data['azi'] = dataOut.data_azi
407 data['azi'] = dataOut.data_azi
408 return data, meta
408 return data, meta
409
409
410 def const_ploteo(self,data_weather,data_azi,step,res):
410 def const_ploteo(self,data_weather,data_azi,step,res):
411 if self.ini==0:
411 if self.ini==0:
412 #------- AZIMUTH
412 #------- AZIMUTH
413 n = (360/res)-len(data_azi)
413 n = (360/res)-len(data_azi)
414 start = data_azi[-1] + res
414 start = data_azi[-1] + res
415 end = data_azi[0] - res
415 end = data_azi[0] - res
416 if start>end:
416 if start>end:
417 end = end + 360
417 end = end + 360
418 azi_vacia = numpy.linspace(start,end,int(n))
418 azi_vacia = numpy.linspace(start,end,int(n))
419 azi_vacia = numpy.where(azi_vacia>360,azi_vacia-360,azi_vacia)
419 azi_vacia = numpy.where(azi_vacia>360,azi_vacia-360,azi_vacia)
420 data_azi = numpy.hstack((data_azi,azi_vacia))
420 data_azi = numpy.hstack((data_azi,azi_vacia))
421 # RADAR
421 # RADAR
422 val_mean = numpy.mean(data_weather[:,0])
422 val_mean = numpy.mean(data_weather[:,0])
423 data_weather_cmp = numpy.ones([(360-data_weather.shape[0]),data_weather.shape[1]])*val_mean
423 data_weather_cmp = numpy.ones([(360-data_weather.shape[0]),data_weather.shape[1]])*val_mean
424 data_weather = numpy.vstack((data_weather,data_weather_cmp))
424 data_weather = numpy.vstack((data_weather,data_weather_cmp))
425 else:
425 else:
426 # azimuth
426 # azimuth
427 flag=0
427 flag=0
428 start_azi = self.res_azi[0]
428 start_azi = self.res_azi[0]
429 start = data_azi[0]
429 start = data_azi[0]
430 end = data_azi[-1]
430 end = data_azi[-1]
431 print("start",start)
431 print("start",start)
432 print("end",end)
432 print("end",end)
433 if start< start_azi:
433 if start< start_azi:
434 start = start +360
434 start = start +360
435 if end <start_azi:
435 if end <start_azi:
436 end = end +360
436 end = end +360
437
437
438 print("start",start)
438 print("start",start)
439 print("end",end)
439 print("end",end)
440 #### AQUI SERA LA MAGIA
440 #### AQUI SERA LA MAGIA
441 pos_ini = int((start-start_azi)/res)
441 pos_ini = int((start-start_azi)/res)
442 len_azi = len(data_azi)
442 len_azi = len(data_azi)
443 if (360-pos_ini)<len_azi:
443 if (360-pos_ini)<len_azi:
444 if pos_ini+1==360:
444 if pos_ini+1==360:
445 pos_ini=0
445 pos_ini=0
446 else:
446 else:
447 flag=1
447 flag=1
448 dif= 360-pos_ini
448 dif= 360-pos_ini
449 comp= len_azi-dif
449 comp= len_azi-dif
450
450
451 print(pos_ini)
451 print(pos_ini)
452 print(len_azi)
452 print(len_azi)
453 print("shape",self.res_azi.shape)
453 print("shape",self.res_azi.shape)
454 if flag==0:
454 if flag==0:
455 # AZIMUTH
455 # AZIMUTH
456 self.res_azi[pos_ini:pos_ini+len_azi] = data_azi
456 self.res_azi[pos_ini:pos_ini+len_azi] = data_azi
457 # RADAR
457 # RADAR
458 self.res_weather[pos_ini:pos_ini+len_azi,:] = data_weather
458 self.res_weather[pos_ini:pos_ini+len_azi,:] = data_weather
459 else:
459 else:
460 # AZIMUTH
460 # AZIMUTH
461 self.res_azi[pos_ini:pos_ini+dif] = data_azi[0:dif]
461 self.res_azi[pos_ini:pos_ini+dif] = data_azi[0:dif]
462 self.res_azi[0:comp] = data_azi[dif:]
462 self.res_azi[0:comp] = data_azi[dif:]
463 # RADAR
463 # RADAR
464 self.res_weather[pos_ini:pos_ini+dif,:] = data_weather[0:dif,:]
464 self.res_weather[pos_ini:pos_ini+dif,:] = data_weather[0:dif,:]
465 self.res_weather[0:comp,:] = data_weather[dif:,:]
465 self.res_weather[0:comp,:] = data_weather[dif:,:]
466 flag=0
466 flag=0
467 data_azi = self.res_azi
467 data_azi = self.res_azi
468 data_weather = self.res_weather
468 data_weather = self.res_weather
469
469
470 return data_weather,data_azi
470 return data_weather,data_azi
471
471
472 def plot(self):
472 def plot(self):
473 print("--------------------------------------",self.ini,"-----------------------------------")
473 print("--------------------------------------",self.ini,"-----------------------------------")
474 #numpy.set_printoptions(suppress=True)
474 #numpy.set_printoptions(suppress=True)
475 #print(self.data.times)
475 #print(self.data.times)
476 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
476 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
477 data = self.data[-1]
477 data = self.data[-1]
478 # ALTURA altura_tmp_h
478 # ALTURA altura_tmp_h
479 altura_h = (data['weather'].shape[1])/10.0
479 altura_h = (data['weather'].shape[1])/10.0
480 stoprange = float(altura_h*1.5)#stoprange = float(33*1.5) por ahora 400
480 stoprange = float(altura_h*1.5)#stoprange = float(33*1.5) por ahora 400
481 rangestep = float(0.15)
481 rangestep = float(0.15)
482 r = numpy.arange(0, stoprange, rangestep)
482 r = numpy.arange(0, stoprange, rangestep)
483 self.y = 2*r
483 self.y = 2*r
484 # RADAR
484 # RADAR
485 #data_weather = data['weather']
485 #data_weather = data['weather']
486 # PEDESTAL
486 # PEDESTAL
487 #data_azi = data['azi']
487 #data_azi = data['azi']
488 res = 1
488 res = 1
489 # STEP
489 # STEP
490 step = (360/(res*data['weather'].shape[0]))
490 step = (360/(res*data['weather'].shape[0]))
491 #print("shape wr_data", wr_data.shape)
491 #print("shape wr_data", wr_data.shape)
492 #print("shape wr_azi",wr_azi.shape)
492 #print("shape wr_azi",wr_azi.shape)
493 #print("step",step)
493 #print("step",step)
494 print("Time---->",self.data.times[-1],thisDatetime)
494 print("Time---->",self.data.times[-1],thisDatetime)
495 #print("alturas", len(self.y))
495 #print("alturas", len(self.y))
496 self.res_weather, self.res_azi = self.const_ploteo(data_weather=data['weather'],data_azi=data['azi'],step=step,res=res)
496 self.res_weather, self.res_azi = self.const_ploteo(data_weather=data['weather'],data_azi=data['azi'],step=step,res=res)
497 #numpy.set_printoptions(suppress=True)
497 #numpy.set_printoptions(suppress=True)
498 #print("resultado",self.res_azi)
498 #print("resultado",self.res_azi)
499 ##########################################################
499 ##########################################################
500 ################# PLOTEO ###################
500 ################# PLOTEO ###################
501 ##########################################################
501 ##########################################################
502
502
503 for i,ax in enumerate(self.axes):
503 for i,ax in enumerate(self.axes):
504 if ax.firsttime:
504 if ax.firsttime:
505 plt.clf()
505 plt.clf()
506 cgax, pm = wrl.vis.plot_ppi(self.res_weather,r=r,az=self.res_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
506 cgax, pm = wrl.vis.plot_ppi(self.res_weather,r=r,az=self.res_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
507 else:
507 else:
508 plt.clf()
508 plt.clf()
509 cgax, pm = wrl.vis.plot_ppi(self.res_weather,r=r,az=self.res_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
509 cgax, pm = wrl.vis.plot_ppi(self.res_weather,r=r,az=self.res_azi,fig=self.figures[0], proj='cg', vmin=1, vmax=60)
510 caax = cgax.parasites[0]
510 caax = cgax.parasites[0]
511 paax = cgax.parasites[1]
511 paax = cgax.parasites[1]
512 cbar = plt.gcf().colorbar(pm, pad=0.075)
512 cbar = plt.gcf().colorbar(pm, pad=0.075)
513 caax.set_xlabel('x_range [km]')
513 caax.set_xlabel('x_range [km]')
514 caax.set_ylabel('y_range [km]')
514 caax.set_ylabel('y_range [km]')
515 plt.text(1.0, 1.05, 'azimuth '+str(thisDatetime)+"step"+str(self.ini), transform=caax.transAxes, va='bottom',ha='right')
515 plt.text(1.0, 1.05, 'azimuth '+str(thisDatetime)+"step"+str(self.ini), transform=caax.transAxes, va='bottom',ha='right')
516
516
517 self.ini= self.ini+1
517 self.ini= self.ini+1
@@ -1,4473 +1,4473
1 import numpy,os,h5py
1 import numpy,os,h5py
2 import math
2 import math
3 from scipy import optimize, interpolate, signal, stats, ndimage
3 from scipy import optimize, interpolate, signal, stats, ndimage
4 import scipy
4 import scipy
5 import re
5 import re
6 import datetime
6 import datetime
7 import copy
7 import copy
8 import sys
8 import sys
9 import importlib
9 import importlib
10 import itertools
10 import itertools
11 from multiprocessing import Pool, TimeoutError
11 from multiprocessing import Pool, TimeoutError
12 from multiprocessing.pool import ThreadPool
12 from multiprocessing.pool import ThreadPool
13 import time
13 import time
14
14
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 from scipy import asarray as ar,exp
18 from scipy import asarray as ar,exp
19 from scipy.optimize import curve_fit
19 from scipy.optimize import curve_fit
20 from schainpy.utils import log
20 from schainpy.utils import log
21 import warnings
21 import warnings
22 from numpy import NaN
22 from numpy import NaN
23 from scipy.optimize.optimize import OptimizeWarning
23 from scipy.optimize.optimize import OptimizeWarning
24 warnings.filterwarnings('ignore')
24 warnings.filterwarnings('ignore')
25
25
26 import matplotlib.pyplot as plt
26 import matplotlib.pyplot as plt
27
27
28 SPEED_OF_LIGHT = 299792458
28 SPEED_OF_LIGHT = 299792458
29
29
30 '''solving pickling issue'''
30 '''solving pickling issue'''
31
31
32 def _pickle_method(method):
32 def _pickle_method(method):
33 func_name = method.__func__.__name__
33 func_name = method.__func__.__name__
34 obj = method.__self__
34 obj = method.__self__
35 cls = method.__self__.__class__
35 cls = method.__self__.__class__
36 return _unpickle_method, (func_name, obj, cls)
36 return _unpickle_method, (func_name, obj, cls)
37
37
38 def _unpickle_method(func_name, obj, cls):
38 def _unpickle_method(func_name, obj, cls):
39 for cls in cls.mro():
39 for cls in cls.mro():
40 try:
40 try:
41 func = cls.__dict__[func_name]
41 func = cls.__dict__[func_name]
42 except KeyError:
42 except KeyError:
43 pass
43 pass
44 else:
44 else:
45 break
45 break
46 return func.__get__(obj, cls)
46 return func.__get__(obj, cls)
47
47
48 def isNumber(str):
48 def isNumber(str):
49 try:
49 try:
50 float(str)
50 float(str)
51 return True
51 return True
52 except:
52 except:
53 return False
53 return False
54
54
55 class ParametersProc(ProcessingUnit):
55 class ParametersProc(ProcessingUnit):
56
56
57 METHODS = {}
57 METHODS = {}
58 nSeconds = None
58 nSeconds = None
59
59
60 def __init__(self):
60 def __init__(self):
61 ProcessingUnit.__init__(self)
61 ProcessingUnit.__init__(self)
62
62
63 # self.objectDict = {}
63 # self.objectDict = {}
64 self.buffer = None
64 self.buffer = None
65 self.firstdatatime = None
65 self.firstdatatime = None
66 self.profIndex = 0
66 self.profIndex = 0
67 self.dataOut = Parameters()
67 self.dataOut = Parameters()
68 self.setupReq = False #Agregar a todas las unidades de proc
68 self.setupReq = False #Agregar a todas las unidades de proc
69
69
70 def __updateObjFromInput(self):
70 def __updateObjFromInput(self):
71
71
72 self.dataOut.inputUnit = self.dataIn.type
72 self.dataOut.inputUnit = self.dataIn.type
73
73
74 self.dataOut.timeZone = self.dataIn.timeZone
74 self.dataOut.timeZone = self.dataIn.timeZone
75 self.dataOut.dstFlag = self.dataIn.dstFlag
75 self.dataOut.dstFlag = self.dataIn.dstFlag
76 self.dataOut.errorCount = self.dataIn.errorCount
76 self.dataOut.errorCount = self.dataIn.errorCount
77 self.dataOut.useLocalTime = self.dataIn.useLocalTime
77 self.dataOut.useLocalTime = self.dataIn.useLocalTime
78
78
79 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
79 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
80 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
80 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
81 self.dataOut.channelList = self.dataIn.channelList
81 self.dataOut.channelList = self.dataIn.channelList
82 self.dataOut.heightList = self.dataIn.heightList
82 self.dataOut.heightList = self.dataIn.heightList
83 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
83 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
84 # self.dataOut.nHeights = self.dataIn.nHeights
84 # self.dataOut.nHeights = self.dataIn.nHeights
85 # self.dataOut.nChannels = self.dataIn.nChannels
85 # self.dataOut.nChannels = self.dataIn.nChannels
86 # self.dataOut.nBaud = self.dataIn.nBaud
86 # self.dataOut.nBaud = self.dataIn.nBaud
87 # self.dataOut.nCode = self.dataIn.nCode
87 # self.dataOut.nCode = self.dataIn.nCode
88 # self.dataOut.code = self.dataIn.code
88 # self.dataOut.code = self.dataIn.code
89 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
89 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
90 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
90 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
91 # self.dataOut.utctime = self.firstdatatime
91 # self.dataOut.utctime = self.firstdatatime
92 self.dataOut.utctime = self.dataIn.utctime
92 self.dataOut.utctime = self.dataIn.utctime
93 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
93 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
94 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
94 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
95 self.dataOut.nCohInt = self.dataIn.nCohInt
95 self.dataOut.nCohInt = self.dataIn.nCohInt
96 # self.dataOut.nIncohInt = 1
96 # self.dataOut.nIncohInt = 1
97 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
97 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
98 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
98 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
99 self.dataOut.timeInterval1 = self.dataIn.timeInterval
99 self.dataOut.timeInterval1 = self.dataIn.timeInterval
100 self.dataOut.heightList = self.dataIn.heightList
100 self.dataOut.heightList = self.dataIn.heightList
101 self.dataOut.frequency = self.dataIn.frequency
101 self.dataOut.frequency = self.dataIn.frequency
102 # self.dataOut.noise = self.dataIn.noise
102 # self.dataOut.noise = self.dataIn.noise
103
103
104 def run(self):
104 def run(self):
105
105
106
106
107 #print("HOLA MUNDO SOY YO")
107 #print("HOLA MUNDO SOY YO")
108 #---------------------- Voltage Data ---------------------------
108 #---------------------- Voltage Data ---------------------------
109
109
110 if self.dataIn.type == "Voltage":
110 if self.dataIn.type == "Voltage":
111
111
112 self.__updateObjFromInput()
112 self.__updateObjFromInput()
113 self.dataOut.data_pre = self.dataIn.data.copy()
113 self.dataOut.data_pre = self.dataIn.data.copy()
114 self.dataOut.flagNoData = False
114 self.dataOut.flagNoData = False
115 self.dataOut.utctimeInit = self.dataIn.utctime
115 self.dataOut.utctimeInit = self.dataIn.utctime
116 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
116 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
117
117
118 if hasattr(self.dataIn, 'flagDataAsBlock'):
118 if hasattr(self.dataIn, 'flagDataAsBlock'):
119 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
119 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
120
120
121 if hasattr(self.dataIn, 'profileIndex'):
121 if hasattr(self.dataIn, 'profileIndex'):
122 self.dataOut.profileIndex = self.dataIn.profileIndex
122 self.dataOut.profileIndex = self.dataIn.profileIndex
123
123
124 if hasattr(self.dataIn, 'dataPP_POW'):
124 if hasattr(self.dataIn, 'dataPP_POW'):
125 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
125 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
126
126
127 if hasattr(self.dataIn, 'dataPP_POWER'):
127 if hasattr(self.dataIn, 'dataPP_POWER'):
128 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
128 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
129
129
130 if hasattr(self.dataIn, 'dataPP_DOP'):
130 if hasattr(self.dataIn, 'dataPP_DOP'):
131 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
131 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
132
132
133 if hasattr(self.dataIn, 'dataPP_SNR'):
133 if hasattr(self.dataIn, 'dataPP_SNR'):
134 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
134 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
135
135
136 if hasattr(self.dataIn, 'dataPP_WIDTH'):
136 if hasattr(self.dataIn, 'dataPP_WIDTH'):
137 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
137 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
138 return
138 return
139
139
140 #---------------------- Spectra Data ---------------------------
140 #---------------------- Spectra Data ---------------------------
141
141
142 if self.dataIn.type == "Spectra":
142 if self.dataIn.type == "Spectra":
143 #print("que paso en spectra")
143 #print("que paso en spectra")
144 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
144 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
145 self.dataOut.data_spc = self.dataIn.data_spc
145 self.dataOut.data_spc = self.dataIn.data_spc
146 self.dataOut.data_cspc = self.dataIn.data_cspc
146 self.dataOut.data_cspc = self.dataIn.data_cspc
147 self.dataOut.nProfiles = self.dataIn.nProfiles
147 self.dataOut.nProfiles = self.dataIn.nProfiles
148 self.dataOut.nIncohInt = self.dataIn.nIncohInt
148 self.dataOut.nIncohInt = self.dataIn.nIncohInt
149 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
149 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
150 self.dataOut.ippFactor = self.dataIn.ippFactor
150 self.dataOut.ippFactor = self.dataIn.ippFactor
151 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
151 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
152 self.dataOut.spc_noise = self.dataIn.getNoise()
152 self.dataOut.spc_noise = self.dataIn.getNoise()
153 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
153 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
154 # self.dataOut.normFactor = self.dataIn.normFactor
154 # self.dataOut.normFactor = self.dataIn.normFactor
155 self.dataOut.pairsList = self.dataIn.pairsList
155 self.dataOut.pairsList = self.dataIn.pairsList
156 self.dataOut.groupList = self.dataIn.pairsList
156 self.dataOut.groupList = self.dataIn.pairsList
157 self.dataOut.flagNoData = False
157 self.dataOut.flagNoData = False
158
158
159 if hasattr(self.dataIn, 'flagDataAsBlock'):
159 if hasattr(self.dataIn, 'flagDataAsBlock'):
160 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
160 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
161
161
162 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
162 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
163 self.dataOut.ChanDist = self.dataIn.ChanDist
163 self.dataOut.ChanDist = self.dataIn.ChanDist
164 else: self.dataOut.ChanDist = None
164 else: self.dataOut.ChanDist = None
165
165
166 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
166 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
167 # self.dataOut.VelRange = self.dataIn.VelRange
167 # self.dataOut.VelRange = self.dataIn.VelRange
168 #else: self.dataOut.VelRange = None
168 #else: self.dataOut.VelRange = None
169
169
170 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
170 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
171 self.dataOut.RadarConst = self.dataIn.RadarConst
171 self.dataOut.RadarConst = self.dataIn.RadarConst
172
172
173 if hasattr(self.dataIn, 'NPW'): #NPW
173 if hasattr(self.dataIn, 'NPW'): #NPW
174 self.dataOut.NPW = self.dataIn.NPW
174 self.dataOut.NPW = self.dataIn.NPW
175
175
176 if hasattr(self.dataIn, 'COFA'): #COFA
176 if hasattr(self.dataIn, 'COFA'): #COFA
177 self.dataOut.COFA = self.dataIn.COFA
177 self.dataOut.COFA = self.dataIn.COFA
178
178
179
179
180
180
181 #---------------------- Correlation Data ---------------------------
181 #---------------------- Correlation Data ---------------------------
182
182
183 if self.dataIn.type == "Correlation":
183 if self.dataIn.type == "Correlation":
184 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
184 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
185
185
186 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
186 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
187 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
187 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
188 self.dataOut.groupList = (acf_pairs, ccf_pairs)
188 self.dataOut.groupList = (acf_pairs, ccf_pairs)
189
189
190 self.dataOut.abscissaList = self.dataIn.lagRange
190 self.dataOut.abscissaList = self.dataIn.lagRange
191 self.dataOut.noise = self.dataIn.noise
191 self.dataOut.noise = self.dataIn.noise
192 self.dataOut.data_snr = self.dataIn.SNR
192 self.dataOut.data_snr = self.dataIn.SNR
193 self.dataOut.flagNoData = False
193 self.dataOut.flagNoData = False
194 self.dataOut.nAvg = self.dataIn.nAvg
194 self.dataOut.nAvg = self.dataIn.nAvg
195
195
196 #---------------------- Parameters Data ---------------------------
196 #---------------------- Parameters Data ---------------------------
197
197
198 if self.dataIn.type == "Parameters":
198 if self.dataIn.type == "Parameters":
199 self.dataOut.copy(self.dataIn)
199 self.dataOut.copy(self.dataIn)
200 self.dataOut.flagNoData = False
200 self.dataOut.flagNoData = False
201 #print("yo si entre")
201 #print("yo si entre")
202
202
203 return True
203 return True
204
204
205 self.__updateObjFromInput()
205 self.__updateObjFromInput()
206 #print("yo si entre2")
206 #print("yo si entre2")
207
207
208 self.dataOut.utctimeInit = self.dataIn.utctime
208 self.dataOut.utctimeInit = self.dataIn.utctime
209 self.dataOut.paramInterval = self.dataIn.timeInterval
209 self.dataOut.paramInterval = self.dataIn.timeInterval
210 #print("soy spectra ",self.dataOut.utctimeInit)
210 #print("soy spectra ",self.dataOut.utctimeInit)
211 return
211 return
212
212
213
213
214 def target(tups):
214 def target(tups):
215
215
216 obj, args = tups
216 obj, args = tups
217
217
218 return obj.FitGau(args)
218 return obj.FitGau(args)
219
219
220 class RemoveWideGC(Operation):
220 class RemoveWideGC(Operation):
221 ''' This class remove the wide clutter and replace it with a simple interpolation points
221 ''' This class remove the wide clutter and replace it with a simple interpolation points
222 This mainly applies to CLAIRE radar
222 This mainly applies to CLAIRE radar
223
223
224 ClutterWidth : Width to look for the clutter peak
224 ClutterWidth : Width to look for the clutter peak
225
225
226 Input:
226 Input:
227
227
228 self.dataOut.data_pre : SPC and CSPC
228 self.dataOut.data_pre : SPC and CSPC
229 self.dataOut.spc_range : To select wind and rainfall velocities
229 self.dataOut.spc_range : To select wind and rainfall velocities
230
230
231 Affected:
231 Affected:
232
232
233 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
233 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
234
234
235 Written by D. ScipiΓ³n 25.02.2021
235 Written by D. ScipiΓ³n 25.02.2021
236 '''
236 '''
237 def __init__(self):
237 def __init__(self):
238 Operation.__init__(self)
238 Operation.__init__(self)
239 self.i = 0
239 self.i = 0
240 self.ich = 0
240 self.ich = 0
241 self.ir = 0
241 self.ir = 0
242
242
243 def run(self, dataOut, ClutterWidth=2.5):
243 def run(self, dataOut, ClutterWidth=2.5):
244 # print ('Entering RemoveWideGC ... ')
244 # print ('Entering RemoveWideGC ... ')
245
245
246 self.spc = dataOut.data_pre[0].copy()
246 self.spc = dataOut.data_pre[0].copy()
247 self.spc_out = dataOut.data_pre[0].copy()
247 self.spc_out = dataOut.data_pre[0].copy()
248 self.Num_Chn = self.spc.shape[0]
248 self.Num_Chn = self.spc.shape[0]
249 self.Num_Hei = self.spc.shape[2]
249 self.Num_Hei = self.spc.shape[2]
250 VelRange = dataOut.spc_range[2][:-1]
250 VelRange = dataOut.spc_range[2][:-1]
251 dv = VelRange[1]-VelRange[0]
251 dv = VelRange[1]-VelRange[0]
252
252
253 # Find the velocities that corresponds to zero
253 # Find the velocities that corresponds to zero
254 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
254 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
255
255
256 # Removing novalid data from the spectra
256 # Removing novalid data from the spectra
257 for ich in range(self.Num_Chn) :
257 for ich in range(self.Num_Chn) :
258 for ir in range(self.Num_Hei) :
258 for ir in range(self.Num_Hei) :
259 # Estimate the noise at each range
259 # Estimate the noise at each range
260 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
260 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
261
261
262 # Removing the noise floor at each range
262 # Removing the noise floor at each range
263 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
263 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
264 self.spc[ich,novalid,ir] = HSn
264 self.spc[ich,novalid,ir] = HSn
265
265
266 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
266 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
267 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
267 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
268 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
268 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
269 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
269 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
270 continue
270 continue
271 junk3 = numpy.squeeze(numpy.diff(j1index))
271 junk3 = numpy.squeeze(numpy.diff(j1index))
272 junk4 = numpy.squeeze(numpy.diff(j2index))
272 junk4 = numpy.squeeze(numpy.diff(j2index))
273
273
274 valleyindex = j2index[numpy.where(junk4>1)]
274 valleyindex = j2index[numpy.where(junk4>1)]
275 peakindex = j1index[numpy.where(junk3>1)]
275 peakindex = j1index[numpy.where(junk3>1)]
276
276
277 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
277 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
278 if numpy.size(isvalid) == 0 :
278 if numpy.size(isvalid) == 0 :
279 continue
279 continue
280 if numpy.size(isvalid) >1 :
280 if numpy.size(isvalid) >1 :
281 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
281 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
282 isvalid = isvalid[vindex]
282 isvalid = isvalid[vindex]
283
283
284 # clutter peak
284 # clutter peak
285 gcpeak = peakindex[isvalid]
285 gcpeak = peakindex[isvalid]
286 vl = numpy.where(valleyindex < gcpeak)
286 vl = numpy.where(valleyindex < gcpeak)
287 if numpy.size(vl) == 0:
287 if numpy.size(vl) == 0:
288 continue
288 continue
289 gcvl = valleyindex[vl[0][-1]]
289 gcvl = valleyindex[vl[0][-1]]
290 vr = numpy.where(valleyindex > gcpeak)
290 vr = numpy.where(valleyindex > gcpeak)
291 if numpy.size(vr) == 0:
291 if numpy.size(vr) == 0:
292 continue
292 continue
293 gcvr = valleyindex[vr[0][0]]
293 gcvr = valleyindex[vr[0][0]]
294
294
295 # Removing the clutter
295 # Removing the clutter
296 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
296 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
297 gcindex = gc_values[gcvl+1:gcvr-1]
297 gcindex = gc_values[gcvl+1:gcvr-1]
298 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
298 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
299
299
300 dataOut.data_pre[0] = self.spc_out
300 dataOut.data_pre[0] = self.spc_out
301 #print ('Leaving RemoveWideGC ... ')
301 #print ('Leaving RemoveWideGC ... ')
302 return dataOut
302 return dataOut
303
303
304 class SpectralFilters(Operation):
304 class SpectralFilters(Operation):
305 ''' This class allows to replace the novalid values with noise for each channel
305 ''' This class allows to replace the novalid values with noise for each channel
306 This applies to CLAIRE RADAR
306 This applies to CLAIRE RADAR
307
307
308 PositiveLimit : RightLimit of novalid data
308 PositiveLimit : RightLimit of novalid data
309 NegativeLimit : LeftLimit of novalid data
309 NegativeLimit : LeftLimit of novalid data
310
310
311 Input:
311 Input:
312
312
313 self.dataOut.data_pre : SPC and CSPC
313 self.dataOut.data_pre : SPC and CSPC
314 self.dataOut.spc_range : To select wind and rainfall velocities
314 self.dataOut.spc_range : To select wind and rainfall velocities
315
315
316 Affected:
316 Affected:
317
317
318 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
318 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
319
319
320 Written by D. ScipiΓ³n 29.01.2021
320 Written by D. ScipiΓ³n 29.01.2021
321 '''
321 '''
322 def __init__(self):
322 def __init__(self):
323 Operation.__init__(self)
323 Operation.__init__(self)
324 self.i = 0
324 self.i = 0
325
325
326 def run(self, dataOut, ):
326 def run(self, dataOut, ):
327
327
328 self.spc = dataOut.data_pre[0].copy()
328 self.spc = dataOut.data_pre[0].copy()
329 self.Num_Chn = self.spc.shape[0]
329 self.Num_Chn = self.spc.shape[0]
330 VelRange = dataOut.spc_range[2]
330 VelRange = dataOut.spc_range[2]
331
331
332 # novalid corresponds to data within the Negative and PositiveLimit
332 # novalid corresponds to data within the Negative and PositiveLimit
333
333
334
334
335 # Removing novalid data from the spectra
335 # Removing novalid data from the spectra
336 for i in range(self.Num_Chn):
336 for i in range(self.Num_Chn):
337 self.spc[i,novalid,:] = dataOut.noise[i]
337 self.spc[i,novalid,:] = dataOut.noise[i]
338 dataOut.data_pre[0] = self.spc
338 dataOut.data_pre[0] = self.spc
339 return dataOut
339 return dataOut
340
340
341 class GaussianFit(Operation):
341 class GaussianFit(Operation):
342
342
343 '''
343 '''
344 Function that fit of one and two generalized gaussians (gg) based
344 Function that fit of one and two generalized gaussians (gg) based
345 on the PSD shape across an "power band" identified from a cumsum of
345 on the PSD shape across an "power band" identified from a cumsum of
346 the measured spectrum - noise.
346 the measured spectrum - noise.
347
347
348 Input:
348 Input:
349 self.dataOut.data_pre : SelfSpectra
349 self.dataOut.data_pre : SelfSpectra
350
350
351 Output:
351 Output:
352 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
352 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
353
353
354 '''
354 '''
355 def __init__(self):
355 def __init__(self):
356 Operation.__init__(self)
356 Operation.__init__(self)
357 self.i=0
357 self.i=0
358
358
359
359
360 # 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
360 # 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
361 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
361 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
362 """This routine will find a couple of generalized Gaussians to a power spectrum
362 """This routine will find a couple of generalized Gaussians to a power spectrum
363 methods: generalized, squared
363 methods: generalized, squared
364 input: spc
364 input: spc
365 output:
365 output:
366 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
366 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
367 """
367 """
368 print ('Entering ',method,' double Gaussian fit')
368 print ('Entering ',method,' double Gaussian fit')
369 self.spc = dataOut.data_pre[0].copy()
369 self.spc = dataOut.data_pre[0].copy()
370 self.Num_Hei = self.spc.shape[2]
370 self.Num_Hei = self.spc.shape[2]
371 self.Num_Bin = self.spc.shape[1]
371 self.Num_Bin = self.spc.shape[1]
372 self.Num_Chn = self.spc.shape[0]
372 self.Num_Chn = self.spc.shape[0]
373
373
374 start_time = time.time()
374 start_time = time.time()
375
375
376 pool = Pool(processes=self.Num_Chn)
376 pool = Pool(processes=self.Num_Chn)
377 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
377 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
378 objs = [self for __ in range(self.Num_Chn)]
378 objs = [self for __ in range(self.Num_Chn)]
379 attrs = list(zip(objs, args))
379 attrs = list(zip(objs, args))
380 DGauFitParam = pool.map(target, attrs)
380 DGauFitParam = pool.map(target, attrs)
381 # Parameters:
381 # Parameters:
382 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
382 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
383 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
383 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
384
384
385 # Double Gaussian Curves
385 # Double Gaussian Curves
386 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
386 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
387 gau0[:] = numpy.NaN
387 gau0[:] = numpy.NaN
388 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
388 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
389 gau1[:] = numpy.NaN
389 gau1[:] = numpy.NaN
390 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
390 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
391 for iCh in range(self.Num_Chn):
391 for iCh in range(self.Num_Chn):
392 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
392 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
393 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
393 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
394 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
394 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
395 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
395 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
396 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
396 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
397 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
397 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
398 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
398 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
399 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
399 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
400 if method == 'genealized':
400 if method == 'genealized':
401 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
401 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
402 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
402 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
403 elif method == 'squared':
403 elif method == 'squared':
404 p0 = 2.
404 p0 = 2.
405 p1 = 2.
405 p1 = 2.
406 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
406 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
407 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
407 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
408 dataOut.GaussFit0 = gau0
408 dataOut.GaussFit0 = gau0
409 dataOut.GaussFit1 = gau1
409 dataOut.GaussFit1 = gau1
410
410
411 print('Leaving ',method ,' double Gaussian fit')
411 print('Leaving ',method ,' double Gaussian fit')
412 return dataOut
412 return dataOut
413
413
414 def FitGau(self, X):
414 def FitGau(self, X):
415 # print('Entering FitGau')
415 # print('Entering FitGau')
416 # Assigning the variables
416 # Assigning the variables
417 Vrange, ch, wnoise, num_intg, SNRlimit = X
417 Vrange, ch, wnoise, num_intg, SNRlimit = X
418 # Noise Limits
418 # Noise Limits
419 noisebl = wnoise * 0.9
419 noisebl = wnoise * 0.9
420 noisebh = wnoise * 1.1
420 noisebh = wnoise * 1.1
421 # Radar Velocity
421 # Radar Velocity
422 Va = max(Vrange)
422 Va = max(Vrange)
423 deltav = Vrange[1] - Vrange[0]
423 deltav = Vrange[1] - Vrange[0]
424 x = numpy.arange(self.Num_Bin)
424 x = numpy.arange(self.Num_Bin)
425
425
426 # print ('stop 0')
426 # print ('stop 0')
427
427
428 # 5 parameters, 2 Gaussians
428 # 5 parameters, 2 Gaussians
429 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
429 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
430 DGauFitParam[:] = numpy.NaN
430 DGauFitParam[:] = numpy.NaN
431
431
432 # SPCparam = []
432 # SPCparam = []
433 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
433 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
434 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
434 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
435 # SPC_ch1[:] = 0 #numpy.NaN
435 # SPC_ch1[:] = 0 #numpy.NaN
436 # SPC_ch2[:] = 0 #numpy.NaN
436 # SPC_ch2[:] = 0 #numpy.NaN
437 # print ('stop 1')
437 # print ('stop 1')
438 for ht in range(self.Num_Hei):
438 for ht in range(self.Num_Hei):
439 # print (ht)
439 # print (ht)
440 # print ('stop 2')
440 # print ('stop 2')
441 # Spectra at each range
441 # Spectra at each range
442 spc = numpy.asarray(self.spc)[ch,:,ht]
442 spc = numpy.asarray(self.spc)[ch,:,ht]
443 snr = ( spc.mean() - wnoise ) / wnoise
443 snr = ( spc.mean() - wnoise ) / wnoise
444 snrdB = 10.*numpy.log10(snr)
444 snrdB = 10.*numpy.log10(snr)
445
445
446 #print ('stop 3')
446 #print ('stop 3')
447 if snrdB < SNRlimit :
447 if snrdB < SNRlimit :
448 # snr = numpy.NaN
448 # snr = numpy.NaN
449 # SPC_ch1[:,ht] = 0#numpy.NaN
449 # SPC_ch1[:,ht] = 0#numpy.NaN
450 # SPC_ch1[:,ht] = 0#numpy.NaN
450 # SPC_ch1[:,ht] = 0#numpy.NaN
451 # SPCparam = (SPC_ch1,SPC_ch2)
451 # SPCparam = (SPC_ch1,SPC_ch2)
452 # print ('SNR less than SNRth')
452 # print ('SNR less than SNRth')
453 continue
453 continue
454 # wnoise = hildebrand_sekhon(spc,num_intg)
454 # wnoise = hildebrand_sekhon(spc,num_intg)
455 # print ('stop 2.01')
455 # print ('stop 2.01')
456 #############################################
456 #############################################
457 # normalizing spc and noise
457 # normalizing spc and noise
458 # This part differs from gg1
458 # This part differs from gg1
459 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
459 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
460 #spc = spc / spc_norm_max
460 #spc = spc / spc_norm_max
461 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
461 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
462 #############################################
462 #############################################
463
463
464 # print ('stop 2.1')
464 # print ('stop 2.1')
465 fatspectra=1.0
465 fatspectra=1.0
466 # noise per channel.... we might want to use the noise at each range
466 # noise per channel.... we might want to use the noise at each range
467
467
468 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
468 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
469 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
469 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
470 #if wnoise>1.1*pnoise: # to be tested later
470 #if wnoise>1.1*pnoise: # to be tested later
471 # wnoise=pnoise
471 # wnoise=pnoise
472 # noisebl = wnoise*0.9
472 # noisebl = wnoise*0.9
473 # noisebh = wnoise*1.1
473 # noisebh = wnoise*1.1
474 spc = spc - wnoise # signal
474 spc = spc - wnoise # signal
475
475
476 # print ('stop 2.2')
476 # print ('stop 2.2')
477 minx = numpy.argmin(spc)
477 minx = numpy.argmin(spc)
478 #spcs=spc.copy()
478 #spcs=spc.copy()
479 spcs = numpy.roll(spc,-minx)
479 spcs = numpy.roll(spc,-minx)
480 cum = numpy.cumsum(spcs)
480 cum = numpy.cumsum(spcs)
481 # tot_noise = wnoise * self.Num_Bin #64;
481 # tot_noise = wnoise * self.Num_Bin #64;
482
482
483 # print ('stop 2.3')
483 # print ('stop 2.3')
484 # snr = sum(spcs) / tot_noise
484 # snr = sum(spcs) / tot_noise
485 # snrdB = 10.*numpy.log10(snr)
485 # snrdB = 10.*numpy.log10(snr)
486 #print ('stop 3')
486 #print ('stop 3')
487 # if snrdB < SNRlimit :
487 # if snrdB < SNRlimit :
488 # snr = numpy.NaN
488 # snr = numpy.NaN
489 # SPC_ch1[:,ht] = 0#numpy.NaN
489 # SPC_ch1[:,ht] = 0#numpy.NaN
490 # SPC_ch1[:,ht] = 0#numpy.NaN
490 # SPC_ch1[:,ht] = 0#numpy.NaN
491 # SPCparam = (SPC_ch1,SPC_ch2)
491 # SPCparam = (SPC_ch1,SPC_ch2)
492 # print ('SNR less than SNRth')
492 # print ('SNR less than SNRth')
493 # continue
493 # continue
494
494
495
495
496 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
496 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
497 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
497 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
498 # print ('stop 4')
498 # print ('stop 4')
499 cummax = max(cum)
499 cummax = max(cum)
500 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
500 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
501 cumlo = cummax * epsi
501 cumlo = cummax * epsi
502 cumhi = cummax * (1-epsi)
502 cumhi = cummax * (1-epsi)
503 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
503 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
504
504
505 # print ('stop 5')
505 # print ('stop 5')
506 if len(powerindex) < 1:# case for powerindex 0
506 if len(powerindex) < 1:# case for powerindex 0
507 # print ('powerindex < 1')
507 # print ('powerindex < 1')
508 continue
508 continue
509 powerlo = powerindex[0]
509 powerlo = powerindex[0]
510 powerhi = powerindex[-1]
510 powerhi = powerindex[-1]
511 powerwidth = powerhi-powerlo
511 powerwidth = powerhi-powerlo
512 if powerwidth <= 1:
512 if powerwidth <= 1:
513 # print('powerwidth <= 1')
513 # print('powerwidth <= 1')
514 continue
514 continue
515
515
516 # print ('stop 6')
516 # print ('stop 6')
517 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
517 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
518 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
518 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
519 midpeak = (firstpeak + secondpeak)/2.
519 midpeak = (firstpeak + secondpeak)/2.
520 firstamp = spcs[int(firstpeak)]
520 firstamp = spcs[int(firstpeak)]
521 secondamp = spcs[int(secondpeak)]
521 secondamp = spcs[int(secondpeak)]
522 midamp = spcs[int(midpeak)]
522 midamp = spcs[int(midpeak)]
523
523
524 y_data = spc + wnoise
524 y_data = spc + wnoise
525
525
526 ''' single Gaussian '''
526 ''' single Gaussian '''
527 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
527 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
528 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
528 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
529 power0 = 2.
529 power0 = 2.
530 amplitude0 = midamp
530 amplitude0 = midamp
531 state0 = [shift0,width0,amplitude0,power0,wnoise]
531 state0 = [shift0,width0,amplitude0,power0,wnoise]
532 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
532 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
533 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
533 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
534 # print ('stop 7.1')
534 # print ('stop 7.1')
535 # print (bnds)
535 # print (bnds)
536
536
537 chiSq1=lsq1[1]
537 chiSq1=lsq1[1]
538
538
539 # print ('stop 8')
539 # print ('stop 8')
540 if fatspectra<1.0 and powerwidth<4:
540 if fatspectra<1.0 and powerwidth<4:
541 choice=0
541 choice=0
542 Amplitude0=lsq1[0][2]
542 Amplitude0=lsq1[0][2]
543 shift0=lsq1[0][0]
543 shift0=lsq1[0][0]
544 width0=lsq1[0][1]
544 width0=lsq1[0][1]
545 p0=lsq1[0][3]
545 p0=lsq1[0][3]
546 Amplitude1=0.
546 Amplitude1=0.
547 shift1=0.
547 shift1=0.
548 width1=0.
548 width1=0.
549 p1=0.
549 p1=0.
550 noise=lsq1[0][4]
550 noise=lsq1[0][4]
551 #return (numpy.array([shift0,width0,Amplitude0,p0]),
551 #return (numpy.array([shift0,width0,Amplitude0,p0]),
552 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
552 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
553
553
554 # print ('stop 9')
554 # print ('stop 9')
555 ''' two Gaussians '''
555 ''' two Gaussians '''
556 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
556 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
557 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
557 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
558 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
558 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
559 width0 = powerwidth/6.
559 width0 = powerwidth/6.
560 width1 = width0
560 width1 = width0
561 power0 = 2.
561 power0 = 2.
562 power1 = power0
562 power1 = power0
563 amplitude0 = firstamp
563 amplitude0 = firstamp
564 amplitude1 = secondamp
564 amplitude1 = secondamp
565 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
565 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
566 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
566 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
567 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))
567 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))
568 #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))
568 #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))
569
569
570 # print ('stop 10')
570 # print ('stop 10')
571 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
571 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
572
572
573 # print ('stop 11')
573 # print ('stop 11')
574 chiSq2 = lsq2[1]
574 chiSq2 = lsq2[1]
575
575
576 # print ('stop 12')
576 # print ('stop 12')
577
577
578 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)
578 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)
579
579
580 # print ('stop 13')
580 # print ('stop 13')
581 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
581 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
582 if oneG:
582 if oneG:
583 choice = 0
583 choice = 0
584 else:
584 else:
585 w1 = lsq2[0][1]; w2 = lsq2[0][5]
585 w1 = lsq2[0][1]; w2 = lsq2[0][5]
586 a1 = lsq2[0][2]; a2 = lsq2[0][6]
586 a1 = lsq2[0][2]; a2 = lsq2[0][6]
587 p1 = lsq2[0][3]; p2 = lsq2[0][7]
587 p1 = lsq2[0][3]; p2 = lsq2[0][7]
588 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
588 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
589 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
589 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
590 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
590 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
591
591
592 if gp1>gp2:
592 if gp1>gp2:
593 if a1>0.7*a2:
593 if a1>0.7*a2:
594 choice = 1
594 choice = 1
595 else:
595 else:
596 choice = 2
596 choice = 2
597 elif gp2>gp1:
597 elif gp2>gp1:
598 if a2>0.7*a1:
598 if a2>0.7*a1:
599 choice = 2
599 choice = 2
600 else:
600 else:
601 choice = 1
601 choice = 1
602 else:
602 else:
603 choice = numpy.argmax([a1,a2])+1
603 choice = numpy.argmax([a1,a2])+1
604 #else:
604 #else:
605 #choice=argmin([std2a,std2b])+1
605 #choice=argmin([std2a,std2b])+1
606
606
607 else: # with low SNR go to the most energetic peak
607 else: # with low SNR go to the most energetic peak
608 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
608 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
609
609
610 # print ('stop 14')
610 # print ('stop 14')
611 shift0 = lsq2[0][0]
611 shift0 = lsq2[0][0]
612 vel0 = Vrange[0] + shift0 * deltav
612 vel0 = Vrange[0] + shift0 * deltav
613 shift1 = lsq2[0][4]
613 shift1 = lsq2[0][4]
614 # vel1=Vrange[0] + shift1 * deltav
614 # vel1=Vrange[0] + shift1 * deltav
615
615
616 # max_vel = 1.0
616 # max_vel = 1.0
617 # Va = max(Vrange)
617 # Va = max(Vrange)
618 # deltav = Vrange[1]-Vrange[0]
618 # deltav = Vrange[1]-Vrange[0]
619 # print ('stop 15')
619 # print ('stop 15')
620 #first peak will be 0, second peak will be 1
620 #first peak will be 0, second peak will be 1
621 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
621 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
622 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
622 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
623 shift0 = lsq2[0][0]
623 shift0 = lsq2[0][0]
624 width0 = lsq2[0][1]
624 width0 = lsq2[0][1]
625 Amplitude0 = lsq2[0][2]
625 Amplitude0 = lsq2[0][2]
626 p0 = lsq2[0][3]
626 p0 = lsq2[0][3]
627
627
628 shift1 = lsq2[0][4]
628 shift1 = lsq2[0][4]
629 width1 = lsq2[0][5]
629 width1 = lsq2[0][5]
630 Amplitude1 = lsq2[0][6]
630 Amplitude1 = lsq2[0][6]
631 p1 = lsq2[0][7]
631 p1 = lsq2[0][7]
632 noise = lsq2[0][8]
632 noise = lsq2[0][8]
633 else:
633 else:
634 shift1 = lsq2[0][0]
634 shift1 = lsq2[0][0]
635 width1 = lsq2[0][1]
635 width1 = lsq2[0][1]
636 Amplitude1 = lsq2[0][2]
636 Amplitude1 = lsq2[0][2]
637 p1 = lsq2[0][3]
637 p1 = lsq2[0][3]
638
638
639 shift0 = lsq2[0][4]
639 shift0 = lsq2[0][4]
640 width0 = lsq2[0][5]
640 width0 = lsq2[0][5]
641 Amplitude0 = lsq2[0][6]
641 Amplitude0 = lsq2[0][6]
642 p0 = lsq2[0][7]
642 p0 = lsq2[0][7]
643 noise = lsq2[0][8]
643 noise = lsq2[0][8]
644
644
645 if Amplitude0<0.05: # in case the peak is noise
645 if Amplitude0<0.05: # in case the peak is noise
646 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
646 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
647 if Amplitude1<0.05:
647 if Amplitude1<0.05:
648 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
648 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
649
649
650 # print ('stop 16 ')
650 # print ('stop 16 ')
651 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
651 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
652 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
652 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
653 # SPCparam = (SPC_ch1,SPC_ch2)
653 # SPCparam = (SPC_ch1,SPC_ch2)
654
654
655 DGauFitParam[0,ht,0] = noise
655 DGauFitParam[0,ht,0] = noise
656 DGauFitParam[0,ht,1] = noise
656 DGauFitParam[0,ht,1] = noise
657 DGauFitParam[1,ht,0] = Amplitude0
657 DGauFitParam[1,ht,0] = Amplitude0
658 DGauFitParam[1,ht,1] = Amplitude1
658 DGauFitParam[1,ht,1] = Amplitude1
659 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
659 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
660 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
660 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
661 DGauFitParam[3,ht,0] = width0 * deltav
661 DGauFitParam[3,ht,0] = width0 * deltav
662 DGauFitParam[3,ht,1] = width1 * deltav
662 DGauFitParam[3,ht,1] = width1 * deltav
663 DGauFitParam[4,ht,0] = p0
663 DGauFitParam[4,ht,0] = p0
664 DGauFitParam[4,ht,1] = p1
664 DGauFitParam[4,ht,1] = p1
665
665
666 # print (DGauFitParam.shape)
666 # print (DGauFitParam.shape)
667 # print ('Leaving FitGau')
667 # print ('Leaving FitGau')
668 return DGauFitParam
668 return DGauFitParam
669 # return SPCparam
669 # return SPCparam
670 # return GauSPC
670 # return GauSPC
671
671
672 def y_model1(self,x,state):
672 def y_model1(self,x,state):
673 shift0, width0, amplitude0, power0, noise = state
673 shift0, width0, amplitude0, power0, noise = state
674 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
674 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
675 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
675 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
676 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
676 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
677 return model0 + model0u + model0d + noise
677 return model0 + model0u + model0d + noise
678
678
679 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
679 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
680 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
680 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
681 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
681 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
682 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
682 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
683 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
683 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
684
684
685 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
685 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
686 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
686 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
687 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
687 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
688 return model0 + model0u + model0d + model1 + model1u + model1d + noise
688 return model0 + model0u + model0d + model1 + model1u + model1d + noise
689
689
690 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.
690 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.
691
691
692 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
692 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
693
693
694 def misfit2(self,state,y_data,x,num_intg):
694 def misfit2(self,state,y_data,x,num_intg):
695 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
695 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
696
696
697
697
698
698
699 class PrecipitationProc(Operation):
699 class PrecipitationProc(Operation):
700
700
701 '''
701 '''
702 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
702 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
703
703
704 Input:
704 Input:
705 self.dataOut.data_pre : SelfSpectra
705 self.dataOut.data_pre : SelfSpectra
706
706
707 Output:
707 Output:
708
708
709 self.dataOut.data_output : Reflectivity factor, rainfall Rate
709 self.dataOut.data_output : Reflectivity factor, rainfall Rate
710
710
711
711
712 Parameters affected:
712 Parameters affected:
713 '''
713 '''
714
714
715 def __init__(self):
715 def __init__(self):
716 Operation.__init__(self)
716 Operation.__init__(self)
717 self.i=0
717 self.i=0
718
718
719 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
719 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
720 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
720 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
721
721
722 # print ('Entering PrecepitationProc ... ')
722 # print ('Entering PrecepitationProc ... ')
723
723
724 if radar == "MIRA35C" :
724 if radar == "MIRA35C" :
725
725
726 self.spc = dataOut.data_pre[0].copy()
726 self.spc = dataOut.data_pre[0].copy()
727 self.Num_Hei = self.spc.shape[2]
727 self.Num_Hei = self.spc.shape[2]
728 self.Num_Bin = self.spc.shape[1]
728 self.Num_Bin = self.spc.shape[1]
729 self.Num_Chn = self.spc.shape[0]
729 self.Num_Chn = self.spc.shape[0]
730 Ze = self.dBZeMODE2(dataOut)
730 Ze = self.dBZeMODE2(dataOut)
731
731
732 else:
732 else:
733
733
734 self.spc = dataOut.data_pre[0].copy()
734 self.spc = dataOut.data_pre[0].copy()
735
735
736 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
736 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
737 self.spc[:,:,0:7]= numpy.NaN
737 self.spc[:,:,0:7]= numpy.NaN
738
738
739 self.Num_Hei = self.spc.shape[2]
739 self.Num_Hei = self.spc.shape[2]
740 self.Num_Bin = self.spc.shape[1]
740 self.Num_Bin = self.spc.shape[1]
741 self.Num_Chn = self.spc.shape[0]
741 self.Num_Chn = self.spc.shape[0]
742
742
743 VelRange = dataOut.spc_range[2]
743 VelRange = dataOut.spc_range[2]
744
744
745 ''' Se obtiene la constante del RADAR '''
745 ''' Se obtiene la constante del RADAR '''
746
746
747 self.Pt = Pt
747 self.Pt = Pt
748 self.Gt = Gt
748 self.Gt = Gt
749 self.Gr = Gr
749 self.Gr = Gr
750 self.Lambda = Lambda
750 self.Lambda = Lambda
751 self.aL = aL
751 self.aL = aL
752 self.tauW = tauW
752 self.tauW = tauW
753 self.ThetaT = ThetaT
753 self.ThetaT = ThetaT
754 self.ThetaR = ThetaR
754 self.ThetaR = ThetaR
755 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
755 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
756 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
756 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
757 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
757 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
758
758
759 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
759 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
760 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
760 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
761 RadarConstant = 10e-26 * Numerator / Denominator #
761 RadarConstant = 10e-26 * Numerator / Denominator #
762 ExpConstant = 10**(40/10) #Constante Experimental
762 ExpConstant = 10**(40/10) #Constante Experimental
763
763
764 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
764 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
765 for i in range(self.Num_Chn):
765 for i in range(self.Num_Chn):
766 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
766 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
767 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
767 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
768
768
769 SPCmean = numpy.mean(SignalPower, 0)
769 SPCmean = numpy.mean(SignalPower, 0)
770 Pr = SPCmean[:,:]/dataOut.normFactor
770 Pr = SPCmean[:,:]/dataOut.normFactor
771
771
772 # Declaring auxiliary variables
772 # Declaring auxiliary variables
773 Range = dataOut.heightList*1000. #Range in m
773 Range = dataOut.heightList*1000. #Range in m
774 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
774 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
775 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
775 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
776 zMtrx = rMtrx+Altitude
776 zMtrx = rMtrx+Altitude
777 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
777 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
778 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
778 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
779
779
780 # height dependence to air density Foote and Du Toit (1969)
780 # height dependence to air density Foote and Du Toit (1969)
781 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
781 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
782 VMtrx = VelMtrx / delv_z #Normalized velocity
782 VMtrx = VelMtrx / delv_z #Normalized velocity
783 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
783 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
784 # Diameter is related to the fall speed of falling drops
784 # Diameter is related to the fall speed of falling drops
785 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
785 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
786 # Only valid for D>= 0.16 mm
786 # Only valid for D>= 0.16 mm
787 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
787 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
788
788
789 #Calculate Radar Reflectivity ETAn
789 #Calculate Radar Reflectivity ETAn
790 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
790 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
791 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
791 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
792 # Radar Cross Section
792 # Radar Cross Section
793 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
793 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
794 # Drop Size Distribution
794 # Drop Size Distribution
795 DSD = ETAn / sigmaD
795 DSD = ETAn / sigmaD
796 # Equivalente Reflectivy
796 # Equivalente Reflectivy
797 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
797 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
798 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
798 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
799 # RainFall Rate
799 # RainFall Rate
800 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
800 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
801
801
802 # Censoring the data
802 # Censoring the data
803 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
803 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
804 SNRth = 10**(SNRdBlimit/10) #-30dB
804 SNRth = 10**(SNRdBlimit/10) #-30dB
805 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
805 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
806 W = numpy.nanmean(dataOut.data_dop,0)
806 W = numpy.nanmean(dataOut.data_dop,0)
807 W[novalid] = numpy.NaN
807 W[novalid] = numpy.NaN
808 Ze_org[novalid] = numpy.NaN
808 Ze_org[novalid] = numpy.NaN
809 RR[novalid] = numpy.NaN
809 RR[novalid] = numpy.NaN
810
810
811 dataOut.data_output = RR[8]
811 dataOut.data_output = RR[8]
812 dataOut.data_param = numpy.ones([3,self.Num_Hei])
812 dataOut.data_param = numpy.ones([3,self.Num_Hei])
813 dataOut.channelList = [0,1,2]
813 dataOut.channelList = [0,1,2]
814
814
815 dataOut.data_param[0]=10*numpy.log10(Ze_org)
815 dataOut.data_param[0]=10*numpy.log10(Ze_org)
816 dataOut.data_param[1]=-W
816 dataOut.data_param[1]=-W
817 dataOut.data_param[2]=RR
817 dataOut.data_param[2]=RR
818
818
819 # print ('Leaving PrecepitationProc ... ')
819 # print ('Leaving PrecepitationProc ... ')
820 return dataOut
820 return dataOut
821
821
822 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
822 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
823
823
824 NPW = dataOut.NPW
824 NPW = dataOut.NPW
825 COFA = dataOut.COFA
825 COFA = dataOut.COFA
826
826
827 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
827 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
828 RadarConst = dataOut.RadarConst
828 RadarConst = dataOut.RadarConst
829 #frequency = 34.85*10**9
829 #frequency = 34.85*10**9
830
830
831 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
831 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
832 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
832 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
833
833
834 ETA = numpy.sum(SNR,1)
834 ETA = numpy.sum(SNR,1)
835
835
836 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
836 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
837
837
838 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
838 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
839
839
840 for r in range(self.Num_Hei):
840 for r in range(self.Num_Hei):
841
841
842 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
842 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
843 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
843 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
844
844
845 return Ze
845 return Ze
846
846
847 # def GetRadarConstant(self):
847 # def GetRadarConstant(self):
848 #
848 #
849 # """
849 # """
850 # Constants:
850 # Constants:
851 #
851 #
852 # Pt: Transmission Power dB 5kW 5000
852 # Pt: Transmission Power dB 5kW 5000
853 # Gt: Transmission Gain dB 24.7 dB 295.1209
853 # Gt: Transmission Gain dB 24.7 dB 295.1209
854 # Gr: Reception Gain dB 18.5 dB 70.7945
854 # Gr: Reception Gain dB 18.5 dB 70.7945
855 # Lambda: Wavelenght m 0.6741 m 0.6741
855 # Lambda: Wavelenght m 0.6741 m 0.6741
856 # aL: Attenuation loses dB 4dB 2.5118
856 # aL: Attenuation loses dB 4dB 2.5118
857 # tauW: Width of transmission pulse s 4us 4e-6
857 # tauW: Width of transmission pulse s 4us 4e-6
858 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
858 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
859 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
859 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
860 #
860 #
861 # """
861 # """
862 #
862 #
863 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
863 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
864 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
864 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
865 # RadarConstant = Numerator / Denominator
865 # RadarConstant = Numerator / Denominator
866 #
866 #
867 # return RadarConstant
867 # return RadarConstant
868
868
869
869
870
870
871 class FullSpectralAnalysis(Operation):
871 class FullSpectralAnalysis(Operation):
872
872
873 """
873 """
874 Function that implements Full Spectral Analysis technique.
874 Function that implements Full Spectral Analysis technique.
875
875
876 Input:
876 Input:
877 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
877 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
878 self.dataOut.groupList : Pairlist of channels
878 self.dataOut.groupList : Pairlist of channels
879 self.dataOut.ChanDist : Physical distance between receivers
879 self.dataOut.ChanDist : Physical distance between receivers
880
880
881
881
882 Output:
882 Output:
883
883
884 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
884 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
885
885
886
886
887 Parameters affected: Winds, height range, SNR
887 Parameters affected: Winds, height range, SNR
888
888
889 """
889 """
890 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
890 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
891 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
891 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
892
892
893 spc = dataOut.data_pre[0].copy()
893 spc = dataOut.data_pre[0].copy()
894 cspc = dataOut.data_pre[1]
894 cspc = dataOut.data_pre[1]
895 nHeights = spc.shape[2]
895 nHeights = spc.shape[2]
896
896
897 # first_height = 0.75 #km (ref: data header 20170822)
897 # first_height = 0.75 #km (ref: data header 20170822)
898 # resolution_height = 0.075 #km
898 # resolution_height = 0.075 #km
899 '''
899 '''
900 finding height range. check this when radar parameters are changed!
900 finding height range. check this when radar parameters are changed!
901 '''
901 '''
902 if maxheight is not None:
902 if maxheight is not None:
903 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
903 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
904 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
904 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
905 else:
905 else:
906 range_max = nHeights
906 range_max = nHeights
907 if minheight is not None:
907 if minheight is not None:
908 # range_min = int((minheight - first_height) / resolution_height) # theoretical
908 # range_min = int((minheight - first_height) / resolution_height) # theoretical
909 range_min = int(13.26 * minheight - 5) # empirical, works better
909 range_min = int(13.26 * minheight - 5) # empirical, works better
910 if range_min < 0:
910 if range_min < 0:
911 range_min = 0
911 range_min = 0
912 else:
912 else:
913 range_min = 0
913 range_min = 0
914
914
915 pairsList = dataOut.groupList
915 pairsList = dataOut.groupList
916 if dataOut.ChanDist is not None :
916 if dataOut.ChanDist is not None :
917 ChanDist = dataOut.ChanDist
917 ChanDist = dataOut.ChanDist
918 else:
918 else:
919 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
919 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
920
920
921 # 4 variables: zonal, meridional, vertical, and average SNR
921 # 4 variables: zonal, meridional, vertical, and average SNR
922 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
922 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
923 velocityX = numpy.zeros([nHeights]) * numpy.NaN
923 velocityX = numpy.zeros([nHeights]) * numpy.NaN
924 velocityY = numpy.zeros([nHeights]) * numpy.NaN
924 velocityY = numpy.zeros([nHeights]) * numpy.NaN
925 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
925 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
926
926
927 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
927 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
928
928
929 '''***********************************************WIND ESTIMATION**************************************'''
929 '''***********************************************WIND ESTIMATION**************************************'''
930 for Height in range(nHeights):
930 for Height in range(nHeights):
931
931
932 if Height >= range_min and Height < range_max:
932 if Height >= range_min and Height < range_max:
933 # error_code will be useful in future analysis
933 # error_code will be useful in future analysis
934 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
934 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
935 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
935 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
936
936
937 if abs(Vzon) < 100. and abs(Vmer) < 100.:
937 if abs(Vzon) < 100. and abs(Vmer) < 100.:
938 velocityX[Height] = Vzon
938 velocityX[Height] = Vzon
939 velocityY[Height] = -Vmer
939 velocityY[Height] = -Vmer
940 velocityZ[Height] = Vver
940 velocityZ[Height] = Vver
941
941
942 # Censoring data with SNR threshold
942 # Censoring data with SNR threshold
943 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
943 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
944
944
945 data_param[0] = velocityX
945 data_param[0] = velocityX
946 data_param[1] = velocityY
946 data_param[1] = velocityY
947 data_param[2] = velocityZ
947 data_param[2] = velocityZ
948 data_param[3] = dbSNR
948 data_param[3] = dbSNR
949 dataOut.data_param = data_param
949 dataOut.data_param = data_param
950 return dataOut
950 return dataOut
951
951
952 def moving_average(self,x, N=2):
952 def moving_average(self,x, N=2):
953 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
953 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
954 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
954 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
955
955
956 def gaus(self,xSamples,Amp,Mu,Sigma):
956 def gaus(self,xSamples,Amp,Mu,Sigma):
957 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
957 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
958
958
959 def Moments(self, ySamples, xSamples):
959 def Moments(self, ySamples, xSamples):
960 Power = numpy.nanmean(ySamples) # Power, 0th Moment
960 Power = numpy.nanmean(ySamples) # Power, 0th Moment
961 yNorm = ySamples / numpy.nansum(ySamples)
961 yNorm = ySamples / numpy.nansum(ySamples)
962 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
962 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
963 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
963 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
964 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
964 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
965 return numpy.array([Power,RadVel,StdDev])
965 return numpy.array([Power,RadVel,StdDev])
966
966
967 def StopWindEstimation(self, error_code):
967 def StopWindEstimation(self, error_code):
968 Vzon = numpy.NaN
968 Vzon = numpy.NaN
969 Vmer = numpy.NaN
969 Vmer = numpy.NaN
970 Vver = numpy.NaN
970 Vver = numpy.NaN
971 return Vzon, Vmer, Vver, error_code
971 return Vzon, Vmer, Vver, error_code
972
972
973 def AntiAliasing(self, interval, maxstep):
973 def AntiAliasing(self, interval, maxstep):
974 """
974 """
975 function to prevent errors from aliased values when computing phaseslope
975 function to prevent errors from aliased values when computing phaseslope
976 """
976 """
977 antialiased = numpy.zeros(len(interval))
977 antialiased = numpy.zeros(len(interval))
978 copyinterval = interval.copy()
978 copyinterval = interval.copy()
979
979
980 antialiased[0] = copyinterval[0]
980 antialiased[0] = copyinterval[0]
981
981
982 for i in range(1,len(antialiased)):
982 for i in range(1,len(antialiased)):
983 step = interval[i] - interval[i-1]
983 step = interval[i] - interval[i-1]
984 if step > maxstep:
984 if step > maxstep:
985 copyinterval -= 2*numpy.pi
985 copyinterval -= 2*numpy.pi
986 antialiased[i] = copyinterval[i]
986 antialiased[i] = copyinterval[i]
987 elif step < maxstep*(-1):
987 elif step < maxstep*(-1):
988 copyinterval += 2*numpy.pi
988 copyinterval += 2*numpy.pi
989 antialiased[i] = copyinterval[i]
989 antialiased[i] = copyinterval[i]
990 else:
990 else:
991 antialiased[i] = copyinterval[i].copy()
991 antialiased[i] = copyinterval[i].copy()
992
992
993 return antialiased
993 return antialiased
994
994
995 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
995 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
996 """
996 """
997 Function that Calculates Zonal, Meridional and Vertical wind velocities.
997 Function that Calculates Zonal, Meridional and Vertical wind velocities.
998 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
998 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
999
999
1000 Input:
1000 Input:
1001 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1001 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1002 pairsList : Pairlist of channels
1002 pairsList : Pairlist of channels
1003 ChanDist : array of xi_ij and eta_ij
1003 ChanDist : array of xi_ij and eta_ij
1004 Height : height at which data is processed
1004 Height : height at which data is processed
1005 noise : noise in [channels] format for specific height
1005 noise : noise in [channels] format for specific height
1006 Abbsisarange : range of the frequencies or velocities
1006 Abbsisarange : range of the frequencies or velocities
1007 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1007 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1008
1008
1009 Output:
1009 Output:
1010 Vzon, Vmer, Vver : wind velocities
1010 Vzon, Vmer, Vver : wind velocities
1011 error_code : int that states where code is terminated
1011 error_code : int that states where code is terminated
1012
1012
1013 0 : no error detected
1013 0 : no error detected
1014 1 : Gaussian of mean spc exceeds widthlimit
1014 1 : Gaussian of mean spc exceeds widthlimit
1015 2 : no Gaussian of mean spc found
1015 2 : no Gaussian of mean spc found
1016 3 : SNR to low or velocity to high -> prec. e.g.
1016 3 : SNR to low or velocity to high -> prec. e.g.
1017 4 : at least one Gaussian of cspc exceeds widthlimit
1017 4 : at least one Gaussian of cspc exceeds widthlimit
1018 5 : zero out of three cspc Gaussian fits converged
1018 5 : zero out of three cspc Gaussian fits converged
1019 6 : phase slope fit could not be found
1019 6 : phase slope fit could not be found
1020 7 : arrays used to fit phase have different length
1020 7 : arrays used to fit phase have different length
1021 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1021 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1022
1022
1023 """
1023 """
1024
1024
1025 error_code = 0
1025 error_code = 0
1026
1026
1027 nChan = spc.shape[0]
1027 nChan = spc.shape[0]
1028 nProf = spc.shape[1]
1028 nProf = spc.shape[1]
1029 nPair = cspc.shape[0]
1029 nPair = cspc.shape[0]
1030
1030
1031 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1031 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1032 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1032 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1033 phase = numpy.zeros([nPair, nProf]) # phase between channels
1033 phase = numpy.zeros([nPair, nProf]) # phase between channels
1034 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1034 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1035 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1035 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1036 xFrec = AbbsisaRange[0][:-1] # frequency range
1036 xFrec = AbbsisaRange[0][:-1] # frequency range
1037 xVel = AbbsisaRange[2][:-1] # velocity range
1037 xVel = AbbsisaRange[2][:-1] # velocity range
1038 xSamples = xFrec # the frequency range is taken
1038 xSamples = xFrec # the frequency range is taken
1039 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1039 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1040
1040
1041 # only consider velocities with in NegativeLimit and PositiveLimit
1041 # only consider velocities with in NegativeLimit and PositiveLimit
1042 if (NegativeLimit is None):
1042 if (NegativeLimit is None):
1043 NegativeLimit = numpy.min(xVel)
1043 NegativeLimit = numpy.min(xVel)
1044 if (PositiveLimit is None):
1044 if (PositiveLimit is None):
1045 PositiveLimit = numpy.max(xVel)
1045 PositiveLimit = numpy.max(xVel)
1046 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1046 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1047 xSamples_zoom = xSamples[xvalid]
1047 xSamples_zoom = xSamples[xvalid]
1048
1048
1049 '''Getting Eij and Nij'''
1049 '''Getting Eij and Nij'''
1050 Xi01, Xi02, Xi12 = ChanDist[:,0]
1050 Xi01, Xi02, Xi12 = ChanDist[:,0]
1051 Eta01, Eta02, Eta12 = ChanDist[:,1]
1051 Eta01, Eta02, Eta12 = ChanDist[:,1]
1052
1052
1053 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1053 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1054 widthlimit = 10
1054 widthlimit = 10
1055 '''************************* SPC is normalized ********************************'''
1055 '''************************* SPC is normalized ********************************'''
1056 spc_norm = spc.copy()
1056 spc_norm = spc.copy()
1057 # For each channel
1057 # For each channel
1058 for i in range(nChan):
1058 for i in range(nChan):
1059 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1059 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1060 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1060 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1061
1061
1062 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1062 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1063
1063
1064 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1064 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1065 you only fit the curve and don't need the absolute value of height for calculation,
1065 you only fit the curve and don't need the absolute value of height for calculation,
1066 only for estimation of width. for normalization of cross spectra, you need initial,
1066 only for estimation of width. for normalization of cross spectra, you need initial,
1067 unnormalized self-spectra With noise.
1067 unnormalized self-spectra With noise.
1068
1068
1069 Technically, you don't even need to normalize the self-spectra, as you only need the
1069 Technically, you don't even need to normalize the self-spectra, as you only need the
1070 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1070 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1071 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1071 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1072 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1072 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1073 """
1073 """
1074 # initial conditions
1074 # initial conditions
1075 popt = [1e-10,0,1e-10]
1075 popt = [1e-10,0,1e-10]
1076 # Spectra average
1076 # Spectra average
1077 SPCMean = numpy.average(SPC_Samples,0)
1077 SPCMean = numpy.average(SPC_Samples,0)
1078 # Moments in frequency
1078 # Moments in frequency
1079 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1079 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1080
1080
1081 # Gauss Fit SPC in frequency domain
1081 # Gauss Fit SPC in frequency domain
1082 if dbSNR > SNRlimit: # only if SNR > SNRth
1082 if dbSNR > SNRlimit: # only if SNR > SNRth
1083 try:
1083 try:
1084 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1084 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1085 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1085 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1086 return self.StopWindEstimation(error_code = 1)
1086 return self.StopWindEstimation(error_code = 1)
1087 FitGauss = self.gaus(xSamples_zoom,*popt)
1087 FitGauss = self.gaus(xSamples_zoom,*popt)
1088 except :#RuntimeError:
1088 except :#RuntimeError:
1089 return self.StopWindEstimation(error_code = 2)
1089 return self.StopWindEstimation(error_code = 2)
1090 else:
1090 else:
1091 return self.StopWindEstimation(error_code = 3)
1091 return self.StopWindEstimation(error_code = 3)
1092
1092
1093 '''***************************** CSPC Normalization *************************
1093 '''***************************** CSPC Normalization *************************
1094 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1094 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1095 influence the norm which is not desired. First, a range is identified where the
1095 influence the norm which is not desired. First, a range is identified where the
1096 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1096 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1097 around it gets cut off and values replaced by mean determined by the boundary
1097 around it gets cut off and values replaced by mean determined by the boundary
1098 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1098 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1099
1099
1100 The sums are then added and multiplied by range/datapoints, because you need
1100 The sums are then added and multiplied by range/datapoints, because you need
1101 an integral and not a sum for normalization.
1101 an integral and not a sum for normalization.
1102
1102
1103 A norm is found according to Briggs 92.
1103 A norm is found according to Briggs 92.
1104 '''
1104 '''
1105 # for each pair
1105 # for each pair
1106 for i in range(nPair):
1106 for i in range(nPair):
1107 cspc_norm = cspc[i,:].copy()
1107 cspc_norm = cspc[i,:].copy()
1108 chan_index0 = pairsList[i][0]
1108 chan_index0 = pairsList[i][0]
1109 chan_index1 = pairsList[i][1]
1109 chan_index1 = pairsList[i][1]
1110 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1110 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1111 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1111 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1112
1112
1113 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1113 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1114 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1114 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1115 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1115 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1116
1116
1117 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1117 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1118 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1118 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1119
1119
1120 '''*******************************FIT GAUSS CSPC************************************'''
1120 '''*******************************FIT GAUSS CSPC************************************'''
1121 try:
1121 try:
1122 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1122 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1123 if popt01[2] > widthlimit: # CONDITION
1123 if popt01[2] > widthlimit: # CONDITION
1124 return self.StopWindEstimation(error_code = 4)
1124 return self.StopWindEstimation(error_code = 4)
1125 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1125 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1126 if popt02[2] > widthlimit: # CONDITION
1126 if popt02[2] > widthlimit: # CONDITION
1127 return self.StopWindEstimation(error_code = 4)
1127 return self.StopWindEstimation(error_code = 4)
1128 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1128 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1129 if popt12[2] > widthlimit: # CONDITION
1129 if popt12[2] > widthlimit: # CONDITION
1130 return self.StopWindEstimation(error_code = 4)
1130 return self.StopWindEstimation(error_code = 4)
1131
1131
1132 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1132 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1133 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1133 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1134 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1134 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1135 except:
1135 except:
1136 return self.StopWindEstimation(error_code = 5)
1136 return self.StopWindEstimation(error_code = 5)
1137
1137
1138
1138
1139 '''************* Getting Fij ***************'''
1139 '''************* Getting Fij ***************'''
1140 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1140 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1141 GaussCenter = popt[1]
1141 GaussCenter = popt[1]
1142 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1142 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1143 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1143 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1144
1144
1145 # Point where e^-1 is located in the gaussian
1145 # Point where e^-1 is located in the gaussian
1146 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1146 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1147 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1147 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1148 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1148 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1149 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1149 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1150
1150
1151 '''********** Taking frequency ranges from mean SPCs **********'''
1151 '''********** Taking frequency ranges from mean SPCs **********'''
1152 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1152 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1153 Range = numpy.empty(2)
1153 Range = numpy.empty(2)
1154 Range[0] = GaussCenter - GauWidth
1154 Range[0] = GaussCenter - GauWidth
1155 Range[1] = GaussCenter + GauWidth
1155 Range[1] = GaussCenter + GauWidth
1156 # Point in x-axis where the bandwidth is located (min:max)
1156 # Point in x-axis where the bandwidth is located (min:max)
1157 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1157 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1158 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1158 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1159 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1159 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1160 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1160 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1161 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1161 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1162 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1162 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1163
1163
1164 '''************************** Getting Phase Slope ***************************'''
1164 '''************************** Getting Phase Slope ***************************'''
1165 for i in range(nPair):
1165 for i in range(nPair):
1166 if len(FrecRange) > 5:
1166 if len(FrecRange) > 5:
1167 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1167 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1168 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1168 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1169 if len(FrecRange) == len(PhaseRange):
1169 if len(FrecRange) == len(PhaseRange):
1170 try:
1170 try:
1171 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1171 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1172 PhaseSlope[i] = slope
1172 PhaseSlope[i] = slope
1173 PhaseInter[i] = intercept
1173 PhaseInter[i] = intercept
1174 except:
1174 except:
1175 return self.StopWindEstimation(error_code = 6)
1175 return self.StopWindEstimation(error_code = 6)
1176 else:
1176 else:
1177 return self.StopWindEstimation(error_code = 7)
1177 return self.StopWindEstimation(error_code = 7)
1178 else:
1178 else:
1179 return self.StopWindEstimation(error_code = 8)
1179 return self.StopWindEstimation(error_code = 8)
1180
1180
1181 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1181 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1182
1182
1183 '''Getting constant C'''
1183 '''Getting constant C'''
1184 cC=(Fij*numpy.pi)**2
1184 cC=(Fij*numpy.pi)**2
1185
1185
1186 '''****** Getting constants F and G ******'''
1186 '''****** Getting constants F and G ******'''
1187 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1187 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1188 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1188 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1189 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1189 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1190 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1190 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1191 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1191 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1192 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1192 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1193 MijResults = numpy.array([MijResult1, MijResult2])
1193 MijResults = numpy.array([MijResult1, MijResult2])
1194 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1194 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1195
1195
1196 '''****** Getting constants A, B and H ******'''
1196 '''****** Getting constants A, B and H ******'''
1197 W01 = numpy.nanmax( FitGauss01 )
1197 W01 = numpy.nanmax( FitGauss01 )
1198 W02 = numpy.nanmax( FitGauss02 )
1198 W02 = numpy.nanmax( FitGauss02 )
1199 W12 = numpy.nanmax( FitGauss12 )
1199 W12 = numpy.nanmax( FitGauss12 )
1200
1200
1201 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1201 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1202 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1202 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1203 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1203 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1204 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1204 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1205
1205
1206 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1206 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1207 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1207 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1208
1208
1209 VxVy = numpy.array([[cA,cH],[cH,cB]])
1209 VxVy = numpy.array([[cA,cH],[cH,cB]])
1210 VxVyResults = numpy.array([-cF,-cG])
1210 VxVyResults = numpy.array([-cF,-cG])
1211 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1211 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1212 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1212 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1213 error_code = 0
1213 error_code = 0
1214
1214
1215 return Vzon, Vmer, Vver, error_code
1215 return Vzon, Vmer, Vver, error_code
1216
1216
1217 class SpectralMoments(Operation):
1217 class SpectralMoments(Operation):
1218
1218
1219 '''
1219 '''
1220 Function SpectralMoments()
1220 Function SpectralMoments()
1221
1221
1222 Calculates moments (power, mean, standard deviation) and SNR of the signal
1222 Calculates moments (power, mean, standard deviation) and SNR of the signal
1223
1223
1224 Type of dataIn: Spectra
1224 Type of dataIn: Spectra
1225
1225
1226 Configuration Parameters:
1226 Configuration Parameters:
1227
1227
1228 dirCosx : Cosine director in X axis
1228 dirCosx : Cosine director in X axis
1229 dirCosy : Cosine director in Y axis
1229 dirCosy : Cosine director in Y axis
1230
1230
1231 elevation :
1231 elevation :
1232 azimuth :
1232 azimuth :
1233
1233
1234 Input:
1234 Input:
1235 channelList : simple channel list to select e.g. [2,3,7]
1235 channelList : simple channel list to select e.g. [2,3,7]
1236 self.dataOut.data_pre : Spectral data
1236 self.dataOut.data_pre : Spectral data
1237 self.dataOut.abscissaList : List of frequencies
1237 self.dataOut.abscissaList : List of frequencies
1238 self.dataOut.noise : Noise level per channel
1238 self.dataOut.noise : Noise level per channel
1239
1239
1240 Affected:
1240 Affected:
1241 self.dataOut.moments : Parameters per channel
1241 self.dataOut.moments : Parameters per channel
1242 self.dataOut.data_snr : SNR per channel
1242 self.dataOut.data_snr : SNR per channel
1243
1243
1244 '''
1244 '''
1245
1245
1246 def run(self, dataOut):
1246 def run(self, dataOut):
1247
1247
1248 data = dataOut.data_pre[0]
1248 data = dataOut.data_pre[0]
1249 absc = dataOut.abscissaList[:-1]
1249 absc = dataOut.abscissaList[:-1]
1250 noise = dataOut.noise
1250 noise = dataOut.noise
1251 nChannel = data.shape[0]
1251 nChannel = data.shape[0]
1252 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1252 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1253
1253
1254 for ind in range(nChannel):
1254 for ind in range(nChannel):
1255 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1255 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1256
1256
1257 dataOut.moments = data_param[:,1:,:]
1257 dataOut.moments = data_param[:,1:,:]
1258 dataOut.data_snr = data_param[:,0]
1258 dataOut.data_snr = data_param[:,0]
1259 dataOut.data_pow = data_param[:,1]
1259 dataOut.data_pow = data_param[:,1]
1260 dataOut.data_dop = data_param[:,2]
1260 dataOut.data_dop = data_param[:,2]
1261 dataOut.data_width = data_param[:,3]
1261 dataOut.data_width = data_param[:,3]
1262 return dataOut
1262 return dataOut
1263
1263
1264 def __calculateMoments(self, oldspec, oldfreq, n0,
1264 def __calculateMoments(self, oldspec, oldfreq, n0,
1265 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1265 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1266
1266
1267 if (nicoh is None): nicoh = 1
1267 if (nicoh is None): nicoh = 1
1268 if (graph is None): graph = 0
1268 if (graph is None): graph = 0
1269 if (smooth is None): smooth = 0
1269 if (smooth is None): smooth = 0
1270 elif (self.smooth < 3): smooth = 0
1270 elif (self.smooth < 3): smooth = 0
1271
1271
1272 if (type1 is None): type1 = 0
1272 if (type1 is None): type1 = 0
1273 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1273 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1274 if (snrth is None): snrth = -3
1274 if (snrth is None): snrth = -3
1275 if (dc is None): dc = 0
1275 if (dc is None): dc = 0
1276 if (aliasing is None): aliasing = 0
1276 if (aliasing is None): aliasing = 0
1277 if (oldfd is None): oldfd = 0
1277 if (oldfd is None): oldfd = 0
1278 if (wwauto is None): wwauto = 0
1278 if (wwauto is None): wwauto = 0
1279
1279
1280 if (n0 < 1.e-20): n0 = 1.e-20
1280 if (n0 < 1.e-20): n0 = 1.e-20
1281
1281
1282 freq = oldfreq
1282 freq = oldfreq
1283 vec_power = numpy.zeros(oldspec.shape[1])
1283 vec_power = numpy.zeros(oldspec.shape[1])
1284 vec_fd = numpy.zeros(oldspec.shape[1])
1284 vec_fd = numpy.zeros(oldspec.shape[1])
1285 vec_w = numpy.zeros(oldspec.shape[1])
1285 vec_w = numpy.zeros(oldspec.shape[1])
1286 vec_snr = numpy.zeros(oldspec.shape[1])
1286 vec_snr = numpy.zeros(oldspec.shape[1])
1287
1287
1288 # oldspec = numpy.ma.masked_invalid(oldspec)
1288 # oldspec = numpy.ma.masked_invalid(oldspec)
1289 for ind in range(oldspec.shape[1]):
1289 for ind in range(oldspec.shape[1]):
1290
1290
1291 spec = oldspec[:,ind]
1291 spec = oldspec[:,ind]
1292 aux = spec*fwindow
1292 aux = spec*fwindow
1293 max_spec = aux.max()
1293 max_spec = aux.max()
1294 m = aux.tolist().index(max_spec)
1294 m = aux.tolist().index(max_spec)
1295
1295
1296 # Smooth
1296 # Smooth
1297 if (smooth == 0):
1297 if (smooth == 0):
1298 spec2 = spec
1298 spec2 = spec
1299 else:
1299 else:
1300 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1300 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1301
1301
1302 # Moments Estimation
1302 # Moments Estimation
1303 bb = spec2[numpy.arange(m,spec2.size)]
1303 bb = spec2[numpy.arange(m,spec2.size)]
1304 bb = (bb<n0).nonzero()
1304 bb = (bb<n0).nonzero()
1305 bb = bb[0]
1305 bb = bb[0]
1306
1306
1307 ss = spec2[numpy.arange(0,m + 1)]
1307 ss = spec2[numpy.arange(0,m + 1)]
1308 ss = (ss<n0).nonzero()
1308 ss = (ss<n0).nonzero()
1309 ss = ss[0]
1309 ss = ss[0]
1310
1310
1311 if (bb.size == 0):
1311 if (bb.size == 0):
1312 bb0 = spec.size - 1 - m
1312 bb0 = spec.size - 1 - m
1313 else:
1313 else:
1314 bb0 = bb[0] - 1
1314 bb0 = bb[0] - 1
1315 if (bb0 < 0):
1315 if (bb0 < 0):
1316 bb0 = 0
1316 bb0 = 0
1317
1317
1318 if (ss.size == 0):
1318 if (ss.size == 0):
1319 ss1 = 1
1319 ss1 = 1
1320 else:
1320 else:
1321 ss1 = max(ss) + 1
1321 ss1 = max(ss) + 1
1322
1322
1323 if (ss1 > m):
1323 if (ss1 > m):
1324 ss1 = m
1324 ss1 = m
1325
1325
1326 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1326 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1327 #valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1327 #valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1328 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1328 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1329 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1329 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1330 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1330 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1331 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1331 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1332 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1332 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1333 snr = (spec2.mean()-n0)/n0
1333 snr = (spec2.mean()-n0)/n0
1334 if (snr < 1.e-20) :
1334 if (snr < 1.e-20) :
1335 snr = 1.e-20
1335 snr = 1.e-20
1336
1336
1337 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1337 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1338 vec_power[ind] = total_power
1338 vec_power[ind] = total_power
1339 vec_fd[ind] = fd
1339 vec_fd[ind] = fd
1340 vec_w[ind] = w
1340 vec_w[ind] = w
1341 vec_snr[ind] = snr
1341 vec_snr[ind] = snr
1342
1342
1343 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1343 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1344
1344
1345 #------------------ Get SA Parameters --------------------------
1345 #------------------ Get SA Parameters --------------------------
1346
1346
1347 def GetSAParameters(self):
1347 def GetSAParameters(self):
1348 #SA en frecuencia
1348 #SA en frecuencia
1349 pairslist = self.dataOut.groupList
1349 pairslist = self.dataOut.groupList
1350 num_pairs = len(pairslist)
1350 num_pairs = len(pairslist)
1351
1351
1352 vel = self.dataOut.abscissaList
1352 vel = self.dataOut.abscissaList
1353 spectra = self.dataOut.data_pre
1353 spectra = self.dataOut.data_pre
1354 cspectra = self.dataIn.data_cspc
1354 cspectra = self.dataIn.data_cspc
1355 delta_v = vel[1] - vel[0]
1355 delta_v = vel[1] - vel[0]
1356
1356
1357 #Calculating the power spectrum
1357 #Calculating the power spectrum
1358 spc_pow = numpy.sum(spectra, 3)*delta_v
1358 spc_pow = numpy.sum(spectra, 3)*delta_v
1359 #Normalizing Spectra
1359 #Normalizing Spectra
1360 norm_spectra = spectra/spc_pow
1360 norm_spectra = spectra/spc_pow
1361 #Calculating the norm_spectra at peak
1361 #Calculating the norm_spectra at peak
1362 max_spectra = numpy.max(norm_spectra, 3)
1362 max_spectra = numpy.max(norm_spectra, 3)
1363
1363
1364 #Normalizing Cross Spectra
1364 #Normalizing Cross Spectra
1365 norm_cspectra = numpy.zeros(cspectra.shape)
1365 norm_cspectra = numpy.zeros(cspectra.shape)
1366
1366
1367 for i in range(num_chan):
1367 for i in range(num_chan):
1368 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1368 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1369
1369
1370 max_cspectra = numpy.max(norm_cspectra,2)
1370 max_cspectra = numpy.max(norm_cspectra,2)
1371 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1371 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1372
1372
1373 for i in range(num_pairs):
1373 for i in range(num_pairs):
1374 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1374 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1375 #------------------- Get Lags ----------------------------------
1375 #------------------- Get Lags ----------------------------------
1376
1376
1377 class SALags(Operation):
1377 class SALags(Operation):
1378 '''
1378 '''
1379 Function GetMoments()
1379 Function GetMoments()
1380
1380
1381 Input:
1381 Input:
1382 self.dataOut.data_pre
1382 self.dataOut.data_pre
1383 self.dataOut.abscissaList
1383 self.dataOut.abscissaList
1384 self.dataOut.noise
1384 self.dataOut.noise
1385 self.dataOut.normFactor
1385 self.dataOut.normFactor
1386 self.dataOut.data_snr
1386 self.dataOut.data_snr
1387 self.dataOut.groupList
1387 self.dataOut.groupList
1388 self.dataOut.nChannels
1388 self.dataOut.nChannels
1389
1389
1390 Affected:
1390 Affected:
1391 self.dataOut.data_param
1391 self.dataOut.data_param
1392
1392
1393 '''
1393 '''
1394 def run(self, dataOut):
1394 def run(self, dataOut):
1395 data_acf = dataOut.data_pre[0]
1395 data_acf = dataOut.data_pre[0]
1396 data_ccf = dataOut.data_pre[1]
1396 data_ccf = dataOut.data_pre[1]
1397 normFactor_acf = dataOut.normFactor[0]
1397 normFactor_acf = dataOut.normFactor[0]
1398 normFactor_ccf = dataOut.normFactor[1]
1398 normFactor_ccf = dataOut.normFactor[1]
1399 pairs_acf = dataOut.groupList[0]
1399 pairs_acf = dataOut.groupList[0]
1400 pairs_ccf = dataOut.groupList[1]
1400 pairs_ccf = dataOut.groupList[1]
1401
1401
1402 nHeights = dataOut.nHeights
1402 nHeights = dataOut.nHeights
1403 absc = dataOut.abscissaList
1403 absc = dataOut.abscissaList
1404 noise = dataOut.noise
1404 noise = dataOut.noise
1405 SNR = dataOut.data_snr
1405 SNR = dataOut.data_snr
1406 nChannels = dataOut.nChannels
1406 nChannels = dataOut.nChannels
1407 # pairsList = dataOut.groupList
1407 # pairsList = dataOut.groupList
1408 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1408 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1409
1409
1410 for l in range(len(pairs_acf)):
1410 for l in range(len(pairs_acf)):
1411 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1411 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1412
1412
1413 for l in range(len(pairs_ccf)):
1413 for l in range(len(pairs_ccf)):
1414 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1414 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1415
1415
1416 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1416 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1417 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1417 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1418 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1418 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1419 return
1419 return
1420
1420
1421 # def __getPairsAutoCorr(self, pairsList, nChannels):
1421 # def __getPairsAutoCorr(self, pairsList, nChannels):
1422 #
1422 #
1423 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1423 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1424 #
1424 #
1425 # for l in range(len(pairsList)):
1425 # for l in range(len(pairsList)):
1426 # firstChannel = pairsList[l][0]
1426 # firstChannel = pairsList[l][0]
1427 # secondChannel = pairsList[l][1]
1427 # secondChannel = pairsList[l][1]
1428 #
1428 #
1429 # #Obteniendo pares de Autocorrelacion
1429 # #Obteniendo pares de Autocorrelacion
1430 # if firstChannel == secondChannel:
1430 # if firstChannel == secondChannel:
1431 # pairsAutoCorr[firstChannel] = int(l)
1431 # pairsAutoCorr[firstChannel] = int(l)
1432 #
1432 #
1433 # pairsAutoCorr = pairsAutoCorr.astype(int)
1433 # pairsAutoCorr = pairsAutoCorr.astype(int)
1434 #
1434 #
1435 # pairsCrossCorr = range(len(pairsList))
1435 # pairsCrossCorr = range(len(pairsList))
1436 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1436 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1437 #
1437 #
1438 # return pairsAutoCorr, pairsCrossCorr
1438 # return pairsAutoCorr, pairsCrossCorr
1439
1439
1440 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1440 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1441
1441
1442 lag0 = data_acf.shape[1]/2
1442 lag0 = data_acf.shape[1]/2
1443 #Funcion de Autocorrelacion
1443 #Funcion de Autocorrelacion
1444 mean_acf = stats.nanmean(data_acf, axis = 0)
1444 mean_acf = stats.nanmean(data_acf, axis = 0)
1445
1445
1446 #Obtencion Indice de TauCross
1446 #Obtencion Indice de TauCross
1447 ind_ccf = data_ccf.argmax(axis = 1)
1447 ind_ccf = data_ccf.argmax(axis = 1)
1448 #Obtencion Indice de TauAuto
1448 #Obtencion Indice de TauAuto
1449 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1449 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1450 ccf_lag0 = data_ccf[:,lag0,:]
1450 ccf_lag0 = data_ccf[:,lag0,:]
1451
1451
1452 for i in range(ccf_lag0.shape[0]):
1452 for i in range(ccf_lag0.shape[0]):
1453 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1453 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1454
1454
1455 #Obtencion de TauCross y TauAuto
1455 #Obtencion de TauCross y TauAuto
1456 tau_ccf = lagRange[ind_ccf]
1456 tau_ccf = lagRange[ind_ccf]
1457 tau_acf = lagRange[ind_acf]
1457 tau_acf = lagRange[ind_acf]
1458
1458
1459 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1459 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1460
1460
1461 tau_ccf[Nan1,Nan2] = numpy.nan
1461 tau_ccf[Nan1,Nan2] = numpy.nan
1462 tau_acf[Nan1,Nan2] = numpy.nan
1462 tau_acf[Nan1,Nan2] = numpy.nan
1463 tau = numpy.vstack((tau_ccf,tau_acf))
1463 tau = numpy.vstack((tau_ccf,tau_acf))
1464
1464
1465 return tau
1465 return tau
1466
1466
1467 def __calculateLag1Phase(self, data, lagTRange):
1467 def __calculateLag1Phase(self, data, lagTRange):
1468 data1 = stats.nanmean(data, axis = 0)
1468 data1 = stats.nanmean(data, axis = 0)
1469 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1469 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1470
1470
1471 phase = numpy.angle(data1[lag1,:])
1471 phase = numpy.angle(data1[lag1,:])
1472
1472
1473 return phase
1473 return phase
1474
1474
1475 class SpectralFitting(Operation):
1475 class SpectralFitting(Operation):
1476 '''
1476 '''
1477 Function GetMoments()
1477 Function GetMoments()
1478
1478
1479 Input:
1479 Input:
1480 Output:
1480 Output:
1481 Variables modified:
1481 Variables modified:
1482 '''
1482 '''
1483
1483
1484 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1484 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1485
1485
1486
1486
1487 if path != None:
1487 if path != None:
1488 sys.path.append(path)
1488 sys.path.append(path)
1489 self.dataOut.library = importlib.import_module(file)
1489 self.dataOut.library = importlib.import_module(file)
1490
1490
1491 #To be inserted as a parameter
1491 #To be inserted as a parameter
1492 groupArray = numpy.array(groupList)
1492 groupArray = numpy.array(groupList)
1493 # groupArray = numpy.array([[0,1],[2,3]])
1493 # groupArray = numpy.array([[0,1],[2,3]])
1494 self.dataOut.groupList = groupArray
1494 self.dataOut.groupList = groupArray
1495
1495
1496 nGroups = groupArray.shape[0]
1496 nGroups = groupArray.shape[0]
1497 nChannels = self.dataIn.nChannels
1497 nChannels = self.dataIn.nChannels
1498 nHeights=self.dataIn.heightList.size
1498 nHeights=self.dataIn.heightList.size
1499
1499
1500 #Parameters Array
1500 #Parameters Array
1501 self.dataOut.data_param = None
1501 self.dataOut.data_param = None
1502
1502
1503 #Set constants
1503 #Set constants
1504 constants = self.dataOut.library.setConstants(self.dataIn)
1504 constants = self.dataOut.library.setConstants(self.dataIn)
1505 self.dataOut.constants = constants
1505 self.dataOut.constants = constants
1506 M = self.dataIn.normFactor
1506 M = self.dataIn.normFactor
1507 N = self.dataIn.nFFTPoints
1507 N = self.dataIn.nFFTPoints
1508 ippSeconds = self.dataIn.ippSeconds
1508 ippSeconds = self.dataIn.ippSeconds
1509 K = self.dataIn.nIncohInt
1509 K = self.dataIn.nIncohInt
1510 pairsArray = numpy.array(self.dataIn.pairsList)
1510 pairsArray = numpy.array(self.dataIn.pairsList)
1511
1511
1512 #List of possible combinations
1512 #List of possible combinations
1513 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1513 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1514 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1514 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1515
1515
1516 if getSNR:
1516 if getSNR:
1517 listChannels = groupArray.reshape((groupArray.size))
1517 listChannels = groupArray.reshape((groupArray.size))
1518 listChannels.sort()
1518 listChannels.sort()
1519 noise = self.dataIn.getNoise()
1519 noise = self.dataIn.getNoise()
1520 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1520 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1521
1521
1522 for i in range(nGroups):
1522 for i in range(nGroups):
1523 coord = groupArray[i,:]
1523 coord = groupArray[i,:]
1524
1524
1525 #Input data array
1525 #Input data array
1526 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1526 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1527 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1527 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1528
1528
1529 #Cross Spectra data array for Covariance Matrixes
1529 #Cross Spectra data array for Covariance Matrixes
1530 ind = 0
1530 ind = 0
1531 for pairs in listComb:
1531 for pairs in listComb:
1532 pairsSel = numpy.array([coord[x],coord[y]])
1532 pairsSel = numpy.array([coord[x],coord[y]])
1533 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1533 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1534 ind += 1
1534 ind += 1
1535 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1535 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1536 dataCross = dataCross**2/K
1536 dataCross = dataCross**2/K
1537
1537
1538 for h in range(nHeights):
1538 for h in range(nHeights):
1539
1539
1540 #Input
1540 #Input
1541 d = data[:,h]
1541 d = data[:,h]
1542
1542
1543 #Covariance Matrix
1543 #Covariance Matrix
1544 D = numpy.diag(d**2/K)
1544 D = numpy.diag(d**2/K)
1545 ind = 0
1545 ind = 0
1546 for pairs in listComb:
1546 for pairs in listComb:
1547 #Coordinates in Covariance Matrix
1547 #Coordinates in Covariance Matrix
1548 x = pairs[0]
1548 x = pairs[0]
1549 y = pairs[1]
1549 y = pairs[1]
1550 #Channel Index
1550 #Channel Index
1551 S12 = dataCross[ind,:,h]
1551 S12 = dataCross[ind,:,h]
1552 D12 = numpy.diag(S12)
1552 D12 = numpy.diag(S12)
1553 #Completing Covariance Matrix with Cross Spectras
1553 #Completing Covariance Matrix with Cross Spectras
1554 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1554 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1555 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1555 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1556 ind += 1
1556 ind += 1
1557 Dinv=numpy.linalg.inv(D)
1557 Dinv=numpy.linalg.inv(D)
1558 L=numpy.linalg.cholesky(Dinv)
1558 L=numpy.linalg.cholesky(Dinv)
1559 LT=L.T
1559 LT=L.T
1560
1560
1561 dp = numpy.dot(LT,d)
1561 dp = numpy.dot(LT,d)
1562
1562
1563 #Initial values
1563 #Initial values
1564 data_spc = self.dataIn.data_spc[coord,:,h]
1564 data_spc = self.dataIn.data_spc[coord,:,h]
1565
1565
1566 if (h>0)and(error1[3]<5):
1566 if (h>0)and(error1[3]<5):
1567 p0 = self.dataOut.data_param[i,:,h-1]
1567 p0 = self.dataOut.data_param[i,:,h-1]
1568 else:
1568 else:
1569 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1569 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1570
1570
1571 try:
1571 try:
1572 #Least Squares
1572 #Least Squares
1573 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1573 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1574 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1574 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1575 #Chi square error
1575 #Chi square error
1576 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1576 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1577 #Error with Jacobian
1577 #Error with Jacobian
1578 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1578 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1579 except:
1579 except:
1580 minp = p0*numpy.nan
1580 minp = p0*numpy.nan
1581 error0 = numpy.nan
1581 error0 = numpy.nan
1582 error1 = p0*numpy.nan
1582 error1 = p0*numpy.nan
1583
1583
1584 #Save
1584 #Save
1585 if self.dataOut.data_param is None:
1585 if self.dataOut.data_param is None:
1586 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1586 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1587 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1587 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1588
1588
1589 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1589 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1590 self.dataOut.data_param[i,:,h] = minp
1590 self.dataOut.data_param[i,:,h] = minp
1591 return
1591 return
1592
1592
1593 def __residFunction(self, p, dp, LT, constants):
1593 def __residFunction(self, p, dp, LT, constants):
1594
1594
1595 fm = self.dataOut.library.modelFunction(p, constants)
1595 fm = self.dataOut.library.modelFunction(p, constants)
1596 fmp=numpy.dot(LT,fm)
1596 fmp=numpy.dot(LT,fm)
1597
1597
1598 return dp-fmp
1598 return dp-fmp
1599
1599
1600 def __getSNR(self, z, noise):
1600 def __getSNR(self, z, noise):
1601
1601
1602 avg = numpy.average(z, axis=1)
1602 avg = numpy.average(z, axis=1)
1603 SNR = (avg.T-noise)/noise
1603 SNR = (avg.T-noise)/noise
1604 SNR = SNR.T
1604 SNR = SNR.T
1605 return SNR
1605 return SNR
1606
1606
1607 def __chisq(p,chindex,hindex):
1607 def __chisq(p,chindex,hindex):
1608 #similar to Resid but calculates CHI**2
1608 #similar to Resid but calculates CHI**2
1609 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1609 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1610 dp=numpy.dot(LT,d)
1610 dp=numpy.dot(LT,d)
1611 fmp=numpy.dot(LT,fm)
1611 fmp=numpy.dot(LT,fm)
1612 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1612 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1613 return chisq
1613 return chisq
1614
1614
1615 class WindProfiler(Operation):
1615 class WindProfiler(Operation):
1616
1616
1617 __isConfig = False
1617 __isConfig = False
1618
1618
1619 __initime = None
1619 __initime = None
1620 __lastdatatime = None
1620 __lastdatatime = None
1621 __integrationtime = None
1621 __integrationtime = None
1622
1622
1623 __buffer = None
1623 __buffer = None
1624
1624
1625 __dataReady = False
1625 __dataReady = False
1626
1626
1627 __firstdata = None
1627 __firstdata = None
1628
1628
1629 n = None
1629 n = None
1630
1630
1631 def __init__(self):
1631 def __init__(self):
1632 Operation.__init__(self)
1632 Operation.__init__(self)
1633
1633
1634 def __calculateCosDir(self, elev, azim):
1634 def __calculateCosDir(self, elev, azim):
1635 zen = (90 - elev)*numpy.pi/180
1635 zen = (90 - elev)*numpy.pi/180
1636 azim = azim*numpy.pi/180
1636 azim = azim*numpy.pi/180
1637 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1637 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1638 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1638 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1639
1639
1640 signX = numpy.sign(numpy.cos(azim))
1640 signX = numpy.sign(numpy.cos(azim))
1641 signY = numpy.sign(numpy.sin(azim))
1641 signY = numpy.sign(numpy.sin(azim))
1642
1642
1643 cosDirX = numpy.copysign(cosDirX, signX)
1643 cosDirX = numpy.copysign(cosDirX, signX)
1644 cosDirY = numpy.copysign(cosDirY, signY)
1644 cosDirY = numpy.copysign(cosDirY, signY)
1645 return cosDirX, cosDirY
1645 return cosDirX, cosDirY
1646
1646
1647 def __calculateAngles(self, theta_x, theta_y, azimuth):
1647 def __calculateAngles(self, theta_x, theta_y, azimuth):
1648
1648
1649 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1649 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1650 zenith_arr = numpy.arccos(dir_cosw)
1650 zenith_arr = numpy.arccos(dir_cosw)
1651 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1651 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1652
1652
1653 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1653 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1654 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1654 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1655
1655
1656 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1656 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1657
1657
1658 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1658 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1659
1659
1660 #
1660 #
1661 if horOnly:
1661 if horOnly:
1662 A = numpy.c_[dir_cosu,dir_cosv]
1662 A = numpy.c_[dir_cosu,dir_cosv]
1663 else:
1663 else:
1664 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1664 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1665 A = numpy.asmatrix(A)
1665 A = numpy.asmatrix(A)
1666 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1666 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1667
1667
1668 return A1
1668 return A1
1669
1669
1670 def __correctValues(self, heiRang, phi, velRadial, SNR):
1670 def __correctValues(self, heiRang, phi, velRadial, SNR):
1671 listPhi = phi.tolist()
1671 listPhi = phi.tolist()
1672 maxid = listPhi.index(max(listPhi))
1672 maxid = listPhi.index(max(listPhi))
1673 minid = listPhi.index(min(listPhi))
1673 minid = listPhi.index(min(listPhi))
1674
1674
1675 rango = list(range(len(phi)))
1675 rango = list(range(len(phi)))
1676 # rango = numpy.delete(rango,maxid)
1676 # rango = numpy.delete(rango,maxid)
1677
1677
1678 heiRang1 = heiRang*math.cos(phi[maxid])
1678 heiRang1 = heiRang*math.cos(phi[maxid])
1679 heiRangAux = heiRang*math.cos(phi[minid])
1679 heiRangAux = heiRang*math.cos(phi[minid])
1680 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1680 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1681 heiRang1 = numpy.delete(heiRang1,indOut)
1681 heiRang1 = numpy.delete(heiRang1,indOut)
1682
1682
1683 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1683 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1684 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1684 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1685
1685
1686 for i in rango:
1686 for i in rango:
1687 x = heiRang*math.cos(phi[i])
1687 x = heiRang*math.cos(phi[i])
1688 y1 = velRadial[i,:]
1688 y1 = velRadial[i,:]
1689 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1689 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1690
1690
1691 x1 = heiRang1
1691 x1 = heiRang1
1692 y11 = f1(x1)
1692 y11 = f1(x1)
1693
1693
1694 y2 = SNR[i,:]
1694 y2 = SNR[i,:]
1695 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1695 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1696 y21 = f2(x1)
1696 y21 = f2(x1)
1697
1697
1698 velRadial1[i,:] = y11
1698 velRadial1[i,:] = y11
1699 SNR1[i,:] = y21
1699 SNR1[i,:] = y21
1700
1700
1701 return heiRang1, velRadial1, SNR1
1701 return heiRang1, velRadial1, SNR1
1702
1702
1703 def __calculateVelUVW(self, A, velRadial):
1703 def __calculateVelUVW(self, A, velRadial):
1704
1704
1705 #Operacion Matricial
1705 #Operacion Matricial
1706 # velUVW = numpy.zeros((velRadial.shape[1],3))
1706 # velUVW = numpy.zeros((velRadial.shape[1],3))
1707 # for ind in range(velRadial.shape[1]):
1707 # for ind in range(velRadial.shape[1]):
1708 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1708 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1709 # velUVW = velUVW.transpose()
1709 # velUVW = velUVW.transpose()
1710 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1710 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1711 velUVW[:,:] = numpy.dot(A,velRadial)
1711 velUVW[:,:] = numpy.dot(A,velRadial)
1712
1712
1713
1713
1714 return velUVW
1714 return velUVW
1715
1715
1716 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1716 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1717
1717
1718 def techniqueDBS(self, kwargs):
1718 def techniqueDBS(self, kwargs):
1719 """
1719 """
1720 Function that implements Doppler Beam Swinging (DBS) technique.
1720 Function that implements Doppler Beam Swinging (DBS) technique.
1721
1721
1722 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1722 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1723 Direction correction (if necessary), Ranges and SNR
1723 Direction correction (if necessary), Ranges and SNR
1724
1724
1725 Output: Winds estimation (Zonal, Meridional and Vertical)
1725 Output: Winds estimation (Zonal, Meridional and Vertical)
1726
1726
1727 Parameters affected: Winds, height range, SNR
1727 Parameters affected: Winds, height range, SNR
1728 """
1728 """
1729 velRadial0 = kwargs['velRadial']
1729 velRadial0 = kwargs['velRadial']
1730 heiRang = kwargs['heightList']
1730 heiRang = kwargs['heightList']
1731 SNR0 = kwargs['SNR']
1731 SNR0 = kwargs['SNR']
1732
1732
1733 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1733 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1734 theta_x = numpy.array(kwargs['dirCosx'])
1734 theta_x = numpy.array(kwargs['dirCosx'])
1735 theta_y = numpy.array(kwargs['dirCosy'])
1735 theta_y = numpy.array(kwargs['dirCosy'])
1736 else:
1736 else:
1737 elev = numpy.array(kwargs['elevation'])
1737 elev = numpy.array(kwargs['elevation'])
1738 azim = numpy.array(kwargs['azimuth'])
1738 azim = numpy.array(kwargs['azimuth'])
1739 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1739 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1740 azimuth = kwargs['correctAzimuth']
1740 azimuth = kwargs['correctAzimuth']
1741 if 'horizontalOnly' in kwargs:
1741 if 'horizontalOnly' in kwargs:
1742 horizontalOnly = kwargs['horizontalOnly']
1742 horizontalOnly = kwargs['horizontalOnly']
1743 else: horizontalOnly = False
1743 else: horizontalOnly = False
1744 if 'correctFactor' in kwargs:
1744 if 'correctFactor' in kwargs:
1745 correctFactor = kwargs['correctFactor']
1745 correctFactor = kwargs['correctFactor']
1746 else: correctFactor = 1
1746 else: correctFactor = 1
1747 if 'channelList' in kwargs:
1747 if 'channelList' in kwargs:
1748 channelList = kwargs['channelList']
1748 channelList = kwargs['channelList']
1749 if len(channelList) == 2:
1749 if len(channelList) == 2:
1750 horizontalOnly = True
1750 horizontalOnly = True
1751 arrayChannel = numpy.array(channelList)
1751 arrayChannel = numpy.array(channelList)
1752 param = param[arrayChannel,:,:]
1752 param = param[arrayChannel,:,:]
1753 theta_x = theta_x[arrayChannel]
1753 theta_x = theta_x[arrayChannel]
1754 theta_y = theta_y[arrayChannel]
1754 theta_y = theta_y[arrayChannel]
1755
1755
1756 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1756 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1757 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1757 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1758 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1758 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1759
1759
1760 #Calculo de Componentes de la velocidad con DBS
1760 #Calculo de Componentes de la velocidad con DBS
1761 winds = self.__calculateVelUVW(A,velRadial1)
1761 winds = self.__calculateVelUVW(A,velRadial1)
1762
1762
1763 return winds, heiRang1, SNR1
1763 return winds, heiRang1, SNR1
1764
1764
1765 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1765 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1766
1766
1767 nPairs = len(pairs_ccf)
1767 nPairs = len(pairs_ccf)
1768 posx = numpy.asarray(posx)
1768 posx = numpy.asarray(posx)
1769 posy = numpy.asarray(posy)
1769 posy = numpy.asarray(posy)
1770
1770
1771 #Rotacion Inversa para alinear con el azimuth
1771 #Rotacion Inversa para alinear con el azimuth
1772 if azimuth!= None:
1772 if azimuth!= None:
1773 azimuth = azimuth*math.pi/180
1773 azimuth = azimuth*math.pi/180
1774 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1774 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1775 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1775 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1776 else:
1776 else:
1777 posx1 = posx
1777 posx1 = posx
1778 posy1 = posy
1778 posy1 = posy
1779
1779
1780 #Calculo de Distancias
1780 #Calculo de Distancias
1781 distx = numpy.zeros(nPairs)
1781 distx = numpy.zeros(nPairs)
1782 disty = numpy.zeros(nPairs)
1782 disty = numpy.zeros(nPairs)
1783 dist = numpy.zeros(nPairs)
1783 dist = numpy.zeros(nPairs)
1784 ang = numpy.zeros(nPairs)
1784 ang = numpy.zeros(nPairs)
1785
1785
1786 for i in range(nPairs):
1786 for i in range(nPairs):
1787 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1787 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1788 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1788 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1789 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1789 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1790 ang[i] = numpy.arctan2(disty[i],distx[i])
1790 ang[i] = numpy.arctan2(disty[i],distx[i])
1791
1791
1792 return distx, disty, dist, ang
1792 return distx, disty, dist, ang
1793 #Calculo de Matrices
1793 #Calculo de Matrices
1794 # nPairs = len(pairs)
1794 # nPairs = len(pairs)
1795 # ang1 = numpy.zeros((nPairs, 2, 1))
1795 # ang1 = numpy.zeros((nPairs, 2, 1))
1796 # dist1 = numpy.zeros((nPairs, 2, 1))
1796 # dist1 = numpy.zeros((nPairs, 2, 1))
1797 #
1797 #
1798 # for j in range(nPairs):
1798 # for j in range(nPairs):
1799 # dist1[j,0,0] = dist[pairs[j][0]]
1799 # dist1[j,0,0] = dist[pairs[j][0]]
1800 # dist1[j,1,0] = dist[pairs[j][1]]
1800 # dist1[j,1,0] = dist[pairs[j][1]]
1801 # ang1[j,0,0] = ang[pairs[j][0]]
1801 # ang1[j,0,0] = ang[pairs[j][0]]
1802 # ang1[j,1,0] = ang[pairs[j][1]]
1802 # ang1[j,1,0] = ang[pairs[j][1]]
1803 #
1803 #
1804 # return distx,disty, dist1,ang1
1804 # return distx,disty, dist1,ang1
1805
1805
1806
1806
1807 def __calculateVelVer(self, phase, lagTRange, _lambda):
1807 def __calculateVelVer(self, phase, lagTRange, _lambda):
1808
1808
1809 Ts = lagTRange[1] - lagTRange[0]
1809 Ts = lagTRange[1] - lagTRange[0]
1810 velW = -_lambda*phase/(4*math.pi*Ts)
1810 velW = -_lambda*phase/(4*math.pi*Ts)
1811
1811
1812 return velW
1812 return velW
1813
1813
1814 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1814 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1815 nPairs = tau1.shape[0]
1815 nPairs = tau1.shape[0]
1816 nHeights = tau1.shape[1]
1816 nHeights = tau1.shape[1]
1817 vel = numpy.zeros((nPairs,3,nHeights))
1817 vel = numpy.zeros((nPairs,3,nHeights))
1818 dist1 = numpy.reshape(dist, (dist.size,1))
1818 dist1 = numpy.reshape(dist, (dist.size,1))
1819
1819
1820 angCos = numpy.cos(ang)
1820 angCos = numpy.cos(ang)
1821 angSin = numpy.sin(ang)
1821 angSin = numpy.sin(ang)
1822
1822
1823 vel0 = dist1*tau1/(2*tau2**2)
1823 vel0 = dist1*tau1/(2*tau2**2)
1824 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1824 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1825 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1825 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1826
1826
1827 ind = numpy.where(numpy.isinf(vel))
1827 ind = numpy.where(numpy.isinf(vel))
1828 vel[ind] = numpy.nan
1828 vel[ind] = numpy.nan
1829
1829
1830 return vel
1830 return vel
1831
1831
1832 # def __getPairsAutoCorr(self, pairsList, nChannels):
1832 # def __getPairsAutoCorr(self, pairsList, nChannels):
1833 #
1833 #
1834 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1834 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1835 #
1835 #
1836 # for l in range(len(pairsList)):
1836 # for l in range(len(pairsList)):
1837 # firstChannel = pairsList[l][0]
1837 # firstChannel = pairsList[l][0]
1838 # secondChannel = pairsList[l][1]
1838 # secondChannel = pairsList[l][1]
1839 #
1839 #
1840 # #Obteniendo pares de Autocorrelacion
1840 # #Obteniendo pares de Autocorrelacion
1841 # if firstChannel == secondChannel:
1841 # if firstChannel == secondChannel:
1842 # pairsAutoCorr[firstChannel] = int(l)
1842 # pairsAutoCorr[firstChannel] = int(l)
1843 #
1843 #
1844 # pairsAutoCorr = pairsAutoCorr.astype(int)
1844 # pairsAutoCorr = pairsAutoCorr.astype(int)
1845 #
1845 #
1846 # pairsCrossCorr = range(len(pairsList))
1846 # pairsCrossCorr = range(len(pairsList))
1847 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1847 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1848 #
1848 #
1849 # return pairsAutoCorr, pairsCrossCorr
1849 # return pairsAutoCorr, pairsCrossCorr
1850
1850
1851 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1851 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1852 def techniqueSA(self, kwargs):
1852 def techniqueSA(self, kwargs):
1853
1853
1854 """
1854 """
1855 Function that implements Spaced Antenna (SA) technique.
1855 Function that implements Spaced Antenna (SA) technique.
1856
1856
1857 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1857 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1858 Direction correction (if necessary), Ranges and SNR
1858 Direction correction (if necessary), Ranges and SNR
1859
1859
1860 Output: Winds estimation (Zonal, Meridional and Vertical)
1860 Output: Winds estimation (Zonal, Meridional and Vertical)
1861
1861
1862 Parameters affected: Winds
1862 Parameters affected: Winds
1863 """
1863 """
1864 position_x = kwargs['positionX']
1864 position_x = kwargs['positionX']
1865 position_y = kwargs['positionY']
1865 position_y = kwargs['positionY']
1866 azimuth = kwargs['azimuth']
1866 azimuth = kwargs['azimuth']
1867
1867
1868 if 'correctFactor' in kwargs:
1868 if 'correctFactor' in kwargs:
1869 correctFactor = kwargs['correctFactor']
1869 correctFactor = kwargs['correctFactor']
1870 else:
1870 else:
1871 correctFactor = 1
1871 correctFactor = 1
1872
1872
1873 groupList = kwargs['groupList']
1873 groupList = kwargs['groupList']
1874 pairs_ccf = groupList[1]
1874 pairs_ccf = groupList[1]
1875 tau = kwargs['tau']
1875 tau = kwargs['tau']
1876 _lambda = kwargs['_lambda']
1876 _lambda = kwargs['_lambda']
1877
1877
1878 #Cross Correlation pairs obtained
1878 #Cross Correlation pairs obtained
1879 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1879 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1880 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1880 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1881 # pairsSelArray = numpy.array(pairsSelected)
1881 # pairsSelArray = numpy.array(pairsSelected)
1882 # pairs = []
1882 # pairs = []
1883 #
1883 #
1884 # #Wind estimation pairs obtained
1884 # #Wind estimation pairs obtained
1885 # for i in range(pairsSelArray.shape[0]/2):
1885 # for i in range(pairsSelArray.shape[0]/2):
1886 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1886 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1887 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1887 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1888 # pairs.append((ind1,ind2))
1888 # pairs.append((ind1,ind2))
1889
1889
1890 indtau = tau.shape[0]/2
1890 indtau = tau.shape[0]/2
1891 tau1 = tau[:indtau,:]
1891 tau1 = tau[:indtau,:]
1892 tau2 = tau[indtau:-1,:]
1892 tau2 = tau[indtau:-1,:]
1893 # tau1 = tau1[pairs,:]
1893 # tau1 = tau1[pairs,:]
1894 # tau2 = tau2[pairs,:]
1894 # tau2 = tau2[pairs,:]
1895 phase1 = tau[-1,:]
1895 phase1 = tau[-1,:]
1896
1896
1897 #---------------------------------------------------------------------
1897 #---------------------------------------------------------------------
1898 #Metodo Directo
1898 #Metodo Directo
1899 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1899 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1900 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1900 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1901 winds = stats.nanmean(winds, axis=0)
1901 winds = stats.nanmean(winds, axis=0)
1902 #---------------------------------------------------------------------
1902 #---------------------------------------------------------------------
1903 #Metodo General
1903 #Metodo General
1904 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1904 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1905 # #Calculo Coeficientes de Funcion de Correlacion
1905 # #Calculo Coeficientes de Funcion de Correlacion
1906 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1906 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1907 # #Calculo de Velocidades
1907 # #Calculo de Velocidades
1908 # winds = self.calculateVelUV(F,G,A,B,H)
1908 # winds = self.calculateVelUV(F,G,A,B,H)
1909
1909
1910 #---------------------------------------------------------------------
1910 #---------------------------------------------------------------------
1911 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1911 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1912 winds = correctFactor*winds
1912 winds = correctFactor*winds
1913 return winds
1913 return winds
1914
1914
1915 def __checkTime(self, currentTime, paramInterval, outputInterval):
1915 def __checkTime(self, currentTime, paramInterval, outputInterval):
1916
1916
1917 dataTime = currentTime + paramInterval
1917 dataTime = currentTime + paramInterval
1918 deltaTime = dataTime - self.__initime
1918 deltaTime = dataTime - self.__initime
1919
1919
1920 if deltaTime >= outputInterval or deltaTime < 0:
1920 if deltaTime >= outputInterval or deltaTime < 0:
1921 self.__dataReady = True
1921 self.__dataReady = True
1922 return
1922 return
1923
1923
1924 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1924 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1925 '''
1925 '''
1926 Function that implements winds estimation technique with detected meteors.
1926 Function that implements winds estimation technique with detected meteors.
1927
1927
1928 Input: Detected meteors, Minimum meteor quantity to wind estimation
1928 Input: Detected meteors, Minimum meteor quantity to wind estimation
1929
1929
1930 Output: Winds estimation (Zonal and Meridional)
1930 Output: Winds estimation (Zonal and Meridional)
1931
1931
1932 Parameters affected: Winds
1932 Parameters affected: Winds
1933 '''
1933 '''
1934 #Settings
1934 #Settings
1935 nInt = (heightMax - heightMin)/2
1935 nInt = (heightMax - heightMin)/2
1936 nInt = int(nInt)
1936 nInt = int(nInt)
1937 winds = numpy.zeros((2,nInt))*numpy.nan
1937 winds = numpy.zeros((2,nInt))*numpy.nan
1938
1938
1939 #Filter errors
1939 #Filter errors
1940 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1940 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1941 finalMeteor = arrayMeteor[error,:]
1941 finalMeteor = arrayMeteor[error,:]
1942
1942
1943 #Meteor Histogram
1943 #Meteor Histogram
1944 finalHeights = finalMeteor[:,2]
1944 finalHeights = finalMeteor[:,2]
1945 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1945 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1946 nMeteorsPerI = hist[0]
1946 nMeteorsPerI = hist[0]
1947 heightPerI = hist[1]
1947 heightPerI = hist[1]
1948
1948
1949 #Sort of meteors
1949 #Sort of meteors
1950 indSort = finalHeights.argsort()
1950 indSort = finalHeights.argsort()
1951 finalMeteor2 = finalMeteor[indSort,:]
1951 finalMeteor2 = finalMeteor[indSort,:]
1952
1952
1953 # Calculating winds
1953 # Calculating winds
1954 ind1 = 0
1954 ind1 = 0
1955 ind2 = 0
1955 ind2 = 0
1956
1956
1957 for i in range(nInt):
1957 for i in range(nInt):
1958 nMet = nMeteorsPerI[i]
1958 nMet = nMeteorsPerI[i]
1959 ind1 = ind2
1959 ind1 = ind2
1960 ind2 = ind1 + nMet
1960 ind2 = ind1 + nMet
1961
1961
1962 meteorAux = finalMeteor2[ind1:ind2,:]
1962 meteorAux = finalMeteor2[ind1:ind2,:]
1963
1963
1964 if meteorAux.shape[0] >= meteorThresh:
1964 if meteorAux.shape[0] >= meteorThresh:
1965 vel = meteorAux[:, 6]
1965 vel = meteorAux[:, 6]
1966 zen = meteorAux[:, 4]*numpy.pi/180
1966 zen = meteorAux[:, 4]*numpy.pi/180
1967 azim = meteorAux[:, 3]*numpy.pi/180
1967 azim = meteorAux[:, 3]*numpy.pi/180
1968
1968
1969 n = numpy.cos(zen)
1969 n = numpy.cos(zen)
1970 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1970 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1971 # l = m*numpy.tan(azim)
1971 # l = m*numpy.tan(azim)
1972 l = numpy.sin(zen)*numpy.sin(azim)
1972 l = numpy.sin(zen)*numpy.sin(azim)
1973 m = numpy.sin(zen)*numpy.cos(azim)
1973 m = numpy.sin(zen)*numpy.cos(azim)
1974
1974
1975 A = numpy.vstack((l, m)).transpose()
1975 A = numpy.vstack((l, m)).transpose()
1976 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1976 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1977 windsAux = numpy.dot(A1, vel)
1977 windsAux = numpy.dot(A1, vel)
1978
1978
1979 winds[0,i] = windsAux[0]
1979 winds[0,i] = windsAux[0]
1980 winds[1,i] = windsAux[1]
1980 winds[1,i] = windsAux[1]
1981
1981
1982 return winds, heightPerI[:-1]
1982 return winds, heightPerI[:-1]
1983
1983
1984 def techniqueNSM_SA(self, **kwargs):
1984 def techniqueNSM_SA(self, **kwargs):
1985 metArray = kwargs['metArray']
1985 metArray = kwargs['metArray']
1986 heightList = kwargs['heightList']
1986 heightList = kwargs['heightList']
1987 timeList = kwargs['timeList']
1987 timeList = kwargs['timeList']
1988
1988
1989 rx_location = kwargs['rx_location']
1989 rx_location = kwargs['rx_location']
1990 groupList = kwargs['groupList']
1990 groupList = kwargs['groupList']
1991 azimuth = kwargs['azimuth']
1991 azimuth = kwargs['azimuth']
1992 dfactor = kwargs['dfactor']
1992 dfactor = kwargs['dfactor']
1993 k = kwargs['k']
1993 k = kwargs['k']
1994
1994
1995 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1995 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1996 d = dist*dfactor
1996 d = dist*dfactor
1997 #Phase calculation
1997 #Phase calculation
1998 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1998 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1999
1999
2000 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2000 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2001
2001
2002 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2002 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2003 azimuth1 = azimuth1*numpy.pi/180
2003 azimuth1 = azimuth1*numpy.pi/180
2004
2004
2005 for i in range(heightList.size):
2005 for i in range(heightList.size):
2006 h = heightList[i]
2006 h = heightList[i]
2007 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2007 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2008 metHeight = metArray1[indH,:]
2008 metHeight = metArray1[indH,:]
2009 if metHeight.shape[0] >= 2:
2009 if metHeight.shape[0] >= 2:
2010 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2010 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2011 iazim = metHeight[:,1].astype(int)
2011 iazim = metHeight[:,1].astype(int)
2012 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2012 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2013 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2013 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2014 A = numpy.asmatrix(A)
2014 A = numpy.asmatrix(A)
2015 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2015 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2016 velHor = numpy.dot(A1,velAux)
2016 velHor = numpy.dot(A1,velAux)
2017
2017
2018 velEst[i,:] = numpy.squeeze(velHor)
2018 velEst[i,:] = numpy.squeeze(velHor)
2019 return velEst
2019 return velEst
2020
2020
2021 def __getPhaseSlope(self, metArray, heightList, timeList):
2021 def __getPhaseSlope(self, metArray, heightList, timeList):
2022 meteorList = []
2022 meteorList = []
2023 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2023 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2024 #Putting back together the meteor matrix
2024 #Putting back together the meteor matrix
2025 utctime = metArray[:,0]
2025 utctime = metArray[:,0]
2026 uniqueTime = numpy.unique(utctime)
2026 uniqueTime = numpy.unique(utctime)
2027
2027
2028 phaseDerThresh = 0.5
2028 phaseDerThresh = 0.5
2029 ippSeconds = timeList[1] - timeList[0]
2029 ippSeconds = timeList[1] - timeList[0]
2030 sec = numpy.where(timeList>1)[0][0]
2030 sec = numpy.where(timeList>1)[0][0]
2031 nPairs = metArray.shape[1] - 6
2031 nPairs = metArray.shape[1] - 6
2032 nHeights = len(heightList)
2032 nHeights = len(heightList)
2033
2033
2034 for t in uniqueTime:
2034 for t in uniqueTime:
2035 metArray1 = metArray[utctime==t,:]
2035 metArray1 = metArray[utctime==t,:]
2036 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2036 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2037 tmet = metArray1[:,1].astype(int)
2037 tmet = metArray1[:,1].astype(int)
2038 hmet = metArray1[:,2].astype(int)
2038 hmet = metArray1[:,2].astype(int)
2039
2039
2040 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2040 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2041 metPhase[:,:] = numpy.nan
2041 metPhase[:,:] = numpy.nan
2042 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2042 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2043
2043
2044 #Delete short trails
2044 #Delete short trails
2045 metBool = ~numpy.isnan(metPhase[0,:,:])
2045 metBool = ~numpy.isnan(metPhase[0,:,:])
2046 heightVect = numpy.sum(metBool, axis = 1)
2046 heightVect = numpy.sum(metBool, axis = 1)
2047 metBool[heightVect<sec,:] = False
2047 metBool[heightVect<sec,:] = False
2048 metPhase[:,heightVect<sec,:] = numpy.nan
2048 metPhase[:,heightVect<sec,:] = numpy.nan
2049
2049
2050 #Derivative
2050 #Derivative
2051 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2051 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2052 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2052 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2053 metPhase[phDerAux] = numpy.nan
2053 metPhase[phDerAux] = numpy.nan
2054
2054
2055 #--------------------------METEOR DETECTION -----------------------------------------
2055 #--------------------------METEOR DETECTION -----------------------------------------
2056 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2056 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2057
2057
2058 for p in numpy.arange(nPairs):
2058 for p in numpy.arange(nPairs):
2059 phase = metPhase[p,:,:]
2059 phase = metPhase[p,:,:]
2060 phDer = metDer[p,:,:]
2060 phDer = metDer[p,:,:]
2061
2061
2062 for h in indMet:
2062 for h in indMet:
2063 height = heightList[h]
2063 height = heightList[h]
2064 phase1 = phase[h,:] #82
2064 phase1 = phase[h,:] #82
2065 phDer1 = phDer[h,:]
2065 phDer1 = phDer[h,:]
2066
2066
2067 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2067 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2068
2068
2069 indValid = numpy.where(~numpy.isnan(phase1))[0]
2069 indValid = numpy.where(~numpy.isnan(phase1))[0]
2070 initMet = indValid[0]
2070 initMet = indValid[0]
2071 endMet = 0
2071 endMet = 0
2072
2072
2073 for i in range(len(indValid)-1):
2073 for i in range(len(indValid)-1):
2074
2074
2075 #Time difference
2075 #Time difference
2076 inow = indValid[i]
2076 inow = indValid[i]
2077 inext = indValid[i+1]
2077 inext = indValid[i+1]
2078 idiff = inext - inow
2078 idiff = inext - inow
2079 #Phase difference
2079 #Phase difference
2080 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2080 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2081
2081
2082 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2082 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2083 sizeTrail = inow - initMet + 1
2083 sizeTrail = inow - initMet + 1
2084 if sizeTrail>3*sec: #Too short meteors
2084 if sizeTrail>3*sec: #Too short meteors
2085 x = numpy.arange(initMet,inow+1)*ippSeconds
2085 x = numpy.arange(initMet,inow+1)*ippSeconds
2086 y = phase1[initMet:inow+1]
2086 y = phase1[initMet:inow+1]
2087 ynnan = ~numpy.isnan(y)
2087 ynnan = ~numpy.isnan(y)
2088 x = x[ynnan]
2088 x = x[ynnan]
2089 y = y[ynnan]
2089 y = y[ynnan]
2090 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2090 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2091 ylin = x*slope + intercept
2091 ylin = x*slope + intercept
2092 rsq = r_value**2
2092 rsq = r_value**2
2093 if rsq > 0.5:
2093 if rsq > 0.5:
2094 vel = slope#*height*1000/(k*d)
2094 vel = slope#*height*1000/(k*d)
2095 estAux = numpy.array([utctime,p,height, vel, rsq])
2095 estAux = numpy.array([utctime,p,height, vel, rsq])
2096 meteorList.append(estAux)
2096 meteorList.append(estAux)
2097 initMet = inext
2097 initMet = inext
2098 metArray2 = numpy.array(meteorList)
2098 metArray2 = numpy.array(meteorList)
2099
2099
2100 return metArray2
2100 return metArray2
2101
2101
2102 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2102 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2103
2103
2104 azimuth1 = numpy.zeros(len(pairslist))
2104 azimuth1 = numpy.zeros(len(pairslist))
2105 dist = numpy.zeros(len(pairslist))
2105 dist = numpy.zeros(len(pairslist))
2106
2106
2107 for i in range(len(rx_location)):
2107 for i in range(len(rx_location)):
2108 ch0 = pairslist[i][0]
2108 ch0 = pairslist[i][0]
2109 ch1 = pairslist[i][1]
2109 ch1 = pairslist[i][1]
2110
2110
2111 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2111 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2112 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2112 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2113 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2113 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2114 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2114 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2115
2115
2116 azimuth1 -= azimuth0
2116 azimuth1 -= azimuth0
2117 return azimuth1, dist
2117 return azimuth1, dist
2118
2118
2119 def techniqueNSM_DBS(self, **kwargs):
2119 def techniqueNSM_DBS(self, **kwargs):
2120 metArray = kwargs['metArray']
2120 metArray = kwargs['metArray']
2121 heightList = kwargs['heightList']
2121 heightList = kwargs['heightList']
2122 timeList = kwargs['timeList']
2122 timeList = kwargs['timeList']
2123 azimuth = kwargs['azimuth']
2123 azimuth = kwargs['azimuth']
2124 theta_x = numpy.array(kwargs['theta_x'])
2124 theta_x = numpy.array(kwargs['theta_x'])
2125 theta_y = numpy.array(kwargs['theta_y'])
2125 theta_y = numpy.array(kwargs['theta_y'])
2126
2126
2127 utctime = metArray[:,0]
2127 utctime = metArray[:,0]
2128 cmet = metArray[:,1].astype(int)
2128 cmet = metArray[:,1].astype(int)
2129 hmet = metArray[:,3].astype(int)
2129 hmet = metArray[:,3].astype(int)
2130 SNRmet = metArray[:,4]
2130 SNRmet = metArray[:,4]
2131 vmet = metArray[:,5]
2131 vmet = metArray[:,5]
2132 spcmet = metArray[:,6]
2132 spcmet = metArray[:,6]
2133
2133
2134 nChan = numpy.max(cmet) + 1
2134 nChan = numpy.max(cmet) + 1
2135 nHeights = len(heightList)
2135 nHeights = len(heightList)
2136
2136
2137 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2137 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2138 hmet = heightList[hmet]
2138 hmet = heightList[hmet]
2139 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2139 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2140
2140
2141 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2141 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2142
2142
2143 for i in range(nHeights - 1):
2143 for i in range(nHeights - 1):
2144 hmin = heightList[i]
2144 hmin = heightList[i]
2145 hmax = heightList[i + 1]
2145 hmax = heightList[i + 1]
2146
2146
2147 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2147 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2148 indthisH = numpy.where(thisH)
2148 indthisH = numpy.where(thisH)
2149
2149
2150 if numpy.size(indthisH) > 3:
2150 if numpy.size(indthisH) > 3:
2151
2151
2152 vel_aux = vmet[thisH]
2152 vel_aux = vmet[thisH]
2153 chan_aux = cmet[thisH]
2153 chan_aux = cmet[thisH]
2154 cosu_aux = dir_cosu[chan_aux]
2154 cosu_aux = dir_cosu[chan_aux]
2155 cosv_aux = dir_cosv[chan_aux]
2155 cosv_aux = dir_cosv[chan_aux]
2156 cosw_aux = dir_cosw[chan_aux]
2156 cosw_aux = dir_cosw[chan_aux]
2157
2157
2158 nch = numpy.size(numpy.unique(chan_aux))
2158 nch = numpy.size(numpy.unique(chan_aux))
2159 if nch > 1:
2159 if nch > 1:
2160 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2160 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2161 velEst[i,:] = numpy.dot(A,vel_aux)
2161 velEst[i,:] = numpy.dot(A,vel_aux)
2162
2162
2163 return velEst
2163 return velEst
2164
2164
2165 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2165 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2166
2166
2167 param = dataOut.data_param
2167 param = dataOut.data_param
2168 if dataOut.abscissaList != None:
2168 if dataOut.abscissaList != None:
2169 absc = dataOut.abscissaList[:-1]
2169 absc = dataOut.abscissaList[:-1]
2170 # noise = dataOut.noise
2170 # noise = dataOut.noise
2171 heightList = dataOut.heightList
2171 heightList = dataOut.heightList
2172 SNR = dataOut.data_snr
2172 SNR = dataOut.data_snr
2173
2173
2174 if technique == 'DBS':
2174 if technique == 'DBS':
2175
2175
2176 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2176 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2177 kwargs['heightList'] = heightList
2177 kwargs['heightList'] = heightList
2178 kwargs['SNR'] = SNR
2178 kwargs['SNR'] = SNR
2179
2179
2180 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2180 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2181 dataOut.utctimeInit = dataOut.utctime
2181 dataOut.utctimeInit = dataOut.utctime
2182 dataOut.outputInterval = dataOut.paramInterval
2182 dataOut.outputInterval = dataOut.paramInterval
2183
2183
2184 elif technique == 'SA':
2184 elif technique == 'SA':
2185
2185
2186 #Parameters
2186 #Parameters
2187 # position_x = kwargs['positionX']
2187 # position_x = kwargs['positionX']
2188 # position_y = kwargs['positionY']
2188 # position_y = kwargs['positionY']
2189 # azimuth = kwargs['azimuth']
2189 # azimuth = kwargs['azimuth']
2190 #
2190 #
2191 # if kwargs.has_key('crosspairsList'):
2191 # if kwargs.has_key('crosspairsList'):
2192 # pairs = kwargs['crosspairsList']
2192 # pairs = kwargs['crosspairsList']
2193 # else:
2193 # else:
2194 # pairs = None
2194 # pairs = None
2195 #
2195 #
2196 # if kwargs.has_key('correctFactor'):
2196 # if kwargs.has_key('correctFactor'):
2197 # correctFactor = kwargs['correctFactor']
2197 # correctFactor = kwargs['correctFactor']
2198 # else:
2198 # else:
2199 # correctFactor = 1
2199 # correctFactor = 1
2200
2200
2201 # tau = dataOut.data_param
2201 # tau = dataOut.data_param
2202 # _lambda = dataOut.C/dataOut.frequency
2202 # _lambda = dataOut.C/dataOut.frequency
2203 # pairsList = dataOut.groupList
2203 # pairsList = dataOut.groupList
2204 # nChannels = dataOut.nChannels
2204 # nChannels = dataOut.nChannels
2205
2205
2206 kwargs['groupList'] = dataOut.groupList
2206 kwargs['groupList'] = dataOut.groupList
2207 kwargs['tau'] = dataOut.data_param
2207 kwargs['tau'] = dataOut.data_param
2208 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2208 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2209 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2209 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2210 dataOut.data_output = self.techniqueSA(kwargs)
2210 dataOut.data_output = self.techniqueSA(kwargs)
2211 dataOut.utctimeInit = dataOut.utctime
2211 dataOut.utctimeInit = dataOut.utctime
2212 dataOut.outputInterval = dataOut.timeInterval
2212 dataOut.outputInterval = dataOut.timeInterval
2213
2213
2214 elif technique == 'Meteors':
2214 elif technique == 'Meteors':
2215 dataOut.flagNoData = True
2215 dataOut.flagNoData = True
2216 self.__dataReady = False
2216 self.__dataReady = False
2217
2217
2218 if 'nHours' in kwargs:
2218 if 'nHours' in kwargs:
2219 nHours = kwargs['nHours']
2219 nHours = kwargs['nHours']
2220 else:
2220 else:
2221 nHours = 1
2221 nHours = 1
2222
2222
2223 if 'meteorsPerBin' in kwargs:
2223 if 'meteorsPerBin' in kwargs:
2224 meteorThresh = kwargs['meteorsPerBin']
2224 meteorThresh = kwargs['meteorsPerBin']
2225 else:
2225 else:
2226 meteorThresh = 6
2226 meteorThresh = 6
2227
2227
2228 if 'hmin' in kwargs:
2228 if 'hmin' in kwargs:
2229 hmin = kwargs['hmin']
2229 hmin = kwargs['hmin']
2230 else: hmin = 70
2230 else: hmin = 70
2231 if 'hmax' in kwargs:
2231 if 'hmax' in kwargs:
2232 hmax = kwargs['hmax']
2232 hmax = kwargs['hmax']
2233 else: hmax = 110
2233 else: hmax = 110
2234
2234
2235 dataOut.outputInterval = nHours*3600
2235 dataOut.outputInterval = nHours*3600
2236
2236
2237 if self.__isConfig == False:
2237 if self.__isConfig == False:
2238 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2238 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2239 #Get Initial LTC time
2239 #Get Initial LTC time
2240 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2240 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2241 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2241 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2242
2242
2243 self.__isConfig = True
2243 self.__isConfig = True
2244
2244
2245 if self.__buffer is None:
2245 if self.__buffer is None:
2246 self.__buffer = dataOut.data_param
2246 self.__buffer = dataOut.data_param
2247 self.__firstdata = copy.copy(dataOut)
2247 self.__firstdata = copy.copy(dataOut)
2248
2248
2249 else:
2249 else:
2250 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2250 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2251
2251
2252 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2252 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2253
2253
2254 if self.__dataReady:
2254 if self.__dataReady:
2255 dataOut.utctimeInit = self.__initime
2255 dataOut.utctimeInit = self.__initime
2256
2256
2257 self.__initime += dataOut.outputInterval #to erase time offset
2257 self.__initime += dataOut.outputInterval #to erase time offset
2258
2258
2259 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2259 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2260 dataOut.flagNoData = False
2260 dataOut.flagNoData = False
2261 self.__buffer = None
2261 self.__buffer = None
2262
2262
2263 elif technique == 'Meteors1':
2263 elif technique == 'Meteors1':
2264 dataOut.flagNoData = True
2264 dataOut.flagNoData = True
2265 self.__dataReady = False
2265 self.__dataReady = False
2266
2266
2267 if 'nMins' in kwargs:
2267 if 'nMins' in kwargs:
2268 nMins = kwargs['nMins']
2268 nMins = kwargs['nMins']
2269 else: nMins = 20
2269 else: nMins = 20
2270 if 'rx_location' in kwargs:
2270 if 'rx_location' in kwargs:
2271 rx_location = kwargs['rx_location']
2271 rx_location = kwargs['rx_location']
2272 else: rx_location = [(0,1),(1,1),(1,0)]
2272 else: rx_location = [(0,1),(1,1),(1,0)]
2273 if 'azimuth' in kwargs:
2273 if 'azimuth' in kwargs:
2274 azimuth = kwargs['azimuth']
2274 azimuth = kwargs['azimuth']
2275 else: azimuth = 51.06
2275 else: azimuth = 51.06
2276 if 'dfactor' in kwargs:
2276 if 'dfactor' in kwargs:
2277 dfactor = kwargs['dfactor']
2277 dfactor = kwargs['dfactor']
2278 if 'mode' in kwargs:
2278 if 'mode' in kwargs:
2279 mode = kwargs['mode']
2279 mode = kwargs['mode']
2280 if 'theta_x' in kwargs:
2280 if 'theta_x' in kwargs:
2281 theta_x = kwargs['theta_x']
2281 theta_x = kwargs['theta_x']
2282 if 'theta_y' in kwargs:
2282 if 'theta_y' in kwargs:
2283 theta_y = kwargs['theta_y']
2283 theta_y = kwargs['theta_y']
2284 else: mode = 'SA'
2284 else: mode = 'SA'
2285
2285
2286 #Borrar luego esto
2286 #Borrar luego esto
2287 if dataOut.groupList is None:
2287 if dataOut.groupList is None:
2288 dataOut.groupList = [(0,1),(0,2),(1,2)]
2288 dataOut.groupList = [(0,1),(0,2),(1,2)]
2289 groupList = dataOut.groupList
2289 groupList = dataOut.groupList
2290 C = 3e8
2290 C = 3e8
2291 freq = 50e6
2291 freq = 50e6
2292 lamb = C/freq
2292 lamb = C/freq
2293 k = 2*numpy.pi/lamb
2293 k = 2*numpy.pi/lamb
2294
2294
2295 timeList = dataOut.abscissaList
2295 timeList = dataOut.abscissaList
2296 heightList = dataOut.heightList
2296 heightList = dataOut.heightList
2297
2297
2298 if self.__isConfig == False:
2298 if self.__isConfig == False:
2299 dataOut.outputInterval = nMins*60
2299 dataOut.outputInterval = nMins*60
2300 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2300 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2301 #Get Initial LTC time
2301 #Get Initial LTC time
2302 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2302 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2303 minuteAux = initime.minute
2303 minuteAux = initime.minute
2304 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2304 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2305 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2305 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2306
2306
2307 self.__isConfig = True
2307 self.__isConfig = True
2308
2308
2309 if self.__buffer is None:
2309 if self.__buffer is None:
2310 self.__buffer = dataOut.data_param
2310 self.__buffer = dataOut.data_param
2311 self.__firstdata = copy.copy(dataOut)
2311 self.__firstdata = copy.copy(dataOut)
2312
2312
2313 else:
2313 else:
2314 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2314 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2315
2315
2316 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2316 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2317
2317
2318 if self.__dataReady:
2318 if self.__dataReady:
2319 dataOut.utctimeInit = self.__initime
2319 dataOut.utctimeInit = self.__initime
2320 self.__initime += dataOut.outputInterval #to erase time offset
2320 self.__initime += dataOut.outputInterval #to erase time offset
2321
2321
2322 metArray = self.__buffer
2322 metArray = self.__buffer
2323 if mode == 'SA':
2323 if mode == 'SA':
2324 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2324 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2325 elif mode == 'DBS':
2325 elif mode == 'DBS':
2326 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2326 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2327 dataOut.data_output = dataOut.data_output.T
2327 dataOut.data_output = dataOut.data_output.T
2328 dataOut.flagNoData = False
2328 dataOut.flagNoData = False
2329 self.__buffer = None
2329 self.__buffer = None
2330
2330
2331 return
2331 return
2332
2332
2333 class EWDriftsEstimation(Operation):
2333 class EWDriftsEstimation(Operation):
2334
2334
2335 def __init__(self):
2335 def __init__(self):
2336 Operation.__init__(self)
2336 Operation.__init__(self)
2337
2337
2338 def __correctValues(self, heiRang, phi, velRadial, SNR):
2338 def __correctValues(self, heiRang, phi, velRadial, SNR):
2339 listPhi = phi.tolist()
2339 listPhi = phi.tolist()
2340 maxid = listPhi.index(max(listPhi))
2340 maxid = listPhi.index(max(listPhi))
2341 minid = listPhi.index(min(listPhi))
2341 minid = listPhi.index(min(listPhi))
2342
2342
2343 rango = list(range(len(phi)))
2343 rango = list(range(len(phi)))
2344 # rango = numpy.delete(rango,maxid)
2344 # rango = numpy.delete(rango,maxid)
2345
2345
2346 heiRang1 = heiRang*math.cos(phi[maxid])
2346 heiRang1 = heiRang*math.cos(phi[maxid])
2347 heiRangAux = heiRang*math.cos(phi[minid])
2347 heiRangAux = heiRang*math.cos(phi[minid])
2348 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2348 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2349 heiRang1 = numpy.delete(heiRang1,indOut)
2349 heiRang1 = numpy.delete(heiRang1,indOut)
2350
2350
2351 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2351 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2352 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2352 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2353
2353
2354 for i in rango:
2354 for i in rango:
2355 x = heiRang*math.cos(phi[i])
2355 x = heiRang*math.cos(phi[i])
2356 y1 = velRadial[i,:]
2356 y1 = velRadial[i,:]
2357 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2357 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2358
2358
2359 x1 = heiRang1
2359 x1 = heiRang1
2360 y11 = f1(x1)
2360 y11 = f1(x1)
2361
2361
2362 y2 = SNR[i,:]
2362 y2 = SNR[i,:]
2363 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2363 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2364 y21 = f2(x1)
2364 y21 = f2(x1)
2365
2365
2366 velRadial1[i,:] = y11
2366 velRadial1[i,:] = y11
2367 SNR1[i,:] = y21
2367 SNR1[i,:] = y21
2368
2368
2369 return heiRang1, velRadial1, SNR1
2369 return heiRang1, velRadial1, SNR1
2370
2370
2371 def run(self, dataOut, zenith, zenithCorrection):
2371 def run(self, dataOut, zenith, zenithCorrection):
2372 heiRang = dataOut.heightList
2372 heiRang = dataOut.heightList
2373 velRadial = dataOut.data_param[:,3,:]
2373 velRadial = dataOut.data_param[:,3,:]
2374 SNR = dataOut.data_snr
2374 SNR = dataOut.data_snr
2375
2375
2376 zenith = numpy.array(zenith)
2376 zenith = numpy.array(zenith)
2377 zenith -= zenithCorrection
2377 zenith -= zenithCorrection
2378 zenith *= numpy.pi/180
2378 zenith *= numpy.pi/180
2379
2379
2380 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2380 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2381
2381
2382 alp = zenith[0]
2382 alp = zenith[0]
2383 bet = zenith[1]
2383 bet = zenith[1]
2384
2384
2385 w_w = velRadial1[0,:]
2385 w_w = velRadial1[0,:]
2386 w_e = velRadial1[1,:]
2386 w_e = velRadial1[1,:]
2387
2387
2388 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2388 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2389 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2389 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2390
2390
2391 winds = numpy.vstack((u,w))
2391 winds = numpy.vstack((u,w))
2392
2392
2393 dataOut.heightList = heiRang1
2393 dataOut.heightList = heiRang1
2394 dataOut.data_output = winds
2394 dataOut.data_output = winds
2395 dataOut.data_snr = SNR1
2395 dataOut.data_snr = SNR1
2396
2396
2397 dataOut.utctimeInit = dataOut.utctime
2397 dataOut.utctimeInit = dataOut.utctime
2398 dataOut.outputInterval = dataOut.timeInterval
2398 dataOut.outputInterval = dataOut.timeInterval
2399 return
2399 return
2400
2400
2401 #--------------- Non Specular Meteor ----------------
2401 #--------------- Non Specular Meteor ----------------
2402
2402
2403 class NonSpecularMeteorDetection(Operation):
2403 class NonSpecularMeteorDetection(Operation):
2404
2404
2405 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2405 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2406 data_acf = dataOut.data_pre[0]
2406 data_acf = dataOut.data_pre[0]
2407 data_ccf = dataOut.data_pre[1]
2407 data_ccf = dataOut.data_pre[1]
2408 pairsList = dataOut.groupList[1]
2408 pairsList = dataOut.groupList[1]
2409
2409
2410 lamb = dataOut.C/dataOut.frequency
2410 lamb = dataOut.C/dataOut.frequency
2411 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2411 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2412 paramInterval = dataOut.paramInterval
2412 paramInterval = dataOut.paramInterval
2413
2413
2414 nChannels = data_acf.shape[0]
2414 nChannels = data_acf.shape[0]
2415 nLags = data_acf.shape[1]
2415 nLags = data_acf.shape[1]
2416 nProfiles = data_acf.shape[2]
2416 nProfiles = data_acf.shape[2]
2417 nHeights = dataOut.nHeights
2417 nHeights = dataOut.nHeights
2418 nCohInt = dataOut.nCohInt
2418 nCohInt = dataOut.nCohInt
2419 sec = numpy.round(nProfiles/dataOut.paramInterval)
2419 sec = numpy.round(nProfiles/dataOut.paramInterval)
2420 heightList = dataOut.heightList
2420 heightList = dataOut.heightList
2421 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2421 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2422 utctime = dataOut.utctime
2422 utctime = dataOut.utctime
2423
2423
2424 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2424 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2425
2425
2426 #------------------------ SNR --------------------------------------
2426 #------------------------ SNR --------------------------------------
2427 power = data_acf[:,0,:,:].real
2427 power = data_acf[:,0,:,:].real
2428 noise = numpy.zeros(nChannels)
2428 noise = numpy.zeros(nChannels)
2429 SNR = numpy.zeros(power.shape)
2429 SNR = numpy.zeros(power.shape)
2430 for i in range(nChannels):
2430 for i in range(nChannels):
2431 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2431 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2432 SNR[i] = (power[i]-noise[i])/noise[i]
2432 SNR[i] = (power[i]-noise[i])/noise[i]
2433 SNRm = numpy.nanmean(SNR, axis = 0)
2433 SNRm = numpy.nanmean(SNR, axis = 0)
2434 SNRdB = 10*numpy.log10(SNR)
2434 SNRdB = 10*numpy.log10(SNR)
2435
2435
2436 if mode == 'SA':
2436 if mode == 'SA':
2437 dataOut.groupList = dataOut.groupList[1]
2437 dataOut.groupList = dataOut.groupList[1]
2438 nPairs = data_ccf.shape[0]
2438 nPairs = data_ccf.shape[0]
2439 #---------------------- Coherence and Phase --------------------------
2439 #---------------------- Coherence and Phase --------------------------
2440 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2440 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2441 # phase1 = numpy.copy(phase)
2441 # phase1 = numpy.copy(phase)
2442 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2442 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2443
2443
2444 for p in range(nPairs):
2444 for p in range(nPairs):
2445 ch0 = pairsList[p][0]
2445 ch0 = pairsList[p][0]
2446 ch1 = pairsList[p][1]
2446 ch1 = pairsList[p][1]
2447 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2447 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2448 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2448 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2449 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2449 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2450 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2450 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2451 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2451 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2452 coh = numpy.nanmax(coh1, axis = 0)
2452 coh = numpy.nanmax(coh1, axis = 0)
2453 # struc = numpy.ones((5,1))
2453 # struc = numpy.ones((5,1))
2454 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2454 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2455 #---------------------- Radial Velocity ----------------------------
2455 #---------------------- Radial Velocity ----------------------------
2456 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2456 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2457 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2457 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2458
2458
2459 if allData:
2459 if allData:
2460 boolMetFin = ~numpy.isnan(SNRm)
2460 boolMetFin = ~numpy.isnan(SNRm)
2461 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2461 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2462 else:
2462 else:
2463 #------------------------ Meteor mask ---------------------------------
2463 #------------------------ Meteor mask ---------------------------------
2464 # #SNR mask
2464 # #SNR mask
2465 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2465 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2466 #
2466 #
2467 # #Erase small objects
2467 # #Erase small objects
2468 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2468 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2469 #
2469 #
2470 # auxEEJ = numpy.sum(boolMet1,axis=0)
2470 # auxEEJ = numpy.sum(boolMet1,axis=0)
2471 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2471 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2472 # indEEJ = numpy.where(indOver)[0]
2472 # indEEJ = numpy.where(indOver)[0]
2473 # indNEEJ = numpy.where(~indOver)[0]
2473 # indNEEJ = numpy.where(~indOver)[0]
2474 #
2474 #
2475 # boolMetFin = boolMet1
2475 # boolMetFin = boolMet1
2476 #
2476 #
2477 # if indEEJ.size > 0:
2477 # if indEEJ.size > 0:
2478 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2478 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2479 #
2479 #
2480 # boolMet2 = coh > cohThresh
2480 # boolMet2 = coh > cohThresh
2481 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2481 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2482 #
2482 #
2483 # #Final Meteor mask
2483 # #Final Meteor mask
2484 # boolMetFin = boolMet1|boolMet2
2484 # boolMetFin = boolMet1|boolMet2
2485
2485
2486 #Coherence mask
2486 #Coherence mask
2487 boolMet1 = coh > 0.75
2487 boolMet1 = coh > 0.75
2488 struc = numpy.ones((30,1))
2488 struc = numpy.ones((30,1))
2489 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2489 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2490
2490
2491 #Derivative mask
2491 #Derivative mask
2492 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2492 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2493 boolMet2 = derPhase < 0.2
2493 boolMet2 = derPhase < 0.2
2494 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2494 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2495 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2495 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2496 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2496 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2497 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2497 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2498 # #Final mask
2498 # #Final mask
2499 # boolMetFin = boolMet2
2499 # boolMetFin = boolMet2
2500 boolMetFin = boolMet1&boolMet2
2500 boolMetFin = boolMet1&boolMet2
2501 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2501 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2502 #Creating data_param
2502 #Creating data_param
2503 coordMet = numpy.where(boolMetFin)
2503 coordMet = numpy.where(boolMetFin)
2504
2504
2505 tmet = coordMet[0]
2505 tmet = coordMet[0]
2506 hmet = coordMet[1]
2506 hmet = coordMet[1]
2507
2507
2508 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2508 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2509 data_param[:,0] = utctime
2509 data_param[:,0] = utctime
2510 data_param[:,1] = tmet
2510 data_param[:,1] = tmet
2511 data_param[:,2] = hmet
2511 data_param[:,2] = hmet
2512 data_param[:,3] = SNRm[tmet,hmet]
2512 data_param[:,3] = SNRm[tmet,hmet]
2513 data_param[:,4] = velRad[tmet,hmet]
2513 data_param[:,4] = velRad[tmet,hmet]
2514 data_param[:,5] = coh[tmet,hmet]
2514 data_param[:,5] = coh[tmet,hmet]
2515 data_param[:,6:] = phase[:,tmet,hmet].T
2515 data_param[:,6:] = phase[:,tmet,hmet].T
2516
2516
2517 elif mode == 'DBS':
2517 elif mode == 'DBS':
2518 dataOut.groupList = numpy.arange(nChannels)
2518 dataOut.groupList = numpy.arange(nChannels)
2519
2519
2520 #Radial Velocities
2520 #Radial Velocities
2521 phase = numpy.angle(data_acf[:,1,:,:])
2521 phase = numpy.angle(data_acf[:,1,:,:])
2522 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2522 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2523 velRad = phase*lamb/(4*numpy.pi*tSamp)
2523 velRad = phase*lamb/(4*numpy.pi*tSamp)
2524
2524
2525 #Spectral width
2525 #Spectral width
2526 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2526 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2527 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2527 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2528 acf1 = data_acf[:,1,:,:]
2528 acf1 = data_acf[:,1,:,:]
2529 acf2 = data_acf[:,2,:,:]
2529 acf2 = data_acf[:,2,:,:]
2530
2530
2531 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2531 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2532 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2532 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2533 if allData:
2533 if allData:
2534 boolMetFin = ~numpy.isnan(SNRdB)
2534 boolMetFin = ~numpy.isnan(SNRdB)
2535 else:
2535 else:
2536 #SNR
2536 #SNR
2537 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2537 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2538 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2538 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2539
2539
2540 #Radial velocity
2540 #Radial velocity
2541 boolMet2 = numpy.abs(velRad) < 20
2541 boolMet2 = numpy.abs(velRad) < 20
2542 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2542 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2543
2543
2544 #Spectral Width
2544 #Spectral Width
2545 boolMet3 = spcWidth < 30
2545 boolMet3 = spcWidth < 30
2546 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2546 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2547 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2547 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2548 boolMetFin = boolMet1&boolMet2&boolMet3
2548 boolMetFin = boolMet1&boolMet2&boolMet3
2549
2549
2550 #Creating data_param
2550 #Creating data_param
2551 coordMet = numpy.where(boolMetFin)
2551 coordMet = numpy.where(boolMetFin)
2552
2552
2553 cmet = coordMet[0]
2553 cmet = coordMet[0]
2554 tmet = coordMet[1]
2554 tmet = coordMet[1]
2555 hmet = coordMet[2]
2555 hmet = coordMet[2]
2556
2556
2557 data_param = numpy.zeros((tmet.size, 7))
2557 data_param = numpy.zeros((tmet.size, 7))
2558 data_param[:,0] = utctime
2558 data_param[:,0] = utctime
2559 data_param[:,1] = cmet
2559 data_param[:,1] = cmet
2560 data_param[:,2] = tmet
2560 data_param[:,2] = tmet
2561 data_param[:,3] = hmet
2561 data_param[:,3] = hmet
2562 data_param[:,4] = SNR[cmet,tmet,hmet].T
2562 data_param[:,4] = SNR[cmet,tmet,hmet].T
2563 data_param[:,5] = velRad[cmet,tmet,hmet].T
2563 data_param[:,5] = velRad[cmet,tmet,hmet].T
2564 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2564 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2565
2565
2566 # self.dataOut.data_param = data_int
2566 # self.dataOut.data_param = data_int
2567 if len(data_param) == 0:
2567 if len(data_param) == 0:
2568 dataOut.flagNoData = True
2568 dataOut.flagNoData = True
2569 else:
2569 else:
2570 dataOut.data_param = data_param
2570 dataOut.data_param = data_param
2571
2571
2572 def __erase_small(self, binArray, threshX, threshY):
2572 def __erase_small(self, binArray, threshX, threshY):
2573 labarray, numfeat = ndimage.measurements.label(binArray)
2573 labarray, numfeat = ndimage.measurements.label(binArray)
2574 binArray1 = numpy.copy(binArray)
2574 binArray1 = numpy.copy(binArray)
2575
2575
2576 for i in range(1,numfeat + 1):
2576 for i in range(1,numfeat + 1):
2577 auxBin = (labarray==i)
2577 auxBin = (labarray==i)
2578 auxSize = auxBin.sum()
2578 auxSize = auxBin.sum()
2579
2579
2580 x,y = numpy.where(auxBin)
2580 x,y = numpy.where(auxBin)
2581 widthX = x.max() - x.min()
2581 widthX = x.max() - x.min()
2582 widthY = y.max() - y.min()
2582 widthY = y.max() - y.min()
2583
2583
2584 #width X: 3 seg -> 12.5*3
2584 #width X: 3 seg -> 12.5*3
2585 #width Y:
2585 #width Y:
2586
2586
2587 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2587 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2588 binArray1[auxBin] = False
2588 binArray1[auxBin] = False
2589
2589
2590 return binArray1
2590 return binArray1
2591
2591
2592 #--------------- Specular Meteor ----------------
2592 #--------------- Specular Meteor ----------------
2593
2593
2594 class SMDetection(Operation):
2594 class SMDetection(Operation):
2595 '''
2595 '''
2596 Function DetectMeteors()
2596 Function DetectMeteors()
2597 Project developed with paper:
2597 Project developed with paper:
2598 HOLDSWORTH ET AL. 2004
2598 HOLDSWORTH ET AL. 2004
2599
2599
2600 Input:
2600 Input:
2601 self.dataOut.data_pre
2601 self.dataOut.data_pre
2602
2602
2603 centerReceiverIndex: From the channels, which is the center receiver
2603 centerReceiverIndex: From the channels, which is the center receiver
2604
2604
2605 hei_ref: Height reference for the Beacon signal extraction
2605 hei_ref: Height reference for the Beacon signal extraction
2606 tauindex:
2606 tauindex:
2607 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2607 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2608
2608
2609 cohDetection: Whether to user Coherent detection or not
2609 cohDetection: Whether to user Coherent detection or not
2610 cohDet_timeStep: Coherent Detection calculation time step
2610 cohDet_timeStep: Coherent Detection calculation time step
2611 cohDet_thresh: Coherent Detection phase threshold to correct phases
2611 cohDet_thresh: Coherent Detection phase threshold to correct phases
2612
2612
2613 noise_timeStep: Noise calculation time step
2613 noise_timeStep: Noise calculation time step
2614 noise_multiple: Noise multiple to define signal threshold
2614 noise_multiple: Noise multiple to define signal threshold
2615
2615
2616 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2616 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2617 multDet_rangeLimit: Multiple Detection Removal range limit in km
2617 multDet_rangeLimit: Multiple Detection Removal range limit in km
2618
2618
2619 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2619 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2620 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2620 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2621
2621
2622 hmin: Minimum Height of the meteor to use it in the further wind estimations
2622 hmin: Minimum Height of the meteor to use it in the further wind estimations
2623 hmax: Maximum Height of the meteor to use it in the further wind estimations
2623 hmax: Maximum Height of the meteor to use it in the further wind estimations
2624 azimuth: Azimuth angle correction
2624 azimuth: Azimuth angle correction
2625
2625
2626 Affected:
2626 Affected:
2627 self.dataOut.data_param
2627 self.dataOut.data_param
2628
2628
2629 Rejection Criteria (Errors):
2629 Rejection Criteria (Errors):
2630 0: No error; analysis OK
2630 0: No error; analysis OK
2631 1: SNR < SNR threshold
2631 1: SNR < SNR threshold
2632 2: angle of arrival (AOA) ambiguously determined
2632 2: angle of arrival (AOA) ambiguously determined
2633 3: AOA estimate not feasible
2633 3: AOA estimate not feasible
2634 4: Large difference in AOAs obtained from different antenna baselines
2634 4: Large difference in AOAs obtained from different antenna baselines
2635 5: echo at start or end of time series
2635 5: echo at start or end of time series
2636 6: echo less than 5 examples long; too short for analysis
2636 6: echo less than 5 examples long; too short for analysis
2637 7: echo rise exceeds 0.3s
2637 7: echo rise exceeds 0.3s
2638 8: echo decay time less than twice rise time
2638 8: echo decay time less than twice rise time
2639 9: large power level before echo
2639 9: large power level before echo
2640 10: large power level after echo
2640 10: large power level after echo
2641 11: poor fit to amplitude for estimation of decay time
2641 11: poor fit to amplitude for estimation of decay time
2642 12: poor fit to CCF phase variation for estimation of radial drift velocity
2642 12: poor fit to CCF phase variation for estimation of radial drift velocity
2643 13: height unresolvable echo: not valid height within 70 to 110 km
2643 13: height unresolvable echo: not valid height within 70 to 110 km
2644 14: height ambiguous echo: more then one possible height within 70 to 110 km
2644 14: height ambiguous echo: more then one possible height within 70 to 110 km
2645 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2645 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2646 16: oscilatory echo, indicating event most likely not an underdense echo
2646 16: oscilatory echo, indicating event most likely not an underdense echo
2647
2647
2648 17: phase difference in meteor Reestimation
2648 17: phase difference in meteor Reestimation
2649
2649
2650 Data Storage:
2650 Data Storage:
2651 Meteors for Wind Estimation (8):
2651 Meteors for Wind Estimation (8):
2652 Utc Time | Range Height
2652 Utc Time | Range Height
2653 Azimuth Zenith errorCosDir
2653 Azimuth Zenith errorCosDir
2654 VelRad errorVelRad
2654 VelRad errorVelRad
2655 Phase0 Phase1 Phase2 Phase3
2655 Phase0 Phase1 Phase2 Phase3
2656 TypeError
2656 TypeError
2657
2657
2658 '''
2658 '''
2659
2659
2660 def run(self, dataOut, hei_ref = None, tauindex = 0,
2660 def run(self, dataOut, hei_ref = None, tauindex = 0,
2661 phaseOffsets = None,
2661 phaseOffsets = None,
2662 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2662 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2663 noise_timeStep = 4, noise_multiple = 4,
2663 noise_timeStep = 4, noise_multiple = 4,
2664 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2664 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2665 phaseThresh = 20, SNRThresh = 5,
2665 phaseThresh = 20, SNRThresh = 5,
2666 hmin = 50, hmax=150, azimuth = 0,
2666 hmin = 50, hmax=150, azimuth = 0,
2667 channelPositions = None) :
2667 channelPositions = None) :
2668
2668
2669
2669
2670 #Getting Pairslist
2670 #Getting Pairslist
2671 if channelPositions is None:
2671 if channelPositions is None:
2672 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2672 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2673 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2673 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2674 meteorOps = SMOperations()
2674 meteorOps = SMOperations()
2675 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2675 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2676 heiRang = dataOut.heightList
2676 heiRang = dataOut.heightList
2677 #Get Beacon signal - No Beacon signal anymore
2677 #Get Beacon signal - No Beacon signal anymore
2678 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2678 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2679 #
2679 #
2680 # if hei_ref != None:
2680 # if hei_ref != None:
2681 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2681 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2682 #
2682 #
2683
2683
2684
2684
2685 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2685 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2686 # see if the user put in pre defined phase shifts
2686 # see if the user put in pre defined phase shifts
2687 voltsPShift = dataOut.data_pre.copy()
2687 voltsPShift = dataOut.data_pre.copy()
2688
2688
2689 # if predefinedPhaseShifts != None:
2689 # if predefinedPhaseShifts != None:
2690 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2690 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2691 #
2691 #
2692 # # elif beaconPhaseShifts:
2692 # # elif beaconPhaseShifts:
2693 # # #get hardware phase shifts using beacon signal
2693 # # #get hardware phase shifts using beacon signal
2694 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2694 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2695 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2695 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2696 #
2696 #
2697 # else:
2697 # else:
2698 # hardwarePhaseShifts = numpy.zeros(5)
2698 # hardwarePhaseShifts = numpy.zeros(5)
2699 #
2699 #
2700 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2700 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2701 # for i in range(self.dataOut.data_pre.shape[0]):
2701 # for i in range(self.dataOut.data_pre.shape[0]):
2702 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2702 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2703
2703
2704 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2704 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2705
2705
2706 #Remove DC
2706 #Remove DC
2707 voltsDC = numpy.mean(voltsPShift,1)
2707 voltsDC = numpy.mean(voltsPShift,1)
2708 voltsDC = numpy.mean(voltsDC,1)
2708 voltsDC = numpy.mean(voltsDC,1)
2709 for i in range(voltsDC.shape[0]):
2709 for i in range(voltsDC.shape[0]):
2710 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2710 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2711
2711
2712 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2712 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2713 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2713 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2714
2714
2715 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2715 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2716 #Coherent Detection
2716 #Coherent Detection
2717 if cohDetection:
2717 if cohDetection:
2718 #use coherent detection to get the net power
2718 #use coherent detection to get the net power
2719 cohDet_thresh = cohDet_thresh*numpy.pi/180
2719 cohDet_thresh = cohDet_thresh*numpy.pi/180
2720 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2720 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2721
2721
2722 #Non-coherent detection!
2722 #Non-coherent detection!
2723 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2723 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2724 #********** END OF COH/NON-COH POWER CALCULATION**********************
2724 #********** END OF COH/NON-COH POWER CALCULATION**********************
2725
2725
2726 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2726 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2727 #Get noise
2727 #Get noise
2728 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2728 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2729 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2729 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2730 #Get signal threshold
2730 #Get signal threshold
2731 signalThresh = noise_multiple*noise
2731 signalThresh = noise_multiple*noise
2732 #Meteor echoes detection
2732 #Meteor echoes detection
2733 listMeteors = self.__findMeteors(powerNet, signalThresh)
2733 listMeteors = self.__findMeteors(powerNet, signalThresh)
2734 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2734 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2735
2735
2736 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2736 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2737 #Parameters
2737 #Parameters
2738 heiRange = dataOut.heightList
2738 heiRange = dataOut.heightList
2739 rangeInterval = heiRange[1] - heiRange[0]
2739 rangeInterval = heiRange[1] - heiRange[0]
2740 rangeLimit = multDet_rangeLimit/rangeInterval
2740 rangeLimit = multDet_rangeLimit/rangeInterval
2741 timeLimit = multDet_timeLimit/dataOut.timeInterval
2741 timeLimit = multDet_timeLimit/dataOut.timeInterval
2742 #Multiple detection removals
2742 #Multiple detection removals
2743 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2743 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2744 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2744 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2745
2745
2746 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2746 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2747 #Parameters
2747 #Parameters
2748 phaseThresh = phaseThresh*numpy.pi/180
2748 phaseThresh = phaseThresh*numpy.pi/180
2749 thresh = [phaseThresh, noise_multiple, SNRThresh]
2749 thresh = [phaseThresh, noise_multiple, SNRThresh]
2750 #Meteor reestimation (Errors N 1, 6, 12, 17)
2750 #Meteor reestimation (Errors N 1, 6, 12, 17)
2751 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2751 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2752 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2752 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2753 #Estimation of decay times (Errors N 7, 8, 11)
2753 #Estimation of decay times (Errors N 7, 8, 11)
2754 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2754 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2755 #******************* END OF METEOR REESTIMATION *******************
2755 #******************* END OF METEOR REESTIMATION *******************
2756
2756
2757 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2757 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2758 #Calculating Radial Velocity (Error N 15)
2758 #Calculating Radial Velocity (Error N 15)
2759 radialStdThresh = 10
2759 radialStdThresh = 10
2760 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2760 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2761
2761
2762 if len(listMeteors4) > 0:
2762 if len(listMeteors4) > 0:
2763 #Setting New Array
2763 #Setting New Array
2764 date = dataOut.utctime
2764 date = dataOut.utctime
2765 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2765 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2766
2766
2767 #Correcting phase offset
2767 #Correcting phase offset
2768 if phaseOffsets != None:
2768 if phaseOffsets != None:
2769 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2769 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2770 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2770 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2771
2771
2772 #Second Pairslist
2772 #Second Pairslist
2773 pairsList = []
2773 pairsList = []
2774 pairx = (0,1)
2774 pairx = (0,1)
2775 pairy = (2,3)
2775 pairy = (2,3)
2776 pairsList.append(pairx)
2776 pairsList.append(pairx)
2777 pairsList.append(pairy)
2777 pairsList.append(pairy)
2778
2778
2779 jph = numpy.array([0,0,0,0])
2779 jph = numpy.array([0,0,0,0])
2780 h = (hmin,hmax)
2780 h = (hmin,hmax)
2781 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2781 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2782
2782
2783 # #Calculate AOA (Error N 3, 4)
2783 # #Calculate AOA (Error N 3, 4)
2784 # #JONES ET AL. 1998
2784 # #JONES ET AL. 1998
2785 # error = arrayParameters[:,-1]
2785 # error = arrayParameters[:,-1]
2786 # AOAthresh = numpy.pi/8
2786 # AOAthresh = numpy.pi/8
2787 # phases = -arrayParameters[:,9:13]
2787 # phases = -arrayParameters[:,9:13]
2788 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2788 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2789 #
2789 #
2790 # #Calculate Heights (Error N 13 and 14)
2790 # #Calculate Heights (Error N 13 and 14)
2791 # error = arrayParameters[:,-1]
2791 # error = arrayParameters[:,-1]
2792 # Ranges = arrayParameters[:,2]
2792 # Ranges = arrayParameters[:,2]
2793 # zenith = arrayParameters[:,5]
2793 # zenith = arrayParameters[:,5]
2794 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2794 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2795 # error = arrayParameters[:,-1]
2795 # error = arrayParameters[:,-1]
2796 #********************* END OF PARAMETERS CALCULATION **************************
2796 #********************* END OF PARAMETERS CALCULATION **************************
2797
2797
2798 #***************************+ PASS DATA TO NEXT STEP **********************
2798 #***************************+ PASS DATA TO NEXT STEP **********************
2799 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2799 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2800 dataOut.data_param = arrayParameters
2800 dataOut.data_param = arrayParameters
2801
2801
2802 if arrayParameters is None:
2802 if arrayParameters is None:
2803 dataOut.flagNoData = True
2803 dataOut.flagNoData = True
2804 else:
2804 else:
2805 dataOut.flagNoData = True
2805 dataOut.flagNoData = True
2806
2806
2807 return
2807 return
2808
2808
2809 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2809 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2810
2810
2811 minIndex = min(newheis[0])
2811 minIndex = min(newheis[0])
2812 maxIndex = max(newheis[0])
2812 maxIndex = max(newheis[0])
2813
2813
2814 voltage = voltage0[:,:,minIndex:maxIndex+1]
2814 voltage = voltage0[:,:,minIndex:maxIndex+1]
2815 nLength = voltage.shape[1]/n
2815 nLength = voltage.shape[1]/n
2816 nMin = 0
2816 nMin = 0
2817 nMax = 0
2817 nMax = 0
2818 phaseOffset = numpy.zeros((len(pairslist),n))
2818 phaseOffset = numpy.zeros((len(pairslist),n))
2819
2819
2820 for i in range(n):
2820 for i in range(n):
2821 nMax += nLength
2821 nMax += nLength
2822 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2822 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2823 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2823 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2824 phaseOffset[:,i] = phaseCCF.transpose()
2824 phaseOffset[:,i] = phaseCCF.transpose()
2825 nMin = nMax
2825 nMin = nMax
2826 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2826 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2827
2827
2828 #Remove Outliers
2828 #Remove Outliers
2829 factor = 2
2829 factor = 2
2830 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2830 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2831 dw = numpy.std(wt,axis = 1)
2831 dw = numpy.std(wt,axis = 1)
2832 dw = dw.reshape((dw.size,1))
2832 dw = dw.reshape((dw.size,1))
2833 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2833 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2834 phaseOffset[ind] = numpy.nan
2834 phaseOffset[ind] = numpy.nan
2835 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2835 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2836
2836
2837 return phaseOffset
2837 return phaseOffset
2838
2838
2839 def __shiftPhase(self, data, phaseShift):
2839 def __shiftPhase(self, data, phaseShift):
2840 #this will shift the phase of a complex number
2840 #this will shift the phase of a complex number
2841 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2841 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2842 return dataShifted
2842 return dataShifted
2843
2843
2844 def __estimatePhaseDifference(self, array, pairslist):
2844 def __estimatePhaseDifference(self, array, pairslist):
2845 nChannel = array.shape[0]
2845 nChannel = array.shape[0]
2846 nHeights = array.shape[2]
2846 nHeights = array.shape[2]
2847 numPairs = len(pairslist)
2847 numPairs = len(pairslist)
2848 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2848 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2849 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2849 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2850
2850
2851 #Correct phases
2851 #Correct phases
2852 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2852 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2853 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2853 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2854
2854
2855 if indDer[0].shape[0] > 0:
2855 if indDer[0].shape[0] > 0:
2856 for i in range(indDer[0].shape[0]):
2856 for i in range(indDer[0].shape[0]):
2857 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2857 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2858 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2858 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2859
2859
2860 # for j in range(numSides):
2860 # for j in range(numSides):
2861 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2861 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2862 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2862 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2863 #
2863 #
2864 #Linear
2864 #Linear
2865 phaseInt = numpy.zeros((numPairs,1))
2865 phaseInt = numpy.zeros((numPairs,1))
2866 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2866 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2867 for j in range(numPairs):
2867 for j in range(numPairs):
2868 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2868 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2869 phaseInt[j] = fit[1]
2869 phaseInt[j] = fit[1]
2870 #Phase Differences
2870 #Phase Differences
2871 phaseDiff = phaseInt - phaseCCF[:,2,:]
2871 phaseDiff = phaseInt - phaseCCF[:,2,:]
2872 phaseArrival = phaseInt.reshape(phaseInt.size)
2872 phaseArrival = phaseInt.reshape(phaseInt.size)
2873
2873
2874 #Dealias
2874 #Dealias
2875 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2875 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2876 # indAlias = numpy.where(phaseArrival > numpy.pi)
2876 # indAlias = numpy.where(phaseArrival > numpy.pi)
2877 # phaseArrival[indAlias] -= 2*numpy.pi
2877 # phaseArrival[indAlias] -= 2*numpy.pi
2878 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2878 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2879 # phaseArrival[indAlias] += 2*numpy.pi
2879 # phaseArrival[indAlias] += 2*numpy.pi
2880
2880
2881 return phaseDiff, phaseArrival
2881 return phaseDiff, phaseArrival
2882
2882
2883 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2883 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2884 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2884 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2885 #find the phase shifts of each channel over 1 second intervals
2885 #find the phase shifts of each channel over 1 second intervals
2886 #only look at ranges below the beacon signal
2886 #only look at ranges below the beacon signal
2887 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2887 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2888 numBlocks = int(volts.shape[1]/numProfPerBlock)
2888 numBlocks = int(volts.shape[1]/numProfPerBlock)
2889 numHeights = volts.shape[2]
2889 numHeights = volts.shape[2]
2890 nChannel = volts.shape[0]
2890 nChannel = volts.shape[0]
2891 voltsCohDet = volts.copy()
2891 voltsCohDet = volts.copy()
2892
2892
2893 pairsarray = numpy.array(pairslist)
2893 pairsarray = numpy.array(pairslist)
2894 indSides = pairsarray[:,1]
2894 indSides = pairsarray[:,1]
2895 # indSides = numpy.array(range(nChannel))
2895 # indSides = numpy.array(range(nChannel))
2896 # indSides = numpy.delete(indSides, indCenter)
2896 # indSides = numpy.delete(indSides, indCenter)
2897 #
2897 #
2898 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2898 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2899 listBlocks = numpy.array_split(volts, numBlocks, 1)
2899 listBlocks = numpy.array_split(volts, numBlocks, 1)
2900
2900
2901 startInd = 0
2901 startInd = 0
2902 endInd = 0
2902 endInd = 0
2903
2903
2904 for i in range(numBlocks):
2904 for i in range(numBlocks):
2905 startInd = endInd
2905 startInd = endInd
2906 endInd = endInd + listBlocks[i].shape[1]
2906 endInd = endInd + listBlocks[i].shape[1]
2907
2907
2908 arrayBlock = listBlocks[i]
2908 arrayBlock = listBlocks[i]
2909 # arrayBlockCenter = listCenter[i]
2909 # arrayBlockCenter = listCenter[i]
2910
2910
2911 #Estimate the Phase Difference
2911 #Estimate the Phase Difference
2912 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2912 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2913 #Phase Difference RMS
2913 #Phase Difference RMS
2914 arrayPhaseRMS = numpy.abs(phaseDiff)
2914 arrayPhaseRMS = numpy.abs(phaseDiff)
2915 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2915 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2916 indPhase = numpy.where(phaseRMSaux==4)
2916 indPhase = numpy.where(phaseRMSaux==4)
2917 #Shifting
2917 #Shifting
2918 if indPhase[0].shape[0] > 0:
2918 if indPhase[0].shape[0] > 0:
2919 for j in range(indSides.size):
2919 for j in range(indSides.size):
2920 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2920 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2921 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2921 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2922
2922
2923 return voltsCohDet
2923 return voltsCohDet
2924
2924
2925 def __calculateCCF(self, volts, pairslist ,laglist):
2925 def __calculateCCF(self, volts, pairslist ,laglist):
2926
2926
2927 nHeights = volts.shape[2]
2927 nHeights = volts.shape[2]
2928 nPoints = volts.shape[1]
2928 nPoints = volts.shape[1]
2929 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2929 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2930
2930
2931 for i in range(len(pairslist)):
2931 for i in range(len(pairslist)):
2932 volts1 = volts[pairslist[i][0]]
2932 volts1 = volts[pairslist[i][0]]
2933 volts2 = volts[pairslist[i][1]]
2933 volts2 = volts[pairslist[i][1]]
2934
2934
2935 for t in range(len(laglist)):
2935 for t in range(len(laglist)):
2936 idxT = laglist[t]
2936 idxT = laglist[t]
2937 if idxT >= 0:
2937 if idxT >= 0:
2938 vStacked = numpy.vstack((volts2[idxT:,:],
2938 vStacked = numpy.vstack((volts2[idxT:,:],
2939 numpy.zeros((idxT, nHeights),dtype='complex')))
2939 numpy.zeros((idxT, nHeights),dtype='complex')))
2940 else:
2940 else:
2941 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2941 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2942 volts2[:(nPoints + idxT),:]))
2942 volts2[:(nPoints + idxT),:]))
2943 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2943 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2944
2944
2945 vStacked = None
2945 vStacked = None
2946 return voltsCCF
2946 return voltsCCF
2947
2947
2948 def __getNoise(self, power, timeSegment, timeInterval):
2948 def __getNoise(self, power, timeSegment, timeInterval):
2949 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2949 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2950 numBlocks = int(power.shape[0]/numProfPerBlock)
2950 numBlocks = int(power.shape[0]/numProfPerBlock)
2951 numHeights = power.shape[1]
2951 numHeights = power.shape[1]
2952
2952
2953 listPower = numpy.array_split(power, numBlocks, 0)
2953 listPower = numpy.array_split(power, numBlocks, 0)
2954 noise = numpy.zeros((power.shape[0], power.shape[1]))
2954 noise = numpy.zeros((power.shape[0], power.shape[1]))
2955 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2955 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2956
2956
2957 startInd = 0
2957 startInd = 0
2958 endInd = 0
2958 endInd = 0
2959
2959
2960 for i in range(numBlocks): #split por canal
2960 for i in range(numBlocks): #split por canal
2961 startInd = endInd
2961 startInd = endInd
2962 endInd = endInd + listPower[i].shape[0]
2962 endInd = endInd + listPower[i].shape[0]
2963
2963
2964 arrayBlock = listPower[i]
2964 arrayBlock = listPower[i]
2965 noiseAux = numpy.mean(arrayBlock, 0)
2965 noiseAux = numpy.mean(arrayBlock, 0)
2966 # noiseAux = numpy.median(noiseAux)
2966 # noiseAux = numpy.median(noiseAux)
2967 # noiseAux = numpy.mean(arrayBlock)
2967 # noiseAux = numpy.mean(arrayBlock)
2968 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2968 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2969
2969
2970 noiseAux1 = numpy.mean(arrayBlock)
2970 noiseAux1 = numpy.mean(arrayBlock)
2971 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2971 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2972
2972
2973 return noise, noise1
2973 return noise, noise1
2974
2974
2975 def __findMeteors(self, power, thresh):
2975 def __findMeteors(self, power, thresh):
2976 nProf = power.shape[0]
2976 nProf = power.shape[0]
2977 nHeights = power.shape[1]
2977 nHeights = power.shape[1]
2978 listMeteors = []
2978 listMeteors = []
2979
2979
2980 for i in range(nHeights):
2980 for i in range(nHeights):
2981 powerAux = power[:,i]
2981 powerAux = power[:,i]
2982 threshAux = thresh[:,i]
2982 threshAux = thresh[:,i]
2983
2983
2984 indUPthresh = numpy.where(powerAux > threshAux)[0]
2984 indUPthresh = numpy.where(powerAux > threshAux)[0]
2985 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2985 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2986
2986
2987 j = 0
2987 j = 0
2988
2988
2989 while (j < indUPthresh.size - 2):
2989 while (j < indUPthresh.size - 2):
2990 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2990 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2991 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2991 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2992 indDNthresh = indDNthresh[indDNAux]
2992 indDNthresh = indDNthresh[indDNAux]
2993
2993
2994 if (indDNthresh.size > 0):
2994 if (indDNthresh.size > 0):
2995 indEnd = indDNthresh[0] - 1
2995 indEnd = indDNthresh[0] - 1
2996 indInit = indUPthresh[j]
2996 indInit = indUPthresh[j]
2997
2997
2998 meteor = powerAux[indInit:indEnd + 1]
2998 meteor = powerAux[indInit:indEnd + 1]
2999 indPeak = meteor.argmax() + indInit
2999 indPeak = meteor.argmax() + indInit
3000 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3000 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3001
3001
3002 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3002 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3003 j = numpy.where(indUPthresh == indEnd)[0] + 1
3003 j = numpy.where(indUPthresh == indEnd)[0] + 1
3004 else: j+=1
3004 else: j+=1
3005 else: j+=1
3005 else: j+=1
3006
3006
3007 return listMeteors
3007 return listMeteors
3008
3008
3009 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3009 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3010
3010
3011 arrayMeteors = numpy.asarray(listMeteors)
3011 arrayMeteors = numpy.asarray(listMeteors)
3012 listMeteors1 = []
3012 listMeteors1 = []
3013
3013
3014 while arrayMeteors.shape[0] > 0:
3014 while arrayMeteors.shape[0] > 0:
3015 FLAs = arrayMeteors[:,4]
3015 FLAs = arrayMeteors[:,4]
3016 maxFLA = FLAs.argmax()
3016 maxFLA = FLAs.argmax()
3017 listMeteors1.append(arrayMeteors[maxFLA,:])
3017 listMeteors1.append(arrayMeteors[maxFLA,:])
3018
3018
3019 MeteorInitTime = arrayMeteors[maxFLA,1]
3019 MeteorInitTime = arrayMeteors[maxFLA,1]
3020 MeteorEndTime = arrayMeteors[maxFLA,3]
3020 MeteorEndTime = arrayMeteors[maxFLA,3]
3021 MeteorHeight = arrayMeteors[maxFLA,0]
3021 MeteorHeight = arrayMeteors[maxFLA,0]
3022
3022
3023 #Check neighborhood
3023 #Check neighborhood
3024 maxHeightIndex = MeteorHeight + rangeLimit
3024 maxHeightIndex = MeteorHeight + rangeLimit
3025 minHeightIndex = MeteorHeight - rangeLimit
3025 minHeightIndex = MeteorHeight - rangeLimit
3026 minTimeIndex = MeteorInitTime - timeLimit
3026 minTimeIndex = MeteorInitTime - timeLimit
3027 maxTimeIndex = MeteorEndTime + timeLimit
3027 maxTimeIndex = MeteorEndTime + timeLimit
3028
3028
3029 #Check Heights
3029 #Check Heights
3030 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3030 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3031 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3031 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3032 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3032 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3033
3033
3034 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3034 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3035
3035
3036 return listMeteors1
3036 return listMeteors1
3037
3037
3038 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3038 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3039 numHeights = volts.shape[2]
3039 numHeights = volts.shape[2]
3040 nChannel = volts.shape[0]
3040 nChannel = volts.shape[0]
3041
3041
3042 thresholdPhase = thresh[0]
3042 thresholdPhase = thresh[0]
3043 thresholdNoise = thresh[1]
3043 thresholdNoise = thresh[1]
3044 thresholdDB = float(thresh[2])
3044 thresholdDB = float(thresh[2])
3045
3045
3046 thresholdDB1 = 10**(thresholdDB/10)
3046 thresholdDB1 = 10**(thresholdDB/10)
3047 pairsarray = numpy.array(pairslist)
3047 pairsarray = numpy.array(pairslist)
3048 indSides = pairsarray[:,1]
3048 indSides = pairsarray[:,1]
3049
3049
3050 pairslist1 = list(pairslist)
3050 pairslist1 = list(pairslist)
3051 pairslist1.append((0,1))
3051 pairslist1.append((0,1))
3052 pairslist1.append((3,4))
3052 pairslist1.append((3,4))
3053
3053
3054 listMeteors1 = []
3054 listMeteors1 = []
3055 listPowerSeries = []
3055 listPowerSeries = []
3056 listVoltageSeries = []
3056 listVoltageSeries = []
3057 #volts has the war data
3057 #volts has the war data
3058
3058
3059 if frequency == 30e6:
3059 if frequency == 30e6:
3060 timeLag = 45*10**-3
3060 timeLag = 45*10**-3
3061 else:
3061 else:
3062 timeLag = 15*10**-3
3062 timeLag = 15*10**-3
3063 lag = numpy.ceil(timeLag/timeInterval)
3063 lag = numpy.ceil(timeLag/timeInterval)
3064
3064
3065 for i in range(len(listMeteors)):
3065 for i in range(len(listMeteors)):
3066
3066
3067 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3067 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3068 meteorAux = numpy.zeros(16)
3068 meteorAux = numpy.zeros(16)
3069
3069
3070 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3070 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3071 mHeight = listMeteors[i][0]
3071 mHeight = listMeteors[i][0]
3072 mStart = listMeteors[i][1]
3072 mStart = listMeteors[i][1]
3073 mPeak = listMeteors[i][2]
3073 mPeak = listMeteors[i][2]
3074 mEnd = listMeteors[i][3]
3074 mEnd = listMeteors[i][3]
3075
3075
3076 #get the volt data between the start and end times of the meteor
3076 #get the volt data between the start and end times of the meteor
3077 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3077 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3078 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3078 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3079
3079
3080 #3.6. Phase Difference estimation
3080 #3.6. Phase Difference estimation
3081 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3081 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3082
3082
3083 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3083 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3084 #meteorVolts0.- all Channels, all Profiles
3084 #meteorVolts0.- all Channels, all Profiles
3085 meteorVolts0 = volts[:,:,mHeight]
3085 meteorVolts0 = volts[:,:,mHeight]
3086 meteorThresh = noise[:,mHeight]*thresholdNoise
3086 meteorThresh = noise[:,mHeight]*thresholdNoise
3087 meteorNoise = noise[:,mHeight]
3087 meteorNoise = noise[:,mHeight]
3088 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3088 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3089 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3089 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3090
3090
3091 #Times reestimation
3091 #Times reestimation
3092 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3092 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3093 if mStart1.size > 0:
3093 if mStart1.size > 0:
3094 mStart1 = mStart1[-1] + 1
3094 mStart1 = mStart1[-1] + 1
3095
3095
3096 else:
3096 else:
3097 mStart1 = mPeak
3097 mStart1 = mPeak
3098
3098
3099 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3099 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3100 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3100 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3101 if mEndDecayTime1.size == 0:
3101 if mEndDecayTime1.size == 0:
3102 mEndDecayTime1 = powerNet0.size
3102 mEndDecayTime1 = powerNet0.size
3103 else:
3103 else:
3104 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3104 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3105 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3105 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3106
3106
3107 #meteorVolts1.- all Channels, from start to end
3107 #meteorVolts1.- all Channels, from start to end
3108 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3108 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3109 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3109 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3110 if meteorVolts2.shape[1] == 0:
3110 if meteorVolts2.shape[1] == 0:
3111 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3111 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3112 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3112 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3113 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3113 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3114 ##################### END PARAMETERS REESTIMATION #########################
3114 ##################### END PARAMETERS REESTIMATION #########################
3115
3115
3116 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3116 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3117 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3117 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3118 if meteorVolts2.shape[1] > 0:
3118 if meteorVolts2.shape[1] > 0:
3119 #Phase Difference re-estimation
3119 #Phase Difference re-estimation
3120 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3120 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3121 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3121 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3122 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3122 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3123 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3123 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3124 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3124 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3125
3125
3126 #Phase Difference RMS
3126 #Phase Difference RMS
3127 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3127 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3128 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3128 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3129 #Data from Meteor
3129 #Data from Meteor
3130 mPeak1 = powerNet1.argmax() + mStart1
3130 mPeak1 = powerNet1.argmax() + mStart1
3131 mPeakPower1 = powerNet1.max()
3131 mPeakPower1 = powerNet1.max()
3132 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3132 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3133 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3133 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3134 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3134 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3135 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3135 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3136 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3136 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3137 #Vectorize
3137 #Vectorize
3138 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3138 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3139 meteorAux[7:11] = phaseDiffint[0:4]
3139 meteorAux[7:11] = phaseDiffint[0:4]
3140
3140
3141 #Rejection Criterions
3141 #Rejection Criterions
3142 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3142 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3143 meteorAux[-1] = 17
3143 meteorAux[-1] = 17
3144 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3144 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3145 meteorAux[-1] = 1
3145 meteorAux[-1] = 1
3146
3146
3147
3147
3148 else:
3148 else:
3149 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3149 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3150 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3150 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3151 PowerSeries = 0
3151 PowerSeries = 0
3152
3152
3153 listMeteors1.append(meteorAux)
3153 listMeteors1.append(meteorAux)
3154 listPowerSeries.append(PowerSeries)
3154 listPowerSeries.append(PowerSeries)
3155 listVoltageSeries.append(meteorVolts1)
3155 listVoltageSeries.append(meteorVolts1)
3156
3156
3157 return listMeteors1, listPowerSeries, listVoltageSeries
3157 return listMeteors1, listPowerSeries, listVoltageSeries
3158
3158
3159 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3159 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3160
3160
3161 threshError = 10
3161 threshError = 10
3162 #Depending if it is 30 or 50 MHz
3162 #Depending if it is 30 or 50 MHz
3163 if frequency == 30e6:
3163 if frequency == 30e6:
3164 timeLag = 45*10**-3
3164 timeLag = 45*10**-3
3165 else:
3165 else:
3166 timeLag = 15*10**-3
3166 timeLag = 15*10**-3
3167 lag = numpy.ceil(timeLag/timeInterval)
3167 lag = numpy.ceil(timeLag/timeInterval)
3168
3168
3169 listMeteors1 = []
3169 listMeteors1 = []
3170
3170
3171 for i in range(len(listMeteors)):
3171 for i in range(len(listMeteors)):
3172 meteorPower = listPower[i]
3172 meteorPower = listPower[i]
3173 meteorAux = listMeteors[i]
3173 meteorAux = listMeteors[i]
3174
3174
3175 if meteorAux[-1] == 0:
3175 if meteorAux[-1] == 0:
3176
3176
3177 try:
3177 try:
3178 indmax = meteorPower.argmax()
3178 indmax = meteorPower.argmax()
3179 indlag = indmax + lag
3179 indlag = indmax + lag
3180
3180
3181 y = meteorPower[indlag:]
3181 y = meteorPower[indlag:]
3182 x = numpy.arange(0, y.size)*timeLag
3182 x = numpy.arange(0, y.size)*timeLag
3183
3183
3184 #first guess
3184 #first guess
3185 a = y[0]
3185 a = y[0]
3186 tau = timeLag
3186 tau = timeLag
3187 #exponential fit
3187 #exponential fit
3188 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3188 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3189 y1 = self.__exponential_function(x, *popt)
3189 y1 = self.__exponential_function(x, *popt)
3190 #error estimation
3190 #error estimation
3191 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3191 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3192
3192
3193 decayTime = popt[1]
3193 decayTime = popt[1]
3194 riseTime = indmax*timeInterval
3194 riseTime = indmax*timeInterval
3195 meteorAux[11:13] = [decayTime, error]
3195 meteorAux[11:13] = [decayTime, error]
3196
3196
3197 #Table items 7, 8 and 11
3197 #Table items 7, 8 and 11
3198 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3198 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3199 meteorAux[-1] = 7
3199 meteorAux[-1] = 7
3200 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3200 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3201 meteorAux[-1] = 8
3201 meteorAux[-1] = 8
3202 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3202 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3203 meteorAux[-1] = 11
3203 meteorAux[-1] = 11
3204
3204
3205
3205
3206 except:
3206 except:
3207 meteorAux[-1] = 11
3207 meteorAux[-1] = 11
3208
3208
3209
3209
3210 listMeteors1.append(meteorAux)
3210 listMeteors1.append(meteorAux)
3211
3211
3212 return listMeteors1
3212 return listMeteors1
3213
3213
3214 #Exponential Function
3214 #Exponential Function
3215
3215
3216 def __exponential_function(self, x, a, tau):
3216 def __exponential_function(self, x, a, tau):
3217 y = a*numpy.exp(-x/tau)
3217 y = a*numpy.exp(-x/tau)
3218 return y
3218 return y
3219
3219
3220 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3220 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3221
3221
3222 pairslist1 = list(pairslist)
3222 pairslist1 = list(pairslist)
3223 pairslist1.append((0,1))
3223 pairslist1.append((0,1))
3224 pairslist1.append((3,4))
3224 pairslist1.append((3,4))
3225 numPairs = len(pairslist1)
3225 numPairs = len(pairslist1)
3226 #Time Lag
3226 #Time Lag
3227 timeLag = 45*10**-3
3227 timeLag = 45*10**-3
3228 c = 3e8
3228 c = 3e8
3229 lag = numpy.ceil(timeLag/timeInterval)
3229 lag = numpy.ceil(timeLag/timeInterval)
3230 freq = 30e6
3230 freq = 30e6
3231
3231
3232 listMeteors1 = []
3232 listMeteors1 = []
3233
3233
3234 for i in range(len(listMeteors)):
3234 for i in range(len(listMeteors)):
3235 meteorAux = listMeteors[i]
3235 meteorAux = listMeteors[i]
3236 if meteorAux[-1] == 0:
3236 if meteorAux[-1] == 0:
3237 mStart = listMeteors[i][1]
3237 mStart = listMeteors[i][1]
3238 mPeak = listMeteors[i][2]
3238 mPeak = listMeteors[i][2]
3239 mLag = mPeak - mStart + lag
3239 mLag = mPeak - mStart + lag
3240
3240
3241 #get the volt data between the start and end times of the meteor
3241 #get the volt data between the start and end times of the meteor
3242 meteorVolts = listVolts[i]
3242 meteorVolts = listVolts[i]
3243 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3243 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3244
3244
3245 #Get CCF
3245 #Get CCF
3246 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3246 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3247
3247
3248 #Method 2
3248 #Method 2
3249 slopes = numpy.zeros(numPairs)
3249 slopes = numpy.zeros(numPairs)
3250 time = numpy.array([-2,-1,1,2])*timeInterval
3250 time = numpy.array([-2,-1,1,2])*timeInterval
3251 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3251 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3252
3252
3253 #Correct phases
3253 #Correct phases
3254 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3254 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3255 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3255 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3256
3256
3257 if indDer[0].shape[0] > 0:
3257 if indDer[0].shape[0] > 0:
3258 for i in range(indDer[0].shape[0]):
3258 for i in range(indDer[0].shape[0]):
3259 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3259 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3260 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3260 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3261
3261
3262 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3262 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3263 for j in range(numPairs):
3263 for j in range(numPairs):
3264 fit = stats.linregress(time, angAllCCF[j,:])
3264 fit = stats.linregress(time, angAllCCF[j,:])
3265 slopes[j] = fit[0]
3265 slopes[j] = fit[0]
3266
3266
3267 #Remove Outlier
3267 #Remove Outlier
3268 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3268 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3269 # slopes = numpy.delete(slopes,indOut)
3269 # slopes = numpy.delete(slopes,indOut)
3270 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3270 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3271 # slopes = numpy.delete(slopes,indOut)
3271 # slopes = numpy.delete(slopes,indOut)
3272
3272
3273 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3273 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3274 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3274 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3275 meteorAux[-2] = radialError
3275 meteorAux[-2] = radialError
3276 meteorAux[-3] = radialVelocity
3276 meteorAux[-3] = radialVelocity
3277
3277
3278 #Setting Error
3278 #Setting Error
3279 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3279 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3280 if numpy.abs(radialVelocity) > 200:
3280 if numpy.abs(radialVelocity) > 200:
3281 meteorAux[-1] = 15
3281 meteorAux[-1] = 15
3282 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3282 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3283 elif radialError > radialStdThresh:
3283 elif radialError > radialStdThresh:
3284 meteorAux[-1] = 12
3284 meteorAux[-1] = 12
3285
3285
3286 listMeteors1.append(meteorAux)
3286 listMeteors1.append(meteorAux)
3287 return listMeteors1
3287 return listMeteors1
3288
3288
3289 def __setNewArrays(self, listMeteors, date, heiRang):
3289 def __setNewArrays(self, listMeteors, date, heiRang):
3290
3290
3291 #New arrays
3291 #New arrays
3292 arrayMeteors = numpy.array(listMeteors)
3292 arrayMeteors = numpy.array(listMeteors)
3293 arrayParameters = numpy.zeros((len(listMeteors), 13))
3293 arrayParameters = numpy.zeros((len(listMeteors), 13))
3294
3294
3295 #Date inclusion
3295 #Date inclusion
3296 # date = re.findall(r'\((.*?)\)', date)
3296 # date = re.findall(r'\((.*?)\)', date)
3297 # date = date[0].split(',')
3297 # date = date[0].split(',')
3298 # date = map(int, date)
3298 # date = map(int, date)
3299 #
3299 #
3300 # if len(date)<6:
3300 # if len(date)<6:
3301 # date.append(0)
3301 # date.append(0)
3302 #
3302 #
3303 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3303 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3304 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3304 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3305 arrayDate = numpy.tile(date, (len(listMeteors)))
3305 arrayDate = numpy.tile(date, (len(listMeteors)))
3306
3306
3307 #Meteor array
3307 #Meteor array
3308 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3308 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3309 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3309 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3310
3310
3311 #Parameters Array
3311 #Parameters Array
3312 arrayParameters[:,0] = arrayDate #Date
3312 arrayParameters[:,0] = arrayDate #Date
3313 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3313 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3314 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3314 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3315 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3315 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3316 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3316 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3317
3317
3318
3318
3319 return arrayParameters
3319 return arrayParameters
3320
3320
3321 class CorrectSMPhases(Operation):
3321 class CorrectSMPhases(Operation):
3322
3322
3323 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3323 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3324
3324
3325 arrayParameters = dataOut.data_param
3325 arrayParameters = dataOut.data_param
3326 pairsList = []
3326 pairsList = []
3327 pairx = (0,1)
3327 pairx = (0,1)
3328 pairy = (2,3)
3328 pairy = (2,3)
3329 pairsList.append(pairx)
3329 pairsList.append(pairx)
3330 pairsList.append(pairy)
3330 pairsList.append(pairy)
3331 jph = numpy.zeros(4)
3331 jph = numpy.zeros(4)
3332
3332
3333 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3333 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3334 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3334 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3335 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3335 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3336
3336
3337 meteorOps = SMOperations()
3337 meteorOps = SMOperations()
3338 if channelPositions is None:
3338 if channelPositions is None:
3339 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3339 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3340 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3340 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3341
3341
3342 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3342 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3343 h = (hmin,hmax)
3343 h = (hmin,hmax)
3344
3344
3345 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3345 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3346
3346
3347 dataOut.data_param = arrayParameters
3347 dataOut.data_param = arrayParameters
3348 return
3348 return
3349
3349
3350 class SMPhaseCalibration(Operation):
3350 class SMPhaseCalibration(Operation):
3351
3351
3352 __buffer = None
3352 __buffer = None
3353
3353
3354 __initime = None
3354 __initime = None
3355
3355
3356 __dataReady = False
3356 __dataReady = False
3357
3357
3358 __isConfig = False
3358 __isConfig = False
3359
3359
3360 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3360 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3361
3361
3362 dataTime = currentTime + paramInterval
3362 dataTime = currentTime + paramInterval
3363 deltaTime = dataTime - initTime
3363 deltaTime = dataTime - initTime
3364
3364
3365 if deltaTime >= outputInterval or deltaTime < 0:
3365 if deltaTime >= outputInterval or deltaTime < 0:
3366 return True
3366 return True
3367
3367
3368 return False
3368 return False
3369
3369
3370 def __getGammas(self, pairs, d, phases):
3370 def __getGammas(self, pairs, d, phases):
3371 gammas = numpy.zeros(2)
3371 gammas = numpy.zeros(2)
3372
3372
3373 for i in range(len(pairs)):
3373 for i in range(len(pairs)):
3374
3374
3375 pairi = pairs[i]
3375 pairi = pairs[i]
3376
3376
3377 phip3 = phases[:,pairi[0]]
3377 phip3 = phases[:,pairi[0]]
3378 d3 = d[pairi[0]]
3378 d3 = d[pairi[0]]
3379 phip2 = phases[:,pairi[1]]
3379 phip2 = phases[:,pairi[1]]
3380 d2 = d[pairi[1]]
3380 d2 = d[pairi[1]]
3381 #Calculating gamma
3381 #Calculating gamma
3382 # jdcos = alp1/(k*d1)
3382 # jdcos = alp1/(k*d1)
3383 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3383 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3384 jgamma = -phip2*d3/d2 - phip3
3384 jgamma = -phip2*d3/d2 - phip3
3385 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3385 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3386 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3386 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3387 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3387 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3388
3388
3389 #Revised distribution
3389 #Revised distribution
3390 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3390 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3391
3391
3392 #Histogram
3392 #Histogram
3393 nBins = 64
3393 nBins = 64
3394 rmin = -0.5*numpy.pi
3394 rmin = -0.5*numpy.pi
3395 rmax = 0.5*numpy.pi
3395 rmax = 0.5*numpy.pi
3396 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3396 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3397
3397
3398 meteorsY = phaseHisto[0]
3398 meteorsY = phaseHisto[0]
3399 phasesX = phaseHisto[1][:-1]
3399 phasesX = phaseHisto[1][:-1]
3400 width = phasesX[1] - phasesX[0]
3400 width = phasesX[1] - phasesX[0]
3401 phasesX += width/2
3401 phasesX += width/2
3402
3402
3403 #Gaussian aproximation
3403 #Gaussian aproximation
3404 bpeak = meteorsY.argmax()
3404 bpeak = meteorsY.argmax()
3405 peak = meteorsY.max()
3405 peak = meteorsY.max()
3406 jmin = bpeak - 5
3406 jmin = bpeak - 5
3407 jmax = bpeak + 5 + 1
3407 jmax = bpeak + 5 + 1
3408
3408
3409 if jmin<0:
3409 if jmin<0:
3410 jmin = 0
3410 jmin = 0
3411 jmax = 6
3411 jmax = 6
3412 elif jmax > meteorsY.size:
3412 elif jmax > meteorsY.size:
3413 jmin = meteorsY.size - 6
3413 jmin = meteorsY.size - 6
3414 jmax = meteorsY.size
3414 jmax = meteorsY.size
3415
3415
3416 x0 = numpy.array([peak,bpeak,50])
3416 x0 = numpy.array([peak,bpeak,50])
3417 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3417 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3418
3418
3419 #Gammas
3419 #Gammas
3420 gammas[i] = coeff[0][1]
3420 gammas[i] = coeff[0][1]
3421
3421
3422 return gammas
3422 return gammas
3423
3423
3424 def __residualFunction(self, coeffs, y, t):
3424 def __residualFunction(self, coeffs, y, t):
3425
3425
3426 return y - self.__gauss_function(t, coeffs)
3426 return y - self.__gauss_function(t, coeffs)
3427
3427
3428 def __gauss_function(self, t, coeffs):
3428 def __gauss_function(self, t, coeffs):
3429
3429
3430 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3430 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3431
3431
3432 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3432 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3433 meteorOps = SMOperations()
3433 meteorOps = SMOperations()
3434 nchan = 4
3434 nchan = 4
3435 pairx = pairsList[0] #x es 0
3435 pairx = pairsList[0] #x es 0
3436 pairy = pairsList[1] #y es 1
3436 pairy = pairsList[1] #y es 1
3437 center_xangle = 0
3437 center_xangle = 0
3438 center_yangle = 0
3438 center_yangle = 0
3439 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3439 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3440 ntimes = len(range_angle)
3440 ntimes = len(range_angle)
3441
3441
3442 nstepsx = 20
3442 nstepsx = 20
3443 nstepsy = 20
3443 nstepsy = 20
3444
3444
3445 for iz in range(ntimes):
3445 for iz in range(ntimes):
3446 min_xangle = -range_angle[iz]/2 + center_xangle
3446 min_xangle = -range_angle[iz]/2 + center_xangle
3447 max_xangle = range_angle[iz]/2 + center_xangle
3447 max_xangle = range_angle[iz]/2 + center_xangle
3448 min_yangle = -range_angle[iz]/2 + center_yangle
3448 min_yangle = -range_angle[iz]/2 + center_yangle
3449 max_yangle = range_angle[iz]/2 + center_yangle
3449 max_yangle = range_angle[iz]/2 + center_yangle
3450
3450
3451 inc_x = (max_xangle-min_xangle)/nstepsx
3451 inc_x = (max_xangle-min_xangle)/nstepsx
3452 inc_y = (max_yangle-min_yangle)/nstepsy
3452 inc_y = (max_yangle-min_yangle)/nstepsy
3453
3453
3454 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3454 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3455 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3455 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3456 penalty = numpy.zeros((nstepsx,nstepsy))
3456 penalty = numpy.zeros((nstepsx,nstepsy))
3457 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3457 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3458 jph = numpy.zeros(nchan)
3458 jph = numpy.zeros(nchan)
3459
3459
3460 # Iterations looking for the offset
3460 # Iterations looking for the offset
3461 for iy in range(int(nstepsy)):
3461 for iy in range(int(nstepsy)):
3462 for ix in range(int(nstepsx)):
3462 for ix in range(int(nstepsx)):
3463 d3 = d[pairsList[1][0]]
3463 d3 = d[pairsList[1][0]]
3464 d2 = d[pairsList[1][1]]
3464 d2 = d[pairsList[1][1]]
3465 d5 = d[pairsList[0][0]]
3465 d5 = d[pairsList[0][0]]
3466 d4 = d[pairsList[0][1]]
3466 d4 = d[pairsList[0][1]]
3467
3467
3468 alp2 = alpha_y[iy] #gamma 1
3468 alp2 = alpha_y[iy] #gamma 1
3469 alp4 = alpha_x[ix] #gamma 0
3469 alp4 = alpha_x[ix] #gamma 0
3470
3470
3471 alp3 = -alp2*d3/d2 - gammas[1]
3471 alp3 = -alp2*d3/d2 - gammas[1]
3472 alp5 = -alp4*d5/d4 - gammas[0]
3472 alp5 = -alp4*d5/d4 - gammas[0]
3473 # jph[pairy[1]] = alpha_y[iy]
3473 # jph[pairy[1]] = alpha_y[iy]
3474 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3474 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3475
3475
3476 # jph[pairx[1]] = alpha_x[ix]
3476 # jph[pairx[1]] = alpha_x[ix]
3477 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3477 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3478 jph[pairsList[0][1]] = alp4
3478 jph[pairsList[0][1]] = alp4
3479 jph[pairsList[0][0]] = alp5
3479 jph[pairsList[0][0]] = alp5
3480 jph[pairsList[1][0]] = alp3
3480 jph[pairsList[1][0]] = alp3
3481 jph[pairsList[1][1]] = alp2
3481 jph[pairsList[1][1]] = alp2
3482 jph_array[:,ix,iy] = jph
3482 jph_array[:,ix,iy] = jph
3483 # d = [2.0,2.5,2.5,2.0]
3483 # d = [2.0,2.5,2.5,2.0]
3484 #falta chequear si va a leer bien los meteoros
3484 #falta chequear si va a leer bien los meteoros
3485 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3485 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3486 error = meteorsArray1[:,-1]
3486 error = meteorsArray1[:,-1]
3487 ind1 = numpy.where(error==0)[0]
3487 ind1 = numpy.where(error==0)[0]
3488 penalty[ix,iy] = ind1.size
3488 penalty[ix,iy] = ind1.size
3489
3489
3490 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3490 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3491 phOffset = jph_array[:,i,j]
3491 phOffset = jph_array[:,i,j]
3492
3492
3493 center_xangle = phOffset[pairx[1]]
3493 center_xangle = phOffset[pairx[1]]
3494 center_yangle = phOffset[pairy[1]]
3494 center_yangle = phOffset[pairy[1]]
3495
3495
3496 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3496 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3497 phOffset = phOffset*180/numpy.pi
3497 phOffset = phOffset*180/numpy.pi
3498 return phOffset
3498 return phOffset
3499
3499
3500
3500
3501 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3501 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3502
3502
3503 dataOut.flagNoData = True
3503 dataOut.flagNoData = True
3504 self.__dataReady = False
3504 self.__dataReady = False
3505 dataOut.outputInterval = nHours*3600
3505 dataOut.outputInterval = nHours*3600
3506
3506
3507 if self.__isConfig == False:
3507 if self.__isConfig == False:
3508 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3508 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3509 #Get Initial LTC time
3509 #Get Initial LTC time
3510 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3510 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3511 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3511 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3512
3512
3513 self.__isConfig = True
3513 self.__isConfig = True
3514
3514
3515 if self.__buffer is None:
3515 if self.__buffer is None:
3516 self.__buffer = dataOut.data_param.copy()
3516 self.__buffer = dataOut.data_param.copy()
3517
3517
3518 else:
3518 else:
3519 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3519 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3520
3520
3521 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3521 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3522
3522
3523 if self.__dataReady:
3523 if self.__dataReady:
3524 dataOut.utctimeInit = self.__initime
3524 dataOut.utctimeInit = self.__initime
3525 self.__initime += dataOut.outputInterval #to erase time offset
3525 self.__initime += dataOut.outputInterval #to erase time offset
3526
3526
3527 freq = dataOut.frequency
3527 freq = dataOut.frequency
3528 c = dataOut.C #m/s
3528 c = dataOut.C #m/s
3529 lamb = c/freq
3529 lamb = c/freq
3530 k = 2*numpy.pi/lamb
3530 k = 2*numpy.pi/lamb
3531 azimuth = 0
3531 azimuth = 0
3532 h = (hmin, hmax)
3532 h = (hmin, hmax)
3533 # pairs = ((0,1),(2,3)) #Estrella
3533 # pairs = ((0,1),(2,3)) #Estrella
3534 # pairs = ((1,0),(2,3)) #T
3534 # pairs = ((1,0),(2,3)) #T
3535
3535
3536 if channelPositions is None:
3536 if channelPositions is None:
3537 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3537 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3538 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3538 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3539 meteorOps = SMOperations()
3539 meteorOps = SMOperations()
3540 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3540 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3541
3541
3542 #Checking correct order of pairs
3542 #Checking correct order of pairs
3543 pairs = []
3543 pairs = []
3544 if distances[1] > distances[0]:
3544 if distances[1] > distances[0]:
3545 pairs.append((1,0))
3545 pairs.append((1,0))
3546 else:
3546 else:
3547 pairs.append((0,1))
3547 pairs.append((0,1))
3548
3548
3549 if distances[3] > distances[2]:
3549 if distances[3] > distances[2]:
3550 pairs.append((3,2))
3550 pairs.append((3,2))
3551 else:
3551 else:
3552 pairs.append((2,3))
3552 pairs.append((2,3))
3553 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3553 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3554
3554
3555 meteorsArray = self.__buffer
3555 meteorsArray = self.__buffer
3556 error = meteorsArray[:,-1]
3556 error = meteorsArray[:,-1]
3557 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3557 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3558 ind1 = numpy.where(boolError)[0]
3558 ind1 = numpy.where(boolError)[0]
3559 meteorsArray = meteorsArray[ind1,:]
3559 meteorsArray = meteorsArray[ind1,:]
3560 meteorsArray[:,-1] = 0
3560 meteorsArray[:,-1] = 0
3561 phases = meteorsArray[:,8:12]
3561 phases = meteorsArray[:,8:12]
3562
3562
3563 #Calculate Gammas
3563 #Calculate Gammas
3564 gammas = self.__getGammas(pairs, distances, phases)
3564 gammas = self.__getGammas(pairs, distances, phases)
3565 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3565 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3566 #Calculate Phases
3566 #Calculate Phases
3567 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3567 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3568 phasesOff = phasesOff.reshape((1,phasesOff.size))
3568 phasesOff = phasesOff.reshape((1,phasesOff.size))
3569 dataOut.data_output = -phasesOff
3569 dataOut.data_output = -phasesOff
3570 dataOut.flagNoData = False
3570 dataOut.flagNoData = False
3571 self.__buffer = None
3571 self.__buffer = None
3572
3572
3573
3573
3574 return
3574 return
3575
3575
3576 class SMOperations():
3576 class SMOperations():
3577
3577
3578 def __init__(self):
3578 def __init__(self):
3579
3579
3580 return
3580 return
3581
3581
3582 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3582 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3583
3583
3584 arrayParameters = arrayParameters0.copy()
3584 arrayParameters = arrayParameters0.copy()
3585 hmin = h[0]
3585 hmin = h[0]
3586 hmax = h[1]
3586 hmax = h[1]
3587
3587
3588 #Calculate AOA (Error N 3, 4)
3588 #Calculate AOA (Error N 3, 4)
3589 #JONES ET AL. 1998
3589 #JONES ET AL. 1998
3590 AOAthresh = numpy.pi/8
3590 AOAthresh = numpy.pi/8
3591 error = arrayParameters[:,-1]
3591 error = arrayParameters[:,-1]
3592 phases = -arrayParameters[:,8:12] + jph
3592 phases = -arrayParameters[:,8:12] + jph
3593 # phases = numpy.unwrap(phases)
3593 # phases = numpy.unwrap(phases)
3594 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3594 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3595
3595
3596 #Calculate Heights (Error N 13 and 14)
3596 #Calculate Heights (Error N 13 and 14)
3597 error = arrayParameters[:,-1]
3597 error = arrayParameters[:,-1]
3598 Ranges = arrayParameters[:,1]
3598 Ranges = arrayParameters[:,1]
3599 zenith = arrayParameters[:,4]
3599 zenith = arrayParameters[:,4]
3600 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3600 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3601
3601
3602 #----------------------- Get Final data ------------------------------------
3602 #----------------------- Get Final data ------------------------------------
3603 # error = arrayParameters[:,-1]
3603 # error = arrayParameters[:,-1]
3604 # ind1 = numpy.where(error==0)[0]
3604 # ind1 = numpy.where(error==0)[0]
3605 # arrayParameters = arrayParameters[ind1,:]
3605 # arrayParameters = arrayParameters[ind1,:]
3606
3606
3607 return arrayParameters
3607 return arrayParameters
3608
3608
3609 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3609 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3610
3610
3611 arrayAOA = numpy.zeros((phases.shape[0],3))
3611 arrayAOA = numpy.zeros((phases.shape[0],3))
3612 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3612 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3613
3613
3614 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3614 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3615 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3615 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3616 arrayAOA[:,2] = cosDirError
3616 arrayAOA[:,2] = cosDirError
3617
3617
3618 azimuthAngle = arrayAOA[:,0]
3618 azimuthAngle = arrayAOA[:,0]
3619 zenithAngle = arrayAOA[:,1]
3619 zenithAngle = arrayAOA[:,1]
3620
3620
3621 #Setting Error
3621 #Setting Error
3622 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3622 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3623 error[indError] = 0
3623 error[indError] = 0
3624 #Number 3: AOA not fesible
3624 #Number 3: AOA not fesible
3625 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3625 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3626 error[indInvalid] = 3
3626 error[indInvalid] = 3
3627 #Number 4: Large difference in AOAs obtained from different antenna baselines
3627 #Number 4: Large difference in AOAs obtained from different antenna baselines
3628 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3628 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3629 error[indInvalid] = 4
3629 error[indInvalid] = 4
3630 return arrayAOA, error
3630 return arrayAOA, error
3631
3631
3632 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3632 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3633
3633
3634 #Initializing some variables
3634 #Initializing some variables
3635 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3635 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3636 ang_aux = ang_aux.reshape(1,ang_aux.size)
3636 ang_aux = ang_aux.reshape(1,ang_aux.size)
3637
3637
3638 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3638 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3639 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3639 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3640
3640
3641
3641
3642 for i in range(2):
3642 for i in range(2):
3643 ph0 = arrayPhase[:,pairsList[i][0]]
3643 ph0 = arrayPhase[:,pairsList[i][0]]
3644 ph1 = arrayPhase[:,pairsList[i][1]]
3644 ph1 = arrayPhase[:,pairsList[i][1]]
3645 d0 = distances[pairsList[i][0]]
3645 d0 = distances[pairsList[i][0]]
3646 d1 = distances[pairsList[i][1]]
3646 d1 = distances[pairsList[i][1]]
3647
3647
3648 ph0_aux = ph0 + ph1
3648 ph0_aux = ph0 + ph1
3649 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3649 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3650 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3650 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3651 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3651 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3652 #First Estimation
3652 #First Estimation
3653 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3653 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3654
3654
3655 #Most-Accurate Second Estimation
3655 #Most-Accurate Second Estimation
3656 phi1_aux = ph0 - ph1
3656 phi1_aux = ph0 - ph1
3657 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3657 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3658 #Direction Cosine 1
3658 #Direction Cosine 1
3659 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3659 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3660
3660
3661 #Searching the correct Direction Cosine
3661 #Searching the correct Direction Cosine
3662 cosdir0_aux = cosdir0[:,i]
3662 cosdir0_aux = cosdir0[:,i]
3663 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3663 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3664 #Minimum Distance
3664 #Minimum Distance
3665 cosDiff = (cosdir1 - cosdir0_aux)**2
3665 cosDiff = (cosdir1 - cosdir0_aux)**2
3666 indcos = cosDiff.argmin(axis = 1)
3666 indcos = cosDiff.argmin(axis = 1)
3667 #Saving Value obtained
3667 #Saving Value obtained
3668 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3668 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3669
3669
3670 return cosdir0, cosdir
3670 return cosdir0, cosdir
3671
3671
3672 def __calculateAOA(self, cosdir, azimuth):
3672 def __calculateAOA(self, cosdir, azimuth):
3673 cosdirX = cosdir[:,0]
3673 cosdirX = cosdir[:,0]
3674 cosdirY = cosdir[:,1]
3674 cosdirY = cosdir[:,1]
3675
3675
3676 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3676 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3677 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3677 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3678 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3678 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3679
3679
3680 return angles
3680 return angles
3681
3681
3682 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3682 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3683
3683
3684 Ramb = 375 #Ramb = c/(2*PRF)
3684 Ramb = 375 #Ramb = c/(2*PRF)
3685 Re = 6371 #Earth Radius
3685 Re = 6371 #Earth Radius
3686 heights = numpy.zeros(Ranges.shape)
3686 heights = numpy.zeros(Ranges.shape)
3687
3687
3688 R_aux = numpy.array([0,1,2])*Ramb
3688 R_aux = numpy.array([0,1,2])*Ramb
3689 R_aux = R_aux.reshape(1,R_aux.size)
3689 R_aux = R_aux.reshape(1,R_aux.size)
3690
3690
3691 Ranges = Ranges.reshape(Ranges.size,1)
3691 Ranges = Ranges.reshape(Ranges.size,1)
3692
3692
3693 Ri = Ranges + R_aux
3693 Ri = Ranges + R_aux
3694 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3694 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3695
3695
3696 #Check if there is a height between 70 and 110 km
3696 #Check if there is a height between 70 and 110 km
3697 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3697 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3698 ind_h = numpy.where(h_bool == 1)[0]
3698 ind_h = numpy.where(h_bool == 1)[0]
3699
3699
3700 hCorr = hi[ind_h, :]
3700 hCorr = hi[ind_h, :]
3701 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3701 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3702
3702
3703 hCorr = hi[ind_hCorr][:len(ind_h)]
3703 hCorr = hi[ind_hCorr][:len(ind_h)]
3704 heights[ind_h] = hCorr
3704 heights[ind_h] = hCorr
3705
3705
3706 #Setting Error
3706 #Setting Error
3707 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3707 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3708 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3708 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3709 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3709 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3710 error[indError] = 0
3710 error[indError] = 0
3711 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3711 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3712 error[indInvalid2] = 14
3712 error[indInvalid2] = 14
3713 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3713 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3714 error[indInvalid1] = 13
3714 error[indInvalid1] = 13
3715
3715
3716 return heights, error
3716 return heights, error
3717
3717
3718 def getPhasePairs(self, channelPositions):
3718 def getPhasePairs(self, channelPositions):
3719 chanPos = numpy.array(channelPositions)
3719 chanPos = numpy.array(channelPositions)
3720 listOper = list(itertools.combinations(list(range(5)),2))
3720 listOper = list(itertools.combinations(list(range(5)),2))
3721
3721
3722 distances = numpy.zeros(4)
3722 distances = numpy.zeros(4)
3723 axisX = []
3723 axisX = []
3724 axisY = []
3724 axisY = []
3725 distX = numpy.zeros(3)
3725 distX = numpy.zeros(3)
3726 distY = numpy.zeros(3)
3726 distY = numpy.zeros(3)
3727 ix = 0
3727 ix = 0
3728 iy = 0
3728 iy = 0
3729
3729
3730 pairX = numpy.zeros((2,2))
3730 pairX = numpy.zeros((2,2))
3731 pairY = numpy.zeros((2,2))
3731 pairY = numpy.zeros((2,2))
3732
3732
3733 for i in range(len(listOper)):
3733 for i in range(len(listOper)):
3734 pairi = listOper[i]
3734 pairi = listOper[i]
3735
3735
3736 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3736 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3737
3737
3738 if posDif[0] == 0:
3738 if posDif[0] == 0:
3739 axisY.append(pairi)
3739 axisY.append(pairi)
3740 distY[iy] = posDif[1]
3740 distY[iy] = posDif[1]
3741 iy += 1
3741 iy += 1
3742 elif posDif[1] == 0:
3742 elif posDif[1] == 0:
3743 axisX.append(pairi)
3743 axisX.append(pairi)
3744 distX[ix] = posDif[0]
3744 distX[ix] = posDif[0]
3745 ix += 1
3745 ix += 1
3746
3746
3747 for i in range(2):
3747 for i in range(2):
3748 if i==0:
3748 if i==0:
3749 dist0 = distX
3749 dist0 = distX
3750 axis0 = axisX
3750 axis0 = axisX
3751 else:
3751 else:
3752 dist0 = distY
3752 dist0 = distY
3753 axis0 = axisY
3753 axis0 = axisY
3754
3754
3755 side = numpy.argsort(dist0)[:-1]
3755 side = numpy.argsort(dist0)[:-1]
3756 axis0 = numpy.array(axis0)[side,:]
3756 axis0 = numpy.array(axis0)[side,:]
3757 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3757 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3758 axis1 = numpy.unique(numpy.reshape(axis0,4))
3758 axis1 = numpy.unique(numpy.reshape(axis0,4))
3759 side = axis1[axis1 != chanC]
3759 side = axis1[axis1 != chanC]
3760 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3760 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3761 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3761 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3762 if diff1<0:
3762 if diff1<0:
3763 chan2 = side[0]
3763 chan2 = side[0]
3764 d2 = numpy.abs(diff1)
3764 d2 = numpy.abs(diff1)
3765 chan1 = side[1]
3765 chan1 = side[1]
3766 d1 = numpy.abs(diff2)
3766 d1 = numpy.abs(diff2)
3767 else:
3767 else:
3768 chan2 = side[1]
3768 chan2 = side[1]
3769 d2 = numpy.abs(diff2)
3769 d2 = numpy.abs(diff2)
3770 chan1 = side[0]
3770 chan1 = side[0]
3771 d1 = numpy.abs(diff1)
3771 d1 = numpy.abs(diff1)
3772
3772
3773 if i==0:
3773 if i==0:
3774 chanCX = chanC
3774 chanCX = chanC
3775 chan1X = chan1
3775 chan1X = chan1
3776 chan2X = chan2
3776 chan2X = chan2
3777 distances[0:2] = numpy.array([d1,d2])
3777 distances[0:2] = numpy.array([d1,d2])
3778 else:
3778 else:
3779 chanCY = chanC
3779 chanCY = chanC
3780 chan1Y = chan1
3780 chan1Y = chan1
3781 chan2Y = chan2
3781 chan2Y = chan2
3782 distances[2:4] = numpy.array([d1,d2])
3782 distances[2:4] = numpy.array([d1,d2])
3783 # axisXsides = numpy.reshape(axisX[ix,:],4)
3783 # axisXsides = numpy.reshape(axisX[ix,:],4)
3784 #
3784 #
3785 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3785 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3786 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3786 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3787 #
3787 #
3788 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3788 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3789 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3789 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3790 # channel25X = int(pairX[0,ind25X])
3790 # channel25X = int(pairX[0,ind25X])
3791 # channel20X = int(pairX[1,ind20X])
3791 # channel20X = int(pairX[1,ind20X])
3792 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3792 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3793 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3793 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3794 # channel25Y = int(pairY[0,ind25Y])
3794 # channel25Y = int(pairY[0,ind25Y])
3795 # channel20Y = int(pairY[1,ind20Y])
3795 # channel20Y = int(pairY[1,ind20Y])
3796
3796
3797 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3797 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3798 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3798 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3799
3799
3800 return pairslist, distances
3800 return pairslist, distances
3801 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3801 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3802 #
3802 #
3803 # arrayAOA = numpy.zeros((phases.shape[0],3))
3803 # arrayAOA = numpy.zeros((phases.shape[0],3))
3804 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3804 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3805 #
3805 #
3806 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3806 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3807 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3807 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3808 # arrayAOA[:,2] = cosDirError
3808 # arrayAOA[:,2] = cosDirError
3809 #
3809 #
3810 # azimuthAngle = arrayAOA[:,0]
3810 # azimuthAngle = arrayAOA[:,0]
3811 # zenithAngle = arrayAOA[:,1]
3811 # zenithAngle = arrayAOA[:,1]
3812 #
3812 #
3813 # #Setting Error
3813 # #Setting Error
3814 # #Number 3: AOA not fesible
3814 # #Number 3: AOA not fesible
3815 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3815 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3816 # error[indInvalid] = 3
3816 # error[indInvalid] = 3
3817 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3817 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3818 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3818 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3819 # error[indInvalid] = 4
3819 # error[indInvalid] = 4
3820 # return arrayAOA, error
3820 # return arrayAOA, error
3821 #
3821 #
3822 # def __getDirectionCosines(self, arrayPhase, pairsList):
3822 # def __getDirectionCosines(self, arrayPhase, pairsList):
3823 #
3823 #
3824 # #Initializing some variables
3824 # #Initializing some variables
3825 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3825 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3826 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3826 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3827 #
3827 #
3828 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3828 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3829 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3829 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3830 #
3830 #
3831 #
3831 #
3832 # for i in range(2):
3832 # for i in range(2):
3833 # #First Estimation
3833 # #First Estimation
3834 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3834 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3835 # #Dealias
3835 # #Dealias
3836 # indcsi = numpy.where(phi0_aux > numpy.pi)
3836 # indcsi = numpy.where(phi0_aux > numpy.pi)
3837 # phi0_aux[indcsi] -= 2*numpy.pi
3837 # phi0_aux[indcsi] -= 2*numpy.pi
3838 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3838 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3839 # phi0_aux[indcsi] += 2*numpy.pi
3839 # phi0_aux[indcsi] += 2*numpy.pi
3840 # #Direction Cosine 0
3840 # #Direction Cosine 0
3841 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3841 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3842 #
3842 #
3843 # #Most-Accurate Second Estimation
3843 # #Most-Accurate Second Estimation
3844 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3844 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3845 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3845 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3846 # #Direction Cosine 1
3846 # #Direction Cosine 1
3847 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3847 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3848 #
3848 #
3849 # #Searching the correct Direction Cosine
3849 # #Searching the correct Direction Cosine
3850 # cosdir0_aux = cosdir0[:,i]
3850 # cosdir0_aux = cosdir0[:,i]
3851 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3851 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3852 # #Minimum Distance
3852 # #Minimum Distance
3853 # cosDiff = (cosdir1 - cosdir0_aux)**2
3853 # cosDiff = (cosdir1 - cosdir0_aux)**2
3854 # indcos = cosDiff.argmin(axis = 1)
3854 # indcos = cosDiff.argmin(axis = 1)
3855 # #Saving Value obtained
3855 # #Saving Value obtained
3856 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3856 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3857 #
3857 #
3858 # return cosdir0, cosdir
3858 # return cosdir0, cosdir
3859 #
3859 #
3860 # def __calculateAOA(self, cosdir, azimuth):
3860 # def __calculateAOA(self, cosdir, azimuth):
3861 # cosdirX = cosdir[:,0]
3861 # cosdirX = cosdir[:,0]
3862 # cosdirY = cosdir[:,1]
3862 # cosdirY = cosdir[:,1]
3863 #
3863 #
3864 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3864 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3865 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3865 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3866 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3866 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3867 #
3867 #
3868 # return angles
3868 # return angles
3869 #
3869 #
3870 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3870 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3871 #
3871 #
3872 # Ramb = 375 #Ramb = c/(2*PRF)
3872 # Ramb = 375 #Ramb = c/(2*PRF)
3873 # Re = 6371 #Earth Radius
3873 # Re = 6371 #Earth Radius
3874 # heights = numpy.zeros(Ranges.shape)
3874 # heights = numpy.zeros(Ranges.shape)
3875 #
3875 #
3876 # R_aux = numpy.array([0,1,2])*Ramb
3876 # R_aux = numpy.array([0,1,2])*Ramb
3877 # R_aux = R_aux.reshape(1,R_aux.size)
3877 # R_aux = R_aux.reshape(1,R_aux.size)
3878 #
3878 #
3879 # Ranges = Ranges.reshape(Ranges.size,1)
3879 # Ranges = Ranges.reshape(Ranges.size,1)
3880 #
3880 #
3881 # Ri = Ranges + R_aux
3881 # Ri = Ranges + R_aux
3882 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3882 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3883 #
3883 #
3884 # #Check if there is a height between 70 and 110 km
3884 # #Check if there is a height between 70 and 110 km
3885 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3885 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3886 # ind_h = numpy.where(h_bool == 1)[0]
3886 # ind_h = numpy.where(h_bool == 1)[0]
3887 #
3887 #
3888 # hCorr = hi[ind_h, :]
3888 # hCorr = hi[ind_h, :]
3889 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3889 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3890 #
3890 #
3891 # hCorr = hi[ind_hCorr]
3891 # hCorr = hi[ind_hCorr]
3892 # heights[ind_h] = hCorr
3892 # heights[ind_h] = hCorr
3893 #
3893 #
3894 # #Setting Error
3894 # #Setting Error
3895 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3895 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3896 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3896 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3897 #
3897 #
3898 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3898 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3899 # error[indInvalid2] = 14
3899 # error[indInvalid2] = 14
3900 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3900 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3901 # error[indInvalid1] = 13
3901 # error[indInvalid1] = 13
3902 #
3902 #
3903 # return heights, error
3903 # return heights, error
3904
3904
3905
3905
3906 class WeatherRadar(Operation):
3906 class WeatherRadar(Operation):
3907 '''
3907 '''
3908 Function tat implements Weather Radar operations-
3908 Function tat implements Weather Radar operations-
3909 Input:
3909 Input:
3910 Output:
3910 Output:
3911 Parameters affected:
3911 Parameters affected:
3912 '''
3912 '''
3913 isConfig = False
3913 isConfig = False
3914
3914
3915 def __init__(self):
3915 def __init__(self):
3916 Operation.__init__(self)
3916 Operation.__init__(self)
3917
3917
3918 def setup(self,dataOut,Pt=0,Gt=0,Gr=0,lambda_=0, aL=0,
3918 def setup(self,dataOut,Pt=0,Gt=0,Gr=0,lambda_=0, aL=0,
3919 tauW= 0,thetaT=0,thetaR=0,Km =0):
3919 tauW= 0,thetaT=0,thetaR=0,Km =0):
3920 self.nCh = dataOut.nChannels
3920 self.nCh = dataOut.nChannels
3921 self.nHeis = dataOut.nHeights
3921 self.nHeis = dataOut.nHeights
3922 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3922 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3923 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3923 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3924 self.Range = self.Range.reshape(1,self.nHeis)
3924 self.Range = self.Range.reshape(1,self.nHeis)
3925 self.Range = numpy.tile(self.Range,[self.nCh,1])
3925 self.Range = numpy.tile(self.Range,[self.nCh,1])
3926 '''-----------1 Constante del Radar----------'''
3926 '''-----------1 Constante del Radar----------'''
3927 self.Pt = Pt
3927 self.Pt = Pt
3928 self.Gt = Gt
3928 self.Gt = Gt
3929 self.Gr = Gr
3929 self.Gr = Gr
3930 self.lambda_ = lambda_
3930 self.lambda_ = lambda_
3931 self.aL = aL
3931 self.aL = aL
3932 self.tauW = tauW
3932 self.tauW = tauW
3933 self.thetaT = thetaT
3933 self.thetaT = thetaT
3934 self.thetaR = thetaR
3934 self.thetaR = thetaR
3935 self.Km = Km
3935 self.Km = Km
3936 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3936 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3937 Denominator = (Pt * Gt * Gr * lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3937 Denominator = (Pt * Gt * Gr * lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3938 self.RadarConstant = Numerator/Denominator
3938 self.RadarConstant = Numerator/Denominator
3939 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3939 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3940 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3940 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3941 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3941 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3942
3942
3943 def setMoments(self,dataOut,i):
3943 def setMoments(self,dataOut,i):
3944
3944
3945 type = dataOut.inputUnit
3945 type = dataOut.inputUnit
3946 nCh = dataOut.nChannels
3946 nCh = dataOut.nChannels
3947 nHeis= dataOut.nHeights
3947 nHeis= dataOut.nHeights
3948 data_param = numpy.zeros((nCh,4,nHeis))
3948 data_param = numpy.zeros((nCh,4,nHeis))
3949 if type == "Voltage":
3949 if type == "Voltage":
3950 data_param[:,0,:] = dataOut.dataPP_POW/(dataOut.nCohInt**2)
3950 data_param[:,0,:] = dataOut.dataPP_POW/(dataOut.nCohInt**2)
3951 data_param[:,1,:] = dataOut.dataPP_DOP
3951 data_param[:,1,:] = dataOut.dataPP_DOP
3952 data_param[:,2,:] = dataOut.dataPP_WIDTH
3952 data_param[:,2,:] = dataOut.dataPP_WIDTH
3953 data_param[:,3,:] = dataOut.dataPP_SNR
3953 data_param[:,3,:] = dataOut.dataPP_SNR
3954 if type == "Spectra":
3954 if type == "Spectra":
3955 data_param[:,0,:] = dataOut.data_POW
3955 data_param[:,0,:] = dataOut.data_POW
3956 data_param[:,1,:] = dataOut.data_DOP
3956 data_param[:,1,:] = dataOut.data_DOP
3957 data_param[:,2,:] = dataOut.data_WIDTH
3957 data_param[:,2,:] = dataOut.data_WIDTH
3958 def setMoments(self,dataOut,i):
3958 def setMoments(self,dataOut,i):
3959 data_param[:,3,:] = dataOut.data_SNR
3959 data_param[:,3,:] = dataOut.data_SNR
3960
3960
3961 return data_param[:,i,:]
3961 return data_param[:,i,:]
3962
3962
3963
3963
3964 def run(self,dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3964 def run(self,dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3965 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93):
3965 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93):
3966
3966
3967 if not self.isConfig:
3967 if not self.isConfig:
3968 self.setup(dataOut= dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3968 self.setup(dataOut= dataOut,Pt=25,Gt=200.0,Gr=50.0,lambda_=0.32, aL=2.5118,
3969 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93)
3969 tauW= 4.0e-6,thetaT=0.165,thetaR=0.367,Km =0.93)
3970 self.isConfig = True
3970 self.isConfig = True
3971 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3971 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3972 Pr = self.setMoments(dataOut,0)
3972 Pr = self.setMoments(dataOut,0)
3973
3973
3974 for R in range(self.nHeis):
3974 for R in range(self.nHeis):
3975 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
3975 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R])**2
3976
3976
3977 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
3977 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
3978
3978
3979 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3979 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3980 Zeh = self.Z_radar
3980 Zeh = self.Z_radar
3981 dBZeh = 10*numpy.log10(Zeh)
3981 dBZeh = 10*numpy.log10(Zeh)
3982 dataOut.factor_Zeh= dBZeh
3982 dataOut.factor_Zeh= dBZeh
3983 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3983 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3984 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3984 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3985
3985
3986 return dataOut
3986 return dataOut
3987
3987
3988 class PedestalInformation(Operation):
3988 class PedestalInformation(Operation):
3989 path_ped = None
3989 path_ped = None
3990 path_adq = None
3990 path_adq = None
3991 t_Interval_p = None
3991 t_Interval_p = None
3992 n_Muestras_p = None
3992 n_Muestras_p = None
3993 isConfig = False
3993 isConfig = False
3994 blocksPerfile= None
3994 blocksPerfile= None
3995 f_a_p = None
3995 f_a_p = None
3996 online = None
3996 online = None
3997 angulo_adq = None
3997 angulo_adq = None
3998 nro_file = None
3998 nro_file = None
3999 nro_key_p = None
3999 nro_key_p = None
4000 tmp = None
4000 tmp = None
4001
4001
4002
4002
4003 def __init__(self):
4003 def __init__(self):
4004 Operation.__init__(self)
4004 Operation.__init__(self)
4005
4005
4006 def getfirstFilefromPath(self,path,meta,ext):
4006 def getfirstFilefromPath(self,path,meta,ext):
4007 validFilelist = []
4007 validFilelist = []
4008 #print("SEARH",path)
4008 #print("SEARH",path)
4009 try:
4009 try:
4010 fileList = os.listdir(path)
4010 fileList = os.listdir(path)
4011 except:
4011 except:
4012 print("check path - fileList")
4012 print("check path - fileList")
4013 if len(fileList)<1:
4013 if len(fileList)<1:
4014 return None
4014 return None
4015 # meta 1234 567 8-18 BCDE
4015 # meta 1234 567 8-18 BCDE
4016 # H,D,PE YYYY DDD EPOC .ext
4016 # H,D,PE YYYY DDD EPOC .ext
4017
4017
4018 for thisFile in fileList:
4018 for thisFile in fileList:
4019 #print("HI",thisFile)
4019 #print("HI",thisFile)
4020 if meta =="PE":
4020 if meta =="PE":
4021 try:
4021 try:
4022 number= int(thisFile[len(meta)+7:len(meta)+17])
4022 number= int(thisFile[len(meta)+7:len(meta)+17])
4023 except:
4023 except:
4024 print("There is a file or folder with different format")
4024 print("There is a file or folder with different format")
4025 if meta == "D":
4025 if meta == "D":
4026 try:
4026 try:
4027 number= int(thisFile[8:11])
4027 number= int(thisFile[8:11])
4028 except:
4028 except:
4029 print("There is a file or folder with different format")
4029 print("There is a file or folder with different format")
4030
4030
4031 if not isNumber(str=number):
4031 if not isNumber(str=number):
4032 continue
4032 continue
4033 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4033 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4034 continue
4034 continue
4035 validFilelist.sort()
4035 validFilelist.sort()
4036 validFilelist.append(thisFile)
4036 validFilelist.append(thisFile)
4037 if len(validFilelist)>0:
4037 if len(validFilelist)>0:
4038 validFilelist = sorted(validFilelist,key=str.lower)
4038 validFilelist = sorted(validFilelist,key=str.lower)
4039 return validFilelist
4039 return validFilelist
4040 return None
4040 return None
4041
4041
4042 def gettimeutcfromDirFilename(self,path,file):
4042 def gettimeutcfromDirFilename(self,path,file):
4043 dir_file= path+"/"+file
4043 dir_file= path+"/"+file
4044 fp = h5py.File(dir_file,'r')
4044 fp = h5py.File(dir_file,'r')
4045 #epoc = fp['Metadata'].get('utctimeInit')[()]
4045 #epoc = fp['Metadata'].get('utctimeInit')[()]
4046 epoc = fp['Data'].get('utc')[()]
4046 epoc = fp['Data'].get('utc')[()]
4047 fp.close()
4047 fp.close()
4048 return epoc
4048 return epoc
4049
4049
4050 def gettimeutcadqfromDirFilename(self,path,file):
4050 def gettimeutcadqfromDirFilename(self,path,file):
4051 dir_file= path+"/"+file
4051 dir_file= path+"/"+file
4052 fp = h5py.File(dir_file,'r')
4052 fp = h5py.File(dir_file,'r')
4053 epoc = fp['Metadata'].get('utctimeInit')[()]
4053 epoc = fp['Metadata'].get('utctimeInit')[()]
4054 #epoc = fp['Data'].get('utc')[()]
4054 #epoc = fp['Data'].get('utc')[()]
4055 fp.close()
4055 fp.close()
4056 return epoc
4056 return epoc
4057
4057
4058 def getDatavaluefromDirFilename(self,path,file,value):
4058 def getDatavaluefromDirFilename(self,path,file,value):
4059 dir_file= path+"/"+file
4059 dir_file= path+"/"+file
4060 fp = h5py.File(dir_file,'r')
4060 fp = h5py.File(dir_file,'r')
4061 array = fp['Data'].get(value)[()]
4061 array = fp['Data'].get(value)[()]
4062 fp.close()
4062 fp.close()
4063 return array
4063 return array
4064
4064
4065 def getFile_KeyP(self,list_pedestal,list_adq):
4065 def getFile_KeyP(self,list_pedestal,list_adq):
4066 print(list_pedestal)
4066 print(list_pedestal)
4067 print(list_adq)
4067 print(list_adq)
4068
4068
4069 def getNROFile(self,utc_adq,utc_ped_list):
4069 def getNROFile(self,utc_adq,utc_ped_list):
4070 c=0
4070 c=0
4071 print("insidegetNROFile")
4071 print("insidegetNROFile")
4072 print(utc_adq)
4072 print(utc_adq)
4073 print(len(utc_ped_list))
4073 print(len(utc_ped_list))
4074 for i in range(len(utc_ped_list)):
4074 for i in range(len(utc_ped_list)):
4075 if utc_adq>utc_ped_list[i]:
4075 if utc_adq>utc_ped_list[i]:
4076 #print("mayor")
4076 #print("mayor")
4077 #print("utc_ped_list",utc_ped_list[i])
4077 #print("utc_ped_list",utc_ped_list[i])
4078 c +=1
4078 c +=1
4079
4079
4080 return c-1,utc_ped_list[c-1],utc_ped_list[c]
4080 return c-1,utc_ped_list[c-1],utc_ped_list[c]
4081
4081
4082 def verificarNROFILE(self,dataOut,utc_ped,f_a_p,n_Muestras_p):
4082 def verificarNROFILE(self,dataOut,utc_ped,f_a_p,n_Muestras_p):
4083 var =int(f_a_p/n_Muestras_p)
4083 var =int(f_a_p/n_Muestras_p)
4084 flag=0
4084 flag=0
4085 for i in range(var):
4085 for i in range(var):
4086 if dataOut.utctime+i==utc_ped:
4086 if dataOut.utctime+i==utc_ped:
4087 flag==1
4087 flag==1
4088 break
4088 break
4089 return flag
4089 return flag
4090
4090
4091 #def setup_offline(self,dataOut,list_pedestal,list_adq):
4091 #def setup_offline(self,dataOut,list_pedestal,list_adq):
4092 def setup_offline(self,dataOut,list_pedestal):
4092 def setup_offline(self,dataOut,list_pedestal):
4093
4093
4094 print("SETUP OFFLINE")
4094 print("SETUP OFFLINE")
4095 print(self.path_ped)
4095 print(self.path_ped)
4096 #print(self.path_adq)
4096 #print(self.path_adq)
4097 print(len(self.list_pedestal))
4097 print(len(self.list_pedestal))
4098 #print(len(self.list_adq))
4098 #print(len(self.list_adq))
4099 utc_ped_list=[]
4099 utc_ped_list=[]
4100 for i in range(len(self.list_pedestal)):
4100 for i in range(len(self.list_pedestal)):
4101 #print(i)# OJO IDENTIFICADOR DE SINCRONISMO
4101 #print(i)# OJO IDENTIFICADOR DE SINCRONISMO
4102 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4102 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4103
4103
4104 #utc_ped_list= utc_ped_list
4104 #utc_ped_list= utc_ped_list
4105 ###utc_adq = self.gettimeutcadqfromDirFilename(path=self.path_adq,file=self.list_adq[0])
4105 ###utc_adq = self.gettimeutcadqfromDirFilename(path=self.path_adq,file=self.list_adq[0])
4106 print("dios existe donde esta")
4106 print("dios existe donde esta")
4107
4107
4108 #print("utc_ped_list",utc_ped_list)
4108 #print("utc_ped_list",utc_ped_list)
4109 ###print("utc_adq",utc_adq)
4109 ###print("utc_adq",utc_adq)
4110 # utc_adq_dataOut
4110 # utc_adq_dataOut
4111 utc_adq_dataOut =dataOut.utctime
4111 utc_adq_dataOut =dataOut.utctime
4112 print("Offline-utc_adq_dataout",utc_adq_dataOut)
4112 print("Offline-utc_adq_dataout",utc_adq_dataOut)
4113
4113
4114 nro_file,utc_ped,utc_ped_1 = self.getNROFile(utc_adq=utc_adq_dataOut, utc_ped_list= utc_ped_list)
4114 nro_file,utc_ped,utc_ped_1 = self.getNROFile(utc_adq=utc_adq_dataOut, utc_ped_list= utc_ped_list)
4115
4115
4116 print("nro_file",nro_file,"utc_ped",utc_ped)
4116 print("nro_file",nro_file,"utc_ped",utc_ped)
4117 print("nro_file",i)
4117 print("nro_file",i)
4118 nro_key_p = int((utc_adq_dataOut-utc_ped)/self.t_Interval_p)-1 # ojito al -1 estimado alex
4118 nro_key_p = int((utc_adq_dataOut-utc_ped)/self.t_Interval_p)-1 # ojito al -1 estimado alex
4119 print("nro_key_p",nro_key_p)
4119 print("nro_key_p",nro_key_p)
4120
4120
4121 ff_pedestal = self.list_pedestal[nro_file]
4121 ff_pedestal = self.list_pedestal[nro_file]
4122 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4122 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4123 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4123 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4124
4124
4125 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4125 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4126 print("angulo_array :",angulo[nro_key_p])
4126 print("angulo_array :",angulo[nro_key_p])
4127 self.nro_file = nro_file
4127 self.nro_file = nro_file
4128 self.nro_key_p = nro_key_p
4128 self.nro_key_p = nro_key_p
4129
4129
4130 def setup_online(self,dataOut):
4130 def setup_online(self,dataOut):
4131 utc_adq =dataOut.utctime
4131 utc_adq =dataOut.utctime
4132 print("Online-utc_adq",utc_adq)
4132 print("Online-utc_adq",utc_adq)
4133 print(len(self.list_pedestal))
4133 print(len(self.list_pedestal))
4134 utc_ped_list=[]
4134 utc_ped_list=[]
4135 for i in range(len(self.list_pedestal)):
4135 for i in range(len(self.list_pedestal)):
4136 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4136 utc_ped_list.append(self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[i]))
4137 print(utc_ped_list[:20])
4137 print(utc_ped_list[:20])
4138 #print(utc_ped_list[488:498])
4138 #print(utc_ped_list[488:498])
4139 print("ultimo UTC-PEDESTAL",utc_ped_list[-1])
4139 print("ultimo UTC-PEDESTAL",utc_ped_list[-1])
4140 nro_file,utc_ped,utc_ped_1 = self.getNROFile(utc_adq=utc_adq, utc_ped_list= utc_ped_list)
4140 nro_file,utc_ped,utc_ped_1 = self.getNROFile(utc_adq=utc_adq, utc_ped_list= utc_ped_list)
4141 print("nro_file",nro_file,"utc_ped",utc_ped,"utc_ped_1",utc_ped_1)
4141 print("nro_file",nro_file,"utc_ped",utc_ped,"utc_ped_1",utc_ped_1)
4142 print("name_PEDESTAL",self.list_pedestal[nro_file])
4142 print("name_PEDESTAL",self.list_pedestal[nro_file])
4143 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1
4143 nro_key_p = int((utc_adq-utc_ped)/self.t_Interval_p)-1
4144 print("nro_key_p",nro_key_p)
4144 print("nro_key_p",nro_key_p)
4145 ff_pedestal = self.list_pedestal[nro_file]
4145 ff_pedestal = self.list_pedestal[nro_file]
4146 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4146 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4147 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4147 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4148
4148
4149 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4149 print("utc_pedestal_init :",utc_ped+nro_key_p*self.t_Interval_p)
4150 print("angulo_array :",angulo[nro_key_p])
4150 print("angulo_array :",angulo[nro_key_p])
4151 self.nro_file = nro_file
4151 self.nro_file = nro_file
4152 self.nro_key_p = nro_key_p
4152 self.nro_key_p = nro_key_p
4153
4153
4154 #def setup(self,dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4154 #def setup(self,dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4155 def setup(self,dataOut,path_ped,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4155 def setup(self,dataOut,path_ped,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4156 print("SETUP PEDESTAL")
4156 print("SETUP PEDESTAL")
4157 self.__dataReady = False
4157 self.__dataReady = False
4158 self.path_ped = path_ped
4158 self.path_ped = path_ped
4159 #self.path_adq = path_adq
4159 #self.path_adq = path_adq
4160 self.t_Interval_p = t_Interval_p
4160 self.t_Interval_p = t_Interval_p
4161 self.n_Muestras_p = n_Muestras_p
4161 self.n_Muestras_p = n_Muestras_p
4162 self.blocksPerfile= blocksPerfile
4162 self.blocksPerfile= blocksPerfile
4163 self.f_a_p = f_a_p
4163 self.f_a_p = f_a_p
4164 self.online = online
4164 self.online = online
4165 self.angulo_adq = numpy.zeros(self.blocksPerfile)
4165 self.angulo_adq = numpy.zeros(self.blocksPerfile)
4166 self.__profIndex = 0
4166 self.__profIndex = 0
4167 self.tmp = 0
4167 self.tmp = 0
4168 self.c_ped = 0
4168 self.c_ped = 0
4169 print(self.path_ped)
4169 print(self.path_ped)
4170 #print(self.path_adq)
4170 #print(self.path_adq)
4171 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4171 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4172 print("LIST NEW", self.list_pedestal[:20])
4172 print("LIST NEW", self.list_pedestal[:20])
4173 #self.list_adq = self.getfirstFilefromPath(path=self.path_adq,meta="D",ext=".hdf5")
4173 #self.list_adq = self.getfirstFilefromPath(path=self.path_adq,meta="D",ext=".hdf5")
4174 print("*************Longitud list pedestal****************",len(self.list_pedestal))
4174 print("*************Longitud list pedestal****************",len(self.list_pedestal))
4175
4175
4176 if self.online:
4176 if self.online:
4177 print("Enable Online")
4177 print("Enable Online")
4178 self.setup_online(dataOut)
4178 self.setup_online(dataOut)
4179 else:
4179 else:
4180 #self.setup_offline(dataOut,list_pedestal=self.list_pedestal,list_adq=self.list_adq)
4180 #self.setup_offline(dataOut,list_pedestal=self.list_pedestal,list_adq=self.list_adq)
4181 self.setup_offline(dataOut,list_pedestal=self.list_pedestal)
4181 self.setup_offline(dataOut,list_pedestal=self.list_pedestal)
4182
4182
4183
4183
4184 def setNextFileP(self,dataOut):
4184 def setNextFileP(self,dataOut):
4185 if self.online:
4185 if self.online:
4186 data_pedestal = self.setNextFileonline()
4186 data_pedestal = self.setNextFileonline()
4187 else:
4187 else:
4188 data_pedestal = self.setNextFileoffline(dataOut)
4188 data_pedestal = self.setNextFileoffline(dataOut)
4189
4189
4190 return data_pedestal
4190 return data_pedestal
4191
4191
4192
4192
4193 def setNextFileoffline(self,dataOut):
4193 def setNextFileoffline(self,dataOut):
4194 ##tmp=0
4194 ##tmp=0
4195 for j in range(self.blocksPerfile):
4195 for j in range(self.blocksPerfile):
4196 ###print("NUMERO DEL BLOQUE---->",j)
4196 ###print("NUMERO DEL BLOQUE---->",j)
4197 ###print("nro_key_p",self.nro_key_p)
4197 ###print("nro_key_p",self.nro_key_p)
4198
4198
4199 #iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4199 #iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4200 iterador = self.nro_key_p +self.f_a_p*self.c_ped
4200 iterador = self.nro_key_p +self.f_a_p*self.c_ped
4201 self.c_ped = self.c_ped +1
4201 self.c_ped = self.c_ped +1
4202
4202
4203 print("iterador------------->",iterador)
4203 print("iterador------------->",iterador)
4204 if iterador < self.n_Muestras_p:
4204 if iterador < self.n_Muestras_p:
4205 self.nro_file = self.nro_file
4205 self.nro_file = self.nro_file
4206 else:
4206 else:
4207 self.nro_file = self.nro_file+1
4207 self.nro_file = self.nro_file+1
4208 print("PRUEBA-------------")
4208 print("PRUEBA-------------")
4209 utc_ped_setnext=self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[self.nro_file])
4209 utc_ped_setnext=self.gettimeutcfromDirFilename(path=self.path_ped,file=self.list_pedestal[self.nro_file])
4210 utc_adq_setnext=dataOut.utctime
4210 utc_adq_setnext=dataOut.utctime
4211 print("utc_pedestal",utc_ped_setnext)
4211 print("utc_pedestal",utc_ped_setnext)
4212 print("utc_adq",utc_adq_setnext)
4212 print("utc_adq",utc_adq_setnext)
4213
4213
4214 print("self.c_ped",self.c_ped)
4214 print("self.c_ped",self.c_ped)
4215 #dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(self.c_ped-2))
4215 #dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(self.c_ped-2))
4216 dif = self.n_Muestras_p-(self.nro_key_p+self.f_a_p*(self.c_ped-2))
4216 dif = self.n_Muestras_p-(self.nro_key_p+self.f_a_p*(self.c_ped-2))
4217
4217
4218 self.c_ped = 1
4218 self.c_ped = 1
4219 ##tmp = j
4219 ##tmp = j
4220 ##print("tmp else",tmp)
4220 ##print("tmp else",tmp)
4221 self.nro_key_p= self.f_a_p-dif
4221 self.nro_key_p= self.f_a_p-dif
4222 iterador = self.nro_key_p
4222 iterador = self.nro_key_p
4223 print("iterador else",iterador)
4223 print("iterador else",iterador)
4224 #self.c_ped = self.c_ped +1
4224 #self.c_ped = self.c_ped +1
4225
4225
4226 print("nro_file",self.nro_file)
4226 print("nro_file",self.nro_file)
4227 #print("tmp",tmp)
4227 #print("tmp",tmp)
4228 try:
4228 try:
4229 ff_pedestal = self.list_pedestal[self.nro_file]
4229 ff_pedestal = self.list_pedestal[self.nro_file]
4230 print("ff_pedestal",ff_pedestal)
4230 print("ff_pedestal",ff_pedestal)
4231 except:
4231 except:
4232 print("############# EXCEPCION ######################")
4232 print("############# EXCEPCION ######################")
4233 return numpy.ones(self.blocksPerfile)*numpy.nan
4233 return numpy.ones(self.blocksPerfile)*numpy.nan
4234
4234
4235 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4235 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4236 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4236 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4237
4237
4238 self.angulo_adq[j]= angulo[iterador]
4238 self.angulo_adq[j]= angulo[iterador]
4239
4239
4240 return self.angulo_adq
4240 return self.angulo_adq
4241
4241
4242 def setNextFileonline(self):
4242 def setNextFileonline(self):
4243 tmp = 0
4243 tmp = 0
4244 self.nTries_p = 3
4244 self.nTries_p = 3
4245 self.delay = 3
4245 self.delay = 3
4246 ready = 1
4246 ready = 1
4247 for j in range(self.blocksPerfile):
4247 for j in range(self.blocksPerfile):
4248 iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4248 iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4249 if iterador < self.n_Muestras_p:
4249 if iterador < self.n_Muestras_p:
4250 self.nro_file = self.nro_file
4250 self.nro_file = self.nro_file
4251 else:
4251 else:
4252 self.nro_file = self.nro_file+1
4252 self.nro_file = self.nro_file+1
4253 dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(j-tmp-1))
4253 dif = self.blocksPerfile-(self.nro_key_p+self.f_a_p*(j-tmp-1))
4254 tmp = j
4254 tmp = j
4255 self.nro_key_p= self.f_a_p-dif
4255 self.nro_key_p= self.f_a_p-dif
4256 iterador = self.nro_key_p
4256 iterador = self.nro_key_p
4257 #print("nro_file---------------- :",self.nro_file)
4257 #print("nro_file---------------- :",self.nro_file)
4258 try:
4258 try:
4259 # update list_pedestal
4259 # update list_pedestal
4260 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4260 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4261 ff_pedestal = self.list_pedestal[self.nro_file]
4261 ff_pedestal = self.list_pedestal[self.nro_file]
4262 except:
4262 except:
4263 ff_pedestal = None
4263 ff_pedestal = None
4264 ready = 0
4264 ready = 0
4265 for nTries_p in range(self.nTries_p):
4265 for nTries_p in range(self.nTries_p):
4266 try:
4266 try:
4267 # update list_pedestal
4267 # update list_pedestal
4268 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4268 self.list_pedestal = self.getfirstFilefromPath(path=self.path_ped,meta="PE",ext=".hdf5")
4269 ff_pedestal = self.list_pedestal[self.nro_file]
4269 ff_pedestal = self.list_pedestal[self.nro_file]
4270 except:
4270 except:
4271 ff_pedestal = None
4271 ff_pedestal = None
4272 if ff_pedestal is not None:
4272 if ff_pedestal is not None:
4273 ready=1
4273 ready=1
4274 break
4274 break
4275 log.warning("Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, self.nro_file, nTries_p + 1))
4275 log.warning("Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, self.nro_file, nTries_p + 1))
4276 time.sleep(self.delay)
4276 time.sleep(self.delay)
4277 continue
4277 continue
4278 #return numpy.ones(self.blocksPerfile)*numpy.nan
4278 #return numpy.ones(self.blocksPerfile)*numpy.nan
4279
4279
4280 if ready == 1:
4280 if ready == 1:
4281 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4281 #angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azimuth")
4282 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4282 angulo = self.getDatavaluefromDirFilename(path=self.path_ped,file=ff_pedestal,value="azi_pos")
4283
4283
4284 else:
4284 else:
4285 print("there is no pedestal file")
4285 print("there is no pedestal file")
4286 angulo = numpy.ones(self.n_Muestras_p)*numpy.nan
4286 angulo = numpy.ones(self.n_Muestras_p)*numpy.nan
4287 self.angulo_adq[j]= angulo[iterador]
4287 self.angulo_adq[j]= angulo[iterador]
4288 ####print("Angulo",self.angulo_adq)
4288 ####print("Angulo",self.angulo_adq)
4289 ####print("Angulo",len(self.angulo_adq))
4289 ####print("Angulo",len(self.angulo_adq))
4290 #self.nro_key_p=iterador + self.f_a_p
4290 #self.nro_key_p=iterador + self.f_a_p
4291 #if self.nro_key_p< self.n_Muestras_p:
4291 #if self.nro_key_p< self.n_Muestras_p:
4292 # self.nro_file = self.nro_file
4292 # self.nro_file = self.nro_file
4293 #else:
4293 #else:
4294 # self.nro_file = self.nro_file+1
4294 # self.nro_file = self.nro_file+1
4295 # self.nro_key_p= self.nro_key_p
4295 # self.nro_key_p= self.nro_key_p
4296 return self.angulo_adq
4296 return self.angulo_adq
4297
4297
4298
4298
4299 #def run(self, dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4299 #def run(self, dataOut,path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4300 def run(self, dataOut,path_ped,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4300 def run(self, dataOut,path_ped,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online):
4301
4301
4302 if not self.isConfig:
4302 if not self.isConfig:
4303 print("######################SETUP#########################################")
4303 print("######################SETUP#########################################")
4304 #self.setup( dataOut, path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online)
4304 #self.setup( dataOut, path_ped,path_adq,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online)
4305 self.setup( dataOut, path_ped,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online)
4305 self.setup( dataOut, path_ped,t_Interval_p,n_Muestras_p,blocksPerfile,f_a_p,online)
4306 self.isConfig = True
4306 self.isConfig = True
4307
4307
4308 dataOut.flagNoData = True
4308 dataOut.flagNoData = True
4309 print("profIndex",self.__profIndex)
4309 ###print("profIndex",self.__profIndex)
4310
4310
4311 if self.__profIndex==0:
4311 if self.__profIndex==0:
4312 angulo_adq = self.setNextFileP(dataOut)
4312 angulo_adq = self.setNextFileP(dataOut)
4313 dataOut.azimuth = angulo_adq
4313 dataOut.azimuth = angulo_adq
4314 print("TIEMPO:",dataOut.utctime)
4314 ######print("TIEMPO:",dataOut.utctime)
4315 ##print("####################################################################")
4315 ##print("####################################################################")
4316 print("angulos",dataOut.azimuth,len(dataOut.azimuth))
4316 ######print("angulos",dataOut.azimuth,len(dataOut.azimuth))
4317 self.__dataReady = True
4317 self.__dataReady = True
4318 self.__profIndex += 1
4318 self.__profIndex += 1
4319 print("TIEMPO_bucle:",dataOut.utctime)
4319 ####print("TIEMPO_bucle:",dataOut.utctime)
4320 print("profIndex",self.__profIndex)
4320 ####print("profIndex",self.__profIndex)
4321 if self.__profIndex== blocksPerfile:
4321 if self.__profIndex== blocksPerfile:
4322 self.__profIndex = 0
4322 self.__profIndex = 0
4323 if self.__dataReady:
4323 if self.__dataReady:
4324 #print(self.__profIndex,dataOut.azimuth[:10])
4324 #print(self.__profIndex,dataOut.azimuth[:10])
4325 dataOut.flagNoData = False
4325 dataOut.flagNoData = False
4326 return dataOut
4326 return dataOut
4327
4327
4328
4328
4329 class Block360(Operation):
4329 class Block360(Operation):
4330 '''
4330 '''
4331 '''
4331 '''
4332 isConfig = False
4332 isConfig = False
4333 __profIndex = 0
4333 __profIndex = 0
4334 __initime = None
4334 __initime = None
4335 __lastdatatime = None
4335 __lastdatatime = None
4336 __buffer = None
4336 __buffer = None
4337 __dataReady = False
4337 __dataReady = False
4338 n = None
4338 n = None
4339 __nch = 0
4339 __nch = 0
4340 __nHeis = 0
4340 __nHeis = 0
4341 index = 0
4341 index = 0
4342 mode = 0
4342 mode = 0
4343
4343
4344 def __init__(self,**kwargs):
4344 def __init__(self,**kwargs):
4345 Operation.__init__(self,**kwargs)
4345 Operation.__init__(self,**kwargs)
4346
4346
4347 def setup(self, dataOut, n = None, mode = None):
4347 def setup(self, dataOut, n = None, mode = None):
4348 '''
4348 '''
4349 n= Numero de PRF's de entrada
4349 n= Numero de PRF's de entrada
4350 '''
4350 '''
4351 self.__initime = None
4351 self.__initime = None
4352 self.__lastdatatime = 0
4352 self.__lastdatatime = 0
4353 self.__dataReady = False
4353 self.__dataReady = False
4354 self.__buffer = 0
4354 self.__buffer = 0
4355 self.__buffer_1D = 0
4355 self.__buffer_1D = 0
4356 self.__profIndex = 0
4356 self.__profIndex = 0
4357 self.index = 0
4357 self.index = 0
4358 self.__nch = dataOut.nChannels
4358 self.__nch = dataOut.nChannels
4359 self.__nHeis = dataOut.nHeights
4359 self.__nHeis = dataOut.nHeights
4360 ##print("ELVALOR DE n es:", n)
4360 ##print("ELVALOR DE n es:", n)
4361 if n == None:
4361 if n == None:
4362 raise ValueError("n should be specified.")
4362 raise ValueError("n should be specified.")
4363
4363
4364 if mode == None:
4364 if mode == None:
4365 raise ValueError("mode should be specified.")
4365 raise ValueError("mode should be specified.")
4366
4366
4367 if n != None:
4367 if n != None:
4368 if n<1:
4368 if n<1:
4369 print("n should be greater than 2")
4369 print("n should be greater than 2")
4370 raise ValueError("n should be greater than 2")
4370 raise ValueError("n should be greater than 2")
4371
4371
4372 self.n = n
4372 self.n = n
4373 self.mode = mode
4373 self.mode = mode
4374 print("self.mode",self.mode)
4374 print("self.mode",self.mode)
4375 #print("nHeights")
4375 #print("nHeights")
4376 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4376 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4377 self.__buffer2= numpy.zeros(n)
4377 self.__buffer2= numpy.zeros(n)
4378
4378
4379 def putData(self,data,mode):
4379 def putData(self,data,mode):
4380 '''
4380 '''
4381 Add a profile to he __buffer and increase in one the __profiel Index
4381 Add a profile to he __buffer and increase in one the __profiel Index
4382 '''
4382 '''
4383 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4383 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4384 #print("line 4049",data.azimuth.shape,data.azimuth)
4384 #print("line 4049",data.azimuth.shape,data.azimuth)
4385 if self.mode==0:
4385 if self.mode==0:
4386 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4386 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4387 if self.mode==1:
4387 if self.mode==1:
4388 self.__buffer[:,self.__profIndex,:]= data.data_pow
4388 self.__buffer[:,self.__profIndex,:]= data.data_pow
4389 #print("me casi",self.index,data.azimuth[self.index])
4389 #print("me casi",self.index,data.azimuth[self.index])
4390 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4390 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4391 #print("magic",data.profileIndex)
4391 #print("magic",data.profileIndex)
4392 #print(data.azimuth[self.index])
4392 #print(data.azimuth[self.index])
4393 #print("index",self.index)
4393 #print("index",self.index)
4394
4394
4395 self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4395 self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4396 #print("q pasa")
4396 #print("q pasa")
4397 self.index+=1
4397 self.index+=1
4398 #print("index",self.index,data.azimuth[:10])
4398 #print("index",self.index,data.azimuth[:10])
4399 self.__profIndex += 1
4399 self.__profIndex += 1
4400 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4400 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4401
4401
4402 def pushData(self,data):
4402 def pushData(self,data):
4403 '''
4403 '''
4404 Return the PULSEPAIR and the profiles used in the operation
4404 Return the PULSEPAIR and the profiles used in the operation
4405 Affected : self.__profileIndex
4405 Affected : self.__profileIndex
4406 '''
4406 '''
4407 #print("pushData")
4407 #print("pushData")
4408
4408
4409 data_360 = self.__buffer
4409 data_360 = self.__buffer
4410 data_p = self.__buffer2
4410 data_p = self.__buffer2
4411 n = self.__profIndex
4411 n = self.__profIndex
4412
4412
4413 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4413 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4414 self.__buffer2 = numpy.zeros(self.n)
4414 self.__buffer2 = numpy.zeros(self.n)
4415 self.__profIndex = 0
4415 self.__profIndex = 0
4416 #print("pushData")
4416 #print("pushData")
4417 return data_360,n,data_p
4417 return data_360,n,data_p
4418
4418
4419
4419
4420 def byProfiles(self,dataOut):
4420 def byProfiles(self,dataOut):
4421
4421
4422 self.__dataReady = False
4422 self.__dataReady = False
4423 data_360 = None
4423 data_360 = None
4424 data_p = None
4424 data_p = None
4425 #print("dataOu",dataOut.dataPP_POW)
4425 #print("dataOu",dataOut.dataPP_POW)
4426 self.putData(data=dataOut,mode = self.mode)
4426 self.putData(data=dataOut,mode = self.mode)
4427 #print("profIndex",self.__profIndex)
4427 #print("profIndex",self.__profIndex)
4428 if self.__profIndex == self.n:
4428 if self.__profIndex == self.n:
4429 data_360,n,data_p = self.pushData(data=dataOut)
4429 data_360,n,data_p = self.pushData(data=dataOut)
4430 self.__dataReady = True
4430 self.__dataReady = True
4431
4431
4432 return data_360,data_p
4432 return data_360,data_p
4433
4433
4434
4434
4435 def blockOp(self, dataOut, datatime= None):
4435 def blockOp(self, dataOut, datatime= None):
4436 if self.__initime == None:
4436 if self.__initime == None:
4437 self.__initime = datatime
4437 self.__initime = datatime
4438 data_360,data_p = self.byProfiles(dataOut)
4438 data_360,data_p = self.byProfiles(dataOut)
4439 self.__lastdatatime = datatime
4439 self.__lastdatatime = datatime
4440
4440
4441 if data_360 is None:
4441 if data_360 is None:
4442 return None, None,None
4442 return None, None,None
4443
4443
4444 avgdatatime = self.__initime
4444 avgdatatime = self.__initime
4445 deltatime = datatime - self.__lastdatatime
4445 deltatime = datatime - self.__lastdatatime
4446 self.__initime = datatime
4446 self.__initime = datatime
4447 #print(data_360.shape,avgdatatime,data_p.shape)
4447 #print(data_360.shape,avgdatatime,data_p.shape)
4448 return data_360,avgdatatime,data_p
4448 return data_360,avgdatatime,data_p
4449
4449
4450 def run(self, dataOut,n = None,mode=None,**kwargs):
4450 def run(self, dataOut,n = None,mode=None,**kwargs):
4451 print("BLOCK 360 HERE WE GO MOMENTOS")
4451 ####print("BLOCK 360 HERE WE GO MOMENTOS")
4452 if not self.isConfig:
4452 if not self.isConfig:
4453 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4453 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4454 self.index = 0
4454 self.index = 0
4455 #print("comova",self.isConfig)
4455 #print("comova",self.isConfig)
4456 self.isConfig = True
4456 self.isConfig = True
4457 if self.index==dataOut.azimuth.shape[0]:
4457 if self.index==dataOut.azimuth.shape[0]:
4458 self.index=0
4458 self.index=0
4459 data_360, avgdatatime,data_p = self.blockOp(dataOut, dataOut.utctime)
4459 data_360, avgdatatime,data_p = self.blockOp(dataOut, dataOut.utctime)
4460 dataOut.flagNoData = True
4460 dataOut.flagNoData = True
4461
4461
4462 if self.__dataReady:
4462 if self.__dataReady:
4463 dataOut.data_360 = data_360 # S
4463 dataOut.data_360 = data_360 # S
4464 ##print("---------------------------------------------------------------------------------")
4464 ##print("---------------------------------------------------------------------------------")
4465 ##print("---------------------------DATAREADY---------------------------------------------")
4465 ##print("---------------------------DATAREADY---------------------------------------------")
4466 ##print("---------------------------------------------------------------------------------")
4466 ##print("---------------------------------------------------------------------------------")
4467 ##print("data_360",dataOut.data_360.shape)
4467 ##print("data_360",dataOut.data_360.shape)
4468 dataOut.data_azi = data_p
4468 dataOut.data_azi = data_p
4469 ##print("azi: ",dataOut.data_azi)
4469 ##print("azi: ",dataOut.data_azi)
4470 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4470 #print("jroproc_parameters",data_p[0],data_p[-1])#,data_360.shape,avgdatatime)
4471 dataOut.utctime = avgdatatime
4471 dataOut.utctime = avgdatatime
4472 dataOut.flagNoData = False
4472 dataOut.flagNoData = False
4473 return dataOut
4473 return dataOut
@@ -1,1628 +1,1627
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
219
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
957
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
1005
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 print("[INICIO]-setup del METODO PULSE PAIR")
1327 print("[INICIO]-setup del METODO PULSE PAIR")
1328 self.__initime = None
1328 self.__initime = None
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
1341
1342 print("ELVALOR DE n es:", n)
1342 print("ELVALOR DE n es:", n)
1343 if n == None:
1343 if n == None:
1344 raise ValueError("n should be specified.")
1344 raise ValueError("n should be specified.")
1345
1345
1346 if n != None:
1346 if n != None:
1347 if n<2:
1347 if n<2:
1348 raise ValueError("n should be greater than 2")
1348 raise ValueError("n should be greater than 2")
1349
1349
1350 self.n = n
1350 self.n = n
1351 self.__nProf = n
1351 self.__nProf = n
1352
1352
1353 self.__buffer = numpy.zeros((dataOut.nChannels,
1353 self.__buffer = numpy.zeros((dataOut.nChannels,
1354 n,
1354 n,
1355 dataOut.nHeights),
1355 dataOut.nHeights),
1356 dtype='complex')
1356 dtype='complex')
1357
1357
1358 def putData(self,data):
1358 def putData(self,data):
1359 '''
1359 '''
1360 Add a profile to he __buffer and increase in one the __profiel Index
1360 Add a profile to he __buffer and increase in one the __profiel Index
1361 '''
1361 '''
1362 self.__buffer[:,self.__profIndex,:]= data
1362 self.__buffer[:,self.__profIndex,:]= data
1363 self.__profIndex += 1
1363 self.__profIndex += 1
1364 return
1364 return
1365
1365
1366 def pushData(self,dataOut):
1366 def pushData(self,dataOut):
1367 '''
1367 '''
1368 Return the PULSEPAIR and the profiles used in the operation
1368 Return the PULSEPAIR and the profiles used in the operation
1369 Affected : self.__profileIndex
1369 Affected : self.__profileIndex
1370 '''
1370 '''
1371 #----------------- Remove DC-----------------------------------
1371 #----------------- Remove DC-----------------------------------
1372 if self.removeDC==True:
1372 if self.removeDC==True:
1373 mean = numpy.mean(self.__buffer,1)
1373 mean = numpy.mean(self.__buffer,1)
1374 tmp = mean.reshape(self.__nch,1,self.__nHeis)
1374 tmp = mean.reshape(self.__nch,1,self.__nHeis)
1375 dc= numpy.tile(tmp,[1,self.__nProf,1])
1375 dc= numpy.tile(tmp,[1,self.__nProf,1])
1376 self.__buffer = self.__buffer - dc
1376 self.__buffer = self.__buffer - dc
1377 #------------------Calculo de Potencia ------------------------
1377 #------------------Calculo de Potencia ------------------------
1378 pair0 = self.__buffer*numpy.conj(self.__buffer)
1378 pair0 = self.__buffer*numpy.conj(self.__buffer)
1379 pair0 = pair0.real
1379 pair0 = pair0.real
1380 lag_0 = numpy.sum(pair0,1)
1380 lag_0 = numpy.sum(pair0,1)
1381 #------------------Calculo de Ruido x canal--------------------
1381 #------------------Calculo de Ruido x canal--------------------
1382 self.noise = numpy.zeros(self.__nch)
1382 self.noise = numpy.zeros(self.__nch)
1383 for i in range(self.__nch):
1383 for i in range(self.__nch):
1384 daux = numpy.sort(pair0[i,:,:],axis= None)
1384 daux = numpy.sort(pair0[i,:,:],axis= None)
1385 self.noise[i]=hildebrand_sekhon( daux ,self.nCohInt)
1385 self.noise[i]=hildebrand_sekhon( daux ,self.nCohInt)
1386
1386
1387 self.noise = self.noise.reshape(self.__nch,1)
1387 self.noise = self.noise.reshape(self.__nch,1)
1388 self.noise = numpy.tile(self.noise,[1,self.__nHeis])
1388 self.noise = numpy.tile(self.noise,[1,self.__nHeis])
1389 noise_buffer = self.noise.reshape(self.__nch,1,self.__nHeis)
1389 noise_buffer = self.noise.reshape(self.__nch,1,self.__nHeis)
1390 noise_buffer = numpy.tile(noise_buffer,[1,self.__nProf,1])
1390 noise_buffer = numpy.tile(noise_buffer,[1,self.__nProf,1])
1391 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
1391 #------------------ Potencia recibida= P , Potencia senal = S , Ruido= N--
1392 #------------------ P= S+N ,P=lag_0/N ---------------------------------
1392 #------------------ P= S+N ,P=lag_0/N ---------------------------------
1393 #-------------------- Power --------------------------------------------------
1393 #-------------------- Power --------------------------------------------------
1394 data_power = lag_0/(self.n*self.nCohInt)
1394 data_power = lag_0/(self.n*self.nCohInt)
1395 #------------------ Senal ---------------------------------------------------
1395 #------------------ Senal ---------------------------------------------------
1396 data_intensity = pair0 - noise_buffer
1396 data_intensity = pair0 - noise_buffer
1397 data_intensity = numpy.sum(data_intensity,axis=1)*(self.n*self.nCohInt)#*self.nCohInt)
1397 data_intensity = numpy.sum(data_intensity,axis=1)*(self.n*self.nCohInt)#*self.nCohInt)
1398 #data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
1398 #data_intensity = (lag_0-self.noise*self.n)*(self.n*self.nCohInt)
1399 for i in range(self.__nch):
1399 for i in range(self.__nch):
1400 for j in range(self.__nHeis):
1400 for j in range(self.__nHeis):
1401 if data_intensity[i][j] < 0:
1401 if data_intensity[i][j] < 0:
1402 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
1402 data_intensity[i][j] = numpy.min(numpy.absolute(data_intensity[i][j]))
1403
1403
1404 #----------------- Calculo de Frecuencia y Velocidad doppler--------
1404 #----------------- Calculo de Frecuencia y Velocidad doppler--------
1405 pair1 = self.__buffer[:,:-1,:]*numpy.conjugate(self.__buffer[:,1:,:])
1405 pair1 = self.__buffer[:,:-1,:]*numpy.conjugate(self.__buffer[:,1:,:])
1406 lag_1 = numpy.sum(pair1,1)
1406 lag_1 = numpy.sum(pair1,1)
1407 data_freq = (-1/(2.0*math.pi*self.ippSec*self.nCohInt))*numpy.angle(lag_1)
1407 data_freq = (-1/(2.0*math.pi*self.ippSec*self.nCohInt))*numpy.angle(lag_1)
1408 data_velocity = (self.lambda_/2.0)*data_freq
1408 data_velocity = (self.lambda_/2.0)*data_freq
1409
1409
1410 #---------------- Potencia promedio estimada de la Senal-----------
1410 #---------------- Potencia promedio estimada de la Senal-----------
1411 lag_0 = lag_0/self.n
1411 lag_0 = lag_0/self.n
1412 S = lag_0-self.noise
1412 S = lag_0-self.noise
1413
1413
1414 #---------------- Frecuencia Doppler promedio ---------------------
1414 #---------------- Frecuencia Doppler promedio ---------------------
1415 lag_1 = lag_1/(self.n-1)
1415 lag_1 = lag_1/(self.n-1)
1416 R1 = numpy.abs(lag_1)
1416 R1 = numpy.abs(lag_1)
1417
1417
1418 #---------------- Calculo del SNR----------------------------------
1418 #---------------- Calculo del SNR----------------------------------
1419 data_snrPP = S/self.noise
1419 data_snrPP = S/self.noise
1420 for i in range(self.__nch):
1420 for i in range(self.__nch):
1421 for j in range(self.__nHeis):
1421 for j in range(self.__nHeis):
1422 if data_snrPP[i][j] < 1.e-20:
1422 if data_snrPP[i][j] < 1.e-20:
1423 data_snrPP[i][j] = 1.e-20
1423 data_snrPP[i][j] = 1.e-20
1424
1424
1425 #----------------- Calculo del ancho espectral ----------------------
1425 #----------------- Calculo del ancho espectral ----------------------
1426 L = S/R1
1426 L = S/R1
1427 L = numpy.where(L<0,1,L)
1427 L = numpy.where(L<0,1,L)
1428 L = numpy.log(L)
1428 L = numpy.log(L)
1429 tmp = numpy.sqrt(numpy.absolute(L))
1429 tmp = numpy.sqrt(numpy.absolute(L))
1430 data_specwidth = (self.lambda_/(2*math.sqrt(2)*math.pi*self.ippSec*self.nCohInt))*tmp*numpy.sign(L)
1430 data_specwidth = (self.lambda_/(2*math.sqrt(2)*math.pi*self.ippSec*self.nCohInt))*tmp*numpy.sign(L)
1431 n = self.__profIndex
1431 n = self.__profIndex
1432
1432
1433 self.__buffer = numpy.zeros((self.__nch, self.__nProf,self.__nHeis), dtype='complex')
1433 self.__buffer = numpy.zeros((self.__nch, self.__nProf,self.__nHeis), dtype='complex')
1434 self.__profIndex = 0
1434 self.__profIndex = 0
1435 return data_power,data_intensity,data_velocity,data_snrPP,data_specwidth,n
1435 return data_power,data_intensity,data_velocity,data_snrPP,data_specwidth,n
1436
1436
1437
1437
1438 def pulsePairbyProfiles(self,dataOut):
1438 def pulsePairbyProfiles(self,dataOut):
1439
1439
1440 self.__dataReady = False
1440 self.__dataReady = False
1441 data_power = None
1441 data_power = None
1442 data_intensity = None
1442 data_intensity = None
1443 data_velocity = None
1443 data_velocity = None
1444 data_specwidth = None
1444 data_specwidth = None
1445 data_snrPP = None
1445 data_snrPP = None
1446 self.putData(data=dataOut.data)
1446 self.putData(data=dataOut.data)
1447 if self.__profIndex == self.n:
1447 if self.__profIndex == self.n:
1448 data_power,data_intensity, data_velocity,data_snrPP,data_specwidth, n = self.pushData(dataOut=dataOut)
1448 data_power,data_intensity, data_velocity,data_snrPP,data_specwidth, n = self.pushData(dataOut=dataOut)
1449 self.__dataReady = True
1449 self.__dataReady = True
1450
1450
1451 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth
1451 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth
1452
1452
1453
1453
1454 def pulsePairOp(self, dataOut, datatime= None):
1454 def pulsePairOp(self, dataOut, datatime= None):
1455
1455
1456 if self.__initime == None:
1456 if self.__initime == None:
1457 self.__initime = datatime
1457 self.__initime = datatime
1458 data_power, data_intensity, data_velocity, data_snrPP, data_specwidth = self.pulsePairbyProfiles(dataOut)
1458 data_power, data_intensity, data_velocity, data_snrPP, data_specwidth = self.pulsePairbyProfiles(dataOut)
1459 self.__lastdatatime = datatime
1459 self.__lastdatatime = datatime
1460
1460
1461 if data_power is None:
1461 if data_power is None:
1462 return None, None, None,None,None,None
1462 return None, None, None,None,None,None
1463
1463
1464 avgdatatime = self.__initime
1464 avgdatatime = self.__initime
1465 deltatime = datatime - self.__lastdatatime
1465 deltatime = datatime - self.__lastdatatime
1466 self.__initime = datatime
1466 self.__initime = datatime
1467
1467
1468 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth, avgdatatime
1468 return data_power, data_intensity, data_velocity, data_snrPP, data_specwidth, avgdatatime
1469
1469
1470 def run(self, dataOut,n = None,removeDC= False, overlapping= False,**kwargs):
1470 def run(self, dataOut,n = None,removeDC= False, overlapping= False,**kwargs):
1471
1471
1472 if not self.isConfig:
1472 if not self.isConfig:
1473 self.setup(dataOut = dataOut, n = n , removeDC=removeDC , **kwargs)
1473 self.setup(dataOut = dataOut, n = n , removeDC=removeDC , **kwargs)
1474 self.isConfig = True
1474 self.isConfig = True
1475 data_power, data_intensity, data_velocity,data_snrPP,data_specwidth, avgdatatime = self.pulsePairOp(dataOut, dataOut.utctime)
1475 data_power, data_intensity, data_velocity,data_snrPP,data_specwidth, avgdatatime = self.pulsePairOp(dataOut, dataOut.utctime)
1476 dataOut.flagNoData = True
1476 dataOut.flagNoData = True
1477
1477
1478 if self.__dataReady:
1478 if self.__dataReady:
1479 dataOut.nCohInt *= self.n
1479 dataOut.nCohInt *= self.n
1480 dataOut.dataPP_POW = data_intensity # S
1480 dataOut.dataPP_POW = data_intensity # S
1481 print("help",data_power)
1481 dataOut.dataPP_POWER = data_power # P valor que corresponde a POTENCIA MOMENTO
1482 dataOut.dataPP_POWER = data_power # P
1483 dataOut.dataPP_DOP = data_velocity
1482 dataOut.dataPP_DOP = data_velocity
1484 dataOut.dataPP_SNR = data_snrPP
1483 dataOut.dataPP_SNR = data_snrPP
1485 dataOut.dataPP_WIDTH = data_specwidth
1484 dataOut.dataPP_WIDTH = data_specwidth
1486 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1485 dataOut.PRFbyAngle = self.n #numero de PRF*cada angulo rotado que equivale a un tiempo.
1487 dataOut.nProfiles = int(dataOut.nProfiles/n)
1486 dataOut.nProfiles = int(dataOut.nProfiles/n)
1488 dataOut.utctime = avgdatatime
1487 dataOut.utctime = avgdatatime
1489 dataOut.flagNoData = False
1488 dataOut.flagNoData = False
1490 return dataOut
1489 return dataOut
1491
1490
1492
1491
1493
1492
1494 # import collections
1493 # import collections
1495 # from scipy.stats import mode
1494 # from scipy.stats import mode
1496 #
1495 #
1497 # class Synchronize(Operation):
1496 # class Synchronize(Operation):
1498 #
1497 #
1499 # isConfig = False
1498 # isConfig = False
1500 # __profIndex = 0
1499 # __profIndex = 0
1501 #
1500 #
1502 # def __init__(self, **kwargs):
1501 # def __init__(self, **kwargs):
1503 #
1502 #
1504 # Operation.__init__(self, **kwargs)
1503 # Operation.__init__(self, **kwargs)
1505 # # self.isConfig = False
1504 # # self.isConfig = False
1506 # self.__powBuffer = None
1505 # self.__powBuffer = None
1507 # self.__startIndex = 0
1506 # self.__startIndex = 0
1508 # self.__pulseFound = False
1507 # self.__pulseFound = False
1509 #
1508 #
1510 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1509 # def __findTxPulse(self, dataOut, channel=0, pulse_with = None):
1511 #
1510 #
1512 # #Read data
1511 # #Read data
1513 #
1512 #
1514 # powerdB = dataOut.getPower(channel = channel)
1513 # powerdB = dataOut.getPower(channel = channel)
1515 # noisedB = dataOut.getNoise(channel = channel)[0]
1514 # noisedB = dataOut.getNoise(channel = channel)[0]
1516 #
1515 #
1517 # self.__powBuffer.extend(powerdB.flatten())
1516 # self.__powBuffer.extend(powerdB.flatten())
1518 #
1517 #
1519 # dataArray = numpy.array(self.__powBuffer)
1518 # dataArray = numpy.array(self.__powBuffer)
1520 #
1519 #
1521 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1520 # filteredPower = numpy.correlate(dataArray, dataArray[0:self.__nSamples], "same")
1522 #
1521 #
1523 # maxValue = numpy.nanmax(filteredPower)
1522 # maxValue = numpy.nanmax(filteredPower)
1524 #
1523 #
1525 # if maxValue < noisedB + 10:
1524 # if maxValue < noisedB + 10:
1526 # #No se encuentra ningun pulso de transmision
1525 # #No se encuentra ningun pulso de transmision
1527 # return None
1526 # return None
1528 #
1527 #
1529 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1528 # maxValuesIndex = numpy.where(filteredPower > maxValue - 0.1*abs(maxValue))[0]
1530 #
1529 #
1531 # if len(maxValuesIndex) < 2:
1530 # if len(maxValuesIndex) < 2:
1532 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1531 # #Solo se encontro un solo pulso de transmision de un baudio, esperando por el siguiente TX
1533 # return None
1532 # return None
1534 #
1533 #
1535 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1534 # phasedMaxValuesIndex = maxValuesIndex - self.__nSamples
1536 #
1535 #
1537 # #Seleccionar solo valores con un espaciamiento de nSamples
1536 # #Seleccionar solo valores con un espaciamiento de nSamples
1538 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1537 # pulseIndex = numpy.intersect1d(maxValuesIndex, phasedMaxValuesIndex)
1539 #
1538 #
1540 # if len(pulseIndex) < 2:
1539 # if len(pulseIndex) < 2:
1541 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1540 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1542 # return None
1541 # return None
1543 #
1542 #
1544 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1543 # spacing = pulseIndex[1:] - pulseIndex[:-1]
1545 #
1544 #
1546 # #remover senales que se distancien menos de 10 unidades o muestras
1545 # #remover senales que se distancien menos de 10 unidades o muestras
1547 # #(No deberian existir IPP menor a 10 unidades)
1546 # #(No deberian existir IPP menor a 10 unidades)
1548 #
1547 #
1549 # realIndex = numpy.where(spacing > 10 )[0]
1548 # realIndex = numpy.where(spacing > 10 )[0]
1550 #
1549 #
1551 # if len(realIndex) < 2:
1550 # if len(realIndex) < 2:
1552 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1551 # #Solo se encontro un pulso de transmision con ancho mayor a 1
1553 # return None
1552 # return None
1554 #
1553 #
1555 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1554 # #Eliminar pulsos anchos (deja solo la diferencia entre IPPs)
1556 # realPulseIndex = pulseIndex[realIndex]
1555 # realPulseIndex = pulseIndex[realIndex]
1557 #
1556 #
1558 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1557 # period = mode(realPulseIndex[1:] - realPulseIndex[:-1])[0][0]
1559 #
1558 #
1560 # print "IPP = %d samples" %period
1559 # print "IPP = %d samples" %period
1561 #
1560 #
1562 # self.__newNSamples = dataOut.nHeights #int(period)
1561 # self.__newNSamples = dataOut.nHeights #int(period)
1563 # self.__startIndex = int(realPulseIndex[0])
1562 # self.__startIndex = int(realPulseIndex[0])
1564 #
1563 #
1565 # return 1
1564 # return 1
1566 #
1565 #
1567 #
1566 #
1568 # def setup(self, nSamples, nChannels, buffer_size = 4):
1567 # def setup(self, nSamples, nChannels, buffer_size = 4):
1569 #
1568 #
1570 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1569 # self.__powBuffer = collections.deque(numpy.zeros( buffer_size*nSamples,dtype=numpy.float),
1571 # maxlen = buffer_size*nSamples)
1570 # maxlen = buffer_size*nSamples)
1572 #
1571 #
1573 # bufferList = []
1572 # bufferList = []
1574 #
1573 #
1575 # for i in range(nChannels):
1574 # for i in range(nChannels):
1576 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1575 # bufferByChannel = collections.deque(numpy.zeros( buffer_size*nSamples, dtype=numpy.complex) + numpy.NAN,
1577 # maxlen = buffer_size*nSamples)
1576 # maxlen = buffer_size*nSamples)
1578 #
1577 #
1579 # bufferList.append(bufferByChannel)
1578 # bufferList.append(bufferByChannel)
1580 #
1579 #
1581 # self.__nSamples = nSamples
1580 # self.__nSamples = nSamples
1582 # self.__nChannels = nChannels
1581 # self.__nChannels = nChannels
1583 # self.__bufferList = bufferList
1582 # self.__bufferList = bufferList
1584 #
1583 #
1585 # def run(self, dataOut, channel = 0):
1584 # def run(self, dataOut, channel = 0):
1586 #
1585 #
1587 # if not self.isConfig:
1586 # if not self.isConfig:
1588 # nSamples = dataOut.nHeights
1587 # nSamples = dataOut.nHeights
1589 # nChannels = dataOut.nChannels
1588 # nChannels = dataOut.nChannels
1590 # self.setup(nSamples, nChannels)
1589 # self.setup(nSamples, nChannels)
1591 # self.isConfig = True
1590 # self.isConfig = True
1592 #
1591 #
1593 # #Append new data to internal buffer
1592 # #Append new data to internal buffer
1594 # for thisChannel in range(self.__nChannels):
1593 # for thisChannel in range(self.__nChannels):
1595 # bufferByChannel = self.__bufferList[thisChannel]
1594 # bufferByChannel = self.__bufferList[thisChannel]
1596 # bufferByChannel.extend(dataOut.data[thisChannel])
1595 # bufferByChannel.extend(dataOut.data[thisChannel])
1597 #
1596 #
1598 # if self.__pulseFound:
1597 # if self.__pulseFound:
1599 # self.__startIndex -= self.__nSamples
1598 # self.__startIndex -= self.__nSamples
1600 #
1599 #
1601 # #Finding Tx Pulse
1600 # #Finding Tx Pulse
1602 # if not self.__pulseFound:
1601 # if not self.__pulseFound:
1603 # indexFound = self.__findTxPulse(dataOut, channel)
1602 # indexFound = self.__findTxPulse(dataOut, channel)
1604 #
1603 #
1605 # if indexFound == None:
1604 # if indexFound == None:
1606 # dataOut.flagNoData = True
1605 # dataOut.flagNoData = True
1607 # return
1606 # return
1608 #
1607 #
1609 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1608 # self.__arrayBuffer = numpy.zeros((self.__nChannels, self.__newNSamples), dtype = numpy.complex)
1610 # self.__pulseFound = True
1609 # self.__pulseFound = True
1611 # self.__startIndex = indexFound
1610 # self.__startIndex = indexFound
1612 #
1611 #
1613 # #If pulse was found ...
1612 # #If pulse was found ...
1614 # for thisChannel in range(self.__nChannels):
1613 # for thisChannel in range(self.__nChannels):
1615 # bufferByChannel = self.__bufferList[thisChannel]
1614 # bufferByChannel = self.__bufferList[thisChannel]
1616 # #print self.__startIndex
1615 # #print self.__startIndex
1617 # x = numpy.array(bufferByChannel)
1616 # x = numpy.array(bufferByChannel)
1618 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1617 # self.__arrayBuffer[thisChannel] = x[self.__startIndex:self.__startIndex+self.__newNSamples]
1619 #
1618 #
1620 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1619 # deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
1621 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1620 # dataOut.heightList = numpy.arange(self.__newNSamples)*deltaHeight
1622 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1621 # # dataOut.ippSeconds = (self.__newNSamples / deltaHeight)/1e6
1623 #
1622 #
1624 # dataOut.data = self.__arrayBuffer
1623 # dataOut.data = self.__arrayBuffer
1625 #
1624 #
1626 # self.__startIndex += self.__newNSamples
1625 # self.__startIndex += self.__newNSamples
1627 #
1626 #
1628 # return
1627 # return
@@ -1,217 +1,217
1 # Ing. AVP
1 # Ing. AVP
2 # 06/10/2021
2 # 06/10/2021
3 # ARCHIVO DE LECTURA
3 # ARCHIVO DE LECTURA
4 import os, sys
4 import os, sys
5 import datetime
5 import datetime
6 import time
6 import time
7 from schainpy.controller import Project
7 from schainpy.controller import Project
8 #### NOTA###########################################
8 #### NOTA###########################################
9 # INPUT :
9 # INPUT :
10 # VELOCIDAD PARAMETRO : V = 2Β°/seg
10 # VELOCIDAD PARAMETRO : V = 2Β°/seg
11 # MODO PULSE PAIR O MOMENTOS: 0 : Pulse Pair ,1 : Momentos
11 # MODO PULSE PAIR O MOMENTOS: 0 : Pulse Pair ,1 : Momentos
12 ######################################################
12 ######################################################
13 ##### PROCESAMIENTO ##################################
13 ##### PROCESAMIENTO ##################################
14 ##### OJO TENER EN CUENTA EL n= para el Pulse Pair ##
14 ##### OJO TENER EN CUENTA EL n= para el Pulse Pair ##
15 ##### O EL n= nFFTPoints ###
15 ##### O EL n= nFFTPoints ###
16 ######################################################
16 ######################################################
17 ######## BUSCAMOS EL numero de IPP equivalente 1Β°#####
17 ######## BUSCAMOS EL numero de IPP equivalente 1Β°#####
18 ######## Sea V la velocidad del Pedestal en Β°/seg#####
18 ######## Sea V la velocidad del Pedestal en Β°/seg#####
19 ######## 1Β° sera Recorrido en un tiempo de 1/V ######
19 ######## 1Β° sera Recorrido en un tiempo de 1/V ######
20 ######## IPP del Radar 400 useg --> 60 Km ############
20 ######## IPP del Radar 400 useg --> 60 Km ############
21 ######## n = 1/(V(Β°/seg)*IPP(Km)) , NUMERO DE IPP ##
21 ######## n = 1/(V(Β°/seg)*IPP(Km)) , NUMERO DE IPP ##
22 ######## n = 1/(V*IPP) #############################
22 ######## n = 1/(V*IPP) #############################
23 ######## VELOCIDAD DEL PEDESTAL ######################
23 ######## VELOCIDAD DEL PEDESTAL ######################
24 print("SETUP- RADAR METEOROLOGICO")
24 print("SETUP- RADAR METEOROLOGICO")
25 V = 10
25 V = 10
26 mode = 1
26 mode = 0
27 #path = '/DATA_RM/23/6v'
27 #path = '/DATA_RM/23/6v'
28 #path = '/DATA_RM/TEST_INTEGRACION_2M'
28 #path = '/DATA_RM/TEST_INTEGRACION_2M'
29 path = '/DATA_RM/WR_20_OCT'
29 path = '/DATA_RM/WR_20_OCT'
30
30
31 #path_ped='/DATA_RM/TEST_PEDESTAL/P20211012-082745'
31 #path_ped='/DATA_RM/TEST_PEDESTAL/P20211012-082745'
32 path_ped='/DATA_RM/TEST_PEDESTAL/P20211020-131248'
32 path_ped='/DATA_RM/TEST_PEDESTAL/P20211020-131248'
33
33
34 figpath_pp = "/home/soporte/Pictures/TEST_PP"
34 figpath_pp = "/home/soporte/Pictures/TEST_PP"
35 figpath_mom = "/home/soporte/Pictures/TEST_MOM"
35 figpath_mom = "/home/soporte/Pictures/TEST_MOM"
36 plot = 0
36 plot = 0
37 integration = 1
37 integration = 1
38 save = 0
38 save = 0
39 if save == 1:
39 if save == 1:
40 if mode==0:
40 if mode==0:
41 path_save = '/DATA_RM/TEST_HDF5_PP_23/6v'
41 path_save = '/DATA_RM/TEST_HDF5_PP_23/6v'
42 path_save = '/DATA_RM/TEST_HDF5_PP'
42 path_save = '/DATA_RM/TEST_HDF5_PP'
43 path_save = '/DATA_RM/TEST_HDF5_PP_100'
43 path_save = '/DATA_RM/TEST_HDF5_PP_100'
44 else:
44 else:
45 path_save = '/DATA_RM/TEST_HDF5_SPEC_23_V2/6v'
45 path_save = '/DATA_RM/TEST_HDF5_SPEC_23_V2/6v'
46
46
47 print("* PATH data ADQ :", path)
47 print("* PATH data ADQ :", path)
48 print("* Velocidad Pedestal :",V,"Β°/seg")
48 print("* Velocidad Pedestal :",V,"Β°/seg")
49 ############################ NRO Perfiles PROCESAMIENTO ###################
49 ############################ NRO Perfiles PROCESAMIENTO ###################
50 V=V
50 V=V
51 IPP=400*1e-6
51 IPP=400*1e-6
52 n= int(1/(V*IPP))
52 n= int(1/(V*IPP))
53 print("* n - NRO Perfiles Proc:", n )
53 print("* n - NRO Perfiles Proc:", n )
54 ################################## MODE ###################################
54 ################################## MODE ###################################
55 print("* Modo de Operacion :",mode)
55 print("* Modo de Operacion :",mode)
56 if mode ==0:
56 if mode ==0:
57 print("* Met. Seleccionado : Pulse Pair")
57 print("* Met. Seleccionado : Pulse Pair")
58 else:
58 else:
59 print("* Met. Momentos : Momentos")
59 print("* Met. Momentos : Momentos")
60
60
61 ################################## MODE ###################################
61 ################################## MODE ###################################
62 print("* Grabado de datos :",save)
62 print("* Grabado de datos :",save)
63 if save ==1:
63 if save ==1:
64 if mode==0:
64 if mode==0:
65 ope= "Pulse Pair"
65 ope= "Pulse Pair"
66 else:
66 else:
67 ope= "Momentos"
67 ope= "Momentos"
68 print("* Path-Save Data -", ope , path_save)
68 print("* Path-Save Data -", ope , path_save)
69
69
70 print("* Integracion de datos :",integration)
70 print("* Integracion de datos :",integration)
71
71
72 time.sleep(5)
72 time.sleep(5)
73 #remotefolder = "/home/wmaster/graficos"
73 #remotefolder = "/home/wmaster/graficos"
74 #######################################################################
74 #######################################################################
75 ################# RANGO DE PLOTEO######################################
75 ################# RANGO DE PLOTEO######################################
76 dBmin = '1'
76 dBmin = '1'
77 dBmax = '85'
77 dBmax = '85'
78 xmin = '15'
78 xmin = '15'
79 xmax = '15.25'
79 xmax = '15.25'
80 ymin = '0'
80 ymin = '0'
81 ymax = '600'
81 ymax = '600'
82 #######################################################################
82 #######################################################################
83 ########################FECHA##########################################
83 ########################FECHA##########################################
84 str = datetime.date.today()
84 str = datetime.date.today()
85 today = str.strftime("%Y/%m/%d")
85 today = str.strftime("%Y/%m/%d")
86 str2 = str - datetime.timedelta(days=1)
86 str2 = str - datetime.timedelta(days=1)
87 yesterday = str2.strftime("%Y/%m/%d")
87 yesterday = str2.strftime("%Y/%m/%d")
88 #######################################################################
88 #######################################################################
89 ########################SIGNAL CHAIN ##################################
89 ########################SIGNAL CHAIN ##################################
90 #######################################################################
90 #######################################################################
91 desc = "USRP_test"
91 desc = "USRP_test"
92 filename = "USRP_processing.xml"
92 filename = "USRP_processing.xml"
93 controllerObj = Project()
93 controllerObj = Project()
94 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
94 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
95 #######################################################################
95 #######################################################################
96 ######################## UNIDAD DE LECTURA#############################
96 ######################## UNIDAD DE LECTURA#############################
97 #######################################################################
97 #######################################################################
98 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
98 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
99 path=path,
99 path=path,
100 startDate="2021/01/01",#today,
100 startDate="2021/01/01",#today,
101 endDate="2021/12/30",#today,
101 endDate="2021/12/30",#today,
102 startTime='00:00:00',
102 startTime='00:00:00',
103 endTime='23:59:59',
103 endTime='23:59:59',
104 delay=0,
104 delay=0,
105 #set=0,
105 #set=0,
106 online=0,
106 online=0,
107 walk=1,
107 walk=1,
108 ippKm = 60)
108 ippKm = 60)
109
109
110 opObj11 = readUnitConfObj.addOperation(name='printInfo')
110 opObj11 = readUnitConfObj.addOperation(name='printInfo')
111
111
112 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
112 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
113
113
114 if mode ==0:
114 if mode ==0:
115 ####################### METODO PULSE PAIR ######################################################################
115 ####################### METODO PULSE PAIR ######################################################################
116 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
116 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
117 opObj11.addParameter(name='n', value=int(n), format='int')#10 VOY A USAR 250 DADO QUE LA VELOCIDAD ES 10 GRADOS
117 opObj11.addParameter(name='n', value=int(n), format='int')#10 VOY A USAR 250 DADO QUE LA VELOCIDAD ES 10 GRADOS
118 #opObj11.addParameter(name='removeDC', value=1, format='int')
118 #opObj11.addParameter(name='removeDC', value=1, format='int')
119 ####################### METODO Parametros ######################################################################
119 ####################### METODO Parametros ######################################################################
120 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
120 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
121 if plot==1:
121 if plot==1:
122 opObj11 = procUnitConfObjB.addOperation(name='GenericRTIPlot',optype='external')
122 opObj11 = procUnitConfObjB.addOperation(name='GenericRTIPlot',optype='external')
123 opObj11.addParameter(name='attr_data', value='dataPP_POW')
123 opObj11.addParameter(name='attr_data', value='dataPP_POW')
124 opObj11.addParameter(name='colormap', value='jet')
124 opObj11.addParameter(name='colormap', value='jet')
125 opObj11.addParameter(name='xmin', value=xmin)
125 opObj11.addParameter(name='xmin', value=xmin)
126 opObj11.addParameter(name='xmax', value=xmax)
126 opObj11.addParameter(name='xmax', value=xmax)
127 opObj11.addParameter(name='zmin', value=dBmin)
127 opObj11.addParameter(name='zmin', value=dBmin)
128 opObj11.addParameter(name='zmax', value=dBmax)
128 opObj11.addParameter(name='zmax', value=dBmax)
129 opObj11.addParameter(name='save', value=figpath_pp)
129 opObj11.addParameter(name='save', value=figpath_pp)
130 opObj11.addParameter(name='showprofile', value=0)
130 opObj11.addParameter(name='showprofile', value=0)
131 opObj11.addParameter(name='save_period', value=50)
131 opObj11.addParameter(name='save_period', value=50)
132
132
133 ####################### METODO ESCRITURA #######################################################################
133 ####################### METODO ESCRITURA #######################################################################
134 if save==1:
134 if save==1:
135 opObj10 = procUnitConfObjB.addOperation(name='HDFWriter')
135 opObj10 = procUnitConfObjB.addOperation(name='HDFWriter')
136 opObj10.addParameter(name='path',value=path_save)
136 opObj10.addParameter(name='path',value=path_save)
137 #opObj10.addParameter(name='mode',value=0)
137 #opObj10.addParameter(name='mode',value=0)
138 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
138 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
139 opObj10.addParameter(name='metadataList',value='utctimeInit,timeZone,paramInterval,profileIndex,channelList,heightList,flagDataAsBlock',format='list')
139 opObj10.addParameter(name='metadataList',value='utctimeInit,timeZone,paramInterval,profileIndex,channelList,heightList,flagDataAsBlock',format='list')
140 opObj10.addParameter(name='dataList',value='dataPP_POW,dataPP_DOP,utctime',format='list')#,format='list'
140 opObj10.addParameter(name='dataList',value='dataPP_POW,dataPP_DOP,utctime',format='list')#,format='list'
141 if integration==1:
141 if integration==1:
142 V=10
142 V=10
143 blocksPerfile=360
143 blocksPerfile=360
144 print("* Velocidad del Pedestal:",V)
144 print("* Velocidad del Pedestal:",V)
145 tmp_blocksPerfile = 100
145 tmp_blocksPerfile = 100
146 f_a_p= int(tmp_blocksPerfile/V)
146 f_a_p= int(tmp_blocksPerfile/V)
147
147
148 opObj11 = procUnitConfObjB.addOperation(name='PedestalInformation')
148 opObj11 = procUnitConfObjB.addOperation(name='PedestalInformation')
149 opObj11.addParameter(name='path_ped', value=path_ped)
149 opObj11.addParameter(name='path_ped', value=path_ped)
150 #opObj11.addParameter(name='path_adq', value=path_adq)
150 #opObj11.addParameter(name='path_adq', value=path_adq)
151 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
151 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
152 opObj11.addParameter(name='blocksPerfile', value=blocksPerfile, format='int')
152 opObj11.addParameter(name='blocksPerfile', value=blocksPerfile, format='int')
153 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
153 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
154 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
154 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
155 opObj11.addParameter(name='online', value='0', format='int')
155 opObj11.addParameter(name='online', value='0', format='int')
156
156
157 opObj11 = procUnitConfObjB.addOperation(name='Block360')
157 opObj11 = procUnitConfObjB.addOperation(name='Block360')
158 opObj11.addParameter(name='n', value='10', format='int')
158 opObj11.addParameter(name='n', value='10', format='int')
159 opObj11.addParameter(name='mode', value=mode, format='int')
159 opObj11.addParameter(name='mode', value=mode, format='int')
160
160
161 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
161 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
162
162
163 opObj11= procUnitConfObjB.addOperation(name='WeatherPlot',optype='other')
163 opObj11= procUnitConfObjB.addOperation(name='WeatherPlot',optype='other')
164
164
165
165
166 else:
166 else:
167 ####################### METODO SPECTROS ######################################################################
167 ####################### METODO SPECTROS ######################################################################
168 procUnitConfObjB = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjA.getId())
168 procUnitConfObjB = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjA.getId())
169 procUnitConfObjB.addParameter(name='nFFTPoints', value=n, format='int')
169 procUnitConfObjB.addParameter(name='nFFTPoints', value=n, format='int')
170 procUnitConfObjB.addParameter(name='nProfiles' , value=n, format='int')
170 procUnitConfObjB.addParameter(name='nProfiles' , value=n, format='int')
171
171
172 procUnitConfObjC = controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjB.getId())
172 procUnitConfObjC = controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjB.getId())
173 procUnitConfObjC.addOperation(name='SpectralMoments')
173 procUnitConfObjC.addOperation(name='SpectralMoments')
174 if plot==1:
174 if plot==1:
175 dBmin = '1'
175 dBmin = '1'
176 dBmax = '65'
176 dBmax = '65'
177 opObj11 = procUnitConfObjC.addOperation(name='PowerPlot',optype='external')
177 opObj11 = procUnitConfObjC.addOperation(name='PowerPlot',optype='external')
178 opObj11.addParameter(name='xmin', value=xmin)
178 opObj11.addParameter(name='xmin', value=xmin)
179 opObj11.addParameter(name='xmax', value=xmax)
179 opObj11.addParameter(name='xmax', value=xmax)
180 opObj11.addParameter(name='zmin', value=dBmin)
180 opObj11.addParameter(name='zmin', value=dBmin)
181 opObj11.addParameter(name='zmax', value=dBmax)
181 opObj11.addParameter(name='zmax', value=dBmax)
182 opObj11.addParameter(name='save', value=figpath_mom)
182 opObj11.addParameter(name='save', value=figpath_mom)
183 opObj11.addParameter(name='showprofile', value=0)
183 opObj11.addParameter(name='showprofile', value=0)
184 opObj11.addParameter(name='save_period', value=100)
184 opObj11.addParameter(name='save_period', value=100)
185
185
186 if save==1:
186 if save==1:
187 opObj10 = procUnitConfObjC.addOperation(name='HDFWriter')
187 opObj10 = procUnitConfObjC.addOperation(name='HDFWriter')
188 opObj10.addParameter(name='path',value=path_save)
188 opObj10.addParameter(name='path',value=path_save)
189 #opObj10.addParameter(name='mode',value=0)
189 #opObj10.addParameter(name='mode',value=0)
190 opObj10.addParameter(name='blocksPerFile',value='360',format='int')
190 opObj10.addParameter(name='blocksPerFile',value='360',format='int')
191 #opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
191 #opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
192 opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
192 opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
193 opObj10.addParameter(name='dataList',value='data_pow,data_dop,utctime',format='list')#,format='list'
193 opObj10.addParameter(name='dataList',value='data_pow,data_dop,utctime',format='list')#,format='list'
194
194
195 if integration==1:
195 if integration==1:
196 V=10
196 V=10
197 blocksPerfile=360
197 blocksPerfile=360
198 print("* Velocidad del Pedestal:",V)
198 print("* Velocidad del Pedestal:",V)
199 tmp_blocksPerfile = 100
199 tmp_blocksPerfile = 100
200 f_a_p= int(tmp_blocksPerfile/V)
200 f_a_p= int(tmp_blocksPerfile/V)
201
201
202 opObj11 = procUnitConfObjC.addOperation(name='PedestalInformation')
202 opObj11 = procUnitConfObjC.addOperation(name='PedestalInformation')
203 opObj11.addParameter(name='path_ped', value=path_ped)
203 opObj11.addParameter(name='path_ped', value=path_ped)
204 #opObj11.addParameter(name='path_adq', value=path_adq)
204 #opObj11.addParameter(name='path_adq', value=path_adq)
205 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
205 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
206 opObj11.addParameter(name='blocksPerfile', value=blocksPerfile, format='int')
206 opObj11.addParameter(name='blocksPerfile', value=blocksPerfile, format='int')
207 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
207 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
208 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
208 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
209 opObj11.addParameter(name='online', value='0', format='int')
209 opObj11.addParameter(name='online', value='0', format='int')
210
210
211 opObj11 = procUnitConfObjC.addOperation(name='Block360')
211 opObj11 = procUnitConfObjC.addOperation(name='Block360')
212 opObj11.addParameter(name='n', value='10', format='int')
212 opObj11.addParameter(name='n', value='10', format='int')
213 opObj11.addParameter(name='mode', value=mode, format='int')
213 opObj11.addParameter(name='mode', value=mode, format='int')
214
214
215 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
215 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
216 opObj11= procUnitConfObjC.addOperation(name='WeatherPlot',optype='other')
216 opObj11= procUnitConfObjC.addOperation(name='WeatherPlot',optype='other')
217 controllerObj.start()
217 controllerObj.start()
General Comments 0
You need to be logged in to leave comments. Login now