##// END OF EJS Templates
valid en jroproc_parameters
avaldez -
r1394:99588b4ace71
parent child
Show More
@@ -1,509 +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 data['weather'] = 10*numpy.log10(dataOut.data_360[0]/(250.0))
398 if hasattr(dataOut, 'dataPP_POWER'):
399 factor = 1
400
401 if hasattr(dataOut, 'nFFTPoints'):
402 factor = dataOut.normFactor
403
404 print("factor",factor)
405 data['weather'] = 10*numpy.log10(dataOut.data_360[0]/(factor))
406 print("weather",data['weather'])
399 data['azi'] = dataOut.data_azi
407 data['azi'] = dataOut.data_azi
400 return data, meta
408 return data, meta
401
409
402 def const_ploteo(self,data_weather,data_azi,step,res):
410 def const_ploteo(self,data_weather,data_azi,step,res):
403 if self.ini==0:
411 if self.ini==0:
404 #------- AZIMUTH
412 #------- AZIMUTH
405 n = (360/res)-len(data_azi)
413 n = (360/res)-len(data_azi)
406 start = data_azi[-1] + res
414 start = data_azi[-1] + res
407 end = data_azi[0] - res
415 end = data_azi[0] - res
408 if start>end:
416 if start>end:
409 end = end + 360
417 end = end + 360
410 azi_vacia = numpy.linspace(start,end,int(n))
418 azi_vacia = numpy.linspace(start,end,int(n))
411 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)
412 data_azi = numpy.hstack((data_azi,azi_vacia))
420 data_azi = numpy.hstack((data_azi,azi_vacia))
413 # RADAR
421 # RADAR
414 val_mean = numpy.mean(data_weather[:,0])
422 val_mean = numpy.mean(data_weather[:,0])
415 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
416 data_weather = numpy.vstack((data_weather,data_weather_cmp))
424 data_weather = numpy.vstack((data_weather,data_weather_cmp))
417 else:
425 else:
418 # azimuth
426 # azimuth
419 flag=0
427 flag=0
420 start_azi = self.res_azi[0]
428 start_azi = self.res_azi[0]
421 start = data_azi[0]
429 start = data_azi[0]
422 end = data_azi[-1]
430 end = data_azi[-1]
423 print("start",start)
431 print("start",start)
424 print("end",end)
432 print("end",end)
425 if start< start_azi:
433 if start< start_azi:
426 start = start +360
434 start = start +360
427 if end <start_azi:
435 if end <start_azi:
428 end = end +360
436 end = end +360
429
437
430 print("start",start)
438 print("start",start)
431 print("end",end)
439 print("end",end)
432 #### AQUI SERA LA MAGIA
440 #### AQUI SERA LA MAGIA
433 pos_ini = int((start-start_azi)/res)
441 pos_ini = int((start-start_azi)/res)
434 len_azi = len(data_azi)
442 len_azi = len(data_azi)
435 if (360-pos_ini)<len_azi:
443 if (360-pos_ini)<len_azi:
436 if pos_ini+1==360:
444 if pos_ini+1==360:
437 pos_ini=0
445 pos_ini=0
438 else:
446 else:
439 flag=1
447 flag=1
440 dif= 360-pos_ini
448 dif= 360-pos_ini
441 comp= len_azi-dif
449 comp= len_azi-dif
442
450
443 print(pos_ini)
451 print(pos_ini)
444 print(len_azi)
452 print(len_azi)
445 print("shape",self.res_azi.shape)
453 print("shape",self.res_azi.shape)
446 if flag==0:
454 if flag==0:
447 # AZIMUTH
455 # AZIMUTH
448 self.res_azi[pos_ini:pos_ini+len_azi] = data_azi
456 self.res_azi[pos_ini:pos_ini+len_azi] = data_azi
449 # RADAR
457 # RADAR
450 self.res_weather[pos_ini:pos_ini+len_azi,:] = data_weather
458 self.res_weather[pos_ini:pos_ini+len_azi,:] = data_weather
451 else:
459 else:
452 # AZIMUTH
460 # AZIMUTH
453 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]
454 self.res_azi[0:comp] = data_azi[dif:]
462 self.res_azi[0:comp] = data_azi[dif:]
455 # RADAR
463 # RADAR
456 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,:]
457 self.res_weather[0:comp,:] = data_weather[dif:,:]
465 self.res_weather[0:comp,:] = data_weather[dif:,:]
458 flag=0
466 flag=0
459 data_azi = self.res_azi
467 data_azi = self.res_azi
460 data_weather = self.res_weather
468 data_weather = self.res_weather
461
469
462 return data_weather,data_azi
470 return data_weather,data_azi
463
471
464 def plot(self):
472 def plot(self):
465 print("--------------------------------------",self.ini,"-----------------------------------")
473 print("--------------------------------------",self.ini,"-----------------------------------")
466 #numpy.set_printoptions(suppress=True)
474 #numpy.set_printoptions(suppress=True)
467 #print(self.data.times)
475 #print(self.data.times)
468 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
476 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
469 data = self.data[-1]
477 data = self.data[-1]
470 # ALTURA altura_tmp_h
478 # ALTURA altura_tmp_h
471 altura_h = (data['weather'].shape[1])/10.0
479 altura_h = (data['weather'].shape[1])/10.0
472 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
473 rangestep = float(0.15)
481 rangestep = float(0.15)
474 r = numpy.arange(0, stoprange, rangestep)
482 r = numpy.arange(0, stoprange, rangestep)
475 self.y = 2*r
483 self.y = 2*r
476 # RADAR
484 # RADAR
477 #data_weather = data['weather']
485 #data_weather = data['weather']
478 # PEDESTAL
486 # PEDESTAL
479 #data_azi = data['azi']
487 #data_azi = data['azi']
480 res = 1
488 res = 1
481 # STEP
489 # STEP
482 step = (360/(res*data['weather'].shape[0]))
490 step = (360/(res*data['weather'].shape[0]))
483 #print("shape wr_data", wr_data.shape)
491 #print("shape wr_data", wr_data.shape)
484 #print("shape wr_azi",wr_azi.shape)
492 #print("shape wr_azi",wr_azi.shape)
485 #print("step",step)
493 #print("step",step)
486 print("Time---->",self.data.times[-1],thisDatetime)
494 print("Time---->",self.data.times[-1],thisDatetime)
487 #print("alturas", len(self.y))
495 #print("alturas", len(self.y))
488 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)
489 #numpy.set_printoptions(suppress=True)
497 #numpy.set_printoptions(suppress=True)
490 #print("resultado",self.res_azi)
498 #print("resultado",self.res_azi)
491 ##########################################################
499 ##########################################################
492 ################# PLOTEO ###################
500 ################# PLOTEO ###################
493 ##########################################################
501 ##########################################################
494
502
495 for i,ax in enumerate(self.axes):
503 for i,ax in enumerate(self.axes):
496 if ax.firsttime:
504 if ax.firsttime:
497 plt.clf()
505 plt.clf()
498 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)
499 else:
507 else:
500 plt.clf()
508 plt.clf()
501 cgax, pm = wrl.vis.plot_ppi(self.res_weather,r=r,az=self.res_azi,fig=self.figures[0], proj='cg', vmin=0, 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)
502 caax = cgax.parasites[0]
510 caax = cgax.parasites[0]
503 paax = cgax.parasites[1]
511 paax = cgax.parasites[1]
504 cbar = plt.gcf().colorbar(pm, pad=0.075)
512 cbar = plt.gcf().colorbar(pm, pad=0.075)
505 caax.set_xlabel('x_range [km]')
513 caax.set_xlabel('x_range [km]')
506 caax.set_ylabel('y_range [km]')
514 caax.set_ylabel('y_range [km]')
507 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')
508
516
509 self.ini= self.ini+1
517 self.ini= self.ini+1
@@ -1,4474 +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
1290 for ind in range(oldspec.shape[1]):
1289 for ind in range(oldspec.shape[1]):
1291
1290
1292 spec = oldspec[:,ind]
1291 spec = oldspec[:,ind]
1293 aux = spec*fwindow
1292 aux = spec*fwindow
1294 max_spec = aux.max()
1293 max_spec = aux.max()
1295 m = aux.tolist().index(max_spec)
1294 m = aux.tolist().index(max_spec)
1296
1295
1297 # Smooth
1296 # Smooth
1298 if (smooth == 0):
1297 if (smooth == 0):
1299 spec2 = spec
1298 spec2 = spec
1300 else:
1299 else:
1301 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1300 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1302
1301
1303 # Moments Estimation
1302 # Moments Estimation
1304 bb = spec2[numpy.arange(m,spec2.size)]
1303 bb = spec2[numpy.arange(m,spec2.size)]
1305 bb = (bb<n0).nonzero()
1304 bb = (bb<n0).nonzero()
1306 bb = bb[0]
1305 bb = bb[0]
1307
1306
1308 ss = spec2[numpy.arange(0,m + 1)]
1307 ss = spec2[numpy.arange(0,m + 1)]
1309 ss = (ss<n0).nonzero()
1308 ss = (ss<n0).nonzero()
1310 ss = ss[0]
1309 ss = ss[0]
1311
1310
1312 if (bb.size == 0):
1311 if (bb.size == 0):
1313 bb0 = spec.size - 1 - m
1312 bb0 = spec.size - 1 - m
1314 else:
1313 else:
1315 bb0 = bb[0] - 1
1314 bb0 = bb[0] - 1
1316 if (bb0 < 0):
1315 if (bb0 < 0):
1317 bb0 = 0
1316 bb0 = 0
1318
1317
1319 if (ss.size == 0):
1318 if (ss.size == 0):
1320 ss1 = 1
1319 ss1 = 1
1321 else:
1320 else:
1322 ss1 = max(ss) + 1
1321 ss1 = max(ss) + 1
1323
1322
1324 if (ss1 > m):
1323 if (ss1 > m):
1325 ss1 = m
1324 ss1 = m
1326
1325
1327 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1326 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1328
1327 #valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1329 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
1330 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
1331 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1330 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1332 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1331 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1333 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)
1334 snr = (spec2.mean()-n0)/n0
1333 snr = (spec2.mean()-n0)/n0
1335 if (snr < 1.e-20) :
1334 if (snr < 1.e-20) :
1336 snr = 1.e-20
1335 snr = 1.e-20
1337
1336
1338 # 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
1339 vec_power[ind] = total_power
1338 vec_power[ind] = total_power
1340 vec_fd[ind] = fd
1339 vec_fd[ind] = fd
1341 vec_w[ind] = w
1340 vec_w[ind] = w
1342 vec_snr[ind] = snr
1341 vec_snr[ind] = snr
1343
1342
1344 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1343 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1345
1344
1346 #------------------ Get SA Parameters --------------------------
1345 #------------------ Get SA Parameters --------------------------
1347
1346
1348 def GetSAParameters(self):
1347 def GetSAParameters(self):
1349 #SA en frecuencia
1348 #SA en frecuencia
1350 pairslist = self.dataOut.groupList
1349 pairslist = self.dataOut.groupList
1351 num_pairs = len(pairslist)
1350 num_pairs = len(pairslist)
1352
1351
1353 vel = self.dataOut.abscissaList
1352 vel = self.dataOut.abscissaList
1354 spectra = self.dataOut.data_pre
1353 spectra = self.dataOut.data_pre
1355 cspectra = self.dataIn.data_cspc
1354 cspectra = self.dataIn.data_cspc
1356 delta_v = vel[1] - vel[0]
1355 delta_v = vel[1] - vel[0]
1357
1356
1358 #Calculating the power spectrum
1357 #Calculating the power spectrum
1359 spc_pow = numpy.sum(spectra, 3)*delta_v
1358 spc_pow = numpy.sum(spectra, 3)*delta_v
1360 #Normalizing Spectra
1359 #Normalizing Spectra
1361 norm_spectra = spectra/spc_pow
1360 norm_spectra = spectra/spc_pow
1362 #Calculating the norm_spectra at peak
1361 #Calculating the norm_spectra at peak
1363 max_spectra = numpy.max(norm_spectra, 3)
1362 max_spectra = numpy.max(norm_spectra, 3)
1364
1363
1365 #Normalizing Cross Spectra
1364 #Normalizing Cross Spectra
1366 norm_cspectra = numpy.zeros(cspectra.shape)
1365 norm_cspectra = numpy.zeros(cspectra.shape)
1367
1366
1368 for i in range(num_chan):
1367 for i in range(num_chan):
1369 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],:])
1370
1369
1371 max_cspectra = numpy.max(norm_cspectra,2)
1370 max_cspectra = numpy.max(norm_cspectra,2)
1372 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1371 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1373
1372
1374 for i in range(num_pairs):
1373 for i in range(num_pairs):
1375 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1374 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1376 #------------------- Get Lags ----------------------------------
1375 #------------------- Get Lags ----------------------------------
1377
1376
1378 class SALags(Operation):
1377 class SALags(Operation):
1379 '''
1378 '''
1380 Function GetMoments()
1379 Function GetMoments()
1381
1380
1382 Input:
1381 Input:
1383 self.dataOut.data_pre
1382 self.dataOut.data_pre
1384 self.dataOut.abscissaList
1383 self.dataOut.abscissaList
1385 self.dataOut.noise
1384 self.dataOut.noise
1386 self.dataOut.normFactor
1385 self.dataOut.normFactor
1387 self.dataOut.data_snr
1386 self.dataOut.data_snr
1388 self.dataOut.groupList
1387 self.dataOut.groupList
1389 self.dataOut.nChannels
1388 self.dataOut.nChannels
1390
1389
1391 Affected:
1390 Affected:
1392 self.dataOut.data_param
1391 self.dataOut.data_param
1393
1392
1394 '''
1393 '''
1395 def run(self, dataOut):
1394 def run(self, dataOut):
1396 data_acf = dataOut.data_pre[0]
1395 data_acf = dataOut.data_pre[0]
1397 data_ccf = dataOut.data_pre[1]
1396 data_ccf = dataOut.data_pre[1]
1398 normFactor_acf = dataOut.normFactor[0]
1397 normFactor_acf = dataOut.normFactor[0]
1399 normFactor_ccf = dataOut.normFactor[1]
1398 normFactor_ccf = dataOut.normFactor[1]
1400 pairs_acf = dataOut.groupList[0]
1399 pairs_acf = dataOut.groupList[0]
1401 pairs_ccf = dataOut.groupList[1]
1400 pairs_ccf = dataOut.groupList[1]
1402
1401
1403 nHeights = dataOut.nHeights
1402 nHeights = dataOut.nHeights
1404 absc = dataOut.abscissaList
1403 absc = dataOut.abscissaList
1405 noise = dataOut.noise
1404 noise = dataOut.noise
1406 SNR = dataOut.data_snr
1405 SNR = dataOut.data_snr
1407 nChannels = dataOut.nChannels
1406 nChannels = dataOut.nChannels
1408 # pairsList = dataOut.groupList
1407 # pairsList = dataOut.groupList
1409 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1408 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1410
1409
1411 for l in range(len(pairs_acf)):
1410 for l in range(len(pairs_acf)):
1412 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1411 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1413
1412
1414 for l in range(len(pairs_ccf)):
1413 for l in range(len(pairs_ccf)):
1415 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1414 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1416
1415
1417 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1416 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1418 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1417 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1419 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1418 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1420 return
1419 return
1421
1420
1422 # def __getPairsAutoCorr(self, pairsList, nChannels):
1421 # def __getPairsAutoCorr(self, pairsList, nChannels):
1423 #
1422 #
1424 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1423 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1425 #
1424 #
1426 # for l in range(len(pairsList)):
1425 # for l in range(len(pairsList)):
1427 # firstChannel = pairsList[l][0]
1426 # firstChannel = pairsList[l][0]
1428 # secondChannel = pairsList[l][1]
1427 # secondChannel = pairsList[l][1]
1429 #
1428 #
1430 # #Obteniendo pares de Autocorrelacion
1429 # #Obteniendo pares de Autocorrelacion
1431 # if firstChannel == secondChannel:
1430 # if firstChannel == secondChannel:
1432 # pairsAutoCorr[firstChannel] = int(l)
1431 # pairsAutoCorr[firstChannel] = int(l)
1433 #
1432 #
1434 # pairsAutoCorr = pairsAutoCorr.astype(int)
1433 # pairsAutoCorr = pairsAutoCorr.astype(int)
1435 #
1434 #
1436 # pairsCrossCorr = range(len(pairsList))
1435 # pairsCrossCorr = range(len(pairsList))
1437 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1436 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1438 #
1437 #
1439 # return pairsAutoCorr, pairsCrossCorr
1438 # return pairsAutoCorr, pairsCrossCorr
1440
1439
1441 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1440 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1442
1441
1443 lag0 = data_acf.shape[1]/2
1442 lag0 = data_acf.shape[1]/2
1444 #Funcion de Autocorrelacion
1443 #Funcion de Autocorrelacion
1445 mean_acf = stats.nanmean(data_acf, axis = 0)
1444 mean_acf = stats.nanmean(data_acf, axis = 0)
1446
1445
1447 #Obtencion Indice de TauCross
1446 #Obtencion Indice de TauCross
1448 ind_ccf = data_ccf.argmax(axis = 1)
1447 ind_ccf = data_ccf.argmax(axis = 1)
1449 #Obtencion Indice de TauAuto
1448 #Obtencion Indice de TauAuto
1450 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1449 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1451 ccf_lag0 = data_ccf[:,lag0,:]
1450 ccf_lag0 = data_ccf[:,lag0,:]
1452
1451
1453 for i in range(ccf_lag0.shape[0]):
1452 for i in range(ccf_lag0.shape[0]):
1454 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)
1455
1454
1456 #Obtencion de TauCross y TauAuto
1455 #Obtencion de TauCross y TauAuto
1457 tau_ccf = lagRange[ind_ccf]
1456 tau_ccf = lagRange[ind_ccf]
1458 tau_acf = lagRange[ind_acf]
1457 tau_acf = lagRange[ind_acf]
1459
1458
1460 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1459 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1461
1460
1462 tau_ccf[Nan1,Nan2] = numpy.nan
1461 tau_ccf[Nan1,Nan2] = numpy.nan
1463 tau_acf[Nan1,Nan2] = numpy.nan
1462 tau_acf[Nan1,Nan2] = numpy.nan
1464 tau = numpy.vstack((tau_ccf,tau_acf))
1463 tau = numpy.vstack((tau_ccf,tau_acf))
1465
1464
1466 return tau
1465 return tau
1467
1466
1468 def __calculateLag1Phase(self, data, lagTRange):
1467 def __calculateLag1Phase(self, data, lagTRange):
1469 data1 = stats.nanmean(data, axis = 0)
1468 data1 = stats.nanmean(data, axis = 0)
1470 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1469 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1471
1470
1472 phase = numpy.angle(data1[lag1,:])
1471 phase = numpy.angle(data1[lag1,:])
1473
1472
1474 return phase
1473 return phase
1475
1474
1476 class SpectralFitting(Operation):
1475 class SpectralFitting(Operation):
1477 '''
1476 '''
1478 Function GetMoments()
1477 Function GetMoments()
1479
1478
1480 Input:
1479 Input:
1481 Output:
1480 Output:
1482 Variables modified:
1481 Variables modified:
1483 '''
1482 '''
1484
1483
1485 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):
1486
1485
1487
1486
1488 if path != None:
1487 if path != None:
1489 sys.path.append(path)
1488 sys.path.append(path)
1490 self.dataOut.library = importlib.import_module(file)
1489 self.dataOut.library = importlib.import_module(file)
1491
1490
1492 #To be inserted as a parameter
1491 #To be inserted as a parameter
1493 groupArray = numpy.array(groupList)
1492 groupArray = numpy.array(groupList)
1494 # groupArray = numpy.array([[0,1],[2,3]])
1493 # groupArray = numpy.array([[0,1],[2,3]])
1495 self.dataOut.groupList = groupArray
1494 self.dataOut.groupList = groupArray
1496
1495
1497 nGroups = groupArray.shape[0]
1496 nGroups = groupArray.shape[0]
1498 nChannels = self.dataIn.nChannels
1497 nChannels = self.dataIn.nChannels
1499 nHeights=self.dataIn.heightList.size
1498 nHeights=self.dataIn.heightList.size
1500
1499
1501 #Parameters Array
1500 #Parameters Array
1502 self.dataOut.data_param = None
1501 self.dataOut.data_param = None
1503
1502
1504 #Set constants
1503 #Set constants
1505 constants = self.dataOut.library.setConstants(self.dataIn)
1504 constants = self.dataOut.library.setConstants(self.dataIn)
1506 self.dataOut.constants = constants
1505 self.dataOut.constants = constants
1507 M = self.dataIn.normFactor
1506 M = self.dataIn.normFactor
1508 N = self.dataIn.nFFTPoints
1507 N = self.dataIn.nFFTPoints
1509 ippSeconds = self.dataIn.ippSeconds
1508 ippSeconds = self.dataIn.ippSeconds
1510 K = self.dataIn.nIncohInt
1509 K = self.dataIn.nIncohInt
1511 pairsArray = numpy.array(self.dataIn.pairsList)
1510 pairsArray = numpy.array(self.dataIn.pairsList)
1512
1511
1513 #List of possible combinations
1512 #List of possible combinations
1514 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1513 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1515 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1514 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1516
1515
1517 if getSNR:
1516 if getSNR:
1518 listChannels = groupArray.reshape((groupArray.size))
1517 listChannels = groupArray.reshape((groupArray.size))
1519 listChannels.sort()
1518 listChannels.sort()
1520 noise = self.dataIn.getNoise()
1519 noise = self.dataIn.getNoise()
1521 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])
1522
1521
1523 for i in range(nGroups):
1522 for i in range(nGroups):
1524 coord = groupArray[i,:]
1523 coord = groupArray[i,:]
1525
1524
1526 #Input data array
1525 #Input data array
1527 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1526 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1528 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]))
1529
1528
1530 #Cross Spectra data array for Covariance Matrixes
1529 #Cross Spectra data array for Covariance Matrixes
1531 ind = 0
1530 ind = 0
1532 for pairs in listComb:
1531 for pairs in listComb:
1533 pairsSel = numpy.array([coord[x],coord[y]])
1532 pairsSel = numpy.array([coord[x],coord[y]])
1534 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])
1535 ind += 1
1534 ind += 1
1536 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1535 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1537 dataCross = dataCross**2/K
1536 dataCross = dataCross**2/K
1538
1537
1539 for h in range(nHeights):
1538 for h in range(nHeights):
1540
1539
1541 #Input
1540 #Input
1542 d = data[:,h]
1541 d = data[:,h]
1543
1542
1544 #Covariance Matrix
1543 #Covariance Matrix
1545 D = numpy.diag(d**2/K)
1544 D = numpy.diag(d**2/K)
1546 ind = 0
1545 ind = 0
1547 for pairs in listComb:
1546 for pairs in listComb:
1548 #Coordinates in Covariance Matrix
1547 #Coordinates in Covariance Matrix
1549 x = pairs[0]
1548 x = pairs[0]
1550 y = pairs[1]
1549 y = pairs[1]
1551 #Channel Index
1550 #Channel Index
1552 S12 = dataCross[ind,:,h]
1551 S12 = dataCross[ind,:,h]
1553 D12 = numpy.diag(S12)
1552 D12 = numpy.diag(S12)
1554 #Completing Covariance Matrix with Cross Spectras
1553 #Completing Covariance Matrix with Cross Spectras
1555 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
1556 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
1557 ind += 1
1556 ind += 1
1558 Dinv=numpy.linalg.inv(D)
1557 Dinv=numpy.linalg.inv(D)
1559 L=numpy.linalg.cholesky(Dinv)
1558 L=numpy.linalg.cholesky(Dinv)
1560 LT=L.T
1559 LT=L.T
1561
1560
1562 dp = numpy.dot(LT,d)
1561 dp = numpy.dot(LT,d)
1563
1562
1564 #Initial values
1563 #Initial values
1565 data_spc = self.dataIn.data_spc[coord,:,h]
1564 data_spc = self.dataIn.data_spc[coord,:,h]
1566
1565
1567 if (h>0)and(error1[3]<5):
1566 if (h>0)and(error1[3]<5):
1568 p0 = self.dataOut.data_param[i,:,h-1]
1567 p0 = self.dataOut.data_param[i,:,h-1]
1569 else:
1568 else:
1570 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1569 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1571
1570
1572 try:
1571 try:
1573 #Least Squares
1572 #Least Squares
1574 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)
1575 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1574 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1576 #Chi square error
1575 #Chi square error
1577 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1576 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1578 #Error with Jacobian
1577 #Error with Jacobian
1579 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1578 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1580 except:
1579 except:
1581 minp = p0*numpy.nan
1580 minp = p0*numpy.nan
1582 error0 = numpy.nan
1581 error0 = numpy.nan
1583 error1 = p0*numpy.nan
1582 error1 = p0*numpy.nan
1584
1583
1585 #Save
1584 #Save
1586 if self.dataOut.data_param is None:
1585 if self.dataOut.data_param is None:
1587 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
1588 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
1589
1588
1590 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1589 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1591 self.dataOut.data_param[i,:,h] = minp
1590 self.dataOut.data_param[i,:,h] = minp
1592 return
1591 return
1593
1592
1594 def __residFunction(self, p, dp, LT, constants):
1593 def __residFunction(self, p, dp, LT, constants):
1595
1594
1596 fm = self.dataOut.library.modelFunction(p, constants)
1595 fm = self.dataOut.library.modelFunction(p, constants)
1597 fmp=numpy.dot(LT,fm)
1596 fmp=numpy.dot(LT,fm)
1598
1597
1599 return dp-fmp
1598 return dp-fmp
1600
1599
1601 def __getSNR(self, z, noise):
1600 def __getSNR(self, z, noise):
1602
1601
1603 avg = numpy.average(z, axis=1)
1602 avg = numpy.average(z, axis=1)
1604 SNR = (avg.T-noise)/noise
1603 SNR = (avg.T-noise)/noise
1605 SNR = SNR.T
1604 SNR = SNR.T
1606 return SNR
1605 return SNR
1607
1606
1608 def __chisq(p,chindex,hindex):
1607 def __chisq(p,chindex,hindex):
1609 #similar to Resid but calculates CHI**2
1608 #similar to Resid but calculates CHI**2
1610 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1609 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1611 dp=numpy.dot(LT,d)
1610 dp=numpy.dot(LT,d)
1612 fmp=numpy.dot(LT,fm)
1611 fmp=numpy.dot(LT,fm)
1613 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1612 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1614 return chisq
1613 return chisq
1615
1614
1616 class WindProfiler(Operation):
1615 class WindProfiler(Operation):
1617
1616
1618 __isConfig = False
1617 __isConfig = False
1619
1618
1620 __initime = None
1619 __initime = None
1621 __lastdatatime = None
1620 __lastdatatime = None
1622 __integrationtime = None
1621 __integrationtime = None
1623
1622
1624 __buffer = None
1623 __buffer = None
1625
1624
1626 __dataReady = False
1625 __dataReady = False
1627
1626
1628 __firstdata = None
1627 __firstdata = None
1629
1628
1630 n = None
1629 n = None
1631
1630
1632 def __init__(self):
1631 def __init__(self):
1633 Operation.__init__(self)
1632 Operation.__init__(self)
1634
1633
1635 def __calculateCosDir(self, elev, azim):
1634 def __calculateCosDir(self, elev, azim):
1636 zen = (90 - elev)*numpy.pi/180
1635 zen = (90 - elev)*numpy.pi/180
1637 azim = azim*numpy.pi/180
1636 azim = azim*numpy.pi/180
1638 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)))
1639 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1638 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1640
1639
1641 signX = numpy.sign(numpy.cos(azim))
1640 signX = numpy.sign(numpy.cos(azim))
1642 signY = numpy.sign(numpy.sin(azim))
1641 signY = numpy.sign(numpy.sin(azim))
1643
1642
1644 cosDirX = numpy.copysign(cosDirX, signX)
1643 cosDirX = numpy.copysign(cosDirX, signX)
1645 cosDirY = numpy.copysign(cosDirY, signY)
1644 cosDirY = numpy.copysign(cosDirY, signY)
1646 return cosDirX, cosDirY
1645 return cosDirX, cosDirY
1647
1646
1648 def __calculateAngles(self, theta_x, theta_y, azimuth):
1647 def __calculateAngles(self, theta_x, theta_y, azimuth):
1649
1648
1650 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1649 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1651 zenith_arr = numpy.arccos(dir_cosw)
1650 zenith_arr = numpy.arccos(dir_cosw)
1652 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
1653
1652
1654 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1653 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1655 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1654 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1656
1655
1657 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1656 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1658
1657
1659 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1658 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1660
1659
1661 #
1660 #
1662 if horOnly:
1661 if horOnly:
1663 A = numpy.c_[dir_cosu,dir_cosv]
1662 A = numpy.c_[dir_cosu,dir_cosv]
1664 else:
1663 else:
1665 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1664 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1666 A = numpy.asmatrix(A)
1665 A = numpy.asmatrix(A)
1667 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1666 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1668
1667
1669 return A1
1668 return A1
1670
1669
1671 def __correctValues(self, heiRang, phi, velRadial, SNR):
1670 def __correctValues(self, heiRang, phi, velRadial, SNR):
1672 listPhi = phi.tolist()
1671 listPhi = phi.tolist()
1673 maxid = listPhi.index(max(listPhi))
1672 maxid = listPhi.index(max(listPhi))
1674 minid = listPhi.index(min(listPhi))
1673 minid = listPhi.index(min(listPhi))
1675
1674
1676 rango = list(range(len(phi)))
1675 rango = list(range(len(phi)))
1677 # rango = numpy.delete(rango,maxid)
1676 # rango = numpy.delete(rango,maxid)
1678
1677
1679 heiRang1 = heiRang*math.cos(phi[maxid])
1678 heiRang1 = heiRang*math.cos(phi[maxid])
1680 heiRangAux = heiRang*math.cos(phi[minid])
1679 heiRangAux = heiRang*math.cos(phi[minid])
1681 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1680 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1682 heiRang1 = numpy.delete(heiRang1,indOut)
1681 heiRang1 = numpy.delete(heiRang1,indOut)
1683
1682
1684 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1683 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1685 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1684 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1686
1685
1687 for i in rango:
1686 for i in rango:
1688 x = heiRang*math.cos(phi[i])
1687 x = heiRang*math.cos(phi[i])
1689 y1 = velRadial[i,:]
1688 y1 = velRadial[i,:]
1690 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1689 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1691
1690
1692 x1 = heiRang1
1691 x1 = heiRang1
1693 y11 = f1(x1)
1692 y11 = f1(x1)
1694
1693
1695 y2 = SNR[i,:]
1694 y2 = SNR[i,:]
1696 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1695 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1697 y21 = f2(x1)
1696 y21 = f2(x1)
1698
1697
1699 velRadial1[i,:] = y11
1698 velRadial1[i,:] = y11
1700 SNR1[i,:] = y21
1699 SNR1[i,:] = y21
1701
1700
1702 return heiRang1, velRadial1, SNR1
1701 return heiRang1, velRadial1, SNR1
1703
1702
1704 def __calculateVelUVW(self, A, velRadial):
1703 def __calculateVelUVW(self, A, velRadial):
1705
1704
1706 #Operacion Matricial
1705 #Operacion Matricial
1707 # velUVW = numpy.zeros((velRadial.shape[1],3))
1706 # velUVW = numpy.zeros((velRadial.shape[1],3))
1708 # for ind in range(velRadial.shape[1]):
1707 # for ind in range(velRadial.shape[1]):
1709 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1708 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1710 # velUVW = velUVW.transpose()
1709 # velUVW = velUVW.transpose()
1711 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1710 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1712 velUVW[:,:] = numpy.dot(A,velRadial)
1711 velUVW[:,:] = numpy.dot(A,velRadial)
1713
1712
1714
1713
1715 return velUVW
1714 return velUVW
1716
1715
1717 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1716 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1718
1717
1719 def techniqueDBS(self, kwargs):
1718 def techniqueDBS(self, kwargs):
1720 """
1719 """
1721 Function that implements Doppler Beam Swinging (DBS) technique.
1720 Function that implements Doppler Beam Swinging (DBS) technique.
1722
1721
1723 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,
1724 Direction correction (if necessary), Ranges and SNR
1723 Direction correction (if necessary), Ranges and SNR
1725
1724
1726 Output: Winds estimation (Zonal, Meridional and Vertical)
1725 Output: Winds estimation (Zonal, Meridional and Vertical)
1727
1726
1728 Parameters affected: Winds, height range, SNR
1727 Parameters affected: Winds, height range, SNR
1729 """
1728 """
1730 velRadial0 = kwargs['velRadial']
1729 velRadial0 = kwargs['velRadial']
1731 heiRang = kwargs['heightList']
1730 heiRang = kwargs['heightList']
1732 SNR0 = kwargs['SNR']
1731 SNR0 = kwargs['SNR']
1733
1732
1734 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1733 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1735 theta_x = numpy.array(kwargs['dirCosx'])
1734 theta_x = numpy.array(kwargs['dirCosx'])
1736 theta_y = numpy.array(kwargs['dirCosy'])
1735 theta_y = numpy.array(kwargs['dirCosy'])
1737 else:
1736 else:
1738 elev = numpy.array(kwargs['elevation'])
1737 elev = numpy.array(kwargs['elevation'])
1739 azim = numpy.array(kwargs['azimuth'])
1738 azim = numpy.array(kwargs['azimuth'])
1740 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1739 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1741 azimuth = kwargs['correctAzimuth']
1740 azimuth = kwargs['correctAzimuth']
1742 if 'horizontalOnly' in kwargs:
1741 if 'horizontalOnly' in kwargs:
1743 horizontalOnly = kwargs['horizontalOnly']
1742 horizontalOnly = kwargs['horizontalOnly']
1744 else: horizontalOnly = False
1743 else: horizontalOnly = False
1745 if 'correctFactor' in kwargs:
1744 if 'correctFactor' in kwargs:
1746 correctFactor = kwargs['correctFactor']
1745 correctFactor = kwargs['correctFactor']
1747 else: correctFactor = 1
1746 else: correctFactor = 1
1748 if 'channelList' in kwargs:
1747 if 'channelList' in kwargs:
1749 channelList = kwargs['channelList']
1748 channelList = kwargs['channelList']
1750 if len(channelList) == 2:
1749 if len(channelList) == 2:
1751 horizontalOnly = True
1750 horizontalOnly = True
1752 arrayChannel = numpy.array(channelList)
1751 arrayChannel = numpy.array(channelList)
1753 param = param[arrayChannel,:,:]
1752 param = param[arrayChannel,:,:]
1754 theta_x = theta_x[arrayChannel]
1753 theta_x = theta_x[arrayChannel]
1755 theta_y = theta_y[arrayChannel]
1754 theta_y = theta_y[arrayChannel]
1756
1755
1757 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)
1758 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1757 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1759 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1758 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1760
1759
1761 #Calculo de Componentes de la velocidad con DBS
1760 #Calculo de Componentes de la velocidad con DBS
1762 winds = self.__calculateVelUVW(A,velRadial1)
1761 winds = self.__calculateVelUVW(A,velRadial1)
1763
1762
1764 return winds, heiRang1, SNR1
1763 return winds, heiRang1, SNR1
1765
1764
1766 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1765 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1767
1766
1768 nPairs = len(pairs_ccf)
1767 nPairs = len(pairs_ccf)
1769 posx = numpy.asarray(posx)
1768 posx = numpy.asarray(posx)
1770 posy = numpy.asarray(posy)
1769 posy = numpy.asarray(posy)
1771
1770
1772 #Rotacion Inversa para alinear con el azimuth
1771 #Rotacion Inversa para alinear con el azimuth
1773 if azimuth!= None:
1772 if azimuth!= None:
1774 azimuth = azimuth*math.pi/180
1773 azimuth = azimuth*math.pi/180
1775 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1774 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1776 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1775 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1777 else:
1776 else:
1778 posx1 = posx
1777 posx1 = posx
1779 posy1 = posy
1778 posy1 = posy
1780
1779
1781 #Calculo de Distancias
1780 #Calculo de Distancias
1782 distx = numpy.zeros(nPairs)
1781 distx = numpy.zeros(nPairs)
1783 disty = numpy.zeros(nPairs)
1782 disty = numpy.zeros(nPairs)
1784 dist = numpy.zeros(nPairs)
1783 dist = numpy.zeros(nPairs)
1785 ang = numpy.zeros(nPairs)
1784 ang = numpy.zeros(nPairs)
1786
1785
1787 for i in range(nPairs):
1786 for i in range(nPairs):
1788 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]]
1789 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]]
1790 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1789 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1791 ang[i] = numpy.arctan2(disty[i],distx[i])
1790 ang[i] = numpy.arctan2(disty[i],distx[i])
1792
1791
1793 return distx, disty, dist, ang
1792 return distx, disty, dist, ang
1794 #Calculo de Matrices
1793 #Calculo de Matrices
1795 # nPairs = len(pairs)
1794 # nPairs = len(pairs)
1796 # ang1 = numpy.zeros((nPairs, 2, 1))
1795 # ang1 = numpy.zeros((nPairs, 2, 1))
1797 # dist1 = numpy.zeros((nPairs, 2, 1))
1796 # dist1 = numpy.zeros((nPairs, 2, 1))
1798 #
1797 #
1799 # for j in range(nPairs):
1798 # for j in range(nPairs):
1800 # dist1[j,0,0] = dist[pairs[j][0]]
1799 # dist1[j,0,0] = dist[pairs[j][0]]
1801 # dist1[j,1,0] = dist[pairs[j][1]]
1800 # dist1[j,1,0] = dist[pairs[j][1]]
1802 # ang1[j,0,0] = ang[pairs[j][0]]
1801 # ang1[j,0,0] = ang[pairs[j][0]]
1803 # ang1[j,1,0] = ang[pairs[j][1]]
1802 # ang1[j,1,0] = ang[pairs[j][1]]
1804 #
1803 #
1805 # return distx,disty, dist1,ang1
1804 # return distx,disty, dist1,ang1
1806
1805
1807
1806
1808 def __calculateVelVer(self, phase, lagTRange, _lambda):
1807 def __calculateVelVer(self, phase, lagTRange, _lambda):
1809
1808
1810 Ts = lagTRange[1] - lagTRange[0]
1809 Ts = lagTRange[1] - lagTRange[0]
1811 velW = -_lambda*phase/(4*math.pi*Ts)
1810 velW = -_lambda*phase/(4*math.pi*Ts)
1812
1811
1813 return velW
1812 return velW
1814
1813
1815 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1814 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1816 nPairs = tau1.shape[0]
1815 nPairs = tau1.shape[0]
1817 nHeights = tau1.shape[1]
1816 nHeights = tau1.shape[1]
1818 vel = numpy.zeros((nPairs,3,nHeights))
1817 vel = numpy.zeros((nPairs,3,nHeights))
1819 dist1 = numpy.reshape(dist, (dist.size,1))
1818 dist1 = numpy.reshape(dist, (dist.size,1))
1820
1819
1821 angCos = numpy.cos(ang)
1820 angCos = numpy.cos(ang)
1822 angSin = numpy.sin(ang)
1821 angSin = numpy.sin(ang)
1823
1822
1824 vel0 = dist1*tau1/(2*tau2**2)
1823 vel0 = dist1*tau1/(2*tau2**2)
1825 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1824 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1826 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1825 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1827
1826
1828 ind = numpy.where(numpy.isinf(vel))
1827 ind = numpy.where(numpy.isinf(vel))
1829 vel[ind] = numpy.nan
1828 vel[ind] = numpy.nan
1830
1829
1831 return vel
1830 return vel
1832
1831
1833 # def __getPairsAutoCorr(self, pairsList, nChannels):
1832 # def __getPairsAutoCorr(self, pairsList, nChannels):
1834 #
1833 #
1835 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1834 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1836 #
1835 #
1837 # for l in range(len(pairsList)):
1836 # for l in range(len(pairsList)):
1838 # firstChannel = pairsList[l][0]
1837 # firstChannel = pairsList[l][0]
1839 # secondChannel = pairsList[l][1]
1838 # secondChannel = pairsList[l][1]
1840 #
1839 #
1841 # #Obteniendo pares de Autocorrelacion
1840 # #Obteniendo pares de Autocorrelacion
1842 # if firstChannel == secondChannel:
1841 # if firstChannel == secondChannel:
1843 # pairsAutoCorr[firstChannel] = int(l)
1842 # pairsAutoCorr[firstChannel] = int(l)
1844 #
1843 #
1845 # pairsAutoCorr = pairsAutoCorr.astype(int)
1844 # pairsAutoCorr = pairsAutoCorr.astype(int)
1846 #
1845 #
1847 # pairsCrossCorr = range(len(pairsList))
1846 # pairsCrossCorr = range(len(pairsList))
1848 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1847 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1849 #
1848 #
1850 # return pairsAutoCorr, pairsCrossCorr
1849 # return pairsAutoCorr, pairsCrossCorr
1851
1850
1852 # 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):
1853 def techniqueSA(self, kwargs):
1852 def techniqueSA(self, kwargs):
1854
1853
1855 """
1854 """
1856 Function that implements Spaced Antenna (SA) technique.
1855 Function that implements Spaced Antenna (SA) technique.
1857
1856
1858 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,
1859 Direction correction (if necessary), Ranges and SNR
1858 Direction correction (if necessary), Ranges and SNR
1860
1859
1861 Output: Winds estimation (Zonal, Meridional and Vertical)
1860 Output: Winds estimation (Zonal, Meridional and Vertical)
1862
1861
1863 Parameters affected: Winds
1862 Parameters affected: Winds
1864 """
1863 """
1865 position_x = kwargs['positionX']
1864 position_x = kwargs['positionX']
1866 position_y = kwargs['positionY']
1865 position_y = kwargs['positionY']
1867 azimuth = kwargs['azimuth']
1866 azimuth = kwargs['azimuth']
1868
1867
1869 if 'correctFactor' in kwargs:
1868 if 'correctFactor' in kwargs:
1870 correctFactor = kwargs['correctFactor']
1869 correctFactor = kwargs['correctFactor']
1871 else:
1870 else:
1872 correctFactor = 1
1871 correctFactor = 1
1873
1872
1874 groupList = kwargs['groupList']
1873 groupList = kwargs['groupList']
1875 pairs_ccf = groupList[1]
1874 pairs_ccf = groupList[1]
1876 tau = kwargs['tau']
1875 tau = kwargs['tau']
1877 _lambda = kwargs['_lambda']
1876 _lambda = kwargs['_lambda']
1878
1877
1879 #Cross Correlation pairs obtained
1878 #Cross Correlation pairs obtained
1880 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1879 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1881 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1880 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1882 # pairsSelArray = numpy.array(pairsSelected)
1881 # pairsSelArray = numpy.array(pairsSelected)
1883 # pairs = []
1882 # pairs = []
1884 #
1883 #
1885 # #Wind estimation pairs obtained
1884 # #Wind estimation pairs obtained
1886 # for i in range(pairsSelArray.shape[0]/2):
1885 # for i in range(pairsSelArray.shape[0]/2):
1887 # 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]
1888 # 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]
1889 # pairs.append((ind1,ind2))
1888 # pairs.append((ind1,ind2))
1890
1889
1891 indtau = tau.shape[0]/2
1890 indtau = tau.shape[0]/2
1892 tau1 = tau[:indtau,:]
1891 tau1 = tau[:indtau,:]
1893 tau2 = tau[indtau:-1,:]
1892 tau2 = tau[indtau:-1,:]
1894 # tau1 = tau1[pairs,:]
1893 # tau1 = tau1[pairs,:]
1895 # tau2 = tau2[pairs,:]
1894 # tau2 = tau2[pairs,:]
1896 phase1 = tau[-1,:]
1895 phase1 = tau[-1,:]
1897
1896
1898 #---------------------------------------------------------------------
1897 #---------------------------------------------------------------------
1899 #Metodo Directo
1898 #Metodo Directo
1900 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)
1901 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1900 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1902 winds = stats.nanmean(winds, axis=0)
1901 winds = stats.nanmean(winds, axis=0)
1903 #---------------------------------------------------------------------
1902 #---------------------------------------------------------------------
1904 #Metodo General
1903 #Metodo General
1905 # 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)
1906 # #Calculo Coeficientes de Funcion de Correlacion
1905 # #Calculo Coeficientes de Funcion de Correlacion
1907 # 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)
1908 # #Calculo de Velocidades
1907 # #Calculo de Velocidades
1909 # winds = self.calculateVelUV(F,G,A,B,H)
1908 # winds = self.calculateVelUV(F,G,A,B,H)
1910
1909
1911 #---------------------------------------------------------------------
1910 #---------------------------------------------------------------------
1912 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1911 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1913 winds = correctFactor*winds
1912 winds = correctFactor*winds
1914 return winds
1913 return winds
1915
1914
1916 def __checkTime(self, currentTime, paramInterval, outputInterval):
1915 def __checkTime(self, currentTime, paramInterval, outputInterval):
1917
1916
1918 dataTime = currentTime + paramInterval
1917 dataTime = currentTime + paramInterval
1919 deltaTime = dataTime - self.__initime
1918 deltaTime = dataTime - self.__initime
1920
1919
1921 if deltaTime >= outputInterval or deltaTime < 0:
1920 if deltaTime >= outputInterval or deltaTime < 0:
1922 self.__dataReady = True
1921 self.__dataReady = True
1923 return
1922 return
1924
1923
1925 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1924 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1926 '''
1925 '''
1927 Function that implements winds estimation technique with detected meteors.
1926 Function that implements winds estimation technique with detected meteors.
1928
1927
1929 Input: Detected meteors, Minimum meteor quantity to wind estimation
1928 Input: Detected meteors, Minimum meteor quantity to wind estimation
1930
1929
1931 Output: Winds estimation (Zonal and Meridional)
1930 Output: Winds estimation (Zonal and Meridional)
1932
1931
1933 Parameters affected: Winds
1932 Parameters affected: Winds
1934 '''
1933 '''
1935 #Settings
1934 #Settings
1936 nInt = (heightMax - heightMin)/2
1935 nInt = (heightMax - heightMin)/2
1937 nInt = int(nInt)
1936 nInt = int(nInt)
1938 winds = numpy.zeros((2,nInt))*numpy.nan
1937 winds = numpy.zeros((2,nInt))*numpy.nan
1939
1938
1940 #Filter errors
1939 #Filter errors
1941 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1940 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1942 finalMeteor = arrayMeteor[error,:]
1941 finalMeteor = arrayMeteor[error,:]
1943
1942
1944 #Meteor Histogram
1943 #Meteor Histogram
1945 finalHeights = finalMeteor[:,2]
1944 finalHeights = finalMeteor[:,2]
1946 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1945 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1947 nMeteorsPerI = hist[0]
1946 nMeteorsPerI = hist[0]
1948 heightPerI = hist[1]
1947 heightPerI = hist[1]
1949
1948
1950 #Sort of meteors
1949 #Sort of meteors
1951 indSort = finalHeights.argsort()
1950 indSort = finalHeights.argsort()
1952 finalMeteor2 = finalMeteor[indSort,:]
1951 finalMeteor2 = finalMeteor[indSort,:]
1953
1952
1954 # Calculating winds
1953 # Calculating winds
1955 ind1 = 0
1954 ind1 = 0
1956 ind2 = 0
1955 ind2 = 0
1957
1956
1958 for i in range(nInt):
1957 for i in range(nInt):
1959 nMet = nMeteorsPerI[i]
1958 nMet = nMeteorsPerI[i]
1960 ind1 = ind2
1959 ind1 = ind2
1961 ind2 = ind1 + nMet
1960 ind2 = ind1 + nMet
1962
1961
1963 meteorAux = finalMeteor2[ind1:ind2,:]
1962 meteorAux = finalMeteor2[ind1:ind2,:]
1964
1963
1965 if meteorAux.shape[0] >= meteorThresh:
1964 if meteorAux.shape[0] >= meteorThresh:
1966 vel = meteorAux[:, 6]
1965 vel = meteorAux[:, 6]
1967 zen = meteorAux[:, 4]*numpy.pi/180
1966 zen = meteorAux[:, 4]*numpy.pi/180
1968 azim = meteorAux[:, 3]*numpy.pi/180
1967 azim = meteorAux[:, 3]*numpy.pi/180
1969
1968
1970 n = numpy.cos(zen)
1969 n = numpy.cos(zen)
1971 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1970 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1972 # l = m*numpy.tan(azim)
1971 # l = m*numpy.tan(azim)
1973 l = numpy.sin(zen)*numpy.sin(azim)
1972 l = numpy.sin(zen)*numpy.sin(azim)
1974 m = numpy.sin(zen)*numpy.cos(azim)
1973 m = numpy.sin(zen)*numpy.cos(azim)
1975
1974
1976 A = numpy.vstack((l, m)).transpose()
1975 A = numpy.vstack((l, m)).transpose()
1977 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())
1978 windsAux = numpy.dot(A1, vel)
1977 windsAux = numpy.dot(A1, vel)
1979
1978
1980 winds[0,i] = windsAux[0]
1979 winds[0,i] = windsAux[0]
1981 winds[1,i] = windsAux[1]
1980 winds[1,i] = windsAux[1]
1982
1981
1983 return winds, heightPerI[:-1]
1982 return winds, heightPerI[:-1]
1984
1983
1985 def techniqueNSM_SA(self, **kwargs):
1984 def techniqueNSM_SA(self, **kwargs):
1986 metArray = kwargs['metArray']
1985 metArray = kwargs['metArray']
1987 heightList = kwargs['heightList']
1986 heightList = kwargs['heightList']
1988 timeList = kwargs['timeList']
1987 timeList = kwargs['timeList']
1989
1988
1990 rx_location = kwargs['rx_location']
1989 rx_location = kwargs['rx_location']
1991 groupList = kwargs['groupList']
1990 groupList = kwargs['groupList']
1992 azimuth = kwargs['azimuth']
1991 azimuth = kwargs['azimuth']
1993 dfactor = kwargs['dfactor']
1992 dfactor = kwargs['dfactor']
1994 k = kwargs['k']
1993 k = kwargs['k']
1995
1994
1996 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1995 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1997 d = dist*dfactor
1996 d = dist*dfactor
1998 #Phase calculation
1997 #Phase calculation
1999 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1998 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2000
1999
2001 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
2002
2001
2003 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2002 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2004 azimuth1 = azimuth1*numpy.pi/180
2003 azimuth1 = azimuth1*numpy.pi/180
2005
2004
2006 for i in range(heightList.size):
2005 for i in range(heightList.size):
2007 h = heightList[i]
2006 h = heightList[i]
2008 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]
2009 metHeight = metArray1[indH,:]
2008 metHeight = metArray1[indH,:]
2010 if metHeight.shape[0] >= 2:
2009 if metHeight.shape[0] >= 2:
2011 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2010 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2012 iazim = metHeight[:,1].astype(int)
2011 iazim = metHeight[:,1].astype(int)
2013 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2012 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2014 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2013 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2015 A = numpy.asmatrix(A)
2014 A = numpy.asmatrix(A)
2016 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2015 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2017 velHor = numpy.dot(A1,velAux)
2016 velHor = numpy.dot(A1,velAux)
2018
2017
2019 velEst[i,:] = numpy.squeeze(velHor)
2018 velEst[i,:] = numpy.squeeze(velHor)
2020 return velEst
2019 return velEst
2021
2020
2022 def __getPhaseSlope(self, metArray, heightList, timeList):
2021 def __getPhaseSlope(self, metArray, heightList, timeList):
2023 meteorList = []
2022 meteorList = []
2024 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2023 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2025 #Putting back together the meteor matrix
2024 #Putting back together the meteor matrix
2026 utctime = metArray[:,0]
2025 utctime = metArray[:,0]
2027 uniqueTime = numpy.unique(utctime)
2026 uniqueTime = numpy.unique(utctime)
2028
2027
2029 phaseDerThresh = 0.5
2028 phaseDerThresh = 0.5
2030 ippSeconds = timeList[1] - timeList[0]
2029 ippSeconds = timeList[1] - timeList[0]
2031 sec = numpy.where(timeList>1)[0][0]
2030 sec = numpy.where(timeList>1)[0][0]
2032 nPairs = metArray.shape[1] - 6
2031 nPairs = metArray.shape[1] - 6
2033 nHeights = len(heightList)
2032 nHeights = len(heightList)
2034
2033
2035 for t in uniqueTime:
2034 for t in uniqueTime:
2036 metArray1 = metArray[utctime==t,:]
2035 metArray1 = metArray[utctime==t,:]
2037 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2036 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2038 tmet = metArray1[:,1].astype(int)
2037 tmet = metArray1[:,1].astype(int)
2039 hmet = metArray1[:,2].astype(int)
2038 hmet = metArray1[:,2].astype(int)
2040
2039
2041 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2040 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2042 metPhase[:,:] = numpy.nan
2041 metPhase[:,:] = numpy.nan
2043 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2042 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2044
2043
2045 #Delete short trails
2044 #Delete short trails
2046 metBool = ~numpy.isnan(metPhase[0,:,:])
2045 metBool = ~numpy.isnan(metPhase[0,:,:])
2047 heightVect = numpy.sum(metBool, axis = 1)
2046 heightVect = numpy.sum(metBool, axis = 1)
2048 metBool[heightVect<sec,:] = False
2047 metBool[heightVect<sec,:] = False
2049 metPhase[:,heightVect<sec,:] = numpy.nan
2048 metPhase[:,heightVect<sec,:] = numpy.nan
2050
2049
2051 #Derivative
2050 #Derivative
2052 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2051 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2053 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))
2054 metPhase[phDerAux] = numpy.nan
2053 metPhase[phDerAux] = numpy.nan
2055
2054
2056 #--------------------------METEOR DETECTION -----------------------------------------
2055 #--------------------------METEOR DETECTION -----------------------------------------
2057 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2056 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2058
2057
2059 for p in numpy.arange(nPairs):
2058 for p in numpy.arange(nPairs):
2060 phase = metPhase[p,:,:]
2059 phase = metPhase[p,:,:]
2061 phDer = metDer[p,:,:]
2060 phDer = metDer[p,:,:]
2062
2061
2063 for h in indMet:
2062 for h in indMet:
2064 height = heightList[h]
2063 height = heightList[h]
2065 phase1 = phase[h,:] #82
2064 phase1 = phase[h,:] #82
2066 phDer1 = phDer[h,:]
2065 phDer1 = phDer[h,:]
2067
2066
2068 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2067 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2069
2068
2070 indValid = numpy.where(~numpy.isnan(phase1))[0]
2069 indValid = numpy.where(~numpy.isnan(phase1))[0]
2071 initMet = indValid[0]
2070 initMet = indValid[0]
2072 endMet = 0
2071 endMet = 0
2073
2072
2074 for i in range(len(indValid)-1):
2073 for i in range(len(indValid)-1):
2075
2074
2076 #Time difference
2075 #Time difference
2077 inow = indValid[i]
2076 inow = indValid[i]
2078 inext = indValid[i+1]
2077 inext = indValid[i+1]
2079 idiff = inext - inow
2078 idiff = inext - inow
2080 #Phase difference
2079 #Phase difference
2081 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2080 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2082
2081
2083 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
2084 sizeTrail = inow - initMet + 1
2083 sizeTrail = inow - initMet + 1
2085 if sizeTrail>3*sec: #Too short meteors
2084 if sizeTrail>3*sec: #Too short meteors
2086 x = numpy.arange(initMet,inow+1)*ippSeconds
2085 x = numpy.arange(initMet,inow+1)*ippSeconds
2087 y = phase1[initMet:inow+1]
2086 y = phase1[initMet:inow+1]
2088 ynnan = ~numpy.isnan(y)
2087 ynnan = ~numpy.isnan(y)
2089 x = x[ynnan]
2088 x = x[ynnan]
2090 y = y[ynnan]
2089 y = y[ynnan]
2091 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)
2092 ylin = x*slope + intercept
2091 ylin = x*slope + intercept
2093 rsq = r_value**2
2092 rsq = r_value**2
2094 if rsq > 0.5:
2093 if rsq > 0.5:
2095 vel = slope#*height*1000/(k*d)
2094 vel = slope#*height*1000/(k*d)
2096 estAux = numpy.array([utctime,p,height, vel, rsq])
2095 estAux = numpy.array([utctime,p,height, vel, rsq])
2097 meteorList.append(estAux)
2096 meteorList.append(estAux)
2098 initMet = inext
2097 initMet = inext
2099 metArray2 = numpy.array(meteorList)
2098 metArray2 = numpy.array(meteorList)
2100
2099
2101 return metArray2
2100 return metArray2
2102
2101
2103 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2102 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2104
2103
2105 azimuth1 = numpy.zeros(len(pairslist))
2104 azimuth1 = numpy.zeros(len(pairslist))
2106 dist = numpy.zeros(len(pairslist))
2105 dist = numpy.zeros(len(pairslist))
2107
2106
2108 for i in range(len(rx_location)):
2107 for i in range(len(rx_location)):
2109 ch0 = pairslist[i][0]
2108 ch0 = pairslist[i][0]
2110 ch1 = pairslist[i][1]
2109 ch1 = pairslist[i][1]
2111
2110
2112 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2111 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2113 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2112 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2114 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2113 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2115 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2114 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2116
2115
2117 azimuth1 -= azimuth0
2116 azimuth1 -= azimuth0
2118 return azimuth1, dist
2117 return azimuth1, dist
2119
2118
2120 def techniqueNSM_DBS(self, **kwargs):
2119 def techniqueNSM_DBS(self, **kwargs):
2121 metArray = kwargs['metArray']
2120 metArray = kwargs['metArray']
2122 heightList = kwargs['heightList']
2121 heightList = kwargs['heightList']
2123 timeList = kwargs['timeList']
2122 timeList = kwargs['timeList']
2124 azimuth = kwargs['azimuth']
2123 azimuth = kwargs['azimuth']
2125 theta_x = numpy.array(kwargs['theta_x'])
2124 theta_x = numpy.array(kwargs['theta_x'])
2126 theta_y = numpy.array(kwargs['theta_y'])
2125 theta_y = numpy.array(kwargs['theta_y'])
2127
2126
2128 utctime = metArray[:,0]
2127 utctime = metArray[:,0]
2129 cmet = metArray[:,1].astype(int)
2128 cmet = metArray[:,1].astype(int)
2130 hmet = metArray[:,3].astype(int)
2129 hmet = metArray[:,3].astype(int)
2131 SNRmet = metArray[:,4]
2130 SNRmet = metArray[:,4]
2132 vmet = metArray[:,5]
2131 vmet = metArray[:,5]
2133 spcmet = metArray[:,6]
2132 spcmet = metArray[:,6]
2134
2133
2135 nChan = numpy.max(cmet) + 1
2134 nChan = numpy.max(cmet) + 1
2136 nHeights = len(heightList)
2135 nHeights = len(heightList)
2137
2136
2138 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)
2139 hmet = heightList[hmet]
2138 hmet = heightList[hmet]
2140 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2139 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2141
2140
2142 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2141 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2143
2142
2144 for i in range(nHeights - 1):
2143 for i in range(nHeights - 1):
2145 hmin = heightList[i]
2144 hmin = heightList[i]
2146 hmax = heightList[i + 1]
2145 hmax = heightList[i + 1]
2147
2146
2148 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)
2149 indthisH = numpy.where(thisH)
2148 indthisH = numpy.where(thisH)
2150
2149
2151 if numpy.size(indthisH) > 3:
2150 if numpy.size(indthisH) > 3:
2152
2151
2153 vel_aux = vmet[thisH]
2152 vel_aux = vmet[thisH]
2154 chan_aux = cmet[thisH]
2153 chan_aux = cmet[thisH]
2155 cosu_aux = dir_cosu[chan_aux]
2154 cosu_aux = dir_cosu[chan_aux]
2156 cosv_aux = dir_cosv[chan_aux]
2155 cosv_aux = dir_cosv[chan_aux]
2157 cosw_aux = dir_cosw[chan_aux]
2156 cosw_aux = dir_cosw[chan_aux]
2158
2157
2159 nch = numpy.size(numpy.unique(chan_aux))
2158 nch = numpy.size(numpy.unique(chan_aux))
2160 if nch > 1:
2159 if nch > 1:
2161 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2160 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2162 velEst[i,:] = numpy.dot(A,vel_aux)
2161 velEst[i,:] = numpy.dot(A,vel_aux)
2163
2162
2164 return velEst
2163 return velEst
2165
2164
2166 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):
2167
2166
2168 param = dataOut.data_param
2167 param = dataOut.data_param
2169 if dataOut.abscissaList != None:
2168 if dataOut.abscissaList != None:
2170 absc = dataOut.abscissaList[:-1]
2169 absc = dataOut.abscissaList[:-1]
2171 # noise = dataOut.noise
2170 # noise = dataOut.noise
2172 heightList = dataOut.heightList
2171 heightList = dataOut.heightList
2173 SNR = dataOut.data_snr
2172 SNR = dataOut.data_snr
2174
2173
2175 if technique == 'DBS':
2174 if technique == 'DBS':
2176
2175
2177 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2176 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2178 kwargs['heightList'] = heightList
2177 kwargs['heightList'] = heightList
2179 kwargs['SNR'] = SNR
2178 kwargs['SNR'] = SNR
2180
2179
2181 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
2182 dataOut.utctimeInit = dataOut.utctime
2181 dataOut.utctimeInit = dataOut.utctime
2183 dataOut.outputInterval = dataOut.paramInterval
2182 dataOut.outputInterval = dataOut.paramInterval
2184
2183
2185 elif technique == 'SA':
2184 elif technique == 'SA':
2186
2185
2187 #Parameters
2186 #Parameters
2188 # position_x = kwargs['positionX']
2187 # position_x = kwargs['positionX']
2189 # position_y = kwargs['positionY']
2188 # position_y = kwargs['positionY']
2190 # azimuth = kwargs['azimuth']
2189 # azimuth = kwargs['azimuth']
2191 #
2190 #
2192 # if kwargs.has_key('crosspairsList'):
2191 # if kwargs.has_key('crosspairsList'):
2193 # pairs = kwargs['crosspairsList']
2192 # pairs = kwargs['crosspairsList']
2194 # else:
2193 # else:
2195 # pairs = None
2194 # pairs = None
2196 #
2195 #
2197 # if kwargs.has_key('correctFactor'):
2196 # if kwargs.has_key('correctFactor'):
2198 # correctFactor = kwargs['correctFactor']
2197 # correctFactor = kwargs['correctFactor']
2199 # else:
2198 # else:
2200 # correctFactor = 1
2199 # correctFactor = 1
2201
2200
2202 # tau = dataOut.data_param
2201 # tau = dataOut.data_param
2203 # _lambda = dataOut.C/dataOut.frequency
2202 # _lambda = dataOut.C/dataOut.frequency
2204 # pairsList = dataOut.groupList
2203 # pairsList = dataOut.groupList
2205 # nChannels = dataOut.nChannels
2204 # nChannels = dataOut.nChannels
2206
2205
2207 kwargs['groupList'] = dataOut.groupList
2206 kwargs['groupList'] = dataOut.groupList
2208 kwargs['tau'] = dataOut.data_param
2207 kwargs['tau'] = dataOut.data_param
2209 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2208 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2210 # 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)
2211 dataOut.data_output = self.techniqueSA(kwargs)
2210 dataOut.data_output = self.techniqueSA(kwargs)
2212 dataOut.utctimeInit = dataOut.utctime
2211 dataOut.utctimeInit = dataOut.utctime
2213 dataOut.outputInterval = dataOut.timeInterval
2212 dataOut.outputInterval = dataOut.timeInterval
2214
2213
2215 elif technique == 'Meteors':
2214 elif technique == 'Meteors':
2216 dataOut.flagNoData = True
2215 dataOut.flagNoData = True
2217 self.__dataReady = False
2216 self.__dataReady = False
2218
2217
2219 if 'nHours' in kwargs:
2218 if 'nHours' in kwargs:
2220 nHours = kwargs['nHours']
2219 nHours = kwargs['nHours']
2221 else:
2220 else:
2222 nHours = 1
2221 nHours = 1
2223
2222
2224 if 'meteorsPerBin' in kwargs:
2223 if 'meteorsPerBin' in kwargs:
2225 meteorThresh = kwargs['meteorsPerBin']
2224 meteorThresh = kwargs['meteorsPerBin']
2226 else:
2225 else:
2227 meteorThresh = 6
2226 meteorThresh = 6
2228
2227
2229 if 'hmin' in kwargs:
2228 if 'hmin' in kwargs:
2230 hmin = kwargs['hmin']
2229 hmin = kwargs['hmin']
2231 else: hmin = 70
2230 else: hmin = 70
2232 if 'hmax' in kwargs:
2231 if 'hmax' in kwargs:
2233 hmax = kwargs['hmax']
2232 hmax = kwargs['hmax']
2234 else: hmax = 110
2233 else: hmax = 110
2235
2234
2236 dataOut.outputInterval = nHours*3600
2235 dataOut.outputInterval = nHours*3600
2237
2236
2238 if self.__isConfig == False:
2237 if self.__isConfig == False:
2239 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2238 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2240 #Get Initial LTC time
2239 #Get Initial LTC time
2241 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2240 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2242 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()
2243
2242
2244 self.__isConfig = True
2243 self.__isConfig = True
2245
2244
2246 if self.__buffer is None:
2245 if self.__buffer is None:
2247 self.__buffer = dataOut.data_param
2246 self.__buffer = dataOut.data_param
2248 self.__firstdata = copy.copy(dataOut)
2247 self.__firstdata = copy.copy(dataOut)
2249
2248
2250 else:
2249 else:
2251 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2250 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2252
2251
2253 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
2254
2253
2255 if self.__dataReady:
2254 if self.__dataReady:
2256 dataOut.utctimeInit = self.__initime
2255 dataOut.utctimeInit = self.__initime
2257
2256
2258 self.__initime += dataOut.outputInterval #to erase time offset
2257 self.__initime += dataOut.outputInterval #to erase time offset
2259
2258
2260 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)
2261 dataOut.flagNoData = False
2260 dataOut.flagNoData = False
2262 self.__buffer = None
2261 self.__buffer = None
2263
2262
2264 elif technique == 'Meteors1':
2263 elif technique == 'Meteors1':
2265 dataOut.flagNoData = True
2264 dataOut.flagNoData = True
2266 self.__dataReady = False
2265 self.__dataReady = False
2267
2266
2268 if 'nMins' in kwargs:
2267 if 'nMins' in kwargs:
2269 nMins = kwargs['nMins']
2268 nMins = kwargs['nMins']
2270 else: nMins = 20
2269 else: nMins = 20
2271 if 'rx_location' in kwargs:
2270 if 'rx_location' in kwargs:
2272 rx_location = kwargs['rx_location']
2271 rx_location = kwargs['rx_location']
2273 else: rx_location = [(0,1),(1,1),(1,0)]
2272 else: rx_location = [(0,1),(1,1),(1,0)]
2274 if 'azimuth' in kwargs:
2273 if 'azimuth' in kwargs:
2275 azimuth = kwargs['azimuth']
2274 azimuth = kwargs['azimuth']
2276 else: azimuth = 51.06
2275 else: azimuth = 51.06
2277 if 'dfactor' in kwargs:
2276 if 'dfactor' in kwargs:
2278 dfactor = kwargs['dfactor']
2277 dfactor = kwargs['dfactor']
2279 if 'mode' in kwargs:
2278 if 'mode' in kwargs:
2280 mode = kwargs['mode']
2279 mode = kwargs['mode']
2281 if 'theta_x' in kwargs:
2280 if 'theta_x' in kwargs:
2282 theta_x = kwargs['theta_x']
2281 theta_x = kwargs['theta_x']
2283 if 'theta_y' in kwargs:
2282 if 'theta_y' in kwargs:
2284 theta_y = kwargs['theta_y']
2283 theta_y = kwargs['theta_y']
2285 else: mode = 'SA'
2284 else: mode = 'SA'
2286
2285
2287 #Borrar luego esto
2286 #Borrar luego esto
2288 if dataOut.groupList is None:
2287 if dataOut.groupList is None:
2289 dataOut.groupList = [(0,1),(0,2),(1,2)]
2288 dataOut.groupList = [(0,1),(0,2),(1,2)]
2290 groupList = dataOut.groupList
2289 groupList = dataOut.groupList
2291 C = 3e8
2290 C = 3e8
2292 freq = 50e6
2291 freq = 50e6
2293 lamb = C/freq
2292 lamb = C/freq
2294 k = 2*numpy.pi/lamb
2293 k = 2*numpy.pi/lamb
2295
2294
2296 timeList = dataOut.abscissaList
2295 timeList = dataOut.abscissaList
2297 heightList = dataOut.heightList
2296 heightList = dataOut.heightList
2298
2297
2299 if self.__isConfig == False:
2298 if self.__isConfig == False:
2300 dataOut.outputInterval = nMins*60
2299 dataOut.outputInterval = nMins*60
2301 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2300 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2302 #Get Initial LTC time
2301 #Get Initial LTC time
2303 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2302 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2304 minuteAux = initime.minute
2303 minuteAux = initime.minute
2305 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2304 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2306 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()
2307
2306
2308 self.__isConfig = True
2307 self.__isConfig = True
2309
2308
2310 if self.__buffer is None:
2309 if self.__buffer is None:
2311 self.__buffer = dataOut.data_param
2310 self.__buffer = dataOut.data_param
2312 self.__firstdata = copy.copy(dataOut)
2311 self.__firstdata = copy.copy(dataOut)
2313
2312
2314 else:
2313 else:
2315 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2314 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2316
2315
2317 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
2318
2317
2319 if self.__dataReady:
2318 if self.__dataReady:
2320 dataOut.utctimeInit = self.__initime
2319 dataOut.utctimeInit = self.__initime
2321 self.__initime += dataOut.outputInterval #to erase time offset
2320 self.__initime += dataOut.outputInterval #to erase time offset
2322
2321
2323 metArray = self.__buffer
2322 metArray = self.__buffer
2324 if mode == 'SA':
2323 if mode == 'SA':
2325 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)
2326 elif mode == 'DBS':
2325 elif mode == 'DBS':
2327 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)
2328 dataOut.data_output = dataOut.data_output.T
2327 dataOut.data_output = dataOut.data_output.T
2329 dataOut.flagNoData = False
2328 dataOut.flagNoData = False
2330 self.__buffer = None
2329 self.__buffer = None
2331
2330
2332 return
2331 return
2333
2332
2334 class EWDriftsEstimation(Operation):
2333 class EWDriftsEstimation(Operation):
2335
2334
2336 def __init__(self):
2335 def __init__(self):
2337 Operation.__init__(self)
2336 Operation.__init__(self)
2338
2337
2339 def __correctValues(self, heiRang, phi, velRadial, SNR):
2338 def __correctValues(self, heiRang, phi, velRadial, SNR):
2340 listPhi = phi.tolist()
2339 listPhi = phi.tolist()
2341 maxid = listPhi.index(max(listPhi))
2340 maxid = listPhi.index(max(listPhi))
2342 minid = listPhi.index(min(listPhi))
2341 minid = listPhi.index(min(listPhi))
2343
2342
2344 rango = list(range(len(phi)))
2343 rango = list(range(len(phi)))
2345 # rango = numpy.delete(rango,maxid)
2344 # rango = numpy.delete(rango,maxid)
2346
2345
2347 heiRang1 = heiRang*math.cos(phi[maxid])
2346 heiRang1 = heiRang*math.cos(phi[maxid])
2348 heiRangAux = heiRang*math.cos(phi[minid])
2347 heiRangAux = heiRang*math.cos(phi[minid])
2349 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2348 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2350 heiRang1 = numpy.delete(heiRang1,indOut)
2349 heiRang1 = numpy.delete(heiRang1,indOut)
2351
2350
2352 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2351 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2353 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2352 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2354
2353
2355 for i in rango:
2354 for i in rango:
2356 x = heiRang*math.cos(phi[i])
2355 x = heiRang*math.cos(phi[i])
2357 y1 = velRadial[i,:]
2356 y1 = velRadial[i,:]
2358 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2357 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2359
2358
2360 x1 = heiRang1
2359 x1 = heiRang1
2361 y11 = f1(x1)
2360 y11 = f1(x1)
2362
2361
2363 y2 = SNR[i,:]
2362 y2 = SNR[i,:]
2364 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2363 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2365 y21 = f2(x1)
2364 y21 = f2(x1)
2366
2365
2367 velRadial1[i,:] = y11
2366 velRadial1[i,:] = y11
2368 SNR1[i,:] = y21
2367 SNR1[i,:] = y21
2369
2368
2370 return heiRang1, velRadial1, SNR1
2369 return heiRang1, velRadial1, SNR1
2371
2370
2372 def run(self, dataOut, zenith, zenithCorrection):
2371 def run(self, dataOut, zenith, zenithCorrection):
2373 heiRang = dataOut.heightList
2372 heiRang = dataOut.heightList
2374 velRadial = dataOut.data_param[:,3,:]
2373 velRadial = dataOut.data_param[:,3,:]
2375 SNR = dataOut.data_snr
2374 SNR = dataOut.data_snr
2376
2375
2377 zenith = numpy.array(zenith)
2376 zenith = numpy.array(zenith)
2378 zenith -= zenithCorrection
2377 zenith -= zenithCorrection
2379 zenith *= numpy.pi/180
2378 zenith *= numpy.pi/180
2380
2379
2381 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2380 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2382
2381
2383 alp = zenith[0]
2382 alp = zenith[0]
2384 bet = zenith[1]
2383 bet = zenith[1]
2385
2384
2386 w_w = velRadial1[0,:]
2385 w_w = velRadial1[0,:]
2387 w_e = velRadial1[1,:]
2386 w_e = velRadial1[1,:]
2388
2387
2389 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))
2390 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))
2391
2390
2392 winds = numpy.vstack((u,w))
2391 winds = numpy.vstack((u,w))
2393
2392
2394 dataOut.heightList = heiRang1
2393 dataOut.heightList = heiRang1
2395 dataOut.data_output = winds
2394 dataOut.data_output = winds
2396 dataOut.data_snr = SNR1
2395 dataOut.data_snr = SNR1
2397
2396
2398 dataOut.utctimeInit = dataOut.utctime
2397 dataOut.utctimeInit = dataOut.utctime
2399 dataOut.outputInterval = dataOut.timeInterval
2398 dataOut.outputInterval = dataOut.timeInterval
2400 return
2399 return
2401
2400
2402 #--------------- Non Specular Meteor ----------------
2401 #--------------- Non Specular Meteor ----------------
2403
2402
2404 class NonSpecularMeteorDetection(Operation):
2403 class NonSpecularMeteorDetection(Operation):
2405
2404
2406 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):
2407 data_acf = dataOut.data_pre[0]
2406 data_acf = dataOut.data_pre[0]
2408 data_ccf = dataOut.data_pre[1]
2407 data_ccf = dataOut.data_pre[1]
2409 pairsList = dataOut.groupList[1]
2408 pairsList = dataOut.groupList[1]
2410
2409
2411 lamb = dataOut.C/dataOut.frequency
2410 lamb = dataOut.C/dataOut.frequency
2412 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2411 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2413 paramInterval = dataOut.paramInterval
2412 paramInterval = dataOut.paramInterval
2414
2413
2415 nChannels = data_acf.shape[0]
2414 nChannels = data_acf.shape[0]
2416 nLags = data_acf.shape[1]
2415 nLags = data_acf.shape[1]
2417 nProfiles = data_acf.shape[2]
2416 nProfiles = data_acf.shape[2]
2418 nHeights = dataOut.nHeights
2417 nHeights = dataOut.nHeights
2419 nCohInt = dataOut.nCohInt
2418 nCohInt = dataOut.nCohInt
2420 sec = numpy.round(nProfiles/dataOut.paramInterval)
2419 sec = numpy.round(nProfiles/dataOut.paramInterval)
2421 heightList = dataOut.heightList
2420 heightList = dataOut.heightList
2422 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2421 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2423 utctime = dataOut.utctime
2422 utctime = dataOut.utctime
2424
2423
2425 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2424 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2426
2425
2427 #------------------------ SNR --------------------------------------
2426 #------------------------ SNR --------------------------------------
2428 power = data_acf[:,0,:,:].real
2427 power = data_acf[:,0,:,:].real
2429 noise = numpy.zeros(nChannels)
2428 noise = numpy.zeros(nChannels)
2430 SNR = numpy.zeros(power.shape)
2429 SNR = numpy.zeros(power.shape)
2431 for i in range(nChannels):
2430 for i in range(nChannels):
2432 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2431 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2433 SNR[i] = (power[i]-noise[i])/noise[i]
2432 SNR[i] = (power[i]-noise[i])/noise[i]
2434 SNRm = numpy.nanmean(SNR, axis = 0)
2433 SNRm = numpy.nanmean(SNR, axis = 0)
2435 SNRdB = 10*numpy.log10(SNR)
2434 SNRdB = 10*numpy.log10(SNR)
2436
2435
2437 if mode == 'SA':
2436 if mode == 'SA':
2438 dataOut.groupList = dataOut.groupList[1]
2437 dataOut.groupList = dataOut.groupList[1]
2439 nPairs = data_ccf.shape[0]
2438 nPairs = data_ccf.shape[0]
2440 #---------------------- Coherence and Phase --------------------------
2439 #---------------------- Coherence and Phase --------------------------
2441 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2440 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2442 # phase1 = numpy.copy(phase)
2441 # phase1 = numpy.copy(phase)
2443 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2442 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2444
2443
2445 for p in range(nPairs):
2444 for p in range(nPairs):
2446 ch0 = pairsList[p][0]
2445 ch0 = pairsList[p][0]
2447 ch1 = pairsList[p][1]
2446 ch1 = pairsList[p][1]
2448 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,:,:])
2449 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
2450 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2449 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2451 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2450 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2452 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2451 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2453 coh = numpy.nanmax(coh1, axis = 0)
2452 coh = numpy.nanmax(coh1, axis = 0)
2454 # struc = numpy.ones((5,1))
2453 # struc = numpy.ones((5,1))
2455 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2454 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2456 #---------------------- Radial Velocity ----------------------------
2455 #---------------------- Radial Velocity ----------------------------
2457 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2456 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2458 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2457 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2459
2458
2460 if allData:
2459 if allData:
2461 boolMetFin = ~numpy.isnan(SNRm)
2460 boolMetFin = ~numpy.isnan(SNRm)
2462 # 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)
2463 else:
2462 else:
2464 #------------------------ Meteor mask ---------------------------------
2463 #------------------------ Meteor mask ---------------------------------
2465 # #SNR mask
2464 # #SNR mask
2466 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2465 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2467 #
2466 #
2468 # #Erase small objects
2467 # #Erase small objects
2469 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2468 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2470 #
2469 #
2471 # auxEEJ = numpy.sum(boolMet1,axis=0)
2470 # auxEEJ = numpy.sum(boolMet1,axis=0)
2472 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2471 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2473 # indEEJ = numpy.where(indOver)[0]
2472 # indEEJ = numpy.where(indOver)[0]
2474 # indNEEJ = numpy.where(~indOver)[0]
2473 # indNEEJ = numpy.where(~indOver)[0]
2475 #
2474 #
2476 # boolMetFin = boolMet1
2475 # boolMetFin = boolMet1
2477 #
2476 #
2478 # if indEEJ.size > 0:
2477 # if indEEJ.size > 0:
2479 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2478 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2480 #
2479 #
2481 # boolMet2 = coh > cohThresh
2480 # boolMet2 = coh > cohThresh
2482 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2481 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2483 #
2482 #
2484 # #Final Meteor mask
2483 # #Final Meteor mask
2485 # boolMetFin = boolMet1|boolMet2
2484 # boolMetFin = boolMet1|boolMet2
2486
2485
2487 #Coherence mask
2486 #Coherence mask
2488 boolMet1 = coh > 0.75
2487 boolMet1 = coh > 0.75
2489 struc = numpy.ones((30,1))
2488 struc = numpy.ones((30,1))
2490 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2489 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2491
2490
2492 #Derivative mask
2491 #Derivative mask
2493 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2492 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2494 boolMet2 = derPhase < 0.2
2493 boolMet2 = derPhase < 0.2
2495 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2494 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2496 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2495 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2497 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2496 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2498 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2497 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2499 # #Final mask
2498 # #Final mask
2500 # boolMetFin = boolMet2
2499 # boolMetFin = boolMet2
2501 boolMetFin = boolMet1&boolMet2
2500 boolMetFin = boolMet1&boolMet2
2502 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2501 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2503 #Creating data_param
2502 #Creating data_param
2504 coordMet = numpy.where(boolMetFin)
2503 coordMet = numpy.where(boolMetFin)
2505
2504
2506 tmet = coordMet[0]
2505 tmet = coordMet[0]
2507 hmet = coordMet[1]
2506 hmet = coordMet[1]
2508
2507
2509 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2508 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2510 data_param[:,0] = utctime
2509 data_param[:,0] = utctime
2511 data_param[:,1] = tmet
2510 data_param[:,1] = tmet
2512 data_param[:,2] = hmet
2511 data_param[:,2] = hmet
2513 data_param[:,3] = SNRm[tmet,hmet]
2512 data_param[:,3] = SNRm[tmet,hmet]
2514 data_param[:,4] = velRad[tmet,hmet]
2513 data_param[:,4] = velRad[tmet,hmet]
2515 data_param[:,5] = coh[tmet,hmet]
2514 data_param[:,5] = coh[tmet,hmet]
2516 data_param[:,6:] = phase[:,tmet,hmet].T
2515 data_param[:,6:] = phase[:,tmet,hmet].T
2517
2516
2518 elif mode == 'DBS':
2517 elif mode == 'DBS':
2519 dataOut.groupList = numpy.arange(nChannels)
2518 dataOut.groupList = numpy.arange(nChannels)
2520
2519
2521 #Radial Velocities
2520 #Radial Velocities
2522 phase = numpy.angle(data_acf[:,1,:,:])
2521 phase = numpy.angle(data_acf[:,1,:,:])
2523 # 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))
2524 velRad = phase*lamb/(4*numpy.pi*tSamp)
2523 velRad = phase*lamb/(4*numpy.pi*tSamp)
2525
2524
2526 #Spectral width
2525 #Spectral width
2527 # 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))
2528 # 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))
2529 acf1 = data_acf[:,1,:,:]
2528 acf1 = data_acf[:,1,:,:]
2530 acf2 = data_acf[:,2,:,:]
2529 acf2 = data_acf[:,2,:,:]
2531
2530
2532 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))
2533 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2532 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2534 if allData:
2533 if allData:
2535 boolMetFin = ~numpy.isnan(SNRdB)
2534 boolMetFin = ~numpy.isnan(SNRdB)
2536 else:
2535 else:
2537 #SNR
2536 #SNR
2538 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2537 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2539 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2538 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2540
2539
2541 #Radial velocity
2540 #Radial velocity
2542 boolMet2 = numpy.abs(velRad) < 20
2541 boolMet2 = numpy.abs(velRad) < 20
2543 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2542 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2544
2543
2545 #Spectral Width
2544 #Spectral Width
2546 boolMet3 = spcWidth < 30
2545 boolMet3 = spcWidth < 30
2547 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2546 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2548 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2547 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2549 boolMetFin = boolMet1&boolMet2&boolMet3
2548 boolMetFin = boolMet1&boolMet2&boolMet3
2550
2549
2551 #Creating data_param
2550 #Creating data_param
2552 coordMet = numpy.where(boolMetFin)
2551 coordMet = numpy.where(boolMetFin)
2553
2552
2554 cmet = coordMet[0]
2553 cmet = coordMet[0]
2555 tmet = coordMet[1]
2554 tmet = coordMet[1]
2556 hmet = coordMet[2]
2555 hmet = coordMet[2]
2557
2556
2558 data_param = numpy.zeros((tmet.size, 7))
2557 data_param = numpy.zeros((tmet.size, 7))
2559 data_param[:,0] = utctime
2558 data_param[:,0] = utctime
2560 data_param[:,1] = cmet
2559 data_param[:,1] = cmet
2561 data_param[:,2] = tmet
2560 data_param[:,2] = tmet
2562 data_param[:,3] = hmet
2561 data_param[:,3] = hmet
2563 data_param[:,4] = SNR[cmet,tmet,hmet].T
2562 data_param[:,4] = SNR[cmet,tmet,hmet].T
2564 data_param[:,5] = velRad[cmet,tmet,hmet].T
2563 data_param[:,5] = velRad[cmet,tmet,hmet].T
2565 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2564 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2566
2565
2567 # self.dataOut.data_param = data_int
2566 # self.dataOut.data_param = data_int
2568 if len(data_param) == 0:
2567 if len(data_param) == 0:
2569 dataOut.flagNoData = True
2568 dataOut.flagNoData = True
2570 else:
2569 else:
2571 dataOut.data_param = data_param
2570 dataOut.data_param = data_param
2572
2571
2573 def __erase_small(self, binArray, threshX, threshY):
2572 def __erase_small(self, binArray, threshX, threshY):
2574 labarray, numfeat = ndimage.measurements.label(binArray)
2573 labarray, numfeat = ndimage.measurements.label(binArray)
2575 binArray1 = numpy.copy(binArray)
2574 binArray1 = numpy.copy(binArray)
2576
2575
2577 for i in range(1,numfeat + 1):
2576 for i in range(1,numfeat + 1):
2578 auxBin = (labarray==i)
2577 auxBin = (labarray==i)
2579 auxSize = auxBin.sum()
2578 auxSize = auxBin.sum()
2580
2579
2581 x,y = numpy.where(auxBin)
2580 x,y = numpy.where(auxBin)
2582 widthX = x.max() - x.min()
2581 widthX = x.max() - x.min()
2583 widthY = y.max() - y.min()
2582 widthY = y.max() - y.min()
2584
2583
2585 #width X: 3 seg -> 12.5*3
2584 #width X: 3 seg -> 12.5*3
2586 #width Y:
2585 #width Y:
2587
2586
2588 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2587 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2589 binArray1[auxBin] = False
2588 binArray1[auxBin] = False
2590
2589
2591 return binArray1
2590 return binArray1
2592
2591
2593 #--------------- Specular Meteor ----------------
2592 #--------------- Specular Meteor ----------------
2594
2593
2595 class SMDetection(Operation):
2594 class SMDetection(Operation):
2596 '''
2595 '''
2597 Function DetectMeteors()
2596 Function DetectMeteors()
2598 Project developed with paper:
2597 Project developed with paper:
2599 HOLDSWORTH ET AL. 2004
2598 HOLDSWORTH ET AL. 2004
2600
2599
2601 Input:
2600 Input:
2602 self.dataOut.data_pre
2601 self.dataOut.data_pre
2603
2602
2604 centerReceiverIndex: From the channels, which is the center receiver
2603 centerReceiverIndex: From the channels, which is the center receiver
2605
2604
2606 hei_ref: Height reference for the Beacon signal extraction
2605 hei_ref: Height reference for the Beacon signal extraction
2607 tauindex:
2606 tauindex:
2608 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2607 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2609
2608
2610 cohDetection: Whether to user Coherent detection or not
2609 cohDetection: Whether to user Coherent detection or not
2611 cohDet_timeStep: Coherent Detection calculation time step
2610 cohDet_timeStep: Coherent Detection calculation time step
2612 cohDet_thresh: Coherent Detection phase threshold to correct phases
2611 cohDet_thresh: Coherent Detection phase threshold to correct phases
2613
2612
2614 noise_timeStep: Noise calculation time step
2613 noise_timeStep: Noise calculation time step
2615 noise_multiple: Noise multiple to define signal threshold
2614 noise_multiple: Noise multiple to define signal threshold
2616
2615
2617 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2616 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2618 multDet_rangeLimit: Multiple Detection Removal range limit in km
2617 multDet_rangeLimit: Multiple Detection Removal range limit in km
2619
2618
2620 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2619 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2621 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
2622
2621
2623 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
2624 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
2625 azimuth: Azimuth angle correction
2624 azimuth: Azimuth angle correction
2626
2625
2627 Affected:
2626 Affected:
2628 self.dataOut.data_param
2627 self.dataOut.data_param
2629
2628
2630 Rejection Criteria (Errors):
2629 Rejection Criteria (Errors):
2631 0: No error; analysis OK
2630 0: No error; analysis OK
2632 1: SNR < SNR threshold
2631 1: SNR < SNR threshold
2633 2: angle of arrival (AOA) ambiguously determined
2632 2: angle of arrival (AOA) ambiguously determined
2634 3: AOA estimate not feasible
2633 3: AOA estimate not feasible
2635 4: Large difference in AOAs obtained from different antenna baselines
2634 4: Large difference in AOAs obtained from different antenna baselines
2636 5: echo at start or end of time series
2635 5: echo at start or end of time series
2637 6: echo less than 5 examples long; too short for analysis
2636 6: echo less than 5 examples long; too short for analysis
2638 7: echo rise exceeds 0.3s
2637 7: echo rise exceeds 0.3s
2639 8: echo decay time less than twice rise time
2638 8: echo decay time less than twice rise time
2640 9: large power level before echo
2639 9: large power level before echo
2641 10: large power level after echo
2640 10: large power level after echo
2642 11: poor fit to amplitude for estimation of decay time
2641 11: poor fit to amplitude for estimation of decay time
2643 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
2644 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
2645 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
2646 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
2647 16: oscilatory echo, indicating event most likely not an underdense echo
2646 16: oscilatory echo, indicating event most likely not an underdense echo
2648
2647
2649 17: phase difference in meteor Reestimation
2648 17: phase difference in meteor Reestimation
2650
2649
2651 Data Storage:
2650 Data Storage:
2652 Meteors for Wind Estimation (8):
2651 Meteors for Wind Estimation (8):
2653 Utc Time | Range Height
2652 Utc Time | Range Height
2654 Azimuth Zenith errorCosDir
2653 Azimuth Zenith errorCosDir
2655 VelRad errorVelRad
2654 VelRad errorVelRad
2656 Phase0 Phase1 Phase2 Phase3
2655 Phase0 Phase1 Phase2 Phase3
2657 TypeError
2656 TypeError
2658
2657
2659 '''
2658 '''
2660
2659
2661 def run(self, dataOut, hei_ref = None, tauindex = 0,
2660 def run(self, dataOut, hei_ref = None, tauindex = 0,
2662 phaseOffsets = None,
2661 phaseOffsets = None,
2663 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2662 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2664 noise_timeStep = 4, noise_multiple = 4,
2663 noise_timeStep = 4, noise_multiple = 4,
2665 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2664 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2666 phaseThresh = 20, SNRThresh = 5,
2665 phaseThresh = 20, SNRThresh = 5,
2667 hmin = 50, hmax=150, azimuth = 0,
2666 hmin = 50, hmax=150, azimuth = 0,
2668 channelPositions = None) :
2667 channelPositions = None) :
2669
2668
2670
2669
2671 #Getting Pairslist
2670 #Getting Pairslist
2672 if channelPositions is None:
2671 if channelPositions is None:
2673 # 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
2674 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
2675 meteorOps = SMOperations()
2674 meteorOps = SMOperations()
2676 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2675 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2677 heiRang = dataOut.heightList
2676 heiRang = dataOut.heightList
2678 #Get Beacon signal - No Beacon signal anymore
2677 #Get Beacon signal - No Beacon signal anymore
2679 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2678 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2680 #
2679 #
2681 # if hei_ref != None:
2680 # if hei_ref != None:
2682 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2681 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2683 #
2682 #
2684
2683
2685
2684
2686 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2685 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2687 # see if the user put in pre defined phase shifts
2686 # see if the user put in pre defined phase shifts
2688 voltsPShift = dataOut.data_pre.copy()
2687 voltsPShift = dataOut.data_pre.copy()
2689
2688
2690 # if predefinedPhaseShifts != None:
2689 # if predefinedPhaseShifts != None:
2691 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2690 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2692 #
2691 #
2693 # # elif beaconPhaseShifts:
2692 # # elif beaconPhaseShifts:
2694 # # #get hardware phase shifts using beacon signal
2693 # # #get hardware phase shifts using beacon signal
2695 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2694 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2696 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2695 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2697 #
2696 #
2698 # else:
2697 # else:
2699 # hardwarePhaseShifts = numpy.zeros(5)
2698 # hardwarePhaseShifts = numpy.zeros(5)
2700 #
2699 #
2701 # 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')
2702 # for i in range(self.dataOut.data_pre.shape[0]):
2701 # for i in range(self.dataOut.data_pre.shape[0]):
2703 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2702 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2704
2703
2705 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2704 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2706
2705
2707 #Remove DC
2706 #Remove DC
2708 voltsDC = numpy.mean(voltsPShift,1)
2707 voltsDC = numpy.mean(voltsPShift,1)
2709 voltsDC = numpy.mean(voltsDC,1)
2708 voltsDC = numpy.mean(voltsDC,1)
2710 for i in range(voltsDC.shape[0]):
2709 for i in range(voltsDC.shape[0]):
2711 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2710 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2712
2711
2713 #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
2714 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2713 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2715
2714
2716 #************ 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) **********
2717 #Coherent Detection
2716 #Coherent Detection
2718 if cohDetection:
2717 if cohDetection:
2719 #use coherent detection to get the net power
2718 #use coherent detection to get the net power
2720 cohDet_thresh = cohDet_thresh*numpy.pi/180
2719 cohDet_thresh = cohDet_thresh*numpy.pi/180
2721 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2720 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2722
2721
2723 #Non-coherent detection!
2722 #Non-coherent detection!
2724 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2723 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2725 #********** END OF COH/NON-COH POWER CALCULATION**********************
2724 #********** END OF COH/NON-COH POWER CALCULATION**********************
2726
2725
2727 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2726 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2728 #Get noise
2727 #Get noise
2729 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2728 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2730 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2729 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2731 #Get signal threshold
2730 #Get signal threshold
2732 signalThresh = noise_multiple*noise
2731 signalThresh = noise_multiple*noise
2733 #Meteor echoes detection
2732 #Meteor echoes detection
2734 listMeteors = self.__findMeteors(powerNet, signalThresh)
2733 listMeteors = self.__findMeteors(powerNet, signalThresh)
2735 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2734 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2736
2735
2737 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2736 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2738 #Parameters
2737 #Parameters
2739 heiRange = dataOut.heightList
2738 heiRange = dataOut.heightList
2740 rangeInterval = heiRange[1] - heiRange[0]
2739 rangeInterval = heiRange[1] - heiRange[0]
2741 rangeLimit = multDet_rangeLimit/rangeInterval
2740 rangeLimit = multDet_rangeLimit/rangeInterval
2742 timeLimit = multDet_timeLimit/dataOut.timeInterval
2741 timeLimit = multDet_timeLimit/dataOut.timeInterval
2743 #Multiple detection removals
2742 #Multiple detection removals
2744 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2743 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2745 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2744 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2746
2745
2747 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2746 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2748 #Parameters
2747 #Parameters
2749 phaseThresh = phaseThresh*numpy.pi/180
2748 phaseThresh = phaseThresh*numpy.pi/180
2750 thresh = [phaseThresh, noise_multiple, SNRThresh]
2749 thresh = [phaseThresh, noise_multiple, SNRThresh]
2751 #Meteor reestimation (Errors N 1, 6, 12, 17)
2750 #Meteor reestimation (Errors N 1, 6, 12, 17)
2752 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)
2753 # 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)
2754 #Estimation of decay times (Errors N 7, 8, 11)
2753 #Estimation of decay times (Errors N 7, 8, 11)
2755 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2754 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2756 #******************* END OF METEOR REESTIMATION *******************
2755 #******************* END OF METEOR REESTIMATION *******************
2757
2756
2758 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2757 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2759 #Calculating Radial Velocity (Error N 15)
2758 #Calculating Radial Velocity (Error N 15)
2760 radialStdThresh = 10
2759 radialStdThresh = 10
2761 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2760 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2762
2761
2763 if len(listMeteors4) > 0:
2762 if len(listMeteors4) > 0:
2764 #Setting New Array
2763 #Setting New Array
2765 date = dataOut.utctime
2764 date = dataOut.utctime
2766 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2765 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2767
2766
2768 #Correcting phase offset
2767 #Correcting phase offset
2769 if phaseOffsets != None:
2768 if phaseOffsets != None:
2770 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2769 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2771 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2770 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2772
2771
2773 #Second Pairslist
2772 #Second Pairslist
2774 pairsList = []
2773 pairsList = []
2775 pairx = (0,1)
2774 pairx = (0,1)
2776 pairy = (2,3)
2775 pairy = (2,3)
2777 pairsList.append(pairx)
2776 pairsList.append(pairx)
2778 pairsList.append(pairy)
2777 pairsList.append(pairy)
2779
2778
2780 jph = numpy.array([0,0,0,0])
2779 jph = numpy.array([0,0,0,0])
2781 h = (hmin,hmax)
2780 h = (hmin,hmax)
2782 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2781 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2783
2782
2784 # #Calculate AOA (Error N 3, 4)
2783 # #Calculate AOA (Error N 3, 4)
2785 # #JONES ET AL. 1998
2784 # #JONES ET AL. 1998
2786 # error = arrayParameters[:,-1]
2785 # error = arrayParameters[:,-1]
2787 # AOAthresh = numpy.pi/8
2786 # AOAthresh = numpy.pi/8
2788 # phases = -arrayParameters[:,9:13]
2787 # phases = -arrayParameters[:,9:13]
2789 # 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)
2790 #
2789 #
2791 # #Calculate Heights (Error N 13 and 14)
2790 # #Calculate Heights (Error N 13 and 14)
2792 # error = arrayParameters[:,-1]
2791 # error = arrayParameters[:,-1]
2793 # Ranges = arrayParameters[:,2]
2792 # Ranges = arrayParameters[:,2]
2794 # zenith = arrayParameters[:,5]
2793 # zenith = arrayParameters[:,5]
2795 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2794 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2796 # error = arrayParameters[:,-1]
2795 # error = arrayParameters[:,-1]
2797 #********************* END OF PARAMETERS CALCULATION **************************
2796 #********************* END OF PARAMETERS CALCULATION **************************
2798
2797
2799 #***************************+ PASS DATA TO NEXT STEP **********************
2798 #***************************+ PASS DATA TO NEXT STEP **********************
2800 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2799 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2801 dataOut.data_param = arrayParameters
2800 dataOut.data_param = arrayParameters
2802
2801
2803 if arrayParameters is None:
2802 if arrayParameters is None:
2804 dataOut.flagNoData = True
2803 dataOut.flagNoData = True
2805 else:
2804 else:
2806 dataOut.flagNoData = True
2805 dataOut.flagNoData = True
2807
2806
2808 return
2807 return
2809
2808
2810 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2809 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2811
2810
2812 minIndex = min(newheis[0])
2811 minIndex = min(newheis[0])
2813 maxIndex = max(newheis[0])
2812 maxIndex = max(newheis[0])
2814
2813
2815 voltage = voltage0[:,:,minIndex:maxIndex+1]
2814 voltage = voltage0[:,:,minIndex:maxIndex+1]
2816 nLength = voltage.shape[1]/n
2815 nLength = voltage.shape[1]/n
2817 nMin = 0
2816 nMin = 0
2818 nMax = 0
2817 nMax = 0
2819 phaseOffset = numpy.zeros((len(pairslist),n))
2818 phaseOffset = numpy.zeros((len(pairslist),n))
2820
2819
2821 for i in range(n):
2820 for i in range(n):
2822 nMax += nLength
2821 nMax += nLength
2823 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2822 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2824 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2823 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2825 phaseOffset[:,i] = phaseCCF.transpose()
2824 phaseOffset[:,i] = phaseCCF.transpose()
2826 nMin = nMax
2825 nMin = nMax
2827 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2826 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2828
2827
2829 #Remove Outliers
2828 #Remove Outliers
2830 factor = 2
2829 factor = 2
2831 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2830 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2832 dw = numpy.std(wt,axis = 1)
2831 dw = numpy.std(wt,axis = 1)
2833 dw = dw.reshape((dw.size,1))
2832 dw = dw.reshape((dw.size,1))
2834 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))
2835 phaseOffset[ind] = numpy.nan
2834 phaseOffset[ind] = numpy.nan
2836 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2835 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2837
2836
2838 return phaseOffset
2837 return phaseOffset
2839
2838
2840 def __shiftPhase(self, data, phaseShift):
2839 def __shiftPhase(self, data, phaseShift):
2841 #this will shift the phase of a complex number
2840 #this will shift the phase of a complex number
2842 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2841 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2843 return dataShifted
2842 return dataShifted
2844
2843
2845 def __estimatePhaseDifference(self, array, pairslist):
2844 def __estimatePhaseDifference(self, array, pairslist):
2846 nChannel = array.shape[0]
2845 nChannel = array.shape[0]
2847 nHeights = array.shape[2]
2846 nHeights = array.shape[2]
2848 numPairs = len(pairslist)
2847 numPairs = len(pairslist)
2849 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2848 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2850 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]))
2851
2850
2852 #Correct phases
2851 #Correct phases
2853 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2852 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2854 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2853 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2855
2854
2856 if indDer[0].shape[0] > 0:
2855 if indDer[0].shape[0] > 0:
2857 for i in range(indDer[0].shape[0]):
2856 for i in range(indDer[0].shape[0]):
2858 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]])
2859 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
2860
2859
2861 # for j in range(numSides):
2860 # for j in range(numSides):
2862 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2861 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2863 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2862 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2864 #
2863 #
2865 #Linear
2864 #Linear
2866 phaseInt = numpy.zeros((numPairs,1))
2865 phaseInt = numpy.zeros((numPairs,1))
2867 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2866 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2868 for j in range(numPairs):
2867 for j in range(numPairs):
2869 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2868 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2870 phaseInt[j] = fit[1]
2869 phaseInt[j] = fit[1]
2871 #Phase Differences
2870 #Phase Differences
2872 phaseDiff = phaseInt - phaseCCF[:,2,:]
2871 phaseDiff = phaseInt - phaseCCF[:,2,:]
2873 phaseArrival = phaseInt.reshape(phaseInt.size)
2872 phaseArrival = phaseInt.reshape(phaseInt.size)
2874
2873
2875 #Dealias
2874 #Dealias
2876 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2875 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2877 # indAlias = numpy.where(phaseArrival > numpy.pi)
2876 # indAlias = numpy.where(phaseArrival > numpy.pi)
2878 # phaseArrival[indAlias] -= 2*numpy.pi
2877 # phaseArrival[indAlias] -= 2*numpy.pi
2879 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2878 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2880 # phaseArrival[indAlias] += 2*numpy.pi
2879 # phaseArrival[indAlias] += 2*numpy.pi
2881
2880
2882 return phaseDiff, phaseArrival
2881 return phaseDiff, phaseArrival
2883
2882
2884 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2883 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2885 #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
2886 #find the phase shifts of each channel over 1 second intervals
2885 #find the phase shifts of each channel over 1 second intervals
2887 #only look at ranges below the beacon signal
2886 #only look at ranges below the beacon signal
2888 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2887 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2889 numBlocks = int(volts.shape[1]/numProfPerBlock)
2888 numBlocks = int(volts.shape[1]/numProfPerBlock)
2890 numHeights = volts.shape[2]
2889 numHeights = volts.shape[2]
2891 nChannel = volts.shape[0]
2890 nChannel = volts.shape[0]
2892 voltsCohDet = volts.copy()
2891 voltsCohDet = volts.copy()
2893
2892
2894 pairsarray = numpy.array(pairslist)
2893 pairsarray = numpy.array(pairslist)
2895 indSides = pairsarray[:,1]
2894 indSides = pairsarray[:,1]
2896 # indSides = numpy.array(range(nChannel))
2895 # indSides = numpy.array(range(nChannel))
2897 # indSides = numpy.delete(indSides, indCenter)
2896 # indSides = numpy.delete(indSides, indCenter)
2898 #
2897 #
2899 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2898 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2900 listBlocks = numpy.array_split(volts, numBlocks, 1)
2899 listBlocks = numpy.array_split(volts, numBlocks, 1)
2901
2900
2902 startInd = 0
2901 startInd = 0
2903 endInd = 0
2902 endInd = 0
2904
2903
2905 for i in range(numBlocks):
2904 for i in range(numBlocks):
2906 startInd = endInd
2905 startInd = endInd
2907 endInd = endInd + listBlocks[i].shape[1]
2906 endInd = endInd + listBlocks[i].shape[1]
2908
2907
2909 arrayBlock = listBlocks[i]
2908 arrayBlock = listBlocks[i]
2910 # arrayBlockCenter = listCenter[i]
2909 # arrayBlockCenter = listCenter[i]
2911
2910
2912 #Estimate the Phase Difference
2911 #Estimate the Phase Difference
2913 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2912 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2914 #Phase Difference RMS
2913 #Phase Difference RMS
2915 arrayPhaseRMS = numpy.abs(phaseDiff)
2914 arrayPhaseRMS = numpy.abs(phaseDiff)
2916 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2915 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2917 indPhase = numpy.where(phaseRMSaux==4)
2916 indPhase = numpy.where(phaseRMSaux==4)
2918 #Shifting
2917 #Shifting
2919 if indPhase[0].shape[0] > 0:
2918 if indPhase[0].shape[0] > 0:
2920 for j in range(indSides.size):
2919 for j in range(indSides.size):
2921 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())
2922 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2921 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2923
2922
2924 return voltsCohDet
2923 return voltsCohDet
2925
2924
2926 def __calculateCCF(self, volts, pairslist ,laglist):
2925 def __calculateCCF(self, volts, pairslist ,laglist):
2927
2926
2928 nHeights = volts.shape[2]
2927 nHeights = volts.shape[2]
2929 nPoints = volts.shape[1]
2928 nPoints = volts.shape[1]
2930 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2929 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2931
2930
2932 for i in range(len(pairslist)):
2931 for i in range(len(pairslist)):
2933 volts1 = volts[pairslist[i][0]]
2932 volts1 = volts[pairslist[i][0]]
2934 volts2 = volts[pairslist[i][1]]
2933 volts2 = volts[pairslist[i][1]]
2935
2934
2936 for t in range(len(laglist)):
2935 for t in range(len(laglist)):
2937 idxT = laglist[t]
2936 idxT = laglist[t]
2938 if idxT >= 0:
2937 if idxT >= 0:
2939 vStacked = numpy.vstack((volts2[idxT:,:],
2938 vStacked = numpy.vstack((volts2[idxT:,:],
2940 numpy.zeros((idxT, nHeights),dtype='complex')))
2939 numpy.zeros((idxT, nHeights),dtype='complex')))
2941 else:
2940 else:
2942 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2941 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2943 volts2[:(nPoints + idxT),:]))
2942 volts2[:(nPoints + idxT),:]))
2944 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2943 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2945
2944
2946 vStacked = None
2945 vStacked = None
2947 return voltsCCF
2946 return voltsCCF
2948
2947
2949 def __getNoise(self, power, timeSegment, timeInterval):
2948 def __getNoise(self, power, timeSegment, timeInterval):
2950 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2949 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2951 numBlocks = int(power.shape[0]/numProfPerBlock)
2950 numBlocks = int(power.shape[0]/numProfPerBlock)
2952 numHeights = power.shape[1]
2951 numHeights = power.shape[1]
2953
2952
2954 listPower = numpy.array_split(power, numBlocks, 0)
2953 listPower = numpy.array_split(power, numBlocks, 0)
2955 noise = numpy.zeros((power.shape[0], power.shape[1]))
2954 noise = numpy.zeros((power.shape[0], power.shape[1]))
2956 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2955 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2957
2956
2958 startInd = 0
2957 startInd = 0
2959 endInd = 0
2958 endInd = 0
2960
2959
2961 for i in range(numBlocks): #split por canal
2960 for i in range(numBlocks): #split por canal
2962 startInd = endInd
2961 startInd = endInd
2963 endInd = endInd + listPower[i].shape[0]
2962 endInd = endInd + listPower[i].shape[0]
2964
2963
2965 arrayBlock = listPower[i]
2964 arrayBlock = listPower[i]
2966 noiseAux = numpy.mean(arrayBlock, 0)
2965 noiseAux = numpy.mean(arrayBlock, 0)
2967 # noiseAux = numpy.median(noiseAux)
2966 # noiseAux = numpy.median(noiseAux)
2968 # noiseAux = numpy.mean(arrayBlock)
2967 # noiseAux = numpy.mean(arrayBlock)
2969 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2968 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2970
2969
2971 noiseAux1 = numpy.mean(arrayBlock)
2970 noiseAux1 = numpy.mean(arrayBlock)
2972 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2971 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2973
2972
2974 return noise, noise1
2973 return noise, noise1
2975
2974
2976 def __findMeteors(self, power, thresh):
2975 def __findMeteors(self, power, thresh):
2977 nProf = power.shape[0]
2976 nProf = power.shape[0]
2978 nHeights = power.shape[1]
2977 nHeights = power.shape[1]
2979 listMeteors = []
2978 listMeteors = []
2980
2979
2981 for i in range(nHeights):
2980 for i in range(nHeights):
2982 powerAux = power[:,i]
2981 powerAux = power[:,i]
2983 threshAux = thresh[:,i]
2982 threshAux = thresh[:,i]
2984
2983
2985 indUPthresh = numpy.where(powerAux > threshAux)[0]
2984 indUPthresh = numpy.where(powerAux > threshAux)[0]
2986 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2985 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2987
2986
2988 j = 0
2987 j = 0
2989
2988
2990 while (j < indUPthresh.size - 2):
2989 while (j < indUPthresh.size - 2):
2991 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2990 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2992 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2991 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2993 indDNthresh = indDNthresh[indDNAux]
2992 indDNthresh = indDNthresh[indDNAux]
2994
2993
2995 if (indDNthresh.size > 0):
2994 if (indDNthresh.size > 0):
2996 indEnd = indDNthresh[0] - 1
2995 indEnd = indDNthresh[0] - 1
2997 indInit = indUPthresh[j]
2996 indInit = indUPthresh[j]
2998
2997
2999 meteor = powerAux[indInit:indEnd + 1]
2998 meteor = powerAux[indInit:indEnd + 1]
3000 indPeak = meteor.argmax() + indInit
2999 indPeak = meteor.argmax() + indInit
3001 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3000 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3002
3001
3003 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3002 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3004 j = numpy.where(indUPthresh == indEnd)[0] + 1
3003 j = numpy.where(indUPthresh == indEnd)[0] + 1
3005 else: j+=1
3004 else: j+=1
3006 else: j+=1
3005 else: j+=1
3007
3006
3008 return listMeteors
3007 return listMeteors
3009
3008
3010 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3009 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3011
3010
3012 arrayMeteors = numpy.asarray(listMeteors)
3011 arrayMeteors = numpy.asarray(listMeteors)
3013 listMeteors1 = []
3012 listMeteors1 = []
3014
3013
3015 while arrayMeteors.shape[0] > 0:
3014 while arrayMeteors.shape[0] > 0:
3016 FLAs = arrayMeteors[:,4]
3015 FLAs = arrayMeteors[:,4]
3017 maxFLA = FLAs.argmax()
3016 maxFLA = FLAs.argmax()
3018 listMeteors1.append(arrayMeteors[maxFLA,:])
3017 listMeteors1.append(arrayMeteors[maxFLA,:])
3019
3018
3020 MeteorInitTime = arrayMeteors[maxFLA,1]
3019 MeteorInitTime = arrayMeteors[maxFLA,1]
3021 MeteorEndTime = arrayMeteors[maxFLA,3]
3020 MeteorEndTime = arrayMeteors[maxFLA,3]
3022 MeteorHeight = arrayMeteors[maxFLA,0]
3021 MeteorHeight = arrayMeteors[maxFLA,0]
3023
3022
3024 #Check neighborhood
3023 #Check neighborhood
3025 maxHeightIndex = MeteorHeight + rangeLimit
3024 maxHeightIndex = MeteorHeight + rangeLimit
3026 minHeightIndex = MeteorHeight - rangeLimit
3025 minHeightIndex = MeteorHeight - rangeLimit
3027 minTimeIndex = MeteorInitTime - timeLimit
3026 minTimeIndex = MeteorInitTime - timeLimit
3028 maxTimeIndex = MeteorEndTime + timeLimit
3027 maxTimeIndex = MeteorEndTime + timeLimit
3029
3028
3030 #Check Heights
3029 #Check Heights
3031 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3030 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3032 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3031 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3033 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3032 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3034
3033
3035 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3034 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3036
3035
3037 return listMeteors1
3036 return listMeteors1
3038
3037
3039 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3038 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3040 numHeights = volts.shape[2]
3039 numHeights = volts.shape[2]
3041 nChannel = volts.shape[0]
3040 nChannel = volts.shape[0]
3042
3041
3043 thresholdPhase = thresh[0]
3042 thresholdPhase = thresh[0]
3044 thresholdNoise = thresh[1]
3043 thresholdNoise = thresh[1]
3045 thresholdDB = float(thresh[2])
3044 thresholdDB = float(thresh[2])
3046
3045
3047 thresholdDB1 = 10**(thresholdDB/10)
3046 thresholdDB1 = 10**(thresholdDB/10)
3048 pairsarray = numpy.array(pairslist)
3047 pairsarray = numpy.array(pairslist)
3049 indSides = pairsarray[:,1]
3048 indSides = pairsarray[:,1]
3050
3049
3051 pairslist1 = list(pairslist)
3050 pairslist1 = list(pairslist)
3052 pairslist1.append((0,1))
3051 pairslist1.append((0,1))
3053 pairslist1.append((3,4))
3052 pairslist1.append((3,4))
3054
3053
3055 listMeteors1 = []
3054 listMeteors1 = []
3056 listPowerSeries = []
3055 listPowerSeries = []
3057 listVoltageSeries = []
3056 listVoltageSeries = []
3058 #volts has the war data
3057 #volts has the war data
3059
3058
3060 if frequency == 30e6:
3059 if frequency == 30e6:
3061 timeLag = 45*10**-3
3060 timeLag = 45*10**-3
3062 else:
3061 else:
3063 timeLag = 15*10**-3
3062 timeLag = 15*10**-3
3064 lag = numpy.ceil(timeLag/timeInterval)
3063 lag = numpy.ceil(timeLag/timeInterval)
3065
3064
3066 for i in range(len(listMeteors)):
3065 for i in range(len(listMeteors)):
3067
3066
3068 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3067 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3069 meteorAux = numpy.zeros(16)
3068 meteorAux = numpy.zeros(16)
3070
3069
3071 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3070 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3072 mHeight = listMeteors[i][0]
3071 mHeight = listMeteors[i][0]
3073 mStart = listMeteors[i][1]
3072 mStart = listMeteors[i][1]
3074 mPeak = listMeteors[i][2]
3073 mPeak = listMeteors[i][2]
3075 mEnd = listMeteors[i][3]
3074 mEnd = listMeteors[i][3]
3076
3075
3077 #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
3078 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3077 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3079 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3078 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3080
3079
3081 #3.6. Phase Difference estimation
3080 #3.6. Phase Difference estimation
3082 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3081 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3083
3082
3084 #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
3085 #meteorVolts0.- all Channels, all Profiles
3084 #meteorVolts0.- all Channels, all Profiles
3086 meteorVolts0 = volts[:,:,mHeight]
3085 meteorVolts0 = volts[:,:,mHeight]
3087 meteorThresh = noise[:,mHeight]*thresholdNoise
3086 meteorThresh = noise[:,mHeight]*thresholdNoise
3088 meteorNoise = noise[:,mHeight]
3087 meteorNoise = noise[:,mHeight]
3089 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3088 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3090 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3089 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3091
3090
3092 #Times reestimation
3091 #Times reestimation
3093 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3092 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3094 if mStart1.size > 0:
3093 if mStart1.size > 0:
3095 mStart1 = mStart1[-1] + 1
3094 mStart1 = mStart1[-1] + 1
3096
3095
3097 else:
3096 else:
3098 mStart1 = mPeak
3097 mStart1 = mPeak
3099
3098
3100 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3099 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3101 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3100 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3102 if mEndDecayTime1.size == 0:
3101 if mEndDecayTime1.size == 0:
3103 mEndDecayTime1 = powerNet0.size
3102 mEndDecayTime1 = powerNet0.size
3104 else:
3103 else:
3105 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3104 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3106 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3105 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3107
3106
3108 #meteorVolts1.- all Channels, from start to end
3107 #meteorVolts1.- all Channels, from start to end
3109 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3108 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3110 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3109 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3111 if meteorVolts2.shape[1] == 0:
3110 if meteorVolts2.shape[1] == 0:
3112 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3111 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3113 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3112 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3114 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3113 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3115 ##################### END PARAMETERS REESTIMATION #########################
3114 ##################### END PARAMETERS REESTIMATION #########################
3116
3115
3117 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3116 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3118 # 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
3119 if meteorVolts2.shape[1] > 0:
3118 if meteorVolts2.shape[1] > 0:
3120 #Phase Difference re-estimation
3119 #Phase Difference re-estimation
3121 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3120 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3122 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3121 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3123 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3122 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3124 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3123 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3125 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3124 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3126
3125
3127 #Phase Difference RMS
3126 #Phase Difference RMS
3128 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3127 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3129 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3128 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3130 #Data from Meteor
3129 #Data from Meteor
3131 mPeak1 = powerNet1.argmax() + mStart1
3130 mPeak1 = powerNet1.argmax() + mStart1
3132 mPeakPower1 = powerNet1.max()
3131 mPeakPower1 = powerNet1.max()
3133 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3132 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3134 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3133 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3135 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3134 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3136 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3135 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3137 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3136 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3138 #Vectorize
3137 #Vectorize
3139 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3138 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3140 meteorAux[7:11] = phaseDiffint[0:4]
3139 meteorAux[7:11] = phaseDiffint[0:4]
3141
3140
3142 #Rejection Criterions
3141 #Rejection Criterions
3143 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3142 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3144 meteorAux[-1] = 17
3143 meteorAux[-1] = 17
3145 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3144 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3146 meteorAux[-1] = 1
3145 meteorAux[-1] = 1
3147
3146
3148
3147
3149 else:
3148 else:
3150 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3149 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3151 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
3152 PowerSeries = 0
3151 PowerSeries = 0
3153
3152
3154 listMeteors1.append(meteorAux)
3153 listMeteors1.append(meteorAux)
3155 listPowerSeries.append(PowerSeries)
3154 listPowerSeries.append(PowerSeries)
3156 listVoltageSeries.append(meteorVolts1)
3155 listVoltageSeries.append(meteorVolts1)
3157
3156
3158 return listMeteors1, listPowerSeries, listVoltageSeries
3157 return listMeteors1, listPowerSeries, listVoltageSeries
3159
3158
3160 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3159 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3161
3160
3162 threshError = 10
3161 threshError = 10
3163 #Depending if it is 30 or 50 MHz
3162 #Depending if it is 30 or 50 MHz
3164 if frequency == 30e6:
3163 if frequency == 30e6:
3165 timeLag = 45*10**-3
3164 timeLag = 45*10**-3
3166 else:
3165 else:
3167 timeLag = 15*10**-3
3166 timeLag = 15*10**-3
3168 lag = numpy.ceil(timeLag/timeInterval)
3167 lag = numpy.ceil(timeLag/timeInterval)
3169
3168
3170 listMeteors1 = []
3169 listMeteors1 = []
3171
3170
3172 for i in range(len(listMeteors)):
3171 for i in range(len(listMeteors)):
3173 meteorPower = listPower[i]
3172 meteorPower = listPower[i]
3174 meteorAux = listMeteors[i]
3173 meteorAux = listMeteors[i]
3175
3174
3176 if meteorAux[-1] == 0:
3175 if meteorAux[-1] == 0:
3177
3176
3178 try:
3177 try:
3179 indmax = meteorPower.argmax()
3178 indmax = meteorPower.argmax()
3180 indlag = indmax + lag
3179 indlag = indmax + lag
3181
3180
3182 y = meteorPower[indlag:]
3181 y = meteorPower[indlag:]
3183 x = numpy.arange(0, y.size)*timeLag
3182 x = numpy.arange(0, y.size)*timeLag
3184
3183
3185 #first guess
3184 #first guess
3186 a = y[0]
3185 a = y[0]
3187 tau = timeLag
3186 tau = timeLag
3188 #exponential fit
3187 #exponential fit
3189 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])
3190 y1 = self.__exponential_function(x, *popt)
3189 y1 = self.__exponential_function(x, *popt)
3191 #error estimation
3190 #error estimation
3192 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))
3193
3192
3194 decayTime = popt[1]
3193 decayTime = popt[1]
3195 riseTime = indmax*timeInterval
3194 riseTime = indmax*timeInterval
3196 meteorAux[11:13] = [decayTime, error]
3195 meteorAux[11:13] = [decayTime, error]
3197
3196
3198 #Table items 7, 8 and 11
3197 #Table items 7, 8 and 11
3199 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3198 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3200 meteorAux[-1] = 7
3199 meteorAux[-1] = 7
3201 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
3202 meteorAux[-1] = 8
3201 meteorAux[-1] = 8
3203 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
3204 meteorAux[-1] = 11
3203 meteorAux[-1] = 11
3205
3204
3206
3205
3207 except:
3206 except:
3208 meteorAux[-1] = 11
3207 meteorAux[-1] = 11
3209
3208
3210
3209
3211 listMeteors1.append(meteorAux)
3210 listMeteors1.append(meteorAux)
3212
3211
3213 return listMeteors1
3212 return listMeteors1
3214
3213
3215 #Exponential Function
3214 #Exponential Function
3216
3215
3217 def __exponential_function(self, x, a, tau):
3216 def __exponential_function(self, x, a, tau):
3218 y = a*numpy.exp(-x/tau)
3217 y = a*numpy.exp(-x/tau)
3219 return y
3218 return y
3220
3219
3221 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3220 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3222
3221
3223 pairslist1 = list(pairslist)
3222 pairslist1 = list(pairslist)
3224 pairslist1.append((0,1))
3223 pairslist1.append((0,1))
3225 pairslist1.append((3,4))
3224 pairslist1.append((3,4))
3226 numPairs = len(pairslist1)
3225 numPairs = len(pairslist1)
3227 #Time Lag
3226 #Time Lag
3228 timeLag = 45*10**-3
3227 timeLag = 45*10**-3
3229 c = 3e8
3228 c = 3e8
3230 lag = numpy.ceil(timeLag/timeInterval)
3229 lag = numpy.ceil(timeLag/timeInterval)
3231 freq = 30e6
3230 freq = 30e6
3232
3231
3233 listMeteors1 = []
3232 listMeteors1 = []
3234
3233
3235 for i in range(len(listMeteors)):
3234 for i in range(len(listMeteors)):
3236 meteorAux = listMeteors[i]
3235 meteorAux = listMeteors[i]
3237 if meteorAux[-1] == 0:
3236 if meteorAux[-1] == 0:
3238 mStart = listMeteors[i][1]
3237 mStart = listMeteors[i][1]
3239 mPeak = listMeteors[i][2]
3238 mPeak = listMeteors[i][2]
3240 mLag = mPeak - mStart + lag
3239 mLag = mPeak - mStart + lag
3241
3240
3242 #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
3243 meteorVolts = listVolts[i]
3242 meteorVolts = listVolts[i]
3244 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3243 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3245
3244
3246 #Get CCF
3245 #Get CCF
3247 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3246 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3248
3247
3249 #Method 2
3248 #Method 2
3250 slopes = numpy.zeros(numPairs)
3249 slopes = numpy.zeros(numPairs)
3251 time = numpy.array([-2,-1,1,2])*timeInterval
3250 time = numpy.array([-2,-1,1,2])*timeInterval
3252 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3251 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3253
3252
3254 #Correct phases
3253 #Correct phases
3255 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3254 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3256 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3255 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3257
3256
3258 if indDer[0].shape[0] > 0:
3257 if indDer[0].shape[0] > 0:
3259 for i in range(indDer[0].shape[0]):
3258 for i in range(indDer[0].shape[0]):
3260 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3259 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3261 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
3262
3261
3263 # 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]]))
3264 for j in range(numPairs):
3263 for j in range(numPairs):
3265 fit = stats.linregress(time, angAllCCF[j,:])
3264 fit = stats.linregress(time, angAllCCF[j,:])
3266 slopes[j] = fit[0]
3265 slopes[j] = fit[0]
3267
3266
3268 #Remove Outlier
3267 #Remove Outlier
3269 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3268 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3270 # slopes = numpy.delete(slopes,indOut)
3269 # slopes = numpy.delete(slopes,indOut)
3271 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3270 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3272 # slopes = numpy.delete(slopes,indOut)
3271 # slopes = numpy.delete(slopes,indOut)
3273
3272
3274 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3273 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3275 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3274 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3276 meteorAux[-2] = radialError
3275 meteorAux[-2] = radialError
3277 meteorAux[-3] = radialVelocity
3276 meteorAux[-3] = radialVelocity
3278
3277
3279 #Setting Error
3278 #Setting Error
3280 #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
3281 if numpy.abs(radialVelocity) > 200:
3280 if numpy.abs(radialVelocity) > 200:
3282 meteorAux[-1] = 15
3281 meteorAux[-1] = 15
3283 #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
3284 elif radialError > radialStdThresh:
3283 elif radialError > radialStdThresh:
3285 meteorAux[-1] = 12
3284 meteorAux[-1] = 12
3286
3285
3287 listMeteors1.append(meteorAux)
3286 listMeteors1.append(meteorAux)
3288 return listMeteors1
3287 return listMeteors1
3289
3288
3290 def __setNewArrays(self, listMeteors, date, heiRang):
3289 def __setNewArrays(self, listMeteors, date, heiRang):
3291
3290
3292 #New arrays
3291 #New arrays
3293 arrayMeteors = numpy.array(listMeteors)
3292 arrayMeteors = numpy.array(listMeteors)
3294 arrayParameters = numpy.zeros((len(listMeteors), 13))
3293 arrayParameters = numpy.zeros((len(listMeteors), 13))
3295
3294
3296 #Date inclusion
3295 #Date inclusion
3297 # date = re.findall(r'\((.*?)\)', date)
3296 # date = re.findall(r'\((.*?)\)', date)
3298 # date = date[0].split(',')
3297 # date = date[0].split(',')
3299 # date = map(int, date)
3298 # date = map(int, date)
3300 #
3299 #
3301 # if len(date)<6:
3300 # if len(date)<6:
3302 # date.append(0)
3301 # date.append(0)
3303 #
3302 #
3304 # 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]]
3305 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3304 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3306 arrayDate = numpy.tile(date, (len(listMeteors)))
3305 arrayDate = numpy.tile(date, (len(listMeteors)))
3307
3306
3308 #Meteor array
3307 #Meteor array
3309 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3308 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3310 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3309 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3311
3310
3312 #Parameters Array
3311 #Parameters Array
3313 arrayParameters[:,0] = arrayDate #Date
3312 arrayParameters[:,0] = arrayDate #Date
3314 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3313 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3315 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3314 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3316 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3315 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3317 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3316 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3318
3317
3319
3318
3320 return arrayParameters
3319 return arrayParameters
3321
3320
3322 class CorrectSMPhases(Operation):
3321 class CorrectSMPhases(Operation):
3323
3322
3324 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):
3325
3324
3326 arrayParameters = dataOut.data_param
3325 arrayParameters = dataOut.data_param
3327 pairsList = []
3326 pairsList = []
3328 pairx = (0,1)
3327 pairx = (0,1)
3329 pairy = (2,3)
3328 pairy = (2,3)
3330 pairsList.append(pairx)
3329 pairsList.append(pairx)
3331 pairsList.append(pairy)
3330 pairsList.append(pairy)
3332 jph = numpy.zeros(4)
3331 jph = numpy.zeros(4)
3333
3332
3334 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3333 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3335 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3334 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3336 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)))
3337
3336
3338 meteorOps = SMOperations()
3337 meteorOps = SMOperations()
3339 if channelPositions is None:
3338 if channelPositions is None:
3340 # 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
3341 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
3342
3341
3343 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3342 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3344 h = (hmin,hmax)
3343 h = (hmin,hmax)
3345
3344
3346 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3345 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3347
3346
3348 dataOut.data_param = arrayParameters
3347 dataOut.data_param = arrayParameters
3349 return
3348 return
3350
3349
3351 class SMPhaseCalibration(Operation):
3350 class SMPhaseCalibration(Operation):
3352
3351
3353 __buffer = None
3352 __buffer = None
3354
3353
3355 __initime = None
3354 __initime = None
3356
3355
3357 __dataReady = False
3356 __dataReady = False
3358
3357
3359 __isConfig = False
3358 __isConfig = False
3360
3359
3361 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3360 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3362
3361
3363 dataTime = currentTime + paramInterval
3362 dataTime = currentTime + paramInterval
3364 deltaTime = dataTime - initTime
3363 deltaTime = dataTime - initTime
3365
3364
3366 if deltaTime >= outputInterval or deltaTime < 0:
3365 if deltaTime >= outputInterval or deltaTime < 0:
3367 return True
3366 return True
3368
3367
3369 return False
3368 return False
3370
3369
3371 def __getGammas(self, pairs, d, phases):
3370 def __getGammas(self, pairs, d, phases):
3372 gammas = numpy.zeros(2)
3371 gammas = numpy.zeros(2)
3373
3372
3374 for i in range(len(pairs)):
3373 for i in range(len(pairs)):
3375
3374
3376 pairi = pairs[i]
3375 pairi = pairs[i]
3377
3376
3378 phip3 = phases[:,pairi[0]]
3377 phip3 = phases[:,pairi[0]]
3379 d3 = d[pairi[0]]
3378 d3 = d[pairi[0]]
3380 phip2 = phases[:,pairi[1]]
3379 phip2 = phases[:,pairi[1]]
3381 d2 = d[pairi[1]]
3380 d2 = d[pairi[1]]
3382 #Calculating gamma
3381 #Calculating gamma
3383 # jdcos = alp1/(k*d1)
3382 # jdcos = alp1/(k*d1)
3384 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3383 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3385 jgamma = -phip2*d3/d2 - phip3
3384 jgamma = -phip2*d3/d2 - phip3
3386 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3385 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3387 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3386 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3388 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3387 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3389
3388
3390 #Revised distribution
3389 #Revised distribution
3391 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))
3392
3391
3393 #Histogram
3392 #Histogram
3394 nBins = 64
3393 nBins = 64
3395 rmin = -0.5*numpy.pi
3394 rmin = -0.5*numpy.pi
3396 rmax = 0.5*numpy.pi
3395 rmax = 0.5*numpy.pi
3397 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3396 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3398
3397
3399 meteorsY = phaseHisto[0]
3398 meteorsY = phaseHisto[0]
3400 phasesX = phaseHisto[1][:-1]
3399 phasesX = phaseHisto[1][:-1]
3401 width = phasesX[1] - phasesX[0]
3400 width = phasesX[1] - phasesX[0]
3402 phasesX += width/2
3401 phasesX += width/2
3403
3402
3404 #Gaussian aproximation
3403 #Gaussian aproximation
3405 bpeak = meteorsY.argmax()
3404 bpeak = meteorsY.argmax()
3406 peak = meteorsY.max()
3405 peak = meteorsY.max()
3407 jmin = bpeak - 5
3406 jmin = bpeak - 5
3408 jmax = bpeak + 5 + 1
3407 jmax = bpeak + 5 + 1
3409
3408
3410 if jmin<0:
3409 if jmin<0:
3411 jmin = 0
3410 jmin = 0
3412 jmax = 6
3411 jmax = 6
3413 elif jmax > meteorsY.size:
3412 elif jmax > meteorsY.size:
3414 jmin = meteorsY.size - 6
3413 jmin = meteorsY.size - 6
3415 jmax = meteorsY.size
3414 jmax = meteorsY.size
3416
3415
3417 x0 = numpy.array([peak,bpeak,50])
3416 x0 = numpy.array([peak,bpeak,50])
3418 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]))
3419
3418
3420 #Gammas
3419 #Gammas
3421 gammas[i] = coeff[0][1]
3420 gammas[i] = coeff[0][1]
3422
3421
3423 return gammas
3422 return gammas
3424
3423
3425 def __residualFunction(self, coeffs, y, t):
3424 def __residualFunction(self, coeffs, y, t):
3426
3425
3427 return y - self.__gauss_function(t, coeffs)
3426 return y - self.__gauss_function(t, coeffs)
3428
3427
3429 def __gauss_function(self, t, coeffs):
3428 def __gauss_function(self, t, coeffs):
3430
3429
3431 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)
3432
3431
3433 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3432 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3434 meteorOps = SMOperations()
3433 meteorOps = SMOperations()
3435 nchan = 4
3434 nchan = 4
3436 pairx = pairsList[0] #x es 0
3435 pairx = pairsList[0] #x es 0
3437 pairy = pairsList[1] #y es 1
3436 pairy = pairsList[1] #y es 1
3438 center_xangle = 0
3437 center_xangle = 0
3439 center_yangle = 0
3438 center_yangle = 0
3440 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])
3441 ntimes = len(range_angle)
3440 ntimes = len(range_angle)
3442
3441
3443 nstepsx = 20
3442 nstepsx = 20
3444 nstepsy = 20
3443 nstepsy = 20
3445
3444
3446 for iz in range(ntimes):
3445 for iz in range(ntimes):
3447 min_xangle = -range_angle[iz]/2 + center_xangle
3446 min_xangle = -range_angle[iz]/2 + center_xangle
3448 max_xangle = range_angle[iz]/2 + center_xangle
3447 max_xangle = range_angle[iz]/2 + center_xangle
3449 min_yangle = -range_angle[iz]/2 + center_yangle
3448 min_yangle = -range_angle[iz]/2 + center_yangle
3450 max_yangle = range_angle[iz]/2 + center_yangle
3449 max_yangle = range_angle[iz]/2 + center_yangle
3451
3450
3452 inc_x = (max_xangle-min_xangle)/nstepsx
3451 inc_x = (max_xangle-min_xangle)/nstepsx
3453 inc_y = (max_yangle-min_yangle)/nstepsy
3452 inc_y = (max_yangle-min_yangle)/nstepsy
3454
3453
3455 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3454 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3456 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3455 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3457 penalty = numpy.zeros((nstepsx,nstepsy))
3456 penalty = numpy.zeros((nstepsx,nstepsy))
3458 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3457 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3459 jph = numpy.zeros(nchan)
3458 jph = numpy.zeros(nchan)
3460
3459
3461 # Iterations looking for the offset
3460 # Iterations looking for the offset
3462 for iy in range(int(nstepsy)):
3461 for iy in range(int(nstepsy)):
3463 for ix in range(int(nstepsx)):
3462 for ix in range(int(nstepsx)):
3464 d3 = d[pairsList[1][0]]
3463 d3 = d[pairsList[1][0]]
3465 d2 = d[pairsList[1][1]]
3464 d2 = d[pairsList[1][1]]
3466 d5 = d[pairsList[0][0]]
3465 d5 = d[pairsList[0][0]]
3467 d4 = d[pairsList[0][1]]
3466 d4 = d[pairsList[0][1]]
3468
3467
3469 alp2 = alpha_y[iy] #gamma 1
3468 alp2 = alpha_y[iy] #gamma 1
3470 alp4 = alpha_x[ix] #gamma 0
3469 alp4 = alpha_x[ix] #gamma 0
3471
3470
3472 alp3 = -alp2*d3/d2 - gammas[1]
3471 alp3 = -alp2*d3/d2 - gammas[1]
3473 alp5 = -alp4*d5/d4 - gammas[0]
3472 alp5 = -alp4*d5/d4 - gammas[0]
3474 # jph[pairy[1]] = alpha_y[iy]
3473 # jph[pairy[1]] = alpha_y[iy]
3475 # 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]]
3476
3475
3477 # jph[pairx[1]] = alpha_x[ix]
3476 # jph[pairx[1]] = alpha_x[ix]
3478 # 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]]
3479 jph[pairsList[0][1]] = alp4
3478 jph[pairsList[0][1]] = alp4
3480 jph[pairsList[0][0]] = alp5
3479 jph[pairsList[0][0]] = alp5
3481 jph[pairsList[1][0]] = alp3
3480 jph[pairsList[1][0]] = alp3
3482 jph[pairsList[1][1]] = alp2
3481 jph[pairsList[1][1]] = alp2
3483 jph_array[:,ix,iy] = jph
3482 jph_array[:,ix,iy] = jph
3484 # d = [2.0,2.5,2.5,2.0]
3483 # d = [2.0,2.5,2.5,2.0]
3485 #falta chequear si va a leer bien los meteoros
3484 #falta chequear si va a leer bien los meteoros
3486 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3485 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3487 error = meteorsArray1[:,-1]
3486 error = meteorsArray1[:,-1]
3488 ind1 = numpy.where(error==0)[0]
3487 ind1 = numpy.where(error==0)[0]
3489 penalty[ix,iy] = ind1.size
3488 penalty[ix,iy] = ind1.size
3490
3489
3491 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3490 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3492 phOffset = jph_array[:,i,j]
3491 phOffset = jph_array[:,i,j]
3493
3492
3494 center_xangle = phOffset[pairx[1]]
3493 center_xangle = phOffset[pairx[1]]
3495 center_yangle = phOffset[pairy[1]]
3494 center_yangle = phOffset[pairy[1]]
3496
3495
3497 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3496 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3498 phOffset = phOffset*180/numpy.pi
3497 phOffset = phOffset*180/numpy.pi
3499 return phOffset
3498 return phOffset
3500
3499
3501
3500
3502 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3501 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3503
3502
3504 dataOut.flagNoData = True
3503 dataOut.flagNoData = True
3505 self.__dataReady = False
3504 self.__dataReady = False
3506 dataOut.outputInterval = nHours*3600
3505 dataOut.outputInterval = nHours*3600
3507
3506
3508 if self.__isConfig == False:
3507 if self.__isConfig == False:
3509 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3508 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3510 #Get Initial LTC time
3509 #Get Initial LTC time
3511 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3510 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3512 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()
3513
3512
3514 self.__isConfig = True
3513 self.__isConfig = True
3515
3514
3516 if self.__buffer is None:
3515 if self.__buffer is None:
3517 self.__buffer = dataOut.data_param.copy()
3516 self.__buffer = dataOut.data_param.copy()
3518
3517
3519 else:
3518 else:
3520 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3519 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3521
3520
3522 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
3523
3522
3524 if self.__dataReady:
3523 if self.__dataReady:
3525 dataOut.utctimeInit = self.__initime
3524 dataOut.utctimeInit = self.__initime
3526 self.__initime += dataOut.outputInterval #to erase time offset
3525 self.__initime += dataOut.outputInterval #to erase time offset
3527
3526
3528 freq = dataOut.frequency
3527 freq = dataOut.frequency
3529 c = dataOut.C #m/s
3528 c = dataOut.C #m/s
3530 lamb = c/freq
3529 lamb = c/freq
3531 k = 2*numpy.pi/lamb
3530 k = 2*numpy.pi/lamb
3532 azimuth = 0
3531 azimuth = 0
3533 h = (hmin, hmax)
3532 h = (hmin, hmax)
3534 # pairs = ((0,1),(2,3)) #Estrella
3533 # pairs = ((0,1),(2,3)) #Estrella
3535 # pairs = ((1,0),(2,3)) #T
3534 # pairs = ((1,0),(2,3)) #T
3536
3535
3537 if channelPositions is None:
3536 if channelPositions is None:
3538 # 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
3539 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
3540 meteorOps = SMOperations()
3539 meteorOps = SMOperations()
3541 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3540 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3542
3541
3543 #Checking correct order of pairs
3542 #Checking correct order of pairs
3544 pairs = []
3543 pairs = []
3545 if distances[1] > distances[0]:
3544 if distances[1] > distances[0]:
3546 pairs.append((1,0))
3545 pairs.append((1,0))
3547 else:
3546 else:
3548 pairs.append((0,1))
3547 pairs.append((0,1))
3549
3548
3550 if distances[3] > distances[2]:
3549 if distances[3] > distances[2]:
3551 pairs.append((3,2))
3550 pairs.append((3,2))
3552 else:
3551 else:
3553 pairs.append((2,3))
3552 pairs.append((2,3))
3554 # 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]
3555
3554
3556 meteorsArray = self.__buffer
3555 meteorsArray = self.__buffer
3557 error = meteorsArray[:,-1]
3556 error = meteorsArray[:,-1]
3558 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3557 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3559 ind1 = numpy.where(boolError)[0]
3558 ind1 = numpy.where(boolError)[0]
3560 meteorsArray = meteorsArray[ind1,:]
3559 meteorsArray = meteorsArray[ind1,:]
3561 meteorsArray[:,-1] = 0
3560 meteorsArray[:,-1] = 0
3562 phases = meteorsArray[:,8:12]
3561 phases = meteorsArray[:,8:12]
3563
3562
3564 #Calculate Gammas
3563 #Calculate Gammas
3565 gammas = self.__getGammas(pairs, distances, phases)
3564 gammas = self.__getGammas(pairs, distances, phases)
3566 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3565 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3567 #Calculate Phases
3566 #Calculate Phases
3568 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3567 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3569 phasesOff = phasesOff.reshape((1,phasesOff.size))
3568 phasesOff = phasesOff.reshape((1,phasesOff.size))
3570 dataOut.data_output = -phasesOff
3569 dataOut.data_output = -phasesOff
3571 dataOut.flagNoData = False
3570 dataOut.flagNoData = False
3572 self.__buffer = None
3571 self.__buffer = None
3573
3572
3574
3573
3575 return
3574 return
3576
3575
3577 class SMOperations():
3576 class SMOperations():
3578
3577
3579 def __init__(self):
3578 def __init__(self):
3580
3579
3581 return
3580 return
3582
3581
3583 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3582 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3584
3583
3585 arrayParameters = arrayParameters0.copy()
3584 arrayParameters = arrayParameters0.copy()
3586 hmin = h[0]
3585 hmin = h[0]
3587 hmax = h[1]
3586 hmax = h[1]
3588
3587
3589 #Calculate AOA (Error N 3, 4)
3588 #Calculate AOA (Error N 3, 4)
3590 #JONES ET AL. 1998
3589 #JONES ET AL. 1998
3591 AOAthresh = numpy.pi/8
3590 AOAthresh = numpy.pi/8
3592 error = arrayParameters[:,-1]
3591 error = arrayParameters[:,-1]
3593 phases = -arrayParameters[:,8:12] + jph
3592 phases = -arrayParameters[:,8:12] + jph
3594 # phases = numpy.unwrap(phases)
3593 # phases = numpy.unwrap(phases)
3595 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)
3596
3595
3597 #Calculate Heights (Error N 13 and 14)
3596 #Calculate Heights (Error N 13 and 14)
3598 error = arrayParameters[:,-1]
3597 error = arrayParameters[:,-1]
3599 Ranges = arrayParameters[:,1]
3598 Ranges = arrayParameters[:,1]
3600 zenith = arrayParameters[:,4]
3599 zenith = arrayParameters[:,4]
3601 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3600 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3602
3601
3603 #----------------------- Get Final data ------------------------------------
3602 #----------------------- Get Final data ------------------------------------
3604 # error = arrayParameters[:,-1]
3603 # error = arrayParameters[:,-1]
3605 # ind1 = numpy.where(error==0)[0]
3604 # ind1 = numpy.where(error==0)[0]
3606 # arrayParameters = arrayParameters[ind1,:]
3605 # arrayParameters = arrayParameters[ind1,:]
3607
3606
3608 return arrayParameters
3607 return arrayParameters
3609
3608
3610 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3609 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3611
3610
3612 arrayAOA = numpy.zeros((phases.shape[0],3))
3611 arrayAOA = numpy.zeros((phases.shape[0],3))
3613 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3612 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3614
3613
3615 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3614 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3616 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3615 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3617 arrayAOA[:,2] = cosDirError
3616 arrayAOA[:,2] = cosDirError
3618
3617
3619 azimuthAngle = arrayAOA[:,0]
3618 azimuthAngle = arrayAOA[:,0]
3620 zenithAngle = arrayAOA[:,1]
3619 zenithAngle = arrayAOA[:,1]
3621
3620
3622 #Setting Error
3621 #Setting Error
3623 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3622 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3624 error[indError] = 0
3623 error[indError] = 0
3625 #Number 3: AOA not fesible
3624 #Number 3: AOA not fesible
3626 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]
3627 error[indInvalid] = 3
3626 error[indInvalid] = 3
3628 #Number 4: Large difference in AOAs obtained from different antenna baselines
3627 #Number 4: Large difference in AOAs obtained from different antenna baselines
3629 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3628 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3630 error[indInvalid] = 4
3629 error[indInvalid] = 4
3631 return arrayAOA, error
3630 return arrayAOA, error
3632
3631
3633 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3632 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3634
3633
3635 #Initializing some variables
3634 #Initializing some variables
3636 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
3637 ang_aux = ang_aux.reshape(1,ang_aux.size)
3636 ang_aux = ang_aux.reshape(1,ang_aux.size)
3638
3637
3639 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3638 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3640 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3639 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3641
3640
3642
3641
3643 for i in range(2):
3642 for i in range(2):
3644 ph0 = arrayPhase[:,pairsList[i][0]]
3643 ph0 = arrayPhase[:,pairsList[i][0]]
3645 ph1 = arrayPhase[:,pairsList[i][1]]
3644 ph1 = arrayPhase[:,pairsList[i][1]]
3646 d0 = distances[pairsList[i][0]]
3645 d0 = distances[pairsList[i][0]]
3647 d1 = distances[pairsList[i][1]]
3646 d1 = distances[pairsList[i][1]]
3648
3647
3649 ph0_aux = ph0 + ph1
3648 ph0_aux = ph0 + ph1
3650 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3649 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3651 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3650 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3652 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3651 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3653 #First Estimation
3652 #First Estimation
3654 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3653 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3655
3654
3656 #Most-Accurate Second Estimation
3655 #Most-Accurate Second Estimation
3657 phi1_aux = ph0 - ph1
3656 phi1_aux = ph0 - ph1
3658 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3657 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3659 #Direction Cosine 1
3658 #Direction Cosine 1
3660 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3659 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3661
3660
3662 #Searching the correct Direction Cosine
3661 #Searching the correct Direction Cosine
3663 cosdir0_aux = cosdir0[:,i]
3662 cosdir0_aux = cosdir0[:,i]
3664 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3663 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3665 #Minimum Distance
3664 #Minimum Distance
3666 cosDiff = (cosdir1 - cosdir0_aux)**2
3665 cosDiff = (cosdir1 - cosdir0_aux)**2
3667 indcos = cosDiff.argmin(axis = 1)
3666 indcos = cosDiff.argmin(axis = 1)
3668 #Saving Value obtained
3667 #Saving Value obtained
3669 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3668 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3670
3669
3671 return cosdir0, cosdir
3670 return cosdir0, cosdir
3672
3671
3673 def __calculateAOA(self, cosdir, azimuth):
3672 def __calculateAOA(self, cosdir, azimuth):
3674 cosdirX = cosdir[:,0]
3673 cosdirX = cosdir[:,0]
3675 cosdirY = cosdir[:,1]
3674 cosdirY = cosdir[:,1]
3676
3675
3677 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
3678 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
3679 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3678 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3680
3679
3681 return angles
3680 return angles
3682
3681
3683 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3682 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3684
3683
3685 Ramb = 375 #Ramb = c/(2*PRF)
3684 Ramb = 375 #Ramb = c/(2*PRF)
3686 Re = 6371 #Earth Radius
3685 Re = 6371 #Earth Radius
3687 heights = numpy.zeros(Ranges.shape)
3686 heights = numpy.zeros(Ranges.shape)
3688
3687
3689 R_aux = numpy.array([0,1,2])*Ramb
3688 R_aux = numpy.array([0,1,2])*Ramb
3690 R_aux = R_aux.reshape(1,R_aux.size)
3689 R_aux = R_aux.reshape(1,R_aux.size)
3691
3690
3692 Ranges = Ranges.reshape(Ranges.size,1)
3691 Ranges = Ranges.reshape(Ranges.size,1)
3693
3692
3694 Ri = Ranges + R_aux
3693 Ri = Ranges + R_aux
3695 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
3696
3695
3697 #Check if there is a height between 70 and 110 km
3696 #Check if there is a height between 70 and 110 km
3698 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)
3699 ind_h = numpy.where(h_bool == 1)[0]
3698 ind_h = numpy.where(h_bool == 1)[0]
3700
3699
3701 hCorr = hi[ind_h, :]
3700 hCorr = hi[ind_h, :]
3702 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3701 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3703
3702
3704 hCorr = hi[ind_hCorr][:len(ind_h)]
3703 hCorr = hi[ind_hCorr][:len(ind_h)]
3705 heights[ind_h] = hCorr
3704 heights[ind_h] = hCorr
3706
3705
3707 #Setting Error
3706 #Setting Error
3708 #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
3709 #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
3710 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3709 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3711 error[indError] = 0
3710 error[indError] = 0
3712 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]
3713 error[indInvalid2] = 14
3712 error[indInvalid2] = 14
3714 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]
3715 error[indInvalid1] = 13
3714 error[indInvalid1] = 13
3716
3715
3717 return heights, error
3716 return heights, error
3718
3717
3719 def getPhasePairs(self, channelPositions):
3718 def getPhasePairs(self, channelPositions):
3720 chanPos = numpy.array(channelPositions)
3719 chanPos = numpy.array(channelPositions)
3721 listOper = list(itertools.combinations(list(range(5)),2))
3720 listOper = list(itertools.combinations(list(range(5)),2))
3722
3721
3723 distances = numpy.zeros(4)
3722 distances = numpy.zeros(4)
3724 axisX = []
3723 axisX = []
3725 axisY = []
3724 axisY = []
3726 distX = numpy.zeros(3)
3725 distX = numpy.zeros(3)
3727 distY = numpy.zeros(3)
3726 distY = numpy.zeros(3)
3728 ix = 0
3727 ix = 0
3729 iy = 0
3728 iy = 0
3730
3729
3731 pairX = numpy.zeros((2,2))
3730 pairX = numpy.zeros((2,2))
3732 pairY = numpy.zeros((2,2))
3731 pairY = numpy.zeros((2,2))
3733
3732
3734 for i in range(len(listOper)):
3733 for i in range(len(listOper)):
3735 pairi = listOper[i]
3734 pairi = listOper[i]
3736
3735
3737 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3736 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3738
3737
3739 if posDif[0] == 0:
3738 if posDif[0] == 0:
3740 axisY.append(pairi)
3739 axisY.append(pairi)
3741 distY[iy] = posDif[1]
3740 distY[iy] = posDif[1]
3742 iy += 1
3741 iy += 1
3743 elif posDif[1] == 0:
3742 elif posDif[1] == 0:
3744 axisX.append(pairi)
3743 axisX.append(pairi)
3745 distX[ix] = posDif[0]
3744 distX[ix] = posDif[0]
3746 ix += 1
3745 ix += 1
3747
3746
3748 for i in range(2):
3747 for i in range(2):
3749 if i==0:
3748 if i==0:
3750 dist0 = distX
3749 dist0 = distX
3751 axis0 = axisX
3750 axis0 = axisX
3752 else:
3751 else:
3753 dist0 = distY
3752 dist0 = distY
3754 axis0 = axisY
3753 axis0 = axisY
3755
3754
3756 side = numpy.argsort(dist0)[:-1]
3755 side = numpy.argsort(dist0)[:-1]
3757 axis0 = numpy.array(axis0)[side,:]
3756 axis0 = numpy.array(axis0)[side,:]
3758 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3757 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3759 axis1 = numpy.unique(numpy.reshape(axis0,4))
3758 axis1 = numpy.unique(numpy.reshape(axis0,4))
3760 side = axis1[axis1 != chanC]
3759 side = axis1[axis1 != chanC]
3761 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3760 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3762 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3761 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3763 if diff1<0:
3762 if diff1<0:
3764 chan2 = side[0]
3763 chan2 = side[0]
3765 d2 = numpy.abs(diff1)
3764 d2 = numpy.abs(diff1)
3766 chan1 = side[1]
3765 chan1 = side[1]
3767 d1 = numpy.abs(diff2)
3766 d1 = numpy.abs(diff2)
3768 else:
3767 else:
3769 chan2 = side[1]
3768 chan2 = side[1]
3770 d2 = numpy.abs(diff2)
3769 d2 = numpy.abs(diff2)
3771 chan1 = side[0]
3770 chan1 = side[0]
3772 d1 = numpy.abs(diff1)
3771 d1 = numpy.abs(diff1)
3773
3772
3774 if i==0:
3773 if i==0:
3775 chanCX = chanC
3774 chanCX = chanC
3776 chan1X = chan1
3775 chan1X = chan1
3777 chan2X = chan2
3776 chan2X = chan2
3778 distances[0:2] = numpy.array([d1,d2])
3777 distances[0:2] = numpy.array([d1,d2])
3779 else:
3778 else:
3780 chanCY = chanC
3779 chanCY = chanC
3781 chan1Y = chan1
3780 chan1Y = chan1
3782 chan2Y = chan2
3781 chan2Y = chan2
3783 distances[2:4] = numpy.array([d1,d2])
3782 distances[2:4] = numpy.array([d1,d2])
3784 # axisXsides = numpy.reshape(axisX[ix,:],4)
3783 # axisXsides = numpy.reshape(axisX[ix,:],4)
3785 #
3784 #
3786 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3785 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3787 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3786 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3788 #
3787 #
3789 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3788 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3790 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3789 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3791 # channel25X = int(pairX[0,ind25X])
3790 # channel25X = int(pairX[0,ind25X])
3792 # channel20X = int(pairX[1,ind20X])
3791 # channel20X = int(pairX[1,ind20X])
3793 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3792 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3794 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3793 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3795 # channel25Y = int(pairY[0,ind25Y])
3794 # channel25Y = int(pairY[0,ind25Y])
3796 # channel20Y = int(pairY[1,ind20Y])
3795 # channel20Y = int(pairY[1,ind20Y])
3797
3796
3798 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3797 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3799 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3798 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3800
3799
3801 return pairslist, distances
3800 return pairslist, distances
3802 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3801 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3803 #
3802 #
3804 # arrayAOA = numpy.zeros((phases.shape[0],3))
3803 # arrayAOA = numpy.zeros((phases.shape[0],3))
3805 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3804 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3806 #
3805 #
3807 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3806 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3808 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3807 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3809 # arrayAOA[:,2] = cosDirError
3808 # arrayAOA[:,2] = cosDirError
3810 #
3809 #
3811 # azimuthAngle = arrayAOA[:,0]
3810 # azimuthAngle = arrayAOA[:,0]
3812 # zenithAngle = arrayAOA[:,1]
3811 # zenithAngle = arrayAOA[:,1]
3813 #
3812 #
3814 # #Setting Error
3813 # #Setting Error
3815 # #Number 3: AOA not fesible
3814 # #Number 3: AOA not fesible
3816 # 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]
3817 # error[indInvalid] = 3
3816 # error[indInvalid] = 3
3818 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3817 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3819 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3818 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3820 # error[indInvalid] = 4
3819 # error[indInvalid] = 4
3821 # return arrayAOA, error
3820 # return arrayAOA, error
3822 #
3821 #
3823 # def __getDirectionCosines(self, arrayPhase, pairsList):
3822 # def __getDirectionCosines(self, arrayPhase, pairsList):
3824 #
3823 #
3825 # #Initializing some variables
3824 # #Initializing some variables
3826 # 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
3827 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3826 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3828 #
3827 #
3829 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3828 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3830 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3829 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3831 #
3830 #
3832 #
3831 #
3833 # for i in range(2):
3832 # for i in range(2):
3834 # #First Estimation
3833 # #First Estimation
3835 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3834 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3836 # #Dealias
3835 # #Dealias
3837 # indcsi = numpy.where(phi0_aux > numpy.pi)
3836 # indcsi = numpy.where(phi0_aux > numpy.pi)
3838 # phi0_aux[indcsi] -= 2*numpy.pi
3837 # phi0_aux[indcsi] -= 2*numpy.pi
3839 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3838 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3840 # phi0_aux[indcsi] += 2*numpy.pi
3839 # phi0_aux[indcsi] += 2*numpy.pi
3841 # #Direction Cosine 0
3840 # #Direction Cosine 0
3842 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3841 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3843 #
3842 #
3844 # #Most-Accurate Second Estimation
3843 # #Most-Accurate Second Estimation
3845 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3844 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3846 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3845 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3847 # #Direction Cosine 1
3846 # #Direction Cosine 1
3848 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3847 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3849 #
3848 #
3850 # #Searching the correct Direction Cosine
3849 # #Searching the correct Direction Cosine
3851 # cosdir0_aux = cosdir0[:,i]
3850 # cosdir0_aux = cosdir0[:,i]
3852 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3851 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3853 # #Minimum Distance
3852 # #Minimum Distance
3854 # cosDiff = (cosdir1 - cosdir0_aux)**2
3853 # cosDiff = (cosdir1 - cosdir0_aux)**2
3855 # indcos = cosDiff.argmin(axis = 1)
3854 # indcos = cosDiff.argmin(axis = 1)
3856 # #Saving Value obtained
3855 # #Saving Value obtained
3857 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3856 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3858 #
3857 #
3859 # return cosdir0, cosdir
3858 # return cosdir0, cosdir
3860 #
3859 #
3861 # def __calculateAOA(self, cosdir, azimuth):
3860 # def __calculateAOA(self, cosdir, azimuth):
3862 # cosdirX = cosdir[:,0]
3861 # cosdirX = cosdir[:,0]
3863 # cosdirY = cosdir[:,1]
3862 # cosdirY = cosdir[:,1]
3864 #
3863 #
3865 # 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
3866 # 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
3867 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3866 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3868 #
3867 #
3869 # return angles
3868 # return angles
3870 #
3869 #
3871 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3870 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3872 #
3871 #
3873 # Ramb = 375 #Ramb = c/(2*PRF)
3872 # Ramb = 375 #Ramb = c/(2*PRF)
3874 # Re = 6371 #Earth Radius
3873 # Re = 6371 #Earth Radius
3875 # heights = numpy.zeros(Ranges.shape)
3874 # heights = numpy.zeros(Ranges.shape)
3876 #
3875 #
3877 # R_aux = numpy.array([0,1,2])*Ramb
3876 # R_aux = numpy.array([0,1,2])*Ramb
3878 # R_aux = R_aux.reshape(1,R_aux.size)
3877 # R_aux = R_aux.reshape(1,R_aux.size)
3879 #
3878 #
3880 # Ranges = Ranges.reshape(Ranges.size,1)
3879 # Ranges = Ranges.reshape(Ranges.size,1)
3881 #
3880 #
3882 # Ri = Ranges + R_aux
3881 # Ri = Ranges + R_aux
3883 # 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
3884 #
3883 #
3885 # #Check if there is a height between 70 and 110 km
3884 # #Check if there is a height between 70 and 110 km
3886 # 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)
3887 # ind_h = numpy.where(h_bool == 1)[0]
3886 # ind_h = numpy.where(h_bool == 1)[0]
3888 #
3887 #
3889 # hCorr = hi[ind_h, :]
3888 # hCorr = hi[ind_h, :]
3890 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3889 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3891 #
3890 #
3892 # hCorr = hi[ind_hCorr]
3891 # hCorr = hi[ind_hCorr]
3893 # heights[ind_h] = hCorr
3892 # heights[ind_h] = hCorr
3894 #
3893 #
3895 # #Setting Error
3894 # #Setting Error
3896 # #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
3897 # #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
3898 #
3897 #
3899 # 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]
3900 # error[indInvalid2] = 14
3899 # error[indInvalid2] = 14
3901 # 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]
3902 # error[indInvalid1] = 13
3901 # error[indInvalid1] = 13
3903 #
3902 #
3904 # return heights, error
3903 # return heights, error
3905
3904
3906
3905
3907 class WeatherRadar(Operation):
3906 class WeatherRadar(Operation):
3908 '''
3907 '''
3909 Function tat implements Weather Radar operations-
3908 Function tat implements Weather Radar operations-
3910 Input:
3909 Input:
3911 Output:
3910 Output:
3912 Parameters affected:
3911 Parameters affected:
3913 '''
3912 '''
3914 isConfig = False
3913 isConfig = False
3915
3914
3916 def __init__(self):
3915 def __init__(self):
3917 Operation.__init__(self)
3916 Operation.__init__(self)
3918
3917
3919 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,
3920 tauW= 0,thetaT=0,thetaR=0,Km =0):
3919 tauW= 0,thetaT=0,thetaR=0,Km =0):
3921 self.nCh = dataOut.nChannels
3920 self.nCh = dataOut.nChannels
3922 self.nHeis = dataOut.nHeights
3921 self.nHeis = dataOut.nHeights
3923 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3922 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3924 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3923 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]
3925 self.Range = self.Range.reshape(1,self.nHeis)
3924 self.Range = self.Range.reshape(1,self.nHeis)
3926 self.Range = numpy.tile(self.Range,[self.nCh,1])
3925 self.Range = numpy.tile(self.Range,[self.nCh,1])
3927 '''-----------1 Constante del Radar----------'''
3926 '''-----------1 Constante del Radar----------'''
3928 self.Pt = Pt
3927 self.Pt = Pt
3929 self.Gt = Gt
3928 self.Gt = Gt
3930 self.Gr = Gr
3929 self.Gr = Gr
3931 self.lambda_ = lambda_
3930 self.lambda_ = lambda_
3932 self.aL = aL
3931 self.aL = aL
3933 self.tauW = tauW
3932 self.tauW = tauW
3934 self.thetaT = thetaT
3933 self.thetaT = thetaT
3935 self.thetaR = thetaR
3934 self.thetaR = thetaR
3936 self.Km = Km
3935 self.Km = Km
3937 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3936 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2))
3938 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)
3939 self.RadarConstant = Numerator/Denominator
3938 self.RadarConstant = Numerator/Denominator
3940 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3939 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
3941 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3940 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3942 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3941 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3943
3942
3944 def setMoments(self,dataOut,i):
3943 def setMoments(self,dataOut,i):
3945
3944
3946 type = dataOut.inputUnit
3945 type = dataOut.inputUnit
3947 nCh = dataOut.nChannels
3946 nCh = dataOut.nChannels
3948 nHeis= dataOut.nHeights
3947 nHeis= dataOut.nHeights
3949 data_param = numpy.zeros((nCh,4,nHeis))
3948 data_param = numpy.zeros((nCh,4,nHeis))
3950 if type == "Voltage":
3949 if type == "Voltage":
3951 data_param[:,0,:] = dataOut.dataPP_POW/(dataOut.nCohInt**2)
3950 data_param[:,0,:] = dataOut.dataPP_POW/(dataOut.nCohInt**2)
3952 data_param[:,1,:] = dataOut.dataPP_DOP
3951 data_param[:,1,:] = dataOut.dataPP_DOP
3953 data_param[:,2,:] = dataOut.dataPP_WIDTH
3952 data_param[:,2,:] = dataOut.dataPP_WIDTH
3954 data_param[:,3,:] = dataOut.dataPP_SNR
3953 data_param[:,3,:] = dataOut.dataPP_SNR
3955 if type == "Spectra":
3954 if type == "Spectra":
3956 data_param[:,0,:] = dataOut.data_POW
3955 data_param[:,0,:] = dataOut.data_POW
3957 data_param[:,1,:] = dataOut.data_DOP
3956 data_param[:,1,:] = dataOut.data_DOP
3958 data_param[:,2,:] = dataOut.data_WIDTH
3957 data_param[:,2,:] = dataOut.data_WIDTH
3959 def setMoments(self,dataOut,i):
3958 def setMoments(self,dataOut,i):
3960 data_param[:,3,:] = dataOut.data_SNR
3959 data_param[:,3,:] = dataOut.data_SNR
3961
3960
3962 return data_param[:,i,:]
3961 return data_param[:,i,:]
3963
3962
3964
3963
3965 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,
3966 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):
3967
3966
3968 if not self.isConfig:
3967 if not self.isConfig:
3969 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,
3970 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)
3971 self.isConfig = True
3970 self.isConfig = True
3972 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3971 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
3973 Pr = self.setMoments(dataOut,0)
3972 Pr = self.setMoments(dataOut,0)
3974
3973
3975 for R in range(self.nHeis):
3974 for R in range(self.nHeis):
3976 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
3977
3976
3978 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)
3979
3978
3980 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3979 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
3981 Zeh = self.Z_radar
3980 Zeh = self.Z_radar
3982 dBZeh = 10*numpy.log10(Zeh)
3981 dBZeh = 10*numpy.log10(Zeh)
3983 dataOut.factor_Zeh= dBZeh
3982 dataOut.factor_Zeh= dBZeh
3984 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3983 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
3985 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3984 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
3986
3985
3987 return dataOut
3986 return dataOut
3988
3987
3989 class PedestalInformation(Operation):
3988 class PedestalInformation(Operation):
3990 path_ped = None
3989 path_ped = None
3991 path_adq = None
3990 path_adq = None
3992 t_Interval_p = None
3991 t_Interval_p = None
3993 n_Muestras_p = None
3992 n_Muestras_p = None
3994 isConfig = False
3993 isConfig = False
3995 blocksPerfile= None
3994 blocksPerfile= None
3996 f_a_p = None
3995 f_a_p = None
3997 online = None
3996 online = None
3998 angulo_adq = None
3997 angulo_adq = None
3999 nro_file = None
3998 nro_file = None
4000 nro_key_p = None
3999 nro_key_p = None
4001 tmp = None
4000 tmp = None
4002
4001
4003
4002
4004 def __init__(self):
4003 def __init__(self):
4005 Operation.__init__(self)
4004 Operation.__init__(self)
4006
4005
4007 def getfirstFilefromPath(self,path,meta,ext):
4006 def getfirstFilefromPath(self,path,meta,ext):
4008 validFilelist = []
4007 validFilelist = []
4009 #print("SEARH",path)
4008 #print("SEARH",path)
4010 try:
4009 try:
4011 fileList = os.listdir(path)
4010 fileList = os.listdir(path)
4012 except:
4011 except:
4013 print("check path - fileList")
4012 print("check path - fileList")
4014 if len(fileList)<1:
4013 if len(fileList)<1:
4015 return None
4014 return None
4016 # meta 1234 567 8-18 BCDE
4015 # meta 1234 567 8-18 BCDE
4017 # H,D,PE YYYY DDD EPOC .ext
4016 # H,D,PE YYYY DDD EPOC .ext
4018
4017
4019 for thisFile in fileList:
4018 for thisFile in fileList:
4020 #print("HI",thisFile)
4019 #print("HI",thisFile)
4021 if meta =="PE":
4020 if meta =="PE":
4022 try:
4021 try:
4023 number= int(thisFile[len(meta)+7:len(meta)+17])
4022 number= int(thisFile[len(meta)+7:len(meta)+17])
4024 except:
4023 except:
4025 print("There is a file or folder with different format")
4024 print("There is a file or folder with different format")
4026 if meta == "D":
4025 if meta == "D":
4027 try:
4026 try:
4028 number= int(thisFile[8:11])
4027 number= int(thisFile[8:11])
4029 except:
4028 except:
4030 print("There is a file or folder with different format")
4029 print("There is a file or folder with different format")
4031
4030
4032 if not isNumber(str=number):
4031 if not isNumber(str=number):
4033 continue
4032 continue
4034 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4033 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
4035 continue
4034 continue
4036 validFilelist.sort()
4035 validFilelist.sort()
4037 validFilelist.append(thisFile)
4036 validFilelist.append(thisFile)
4038 if len(validFilelist)>0:
4037 if len(validFilelist)>0:
4039 validFilelist = sorted(validFilelist,key=str.lower)
4038 validFilelist = sorted(validFilelist,key=str.lower)
4040 return validFilelist
4039 return validFilelist
4041 return None
4040 return None
4042
4041
4043 def gettimeutcfromDirFilename(self,path,file):
4042 def gettimeutcfromDirFilename(self,path,file):
4044 dir_file= path+"/"+file
4043 dir_file= path+"/"+file
4045 fp = h5py.File(dir_file,'r')
4044 fp = h5py.File(dir_file,'r')
4046 #epoc = fp['Metadata'].get('utctimeInit')[()]
4045 #epoc = fp['Metadata'].get('utctimeInit')[()]
4047 epoc = fp['Data'].get('utc')[()]
4046 epoc = fp['Data'].get('utc')[()]
4048 fp.close()
4047 fp.close()
4049 return epoc
4048 return epoc
4050
4049
4051 def gettimeutcadqfromDirFilename(self,path,file):
4050 def gettimeutcadqfromDirFilename(self,path,file):
4052 dir_file= path+"/"+file
4051 dir_file= path+"/"+file
4053 fp = h5py.File(dir_file,'r')
4052 fp = h5py.File(dir_file,'r')
4054 epoc = fp['Metadata'].get('utctimeInit')[()]
4053 epoc = fp['Metadata'].get('utctimeInit')[()]
4055 #epoc = fp['Data'].get('utc')[()]
4054 #epoc = fp['Data'].get('utc')[()]
4056 fp.close()
4055 fp.close()
4057 return epoc
4056 return epoc
4058
4057
4059 def getDatavaluefromDirFilename(self,path,file,value):
4058 def getDatavaluefromDirFilename(self,path,file,value):
4060 dir_file= path+"/"+file
4059 dir_file= path+"/"+file
4061 fp = h5py.File(dir_file,'r')
4060 fp = h5py.File(dir_file,'r')
4062 array = fp['Data'].get(value)[()]
4061 array = fp['Data'].get(value)[()]
4063 fp.close()
4062 fp.close()
4064 return array
4063 return array
4065
4064
4066 def getFile_KeyP(self,list_pedestal,list_adq):
4065 def getFile_KeyP(self,list_pedestal,list_adq):
4067 print(list_pedestal)
4066 print(list_pedestal)
4068 print(list_adq)
4067 print(list_adq)
4069
4068
4070 def getNROFile(self,utc_adq,utc_ped_list):
4069 def getNROFile(self,utc_adq,utc_ped_list):
4071 c=0
4070 c=0
4072 print("insidegetNROFile")
4071 print("insidegetNROFile")
4073 print(utc_adq)
4072 print(utc_adq)
4074 print(len(utc_ped_list))
4073 print(len(utc_ped_list))
4075 for i in range(len(utc_ped_list)):
4074 for i in range(len(utc_ped_list)):
4076 if utc_adq>utc_ped_list[i]:
4075 if utc_adq>utc_ped_list[i]:
4077 #print("mayor")
4076 #print("mayor")
4078 #print("utc_ped_list",utc_ped_list[i])
4077 #print("utc_ped_list",utc_ped_list[i])
4079 c +=1
4078 c +=1
4080
4079
4081 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]
4082
4081
4083 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):
4084 var =int(f_a_p/n_Muestras_p)
4083 var =int(f_a_p/n_Muestras_p)
4085 flag=0
4084 flag=0
4086 for i in range(var):
4085 for i in range(var):
4087 if dataOut.utctime+i==utc_ped:
4086 if dataOut.utctime+i==utc_ped:
4088 flag==1
4087 flag==1
4089 break
4088 break
4090 return flag
4089 return flag
4091
4090
4092 #def setup_offline(self,dataOut,list_pedestal,list_adq):
4091 #def setup_offline(self,dataOut,list_pedestal,list_adq):
4093 def setup_offline(self,dataOut,list_pedestal):
4092 def setup_offline(self,dataOut,list_pedestal):
4094
4093
4095 print("SETUP OFFLINE")
4094 print("SETUP OFFLINE")
4096 print(self.path_ped)
4095 print(self.path_ped)
4097 #print(self.path_adq)
4096 #print(self.path_adq)
4098 print(len(self.list_pedestal))
4097 print(len(self.list_pedestal))
4099 #print(len(self.list_adq))
4098 #print(len(self.list_adq))
4100 utc_ped_list=[]
4099 utc_ped_list=[]
4101 for i in range(len(self.list_pedestal)):
4100 for i in range(len(self.list_pedestal)):
4102 print(i)
4101 #print(i)# OJO IDENTIFICADOR DE SINCRONISMO
4103 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]))
4104
4103
4105 #utc_ped_list= utc_ped_list
4104 #utc_ped_list= utc_ped_list
4106 ###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])
4107 print("dios existe donde esta")
4106 print("dios existe donde esta")
4108
4107
4109 #print("utc_ped_list",utc_ped_list)
4108 #print("utc_ped_list",utc_ped_list)
4110 ###print("utc_adq",utc_adq)
4109 ###print("utc_adq",utc_adq)
4111 # utc_adq_dataOut
4110 # utc_adq_dataOut
4112 utc_adq_dataOut =dataOut.utctime
4111 utc_adq_dataOut =dataOut.utctime
4113 print("Offline-utc_adq_dataout",utc_adq_dataOut)
4112 print("Offline-utc_adq_dataout",utc_adq_dataOut)
4114
4113
4115 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)
4116
4115
4117 print("nro_file",nro_file,"utc_ped",utc_ped)
4116 print("nro_file",nro_file,"utc_ped",utc_ped)
4118 print("nro_file",i)
4117 print("nro_file",i)
4119 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
4120 print("nro_key_p",nro_key_p)
4119 print("nro_key_p",nro_key_p)
4121
4120
4122 ff_pedestal = self.list_pedestal[nro_file]
4121 ff_pedestal = self.list_pedestal[nro_file]
4123 #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")
4124 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")
4125
4124
4126 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)
4127 print("angulo_array :",angulo[nro_key_p])
4126 print("angulo_array :",angulo[nro_key_p])
4128 self.nro_file = nro_file
4127 self.nro_file = nro_file
4129 self.nro_key_p = nro_key_p
4128 self.nro_key_p = nro_key_p
4130
4129
4131 def setup_online(self,dataOut):
4130 def setup_online(self,dataOut):
4132 utc_adq =dataOut.utctime
4131 utc_adq =dataOut.utctime
4133 print("Online-utc_adq",utc_adq)
4132 print("Online-utc_adq",utc_adq)
4134 print(len(self.list_pedestal))
4133 print(len(self.list_pedestal))
4135 utc_ped_list=[]
4134 utc_ped_list=[]
4136 for i in range(len(self.list_pedestal)):
4135 for i in range(len(self.list_pedestal)):
4137 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]))
4138 print(utc_ped_list[:20])
4137 print(utc_ped_list[:20])
4139 #print(utc_ped_list[488:498])
4138 #print(utc_ped_list[488:498])
4140 print("ultimo UTC-PEDESTAL",utc_ped_list[-1])
4139 print("ultimo UTC-PEDESTAL",utc_ped_list[-1])
4141 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)
4142 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)
4143 print("name_PEDESTAL",self.list_pedestal[nro_file])
4142 print("name_PEDESTAL",self.list_pedestal[nro_file])
4144 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
4145 print("nro_key_p",nro_key_p)
4144 print("nro_key_p",nro_key_p)
4146 ff_pedestal = self.list_pedestal[nro_file]
4145 ff_pedestal = self.list_pedestal[nro_file]
4147 #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")
4148 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")
4149
4148
4150 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)
4151 print("angulo_array :",angulo[nro_key_p])
4150 print("angulo_array :",angulo[nro_key_p])
4152 self.nro_file = nro_file
4151 self.nro_file = nro_file
4153 self.nro_key_p = nro_key_p
4152 self.nro_key_p = nro_key_p
4154
4153
4155 #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):
4156 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):
4157 print("SETUP PEDESTAL")
4156 print("SETUP PEDESTAL")
4158 self.__dataReady = False
4157 self.__dataReady = False
4159 self.path_ped = path_ped
4158 self.path_ped = path_ped
4160 #self.path_adq = path_adq
4159 #self.path_adq = path_adq
4161 self.t_Interval_p = t_Interval_p
4160 self.t_Interval_p = t_Interval_p
4162 self.n_Muestras_p = n_Muestras_p
4161 self.n_Muestras_p = n_Muestras_p
4163 self.blocksPerfile= blocksPerfile
4162 self.blocksPerfile= blocksPerfile
4164 self.f_a_p = f_a_p
4163 self.f_a_p = f_a_p
4165 self.online = online
4164 self.online = online
4166 self.angulo_adq = numpy.zeros(self.blocksPerfile)
4165 self.angulo_adq = numpy.zeros(self.blocksPerfile)
4167 self.__profIndex = 0
4166 self.__profIndex = 0
4168 self.tmp = 0
4167 self.tmp = 0
4169 self.c_ped = 0
4168 self.c_ped = 0
4170 print(self.path_ped)
4169 print(self.path_ped)
4171 #print(self.path_adq)
4170 #print(self.path_adq)
4172 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")
4173 print("LIST NEW", self.list_pedestal[:20])
4172 print("LIST NEW", self.list_pedestal[:20])
4174 #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")
4175 print("*************Longitud list pedestal****************",len(self.list_pedestal))
4174 print("*************Longitud list pedestal****************",len(self.list_pedestal))
4176
4175
4177 if self.online:
4176 if self.online:
4178 print("Enable Online")
4177 print("Enable Online")
4179 self.setup_online(dataOut)
4178 self.setup_online(dataOut)
4180 else:
4179 else:
4181 #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)
4182 self.setup_offline(dataOut,list_pedestal=self.list_pedestal)
4181 self.setup_offline(dataOut,list_pedestal=self.list_pedestal)
4183
4182
4184
4183
4185 def setNextFileP(self,dataOut):
4184 def setNextFileP(self,dataOut):
4186 if self.online:
4185 if self.online:
4187 data_pedestal = self.setNextFileonline()
4186 data_pedestal = self.setNextFileonline()
4188 else:
4187 else:
4189 data_pedestal = self.setNextFileoffline(dataOut)
4188 data_pedestal = self.setNextFileoffline(dataOut)
4190
4189
4191 return data_pedestal
4190 return data_pedestal
4192
4191
4193
4192
4194 def setNextFileoffline(self,dataOut):
4193 def setNextFileoffline(self,dataOut):
4195 ##tmp=0
4194 ##tmp=0
4196 for j in range(self.blocksPerfile):
4195 for j in range(self.blocksPerfile):
4197 ###print("NUMERO DEL BLOQUE---->",j)
4196 ###print("NUMERO DEL BLOQUE---->",j)
4198 ###print("nro_key_p",self.nro_key_p)
4197 ###print("nro_key_p",self.nro_key_p)
4199
4198
4200 #iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4199 #iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4201 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
4202 self.c_ped = self.c_ped +1
4201 self.c_ped = self.c_ped +1
4203
4202
4204 print("iterador------------->",iterador)
4203 print("iterador------------->",iterador)
4205 if iterador < self.n_Muestras_p:
4204 if iterador < self.n_Muestras_p:
4206 self.nro_file = self.nro_file
4205 self.nro_file = self.nro_file
4207 else:
4206 else:
4208 self.nro_file = self.nro_file+1
4207 self.nro_file = self.nro_file+1
4209 print("PRUEBA-------------")
4208 print("PRUEBA-------------")
4210 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])
4211 utc_adq_setnext=dataOut.utctime
4210 utc_adq_setnext=dataOut.utctime
4212 print("utc_pedestal",utc_ped_setnext)
4211 print("utc_pedestal",utc_ped_setnext)
4213 print("utc_adq",utc_adq_setnext)
4212 print("utc_adq",utc_adq_setnext)
4214
4213
4215 print("self.c_ped",self.c_ped)
4214 print("self.c_ped",self.c_ped)
4216 #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))
4217 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))
4218
4217
4219 self.c_ped = 1
4218 self.c_ped = 1
4220 ##tmp = j
4219 ##tmp = j
4221 ##print("tmp else",tmp)
4220 ##print("tmp else",tmp)
4222 self.nro_key_p= self.f_a_p-dif
4221 self.nro_key_p= self.f_a_p-dif
4223 iterador = self.nro_key_p
4222 iterador = self.nro_key_p
4224 print("iterador else",iterador)
4223 print("iterador else",iterador)
4225 #self.c_ped = self.c_ped +1
4224 #self.c_ped = self.c_ped +1
4226
4225
4227 print("nro_file",self.nro_file)
4226 print("nro_file",self.nro_file)
4228 #print("tmp",tmp)
4227 #print("tmp",tmp)
4229 try:
4228 try:
4230 ff_pedestal = self.list_pedestal[self.nro_file]
4229 ff_pedestal = self.list_pedestal[self.nro_file]
4231 print("ff_pedestal",ff_pedestal)
4230 print("ff_pedestal",ff_pedestal)
4232 except:
4231 except:
4233 print("############# EXCEPCION ######################")
4232 print("############# EXCEPCION ######################")
4234 return numpy.ones(self.blocksPerfile)*numpy.nan
4233 return numpy.ones(self.blocksPerfile)*numpy.nan
4235
4234
4236 #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")
4237 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")
4238
4237
4239 self.angulo_adq[j]= angulo[iterador]
4238 self.angulo_adq[j]= angulo[iterador]
4240
4239
4241 return self.angulo_adq
4240 return self.angulo_adq
4242
4241
4243 def setNextFileonline(self):
4242 def setNextFileonline(self):
4244 tmp = 0
4243 tmp = 0
4245 self.nTries_p = 3
4244 self.nTries_p = 3
4246 self.delay = 3
4245 self.delay = 3
4247 ready = 1
4246 ready = 1
4248 for j in range(self.blocksPerfile):
4247 for j in range(self.blocksPerfile):
4249 iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4248 iterador = self.nro_key_p +self.f_a_p*(j-tmp)
4250 if iterador < self.n_Muestras_p:
4249 if iterador < self.n_Muestras_p:
4251 self.nro_file = self.nro_file
4250 self.nro_file = self.nro_file
4252 else:
4251 else:
4253 self.nro_file = self.nro_file+1
4252 self.nro_file = self.nro_file+1
4254 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))
4255 tmp = j
4254 tmp = j
4256 self.nro_key_p= self.f_a_p-dif
4255 self.nro_key_p= self.f_a_p-dif
4257 iterador = self.nro_key_p
4256 iterador = self.nro_key_p
4258 #print("nro_file---------------- :",self.nro_file)
4257 #print("nro_file---------------- :",self.nro_file)
4259 try:
4258 try:
4260 # update list_pedestal
4259 # update list_pedestal
4261 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")
4262 ff_pedestal = self.list_pedestal[self.nro_file]
4261 ff_pedestal = self.list_pedestal[self.nro_file]
4263 except:
4262 except:
4264 ff_pedestal = None
4263 ff_pedestal = None
4265 ready = 0
4264 ready = 0
4266 for nTries_p in range(self.nTries_p):
4265 for nTries_p in range(self.nTries_p):
4267 try:
4266 try:
4268 # update list_pedestal
4267 # update list_pedestal
4269 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")
4270 ff_pedestal = self.list_pedestal[self.nro_file]
4269 ff_pedestal = self.list_pedestal[self.nro_file]
4271 except:
4270 except:
4272 ff_pedestal = None
4271 ff_pedestal = None
4273 if ff_pedestal is not None:
4272 if ff_pedestal is not None:
4274 ready=1
4273 ready=1
4275 break
4274 break
4276 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))
4277 time.sleep(self.delay)
4276 time.sleep(self.delay)
4278 continue
4277 continue
4279 #return numpy.ones(self.blocksPerfile)*numpy.nan
4278 #return numpy.ones(self.blocksPerfile)*numpy.nan
4280
4279
4281 if ready == 1:
4280 if ready == 1:
4282 #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")
4283 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")
4284
4283
4285 else:
4284 else:
4286 print("there is no pedestal file")
4285 print("there is no pedestal file")
4287 angulo = numpy.ones(self.n_Muestras_p)*numpy.nan
4286 angulo = numpy.ones(self.n_Muestras_p)*numpy.nan
4288 self.angulo_adq[j]= angulo[iterador]
4287 self.angulo_adq[j]= angulo[iterador]
4289 ####print("Angulo",self.angulo_adq)
4288 ####print("Angulo",self.angulo_adq)
4290 ####print("Angulo",len(self.angulo_adq))
4289 ####print("Angulo",len(self.angulo_adq))
4291 #self.nro_key_p=iterador + self.f_a_p
4290 #self.nro_key_p=iterador + self.f_a_p
4292 #if self.nro_key_p< self.n_Muestras_p:
4291 #if self.nro_key_p< self.n_Muestras_p:
4293 # self.nro_file = self.nro_file
4292 # self.nro_file = self.nro_file
4294 #else:
4293 #else:
4295 # self.nro_file = self.nro_file+1
4294 # self.nro_file = self.nro_file+1
4296 # self.nro_key_p= self.nro_key_p
4295 # self.nro_key_p= self.nro_key_p
4297 return self.angulo_adq
4296 return self.angulo_adq
4298
4297
4299
4298
4300 #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):
4301 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):
4302
4301
4303 if not self.isConfig:
4302 if not self.isConfig:
4304 print("######################SETUP#########################################")
4303 print("######################SETUP#########################################")
4305 #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)
4306 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)
4307 self.isConfig = True
4306 self.isConfig = True
4308
4307
4309 dataOut.flagNoData = True
4308 dataOut.flagNoData = True
4310 print("profIndex",self.__profIndex)
4309 print("profIndex",self.__profIndex)
4311
4310
4312 if self.__profIndex==0:
4311 if self.__profIndex==0:
4313 angulo_adq = self.setNextFileP(dataOut)
4312 angulo_adq = self.setNextFileP(dataOut)
4314 dataOut.azimuth = angulo_adq
4313 dataOut.azimuth = angulo_adq
4315 print("TIEMPO:",dataOut.utctime)
4314 print("TIEMPO:",dataOut.utctime)
4316 ##print("####################################################################")
4315 ##print("####################################################################")
4317 print("angulos",dataOut.azimuth,len(dataOut.azimuth))
4316 print("angulos",dataOut.azimuth,len(dataOut.azimuth))
4318 self.__dataReady = True
4317 self.__dataReady = True
4319 self.__profIndex += 1
4318 self.__profIndex += 1
4320 print("TIEMPO_bucle:",dataOut.utctime)
4319 print("TIEMPO_bucle:",dataOut.utctime)
4321 print("profIndex",self.__profIndex)
4320 print("profIndex",self.__profIndex)
4322 if self.__profIndex== blocksPerfile:
4321 if self.__profIndex== blocksPerfile:
4323 self.__profIndex = 0
4322 self.__profIndex = 0
4324 if self.__dataReady:
4323 if self.__dataReady:
4325 #print(self.__profIndex,dataOut.azimuth[:10])
4324 #print(self.__profIndex,dataOut.azimuth[:10])
4326 dataOut.flagNoData = False
4325 dataOut.flagNoData = False
4327 return dataOut
4326 return dataOut
4328
4327
4329
4328
4330 class Block360(Operation):
4329 class Block360(Operation):
4331 '''
4330 '''
4332 '''
4331 '''
4333 isConfig = False
4332 isConfig = False
4334 __profIndex = 0
4333 __profIndex = 0
4335 __initime = None
4334 __initime = None
4336 __lastdatatime = None
4335 __lastdatatime = None
4337 __buffer = None
4336 __buffer = None
4338 __dataReady = False
4337 __dataReady = False
4339 n = None
4338 n = None
4340 __nch = 0
4339 __nch = 0
4341 __nHeis = 0
4340 __nHeis = 0
4342 index = 0
4341 index = 0
4343 mode = 0
4342 mode = 0
4344
4343
4345 def __init__(self,**kwargs):
4344 def __init__(self,**kwargs):
4346 Operation.__init__(self,**kwargs)
4345 Operation.__init__(self,**kwargs)
4347
4346
4348 def setup(self, dataOut, n = None, mode = None):
4347 def setup(self, dataOut, n = None, mode = None):
4349 '''
4348 '''
4350 n= Numero de PRF's de entrada
4349 n= Numero de PRF's de entrada
4351 '''
4350 '''
4352 self.__initime = None
4351 self.__initime = None
4353 self.__lastdatatime = 0
4352 self.__lastdatatime = 0
4354 self.__dataReady = False
4353 self.__dataReady = False
4355 self.__buffer = 0
4354 self.__buffer = 0
4356 self.__buffer_1D = 0
4355 self.__buffer_1D = 0
4357 self.__profIndex = 0
4356 self.__profIndex = 0
4358 self.index = 0
4357 self.index = 0
4359 self.__nch = dataOut.nChannels
4358 self.__nch = dataOut.nChannels
4360 self.__nHeis = dataOut.nHeights
4359 self.__nHeis = dataOut.nHeights
4361 ##print("ELVALOR DE n es:", n)
4360 ##print("ELVALOR DE n es:", n)
4362 if n == None:
4361 if n == None:
4363 raise ValueError("n should be specified.")
4362 raise ValueError("n should be specified.")
4364
4363
4365 if mode == None:
4364 if mode == None:
4366 raise ValueError("mode should be specified.")
4365 raise ValueError("mode should be specified.")
4367
4366
4368 if n != None:
4367 if n != None:
4369 if n<1:
4368 if n<1:
4370 print("n should be greater than 2")
4369 print("n should be greater than 2")
4371 raise ValueError("n should be greater than 2")
4370 raise ValueError("n should be greater than 2")
4372
4371
4373 self.n = n
4372 self.n = n
4374 self.mode = mode
4373 self.mode = mode
4375 print("self.mode",self.mode)
4374 print("self.mode",self.mode)
4376 #print("nHeights")
4375 #print("nHeights")
4377 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4376 self.__buffer = numpy.zeros(( dataOut.nChannels,n, dataOut.nHeights))
4378 self.__buffer2= numpy.zeros(n)
4377 self.__buffer2= numpy.zeros(n)
4379
4378
4380 def putData(self,data,mode):
4379 def putData(self,data,mode):
4381 '''
4380 '''
4382 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
4383 '''
4382 '''
4384 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4383 #print("line 4049",data.dataPP_POW.shape,data.dataPP_POW[:10])
4385 #print("line 4049",data.azimuth.shape,data.azimuth)
4384 #print("line 4049",data.azimuth.shape,data.azimuth)
4386 if self.mode==0:
4385 if self.mode==0:
4387 self.__buffer[:,self.__profIndex,:]= data.dataPP_POW
4386 self.__buffer[:,self.__profIndex,:]= data.dataPP_POWER# PRIMER MOMENTO
4388 if self.mode==1:
4387 if self.mode==1:
4389 self.__buffer[:,self.__profIndex,:]= data.data_pow
4388 self.__buffer[:,self.__profIndex,:]= data.data_pow
4390 #print("me casi",self.index,data.azimuth[self.index])
4389 #print("me casi",self.index,data.azimuth[self.index])
4391 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4390 #print(self.__profIndex, self.index , data.azimuth[self.index] )
4392 #print("magic",data.profileIndex)
4391 #print("magic",data.profileIndex)
4393 #print(data.azimuth[self.index])
4392 #print(data.azimuth[self.index])
4394 #print("index",self.index)
4393 #print("index",self.index)
4395
4394
4396 self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4395 self.__buffer2[self.__profIndex] = data.azimuth[self.index]
4397 #print("q pasa")
4396 #print("q pasa")
4398 self.index+=1
4397 self.index+=1
4399 #print("index",self.index,data.azimuth[:10])
4398 #print("index",self.index,data.azimuth[:10])
4400 self.__profIndex += 1
4399 self.__profIndex += 1
4401 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4400 return #Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β· Remove DCΒ·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·Β·
4402
4401
4403 def pushData(self,data):
4402 def pushData(self,data):
4404 '''
4403 '''
4405 Return the PULSEPAIR and the profiles used in the operation
4404 Return the PULSEPAIR and the profiles used in the operation
4406 Affected : self.__profileIndex
4405 Affected : self.__profileIndex
4407 '''
4406 '''
4408 #print("pushData")
4407 #print("pushData")
4409
4408
4410 data_360 = self.__buffer
4409 data_360 = self.__buffer
4411 data_p = self.__buffer2
4410 data_p = self.__buffer2
4412 n = self.__profIndex
4411 n = self.__profIndex
4413
4412
4414 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4413 self.__buffer = numpy.zeros((self.__nch, self.n,self.__nHeis))
4415 self.__buffer2 = numpy.zeros(self.n)
4414 self.__buffer2 = numpy.zeros(self.n)
4416 self.__profIndex = 0
4415 self.__profIndex = 0
4417 #print("pushData")
4416 #print("pushData")
4418 return data_360,n,data_p
4417 return data_360,n,data_p
4419
4418
4420
4419
4421 def byProfiles(self,dataOut):
4420 def byProfiles(self,dataOut):
4422
4421
4423 self.__dataReady = False
4422 self.__dataReady = False
4424 data_360 = None
4423 data_360 = None
4425 data_p = None
4424 data_p = None
4426 #print("dataOu",dataOut.dataPP_POW)
4425 #print("dataOu",dataOut.dataPP_POW)
4427 self.putData(data=dataOut,mode = self.mode)
4426 self.putData(data=dataOut,mode = self.mode)
4428 #print("profIndex",self.__profIndex)
4427 #print("profIndex",self.__profIndex)
4429 if self.__profIndex == self.n:
4428 if self.__profIndex == self.n:
4430 data_360,n,data_p = self.pushData(data=dataOut)
4429 data_360,n,data_p = self.pushData(data=dataOut)
4431 self.__dataReady = True
4430 self.__dataReady = True
4432
4431
4433 return data_360,data_p
4432 return data_360,data_p
4434
4433
4435
4434
4436 def blockOp(self, dataOut, datatime= None):
4435 def blockOp(self, dataOut, datatime= None):
4437 if self.__initime == None:
4436 if self.__initime == None:
4438 self.__initime = datatime
4437 self.__initime = datatime
4439 data_360,data_p = self.byProfiles(dataOut)
4438 data_360,data_p = self.byProfiles(dataOut)
4440 self.__lastdatatime = datatime
4439 self.__lastdatatime = datatime
4441
4440
4442 if data_360 is None:
4441 if data_360 is None:
4443 return None, None,None
4442 return None, None,None
4444
4443
4445 avgdatatime = self.__initime
4444 avgdatatime = self.__initime
4446 deltatime = datatime - self.__lastdatatime
4445 deltatime = datatime - self.__lastdatatime
4447 self.__initime = datatime
4446 self.__initime = datatime
4448 #print(data_360.shape,avgdatatime,data_p.shape)
4447 #print(data_360.shape,avgdatatime,data_p.shape)
4449 return data_360,avgdatatime,data_p
4448 return data_360,avgdatatime,data_p
4450
4449
4451 def run(self, dataOut,n = None,mode=None,**kwargs):
4450 def run(self, dataOut,n = None,mode=None,**kwargs):
4452 print("BLOCK 360 HERE WE GO MOMENTOS")
4451 print("BLOCK 360 HERE WE GO MOMENTOS")
4453 if not self.isConfig:
4452 if not self.isConfig:
4454 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4453 self.setup(dataOut = dataOut, n = n ,mode= mode ,**kwargs)
4455 self.index = 0
4454 self.index = 0
4456 #print("comova",self.isConfig)
4455 #print("comova",self.isConfig)
4457 self.isConfig = True
4456 self.isConfig = True
4458 if self.index==dataOut.azimuth.shape[0]:
4457 if self.index==dataOut.azimuth.shape[0]:
4459 self.index=0
4458 self.index=0
4460 data_360, avgdatatime,data_p = self.blockOp(dataOut, dataOut.utctime)
4459 data_360, avgdatatime,data_p = self.blockOp(dataOut, dataOut.utctime)
4461 dataOut.flagNoData = True
4460 dataOut.flagNoData = True
4462
4461
4463 if self.__dataReady:
4462 if self.__dataReady:
4464 dataOut.data_360 = data_360 # S
4463 dataOut.data_360 = data_360 # S
4465 ##print("---------------------------------------------------------------------------------")
4464 ##print("---------------------------------------------------------------------------------")
4466 ##print("---------------------------DATAREADY---------------------------------------------")
4465 ##print("---------------------------DATAREADY---------------------------------------------")
4467 ##print("---------------------------------------------------------------------------------")
4466 ##print("---------------------------------------------------------------------------------")
4468 ##print("data_360",dataOut.data_360.shape)
4467 ##print("data_360",dataOut.data_360.shape)
4469 dataOut.data_azi = data_p
4468 dataOut.data_azi = data_p
4470 ##print("azi: ",dataOut.data_azi)
4469 ##print("azi: ",dataOut.data_azi)
4471 #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)
4472 dataOut.utctime = avgdatatime
4471 dataOut.utctime = avgdatatime
4473 dataOut.flagNoData = False
4472 dataOut.flagNoData = False
4474 return dataOut
4473 return dataOut
1 NO CONTENT: modified file
NO CONTENT: modified file
@@ -1,216 +1,216
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 = 1
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/TEST_19OCTUBRE/10MHZ'
29 #path = '/DATA_RM/TEST_19OCTUBRE/10MHZ'
30 path = '/DATA_RM/WR_20_OCT'
30 path = '/DATA_RM/WR_20_OCT'
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/P20211019-192244'
32 ####path_ped='/DATA_RM/TEST_PEDESTAL/P20211019-192244'
33 figpath_pp = "/home/soporte/Pictures/TEST_PP"
33 figpath_pp = "/home/soporte/Pictures/TEST_PP"
34 figpath_spec = "/home/soporte/Pictures/TEST_MOM"
34 figpath_spec = "/home/soporte/Pictures/TEST_MOM"
35 plot = 1
35 plot = 0
36 integration = 0
36 integration = 1
37 save = 0
37 save = 0
38 if save == 1:
38 if save == 1:
39 if mode==0:
39 if mode==0:
40 path_save = '/DATA_RM/TEST_HDF5_PP_23/6v'
40 path_save = '/DATA_RM/TEST_HDF5_PP_23/6v'
41 path_save = '/DATA_RM/TEST_HDF5_PP'
41 path_save = '/DATA_RM/TEST_HDF5_PP'
42 path_save = '/DATA_RM/TEST_HDF5_PP_100'
42 path_save = '/DATA_RM/TEST_HDF5_PP_100'
43 else:
43 else:
44 path_save = '/DATA_RM/TEST_HDF5_SPEC_23_V2/6v'
44 path_save = '/DATA_RM/TEST_HDF5_SPEC_23_V2/6v'
45
45
46 print("* PATH data ADQ :", path)
46 print("* PATH data ADQ :", path)
47 print("* Velocidad Pedestal :",V,"Β°/seg")
47 print("* Velocidad Pedestal :",V,"Β°/seg")
48 ############################ NRO Perfiles PROCESAMIENTO ###################
48 ############################ NRO Perfiles PROCESAMIENTO ###################
49 V=V
49 V=V
50 IPP=400*1e-6
50 IPP=400*1e-6
51 n= int(1/(V*IPP))
51 n= int(1/(V*IPP))
52 print("* n - NRO Perfiles Proc:", n )
52 print("* n - NRO Perfiles Proc:", n )
53 ################################## MODE ###################################
53 ################################## MODE ###################################
54 print("* Modo de Operacion :",mode)
54 print("* Modo de Operacion :",mode)
55 if mode ==0:
55 if mode ==0:
56 print("* Met. Seleccionado : Pulse Pair")
56 print("* Met. Seleccionado : Pulse Pair")
57 else:
57 else:
58 print("* Met. Momentos : Momentos")
58 print("* Met. Momentos : Momentos")
59
59
60 ################################## MODE ###################################
60 ################################## MODE ###################################
61 print("* Grabado de datos :",save)
61 print("* Grabado de datos :",save)
62 if save ==1:
62 if save ==1:
63 if mode==0:
63 if mode==0:
64 ope= "Pulse Pair"
64 ope= "Pulse Pair"
65 else:
65 else:
66 ope= "Momentos"
66 ope= "Momentos"
67 print("* Path-Save Data -", ope , path_save)
67 print("* Path-Save Data -", ope , path_save)
68
68
69 print("* Integracion de datos :",integration)
69 print("* Integracion de datos :",integration)
70
70
71 time.sleep(15)
71 time.sleep(15)
72 #remotefolder = "/home/wmaster/graficos"
72 #remotefolder = "/home/wmaster/graficos"
73 #######################################################################
73 #######################################################################
74 ################# RANGO DE PLOTEO######################################
74 ################# RANGO DE PLOTEO######################################
75 dBmin = '1'
75 dBmin = '1'
76 dBmax = '65'
76 dBmax = '65'
77 xmin = '13.2'
77 xmin = '13.2'
78 xmax = '13.5'
78 xmax = '13.5'
79 ymin = '0'
79 ymin = '0'
80 ymax = '60'
80 ymax = '60'
81 #######################################################################
81 #######################################################################
82 ########################FECHA##########################################
82 ########################FECHA##########################################
83 str = datetime.date.today()
83 str = datetime.date.today()
84 today = str.strftime("%Y/%m/%d")
84 today = str.strftime("%Y/%m/%d")
85 str2 = str - datetime.timedelta(days=1)
85 str2 = str - datetime.timedelta(days=1)
86 yesterday = str2.strftime("%Y/%m/%d")
86 yesterday = str2.strftime("%Y/%m/%d")
87 #######################################################################
87 #######################################################################
88 ########################SIGNAL CHAIN ##################################
88 ########################SIGNAL CHAIN ##################################
89 #######################################################################
89 #######################################################################
90 desc = "USRP_test"
90 desc = "USRP_test"
91 filename = "USRP_processing.xml"
91 filename = "USRP_processing.xml"
92 controllerObj = Project()
92 controllerObj = Project()
93 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
93 controllerObj.setup(id = '191', name='Test_USRP', description=desc)
94 #######################################################################
94 #######################################################################
95 ######################## UNIDAD DE LECTURA#############################
95 ######################## UNIDAD DE LECTURA#############################
96 #######################################################################
96 #######################################################################
97 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
97 readUnitConfObj = controllerObj.addReadUnit(datatype='DigitalRFReader',
98 path=path,
98 path=path,
99 startDate="2021/01/01",#today,
99 startDate="2021/01/01",#today,
100 endDate="2021/12/30",#today,
100 endDate="2021/12/30",#today,
101 startTime='00:00:00',
101 startTime='00:00:00',
102 endTime='23:59:59',
102 endTime='23:59:59',
103 delay=0,
103 delay=0,
104 #set=0,
104 #set=0,
105 online=0,
105 online=0,
106 walk=1,
106 walk=1,
107 ippKm = 60)
107 ippKm = 60)
108
108
109 opObj11 = readUnitConfObj.addOperation(name='printInfo')
109 opObj11 = readUnitConfObj.addOperation(name='printInfo')
110
110
111 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
111 procUnitConfObjA = controllerObj.addProcUnit(datatype='VoltageProc', inputId=readUnitConfObj.getId())
112
112
113 if mode ==0:
113 if mode ==0:
114 ####################### METODO PULSE PAIR ######################################################################
114 ####################### METODO PULSE PAIR ######################################################################
115 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
115 opObj11 = procUnitConfObjA.addOperation(name='PulsePair', optype='other')
116 opObj11.addParameter(name='n', value=int(n), format='int')#10 VOY A USAR 250 DADO QUE LA VELOCIDAD ES 10 GRADOS
116 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='removeDC', value=1, format='int')
117 #opObj11.addParameter(name='removeDC', value=1, format='int')
118 ####################### METODO Parametros ######################################################################
118 ####################### METODO Parametros ######################################################################
119 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
119 procUnitConfObjB= controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjA.getId())
120 if plot==1:
120 if plot==1:
121 opObj11 = procUnitConfObjB.addOperation(name='GenericRTIPlot',optype='external')
121 opObj11 = procUnitConfObjB.addOperation(name='GenericRTIPlot',optype='external')
122 opObj11.addParameter(name='attr_data', value='dataPP_POWER')
122 opObj11.addParameter(name='attr_data', value='dataPP_POWER')
123 opObj11.addParameter(name='colormap', value='jet')
123 opObj11.addParameter(name='colormap', value='jet')
124 opObj11.addParameter(name='xmin', value=xmin)
124 opObj11.addParameter(name='xmin', value=xmin)
125 opObj11.addParameter(name='xmax', value=xmax)
125 opObj11.addParameter(name='xmax', value=xmax)
126 opObj11.addParameter(name='zmin', value=dBmin)
126 opObj11.addParameter(name='zmin', value=dBmin)
127 opObj11.addParameter(name='zmax', value=dBmax)
127 opObj11.addParameter(name='zmax', value=dBmax)
128 opObj11.addParameter(name='save', value=figpath_pp)
128 opObj11.addParameter(name='save', value=figpath_pp)
129 opObj11.addParameter(name='showprofile', value=0)
129 opObj11.addParameter(name='showprofile', value=0)
130 opObj11.addParameter(name='save_period', value=10)
130 opObj11.addParameter(name='save_period', value=10)
131
131
132 ####################### METODO ESCRITURA #######################################################################
132 ####################### METODO ESCRITURA #######################################################################
133 if save==1:
133 if save==1:
134 opObj10 = procUnitConfObjB.addOperation(name='HDFWriter')
134 opObj10 = procUnitConfObjB.addOperation(name='HDFWriter')
135 opObj10.addParameter(name='path',value=path_save)
135 opObj10.addParameter(name='path',value=path_save)
136 #opObj10.addParameter(name='mode',value=0)
136 #opObj10.addParameter(name='mode',value=0)
137 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
137 opObj10.addParameter(name='blocksPerFile',value='100',format='int')
138 opObj10.addParameter(name='metadataList',value='utctimeInit,timeZone,paramInterval,profileIndex,channelList,heightList,flagDataAsBlock',format='list')
138 opObj10.addParameter(name='metadataList',value='utctimeInit,timeZone,paramInterval,profileIndex,channelList,heightList,flagDataAsBlock',format='list')
139 opObj10.addParameter(name='dataList',value='dataPP_POWER,dataPP_DOP,utctime',format='list')#,format='list'
139 opObj10.addParameter(name='dataList',value='dataPP_POWER,dataPP_DOP,utctime',format='list')#,format='list'
140 if integration==1:
140 if integration==1:
141 V=10
141 V=10
142 blocksPerfile=360
142 blocksPerfile=360
143 print("* Velocidad del Pedestal:",V)
143 print("* Velocidad del Pedestal:",V)
144 tmp_blocksPerfile = 100
144 tmp_blocksPerfile = 100
145 f_a_p= int(tmp_blocksPerfile/V)
145 f_a_p= int(tmp_blocksPerfile/V)
146
146
147 opObj11 = procUnitConfObjB.addOperation(name='PedestalInformation')
147 opObj11 = procUnitConfObjB.addOperation(name='PedestalInformation')
148 opObj11.addParameter(name='path_ped', value=path_ped)
148 opObj11.addParameter(name='path_ped', value=path_ped)
149 #opObj11.addParameter(name='path_adq', value=path_adq)
149 #opObj11.addParameter(name='path_adq', value=path_adq)
150 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
150 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
151 opObj11.addParameter(name='blocksPerfile', value=blocksPerfile, format='int')
151 opObj11.addParameter(name='blocksPerfile', value=blocksPerfile, format='int')
152 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
152 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
153 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
153 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
154 opObj11.addParameter(name='online', value='0', format='int')
154 opObj11.addParameter(name='online', value='0', format='int')
155
155
156 opObj11 = procUnitConfObjB.addOperation(name='Block360')
156 opObj11 = procUnitConfObjB.addOperation(name='Block360')
157 opObj11.addParameter(name='n', value='10', format='int')
157 opObj11.addParameter(name='n', value='10', format='int')
158 opObj11.addParameter(name='mode', value=mode, format='int')
158 opObj11.addParameter(name='mode', value=mode, format='int')
159
159
160 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
160 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
161
161
162 opObj11= procUnitConfObjB.addOperation(name='WeatherPlot',optype='other')
162 opObj11= procUnitConfObjB.addOperation(name='WeatherPlot',optype='other')
163
163
164
164
165 else:
165 else:
166 ####################### METODO SPECTROS ######################################################################
166 ####################### METODO SPECTROS ######################################################################
167 procUnitConfObjB = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjA.getId())
167 procUnitConfObjB = controllerObj.addProcUnit(datatype='SpectraProc', inputId=procUnitConfObjA.getId())
168 procUnitConfObjB.addParameter(name='nFFTPoints', value=n, format='int')
168 procUnitConfObjB.addParameter(name='nFFTPoints', value=n, format='int')
169 procUnitConfObjB.addParameter(name='nProfiles' , value=n, format='int')
169 procUnitConfObjB.addParameter(name='nProfiles' , value=n, format='int')
170
170
171 procUnitConfObjC = controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjB.getId())
171 procUnitConfObjC = controllerObj.addProcUnit(datatype='ParametersProc',inputId=procUnitConfObjB.getId())
172 procUnitConfObjC.addOperation(name='SpectralMoments')
172 procUnitConfObjC.addOperation(name='SpectralMoments')
173 if plot==1:
173 if plot==1:
174 dBmin = '1'
174 dBmin = '1'
175 dBmax = '65'
175 dBmax = '65'
176 opObj11 = procUnitConfObjC.addOperation(name='PowerPlot',optype='external')
176 opObj11 = procUnitConfObjC.addOperation(name='PowerPlot',optype='external')
177 opObj11.addParameter(name='xmin', value=xmin)
177 opObj11.addParameter(name='xmin', value=xmin)
178 opObj11.addParameter(name='xmax', value=xmax)
178 opObj11.addParameter(name='xmax', value=xmax)
179 opObj11.addParameter(name='zmin', value=dBmin)
179 opObj11.addParameter(name='zmin', value=dBmin)
180 opObj11.addParameter(name='zmax', value=dBmax)
180 opObj11.addParameter(name='zmax', value=dBmax)
181 opObj11.addParameter(name='save', value=figpath_spec)
181 opObj11.addParameter(name='save', value=figpath_spec)
182 opObj11.addParameter(name='showprofile', value=0)
182 opObj11.addParameter(name='showprofile', value=0)
183 opObj11.addParameter(name='save_period', value=10)
183 opObj11.addParameter(name='save_period', value=10)
184
184
185 if save==1:
185 if save==1:
186 opObj10 = procUnitConfObjC.addOperation(name='HDFWriter')
186 opObj10 = procUnitConfObjC.addOperation(name='HDFWriter')
187 opObj10.addParameter(name='path',value=path_save)
187 opObj10.addParameter(name='path',value=path_save)
188 #opObj10.addParameter(name='mode',value=0)
188 #opObj10.addParameter(name='mode',value=0)
189 opObj10.addParameter(name='blocksPerFile',value='360',format='int')
189 opObj10.addParameter(name='blocksPerFile',value='360',format='int')
190 #opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
190 #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
191 opObj10.addParameter(name='metadataList',value='utctimeInit,heightList,nIncohInt,nCohInt,nProfiles,channelList',format='list')#profileIndex
192 opObj10.addParameter(name='dataList',value='data_pow,data_dop,utctime',format='list')#,format='list'
192 opObj10.addParameter(name='dataList',value='data_pow,data_dop,utctime',format='list')#,format='list'
193
193
194 if integration==1:
194 if integration==1:
195 V=10
195 V=10
196 blocksPerfile=360
196 blocksPerfile=360
197 print("* Velocidad del Pedestal:",V)
197 print("* Velocidad del Pedestal:",V)
198 tmp_blocksPerfile = 100
198 tmp_blocksPerfile = 100
199 f_a_p= int(tmp_blocksPerfile/V)
199 f_a_p= int(tmp_blocksPerfile/V)
200
200
201 opObj11 = procUnitConfObjC.addOperation(name='PedestalInformation')
201 opObj11 = procUnitConfObjC.addOperation(name='PedestalInformation')
202 opObj11.addParameter(name='path_ped', value=path_ped)
202 opObj11.addParameter(name='path_ped', value=path_ped)
203 #opObj11.addParameter(name='path_adq', value=path_adq)
203 #opObj11.addParameter(name='path_adq', value=path_adq)
204 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
204 opObj11.addParameter(name='t_Interval_p', value='0.01', format='float')
205 opObj11.addParameter(name='blocksPerfile', value=blocksPerfile, format='int')
205 opObj11.addParameter(name='blocksPerfile', value=blocksPerfile, format='int')
206 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
206 opObj11.addParameter(name='n_Muestras_p', value='100', format='float')
207 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
207 opObj11.addParameter(name='f_a_p', value=f_a_p, format='int')
208 opObj11.addParameter(name='online', value='0', format='int')
208 opObj11.addParameter(name='online', value='0', format='int')
209
209
210 opObj11 = procUnitConfObjC.addOperation(name='Block360')
210 opObj11 = procUnitConfObjC.addOperation(name='Block360')
211 opObj11.addParameter(name='n', value='10', format='int')
211 opObj11.addParameter(name='n', value='10', format='int')
212 opObj11.addParameter(name='mode', value=mode, format='int')
212 opObj11.addParameter(name='mode', value=mode, format='int')
213
213
214 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
214 # este bloque funciona bien con divisores de 360 no olvidar 0 10 20 30 40 60 90 120 180
215 opObj11= procUnitConfObjC.addOperation(name='WeatherPlot',optype='other')
215 opObj11= procUnitConfObjC.addOperation(name='WeatherPlot',optype='other')
216 controllerObj.start()
216 controllerObj.start()
@@ -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 = 1
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(15)
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='30', 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