##// END OF EJS Templates
jroplot_parameters.py jroplot_spectra.py jroIO_digitalRF.py jroproc_parameters.py sophy_proc.py
eynilupu -
r1653:f661d02a9309
parent child
Show More
@@ -1,725 +1,736
1 import os
1 import os
2 import datetime
2 import datetime
3 import warnings
3 import warnings
4 import numpy
4 import numpy
5 from mpl_toolkits.axisartist.grid_finder import FixedLocator, DictFormatter
5 from mpl_toolkits.axisartist.grid_finder import FixedLocator, DictFormatter
6 from matplotlib.patches import Circle
6 from matplotlib.patches import Circle
7 import cartopy.crs as ccrs
7 import cartopy.crs as ccrs
8 from cartopy.feature import ShapelyFeature
8 from cartopy.feature import ShapelyFeature
9 import cartopy.io.shapereader as shpreader
9 import cartopy.io.shapereader as shpreader
10
10
11 from schainpy.model.graphics.jroplot_base import Plot, plt
11 from schainpy.model.graphics.jroplot_base import Plot, plt
12 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
12 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
13 from schainpy.utils import log
13 from schainpy.utils import log
14 from schainpy.model.graphics.plotting_codes import cb_tables
14 from schainpy.model.graphics.plotting_codes import cb_tables
15
15
16
16
17 EARTH_RADIUS = 6.3710e3
17 EARTH_RADIUS = 6.3710e3
18
18
19
19
20 def antenna_to_cartesian(ranges, azimuths, elevations):
20 def antenna_to_cartesian(ranges, azimuths, elevations):
21 """
21 """
22 Return Cartesian coordinates from antenna coordinates.
22 Return Cartesian coordinates from antenna coordinates.
23
23
24 Parameters
24 Parameters
25 ----------
25 ----------
26 ranges : array
26 ranges : array
27 Distances to the center of the radar gates (bins) in kilometers.
27 Distances to the center of the radar gates (bins) in kilometers.
28 azimuths : array
28 azimuths : array
29 Azimuth angle of the radar in degrees.
29 Azimuth angle of the radar in degrees.
30 elevations : array
30 elevations : array
31 Elevation angle of the radar in degrees.
31 Elevation angle of the radar in degrees.
32
32
33 Returns
33 Returns
34 -------
34 -------
35 x, y, z : array
35 x, y, z : array
36 Cartesian coordinates in meters from the radar.
36 Cartesian coordinates in meters from the radar.
37
37
38 Notes
38 Notes
39 -----
39 -----
40 The calculation for Cartesian coordinate is adapted from equations
40 The calculation for Cartesian coordinate is adapted from equations
41 2.28(b) and 2.28(c) of Doviak and Zrnic [1]_ assuming a
41 2.28(b) and 2.28(c) of Doviak and Zrnic [1]_ assuming a
42 standard atmosphere (4/3 Earth's radius model).
42 standard atmosphere (4/3 Earth's radius model).
43
43
44 .. math::
44 .. math::
45
45
46 z = \\sqrt{r^2+R^2+2*r*R*sin(\\theta_e)} - R
46 z = \\sqrt{r^2+R^2+2*r*R*sin(\\theta_e)} - R
47
47
48 s = R * arcsin(\\frac{r*cos(\\theta_e)}{R+z})
48 s = R * arcsin(\\frac{r*cos(\\theta_e)}{R+z})
49
49
50 x = s * sin(\\theta_a)
50 x = s * sin(\\theta_a)
51
51
52 y = s * cos(\\theta_a)
52 y = s * cos(\\theta_a)
53
53
54 Where r is the distance from the radar to the center of the gate,
54 Where r is the distance from the radar to the center of the gate,
55 :math:`\\theta_a` is the azimuth angle, :math:`\\theta_e` is the
55 :math:`\\theta_a` is the azimuth angle, :math:`\\theta_e` is the
56 elevation angle, s is the arc length, and R is the effective radius
56 elevation angle, s is the arc length, and R is the effective radius
57 of the earth, taken to be 4/3 the mean radius of earth (6371 km).
57 of the earth, taken to be 4/3 the mean radius of earth (6371 km).
58
58
59 References
59 References
60 ----------
60 ----------
61 .. [1] Doviak and Zrnic, Doppler Radar and Weather Observations, Second
61 .. [1] Doviak and Zrnic, Doppler Radar and Weather Observations, Second
62 Edition, 1993, p. 21.
62 Edition, 1993, p. 21.
63
63
64 """
64 """
65 theta_e = numpy.deg2rad(elevations) # elevation angle in radians.
65 theta_e = numpy.deg2rad(elevations) # elevation angle in radians.
66 theta_a = numpy.deg2rad(azimuths) # azimuth angle in radians.
66 theta_a = numpy.deg2rad(azimuths) # azimuth angle in radians.
67 R = 6371.0 * 1000.0 * 4.0 / 3.0 # effective radius of earth in meters.
67 R = 6371.0 * 1000.0 * 4.0 / 3.0 # effective radius of earth in meters.
68 r = ranges * 1000.0 # distances to gates in meters.
68 r = ranges * 1000.0 # distances to gates in meters.
69
69
70 z = (r ** 2 + R ** 2 + 2.0 * r * R * numpy.sin(theta_e)) ** 0.5 - R
70 z = (r ** 2 + R ** 2 + 2.0 * r * R * numpy.sin(theta_e)) ** 0.5 - R
71 s = R * numpy.arcsin(r * numpy.cos(theta_e) / (R + z)) # arc length in m.
71 s = R * numpy.arcsin(r * numpy.cos(theta_e) / (R + z)) # arc length in m.
72 x = s * numpy.sin(theta_a)
72 x = s * numpy.sin(theta_a)
73 y = s * numpy.cos(theta_a)
73 y = s * numpy.cos(theta_a)
74 return x, y, z
74 return x, y, z
75
75
76 def cartesian_to_geographic_aeqd(x, y, lon_0, lat_0, R=EARTH_RADIUS):
76 def cartesian_to_geographic_aeqd(x, y, lon_0, lat_0, R=EARTH_RADIUS):
77 """
77 """
78 Azimuthal equidistant Cartesian to geographic coordinate transform.
78 Azimuthal equidistant Cartesian to geographic coordinate transform.
79
79
80 Transform a set of Cartesian/Cartographic coordinates (x, y) to
80 Transform a set of Cartesian/Cartographic coordinates (x, y) to
81 geographic coordinate system (lat, lon) using a azimuthal equidistant
81 geographic coordinate system (lat, lon) using a azimuthal equidistant
82 map projection [1]_.
82 map projection [1]_.
83
83
84 .. math::
84 .. math::
85
85
86 lat = \\arcsin(\\cos(c) * \\sin(lat_0) +
86 lat = \\arcsin(\\cos(c) * \\sin(lat_0) +
87 (y * \\sin(c) * \\cos(lat_0) / \\rho))
87 (y * \\sin(c) * \\cos(lat_0) / \\rho))
88
88
89 lon = lon_0 + \\arctan2(
89 lon = lon_0 + \\arctan2(
90 x * \\sin(c),
90 x * \\sin(c),
91 \\rho * \\cos(lat_0) * \\cos(c) - y * \\sin(lat_0) * \\sin(c))
91 \\rho * \\cos(lat_0) * \\cos(c) - y * \\sin(lat_0) * \\sin(c))
92
92
93 \\rho = \\sqrt(x^2 + y^2)
93 \\rho = \\sqrt(x^2 + y^2)
94
94
95 c = \\rho / R
95 c = \\rho / R
96
96
97 Where x, y are the Cartesian position from the center of projection;
97 Where x, y are the Cartesian position from the center of projection;
98 lat, lon the corresponding latitude and longitude; lat_0, lon_0 are the
98 lat, lon the corresponding latitude and longitude; lat_0, lon_0 are the
99 latitude and longitude of the center of the projection; R is the radius of
99 latitude and longitude of the center of the projection; R is the radius of
100 the earth (defaults to ~6371 km). lon is adjusted to be between -180 and
100 the earth (defaults to ~6371 km). lon is adjusted to be between -180 and
101 180.
101 180.
102
102
103 Parameters
103 Parameters
104 ----------
104 ----------
105 x, y : array-like
105 x, y : array-like
106 Cartesian coordinates in the same units as R, typically meters.
106 Cartesian coordinates in the same units as R, typically meters.
107 lon_0, lat_0 : float
107 lon_0, lat_0 : float
108 Longitude and latitude, in degrees, of the center of the projection.
108 Longitude and latitude, in degrees, of the center of the projection.
109 R : float, optional
109 R : float, optional
110 Earth radius in the same units as x and y. The default value is in
110 Earth radius in the same units as x and y. The default value is in
111 units of meters.
111 units of meters.
112
112
113 Returns
113 Returns
114 -------
114 -------
115 lon, lat : array
115 lon, lat : array
116 Longitude and latitude of Cartesian coordinates in degrees.
116 Longitude and latitude of Cartesian coordinates in degrees.
117
117
118 References
118 References
119 ----------
119 ----------
120 .. [1] Snyder, J. P. Map Projections--A Working Manual. U. S. Geological
120 .. [1] Snyder, J. P. Map Projections--A Working Manual. U. S. Geological
121 Survey Professional Paper 1395, 1987, pp. 191-202.
121 Survey Professional Paper 1395, 1987, pp. 191-202.
122
122
123 """
123 """
124 x = numpy.atleast_1d(numpy.asarray(x))
124 x = numpy.atleast_1d(numpy.asarray(x))
125 y = numpy.atleast_1d(numpy.asarray(y))
125 y = numpy.atleast_1d(numpy.asarray(y))
126
126
127 lat_0_rad = numpy.deg2rad(lat_0)
127 lat_0_rad = numpy.deg2rad(lat_0)
128 lon_0_rad = numpy.deg2rad(lon_0)
128 lon_0_rad = numpy.deg2rad(lon_0)
129
129
130 rho = numpy.sqrt(x*x + y*y)
130 rho = numpy.sqrt(x*x + y*y)
131 c = rho / R
131 c = rho / R
132
132
133 with warnings.catch_warnings():
133 with warnings.catch_warnings():
134 # division by zero may occur here but is properly addressed below so
134 # division by zero may occur here but is properly addressed below so
135 # the warnings can be ignored
135 # the warnings can be ignored
136 warnings.simplefilter("ignore", RuntimeWarning)
136 warnings.simplefilter("ignore", RuntimeWarning)
137 lat_rad = numpy.arcsin(numpy.cos(c) * numpy.sin(lat_0_rad) +
137 lat_rad = numpy.arcsin(numpy.cos(c) * numpy.sin(lat_0_rad) +
138 y * numpy.sin(c) * numpy.cos(lat_0_rad) / rho)
138 y * numpy.sin(c) * numpy.cos(lat_0_rad) / rho)
139 lat_deg = numpy.rad2deg(lat_rad)
139 lat_deg = numpy.rad2deg(lat_rad)
140 # fix cases where the distance from the center of the projection is zero
140 # fix cases where the distance from the center of the projection is zero
141 lat_deg[rho == 0] = lat_0
141 lat_deg[rho == 0] = lat_0
142
142
143 x1 = x * numpy.sin(c)
143 x1 = x * numpy.sin(c)
144 x2 = rho*numpy.cos(lat_0_rad)*numpy.cos(c) - y*numpy.sin(lat_0_rad)*numpy.sin(c)
144 x2 = rho*numpy.cos(lat_0_rad)*numpy.cos(c) - y*numpy.sin(lat_0_rad)*numpy.sin(c)
145 lon_rad = lon_0_rad + numpy.arctan2(x1, x2)
145 lon_rad = lon_0_rad + numpy.arctan2(x1, x2)
146 lon_deg = numpy.rad2deg(lon_rad)
146 lon_deg = numpy.rad2deg(lon_rad)
147 # Longitudes should be from -180 to 180 degrees
147 # Longitudes should be from -180 to 180 degrees
148 lon_deg[lon_deg > 180] -= 360.
148 lon_deg[lon_deg > 180] -= 360.
149 lon_deg[lon_deg < -180] += 360.
149 lon_deg[lon_deg < -180] += 360.
150
150
151 return lon_deg, lat_deg
151 return lon_deg, lat_deg
152
152
153 def antenna_to_geographic(ranges, azimuths, elevations, site):
153 def antenna_to_geographic(ranges, azimuths, elevations, site):
154
154
155 x, y, z = antenna_to_cartesian(numpy.array(ranges), numpy.array(azimuths), numpy.array(elevations))
155 x, y, z = antenna_to_cartesian(numpy.array(ranges), numpy.array(azimuths), numpy.array(elevations))
156 lon, lat = cartesian_to_geographic_aeqd(x, y, site[0], site[1], R=6370997.)
156 lon, lat = cartesian_to_geographic_aeqd(x, y, site[0], site[1], R=6370997.)
157
157
158 return lon, lat
158 return lon, lat
159
159
160 def ll2xy(lat1, lon1, lat2, lon2):
160 def ll2xy(lat1, lon1, lat2, lon2):
161
161
162 p = 0.017453292519943295
162 p = 0.017453292519943295
163 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
163 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
164 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
164 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
165 r = 12742 * numpy.arcsin(numpy.sqrt(a))
165 r = 12742 * numpy.arcsin(numpy.sqrt(a))
166 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
166 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
167 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
167 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
168 theta = -theta + numpy.pi/2
168 theta = -theta + numpy.pi/2
169 return r*numpy.cos(theta), r*numpy.sin(theta)
169 return r*numpy.cos(theta), r*numpy.sin(theta)
170
170
171
171
172 def km2deg(km):
172 def km2deg(km):
173 '''
173 '''
174 Convert distance in km to degrees
174 Convert distance in km to degrees
175 '''
175 '''
176
176
177 return numpy.rad2deg(km/EARTH_RADIUS)
177 return numpy.rad2deg(km/EARTH_RADIUS)
178
178
179
179
180
180
181 class SpectralMomentsPlot(SpectraPlot):
181 class SpectralMomentsPlot(SpectraPlot):
182 '''
182 '''
183 Plot for Spectral Moments
183 Plot for Spectral Moments
184 '''
184 '''
185 CODE = 'spc_moments'
185 CODE = 'spc_moments'
186 # colormap = 'jet'
186 # colormap = 'jet'
187 # plot_type = 'pcolor'
187 # plot_type = 'pcolor'
188
188
189 class DobleGaussianPlot(SpectraPlot):
189 class DobleGaussianPlot(SpectraPlot):
190 '''
190 '''
191 Plot for Double Gaussian Plot
191 Plot for Double Gaussian Plot
192 '''
192 '''
193 CODE = 'gaussian_fit'
193 CODE = 'gaussian_fit'
194 # colormap = 'jet'
194 # colormap = 'jet'
195 # plot_type = 'pcolor'
195 # plot_type = 'pcolor'
196
196
197 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
197 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
198 '''
198 '''
199 Plot SpectraCut with Double Gaussian Fit
199 Plot SpectraCut with Double Gaussian Fit
200 '''
200 '''
201 CODE = 'cut_gaussian_fit'
201 CODE = 'cut_gaussian_fit'
202
202
203 class SnrPlot(RTIPlot):
203 class SnrPlot(RTIPlot):
204 '''
204 '''
205 Plot for SNR Data
205 Plot for SNR Data
206 '''
206 '''
207
207
208 CODE = 'snr'
208 CODE = 'snr'
209 colormap = 'jet'
209 colormap = 'jet'
210
210
211 def update(self, dataOut):
211 def update(self, dataOut):
212
212
213 data = {
213 data = {
214 'snr': 10*numpy.log10(dataOut.data_snr)
214 'snr': 10*numpy.log10(dataOut.data_snr)
215 }
215 }
216
216
217 return data, {}
217 return data, {}
218
218
219 class DopplerPlot(RTIPlot):
219 class DopplerPlot(RTIPlot):
220 '''
220 '''
221 Plot for DOPPLER Data (1st moment)
221 Plot for DOPPLER Data (1st moment)
222 '''
222 '''
223
223
224 CODE = 'dop'
224 CODE = 'dop'
225 colormap = 'jet'
225 colormap = 'jet'
226
226
227 def update(self, dataOut):
227 def update(self, dataOut):
228
228
229 data = {
229 data = {
230 'dop': 10*numpy.log10(dataOut.data_dop)
230 'dop': 10*numpy.log10(dataOut.data_dop)
231 }
231 }
232
232
233 return data, {}
233 return data, {}
234
234
235 class PowerPlot(RTIPlot):
235 class PowerPlot(RTIPlot):
236 '''
236 '''
237 Plot for Power Data (0 moment)
237 Plot for Power Data (0 moment)
238 '''
238 '''
239
239
240 CODE = 'pow'
240 CODE = 'pow'
241 colormap = 'jet'
241 colormap = 'jet'
242
242
243 def update(self, dataOut):
243 def update(self, dataOut):
244 data = {
244 data = {
245 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
245 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
246 }
246 }
247 return data, {}
247 return data, {}
248
248
249 class SpectralWidthPlot(RTIPlot):
249 class SpectralWidthPlot(RTIPlot):
250 '''
250 '''
251 Plot for Spectral Width Data (2nd moment)
251 Plot for Spectral Width Data (2nd moment)
252 '''
252 '''
253
253
254 CODE = 'width'
254 CODE = 'width'
255 colormap = 'jet'
255 colormap = 'jet'
256
256
257 def update(self, dataOut):
257 def update(self, dataOut):
258
258
259 data = {
259 data = {
260 'width': dataOut.data_width
260 'width': dataOut.data_width
261 }
261 }
262
262
263 return data, {}
263 return data, {}
264
264
265 class SkyMapPlot(Plot):
265 class SkyMapPlot(Plot):
266 '''
266 '''
267 Plot for meteors detection data
267 Plot for meteors detection data
268 '''
268 '''
269
269
270 CODE = 'param'
270 CODE = 'param'
271
271
272 def setup(self):
272 def setup(self):
273
273
274 self.ncols = 1
274 self.ncols = 1
275 self.nrows = 1
275 self.nrows = 1
276 self.width = 7.2
276 self.width = 7.2
277 self.height = 7.2
277 self.height = 7.2
278 self.nplots = 1
278 self.nplots = 1
279 self.xlabel = 'Zonal Zenith Angle (deg)'
279 self.xlabel = 'Zonal Zenith Angle (deg)'
280 self.ylabel = 'Meridional Zenith Angle (deg)'
280 self.ylabel = 'Meridional Zenith Angle (deg)'
281 self.polar = True
281 self.polar = True
282 self.ymin = -180
282 self.ymin = -180
283 self.ymax = 180
283 self.ymax = 180
284 self.colorbar = False
284 self.colorbar = False
285
285
286 def plot(self):
286 def plot(self):
287
287
288 arrayParameters = numpy.concatenate(self.data['param'])
288 arrayParameters = numpy.concatenate(self.data['param'])
289 error = arrayParameters[:, -1]
289 error = arrayParameters[:, -1]
290 indValid = numpy.where(error == 0)[0]
290 indValid = numpy.where(error == 0)[0]
291 finalMeteor = arrayParameters[indValid, :]
291 finalMeteor = arrayParameters[indValid, :]
292 finalAzimuth = finalMeteor[:, 3]
292 finalAzimuth = finalMeteor[:, 3]
293 finalZenith = finalMeteor[:, 4]
293 finalZenith = finalMeteor[:, 4]
294
294
295 x = finalAzimuth * numpy.pi / 180
295 x = finalAzimuth * numpy.pi / 180
296 y = finalZenith
296 y = finalZenith
297
297
298 ax = self.axes[0]
298 ax = self.axes[0]
299
299
300 if ax.firsttime:
300 if ax.firsttime:
301 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
301 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
302 else:
302 else:
303 ax.plot.set_data(x, y)
303 ax.plot.set_data(x, y)
304
304
305 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
305 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
306 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
306 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
307 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
307 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
308 dt2,
308 dt2,
309 len(x))
309 len(x))
310 self.titles[0] = title
310 self.titles[0] = title
311
311
312
312
313 class GenericRTIPlot(Plot):
313 class GenericRTIPlot(Plot):
314 '''
314 '''
315 Plot for data_xxxx object
315 Plot for data_xxxx object
316 '''
316 '''
317
317
318 CODE = 'param'
318 CODE = 'param'
319 colormap = 'viridis'
319 colormap = 'viridis'
320 plot_type = 'pcolorbuffer'
320 plot_type = 'pcolorbuffer'
321
321
322 def setup(self):
322 def setup(self):
323 self.xaxis = 'time'
323 self.xaxis = 'time'
324 self.ncols = 1
324 self.ncols = 1
325 self.nrows = self.data.shape('param')[0]
325 self.nrows = self.data.shape('param')[0]
326 self.nplots = self.nrows
326 self.nplots = self.nrows
327 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
327 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
328
328
329 if not self.xlabel:
329 if not self.xlabel:
330 self.xlabel = 'Time'
330 self.xlabel = 'Time'
331
331
332 self.ylabel = 'Range [km]'
332 self.ylabel = 'Range [km]'
333 if not self.titles:
333 if not self.titles:
334 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
334 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
335
335
336 def update(self, dataOut):
336 def update(self, dataOut):
337
337
338 data = {
338 data = {
339 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
339 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
340 }
340 }
341
341
342 meta = {}
342 meta = {}
343
343
344 return data, meta
344 return data, meta
345
345
346 def plot(self):
346 def plot(self):
347 # self.data.normalize_heights()
347 # self.data.normalize_heights()
348 self.x = self.data.times
348 self.x = self.data.times
349 self.y = self.data.yrange
349 self.y = self.data.yrange
350 self.z = self.data['param']
350 self.z = self.data['param']
351 self.z = 10*numpy.log10(self.z)
351 self.z = 10*numpy.log10(self.z)
352 self.z = numpy.ma.masked_invalid(self.z)
352 self.z = numpy.ma.masked_invalid(self.z)
353
353
354 if self.decimation is None:
354 if self.decimation is None:
355 x, y, z = self.fill_gaps(self.x, self.y, self.z)
355 x, y, z = self.fill_gaps(self.x, self.y, self.z)
356 else:
356 else:
357 x, y, z = self.fill_gaps(*self.decimate())
357 x, y, z = self.fill_gaps(*self.decimate())
358
358
359 for n, ax in enumerate(self.axes):
359 for n, ax in enumerate(self.axes):
360
360
361 self.zmax = self.zmax if self.zmax is not None else numpy.max(
361 self.zmax = self.zmax if self.zmax is not None else numpy.max(
362 self.z[n])
362 self.z[n])
363 self.zmin = self.zmin if self.zmin is not None else numpy.min(
363 self.zmin = self.zmin if self.zmin is not None else numpy.min(
364 self.z[n])
364 self.z[n])
365
365
366 if ax.firsttime:
366 if ax.firsttime:
367 if self.zlimits is not None:
367 if self.zlimits is not None:
368 self.zmin, self.zmax = self.zlimits[n]
368 self.zmin, self.zmax = self.zlimits[n]
369
369
370 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
370 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
371 vmin=self.zmin,
371 vmin=self.zmin,
372 vmax=self.zmax,
372 vmax=self.zmax,
373 cmap=self.cmaps[n]
373 cmap=self.cmaps[n]
374 )
374 )
375 else:
375 else:
376 if self.zlimits is not None:
376 if self.zlimits is not None:
377 self.zmin, self.zmax = self.zlimits[n]
377 self.zmin, self.zmax = self.zlimits[n]
378 ax.collections.remove(ax.collections[0])
378 ax.collections.remove(ax.collections[0])
379 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
379 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
380 vmin=self.zmin,
380 vmin=self.zmin,
381 vmax=self.zmax,
381 vmax=self.zmax,
382 cmap=self.cmaps[n]
382 cmap=self.cmaps[n]
383 )
383 )
384
384
385
385
386 class PolarMapPlot(Plot):
386 class PolarMapPlot(Plot):
387 '''
387 '''
388 Plot for weather radar
388 Plot for weather radar
389 '''
389 '''
390
390
391 CODE = 'param'
391 CODE = 'param'
392 colormap = 'seismic'
392 colormap = 'seismic'
393
393
394 def setup(self):
394 def setup(self):
395 self.ncols = 1
395 self.ncols = 1
396 self.nrows = 1
396 self.nrows = 1
397 self.width = 9
397 self.width = 9
398 self.height = 8
398 self.height = 8
399 self.mode = self.data.meta['mode']
399 self.mode = self.data.meta['mode']
400 if self.channels is not None:
400 if self.channels is not None:
401 self.nplots = len(self.channels)
401 self.nplots = len(self.channels)
402 self.nrows = len(self.channels)
402 self.nrows = len(self.channels)
403 else:
403 else:
404 self.nplots = self.data.shape(self.CODE)[0]
404 self.nplots = self.data.shape(self.CODE)[0]
405 self.nrows = self.nplots
405 self.nrows = self.nplots
406 self.channels = list(range(self.nplots))
406 self.channels = list(range(self.nplots))
407 if self.mode == 'E':
407 if self.mode == 'E':
408 self.xlabel = 'Longitude'
408 self.xlabel = 'Longitude'
409 self.ylabel = 'Latitude'
409 self.ylabel = 'Latitude'
410 else:
410 else:
411 self.xlabel = 'Range (km)'
411 self.xlabel = 'Range (km)'
412 self.ylabel = 'Height (km)'
412 self.ylabel = 'Height (km)'
413 self.bgcolor = 'white'
413 self.bgcolor = 'white'
414 self.cb_labels = self.data.meta['units']
414 self.cb_labels = self.data.meta['units']
415 self.lat = self.data.meta['latitude']
415 self.lat = self.data.meta['latitude']
416 self.lon = self.data.meta['longitude']
416 self.lon = self.data.meta['longitude']
417 self.xmin, self.xmax = float(
417 self.xmin, self.xmax = float(
418 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
418 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
419 self.ymin, self.ymax = float(
419 self.ymin, self.ymax = float(
420 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
420 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
421 # self.polar = True
421 # self.polar = True
422
422
423 def plot(self):
423 def plot(self):
424
424
425 for n, ax in enumerate(self.axes):
425 for n, ax in enumerate(self.axes):
426 data = self.data['param'][self.channels[n]]
426 data = self.data['param'][self.channels[n]]
427
427
428 zeniths = numpy.linspace(
428 zeniths = numpy.linspace(
429 0, self.data.meta['max_range'], data.shape[1])
429 0, self.data.meta['max_range'], data.shape[1])
430 if self.mode == 'E':
430 if self.mode == 'E':
431 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
431 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
432 r, theta = numpy.meshgrid(zeniths, azimuths)
432 r, theta = numpy.meshgrid(zeniths, azimuths)
433 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
433 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
434 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
434 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
435 x = km2deg(x) + self.lon
435 x = km2deg(x) + self.lon
436 y = km2deg(y) + self.lat
436 y = km2deg(y) + self.lat
437 else:
437 else:
438 azimuths = numpy.radians(self.data.yrange)
438 azimuths = numpy.radians(self.data.yrange)
439 r, theta = numpy.meshgrid(zeniths, azimuths)
439 r, theta = numpy.meshgrid(zeniths, azimuths)
440 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
440 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
441 self.y = zeniths
441 self.y = zeniths
442
442
443 if ax.firsttime:
443 if ax.firsttime:
444 if self.zlimits is not None:
444 if self.zlimits is not None:
445 self.zmin, self.zmax = self.zlimits[n]
445 self.zmin, self.zmax = self.zlimits[n]
446 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
446 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
447 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
447 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
448 vmin=self.zmin,
448 vmin=self.zmin,
449 vmax=self.zmax,
449 vmax=self.zmax,
450 cmap=self.cmaps[n])
450 cmap=self.cmaps[n])
451 else:
451 else:
452 if self.zlimits is not None:
452 if self.zlimits is not None:
453 self.zmin, self.zmax = self.zlimits[n]
453 self.zmin, self.zmax = self.zlimits[n]
454 ax.collections.remove(ax.collections[0])
454 ax.collections.remove(ax.collections[0])
455 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
455 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
456 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
456 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
457 vmin=self.zmin,
457 vmin=self.zmin,
458 vmax=self.zmax,
458 vmax=self.zmax,
459 cmap=self.cmaps[n])
459 cmap=self.cmaps[n])
460
460
461 if self.mode == 'A':
461 if self.mode == 'A':
462 continue
462 continue
463
463
464 # plot district names
464 # plot district names
465 f = open('/data/workspace/schain_scripts/distrito.csv')
465 f = open('/data/workspace/schain_scripts/distrito.csv')
466 for line in f:
466 for line in f:
467 label, lon, lat = [s.strip() for s in line.split(',') if s]
467 label, lon, lat = [s.strip() for s in line.split(',') if s]
468 lat = float(lat)
468 lat = float(lat)
469 lon = float(lon)
469 lon = float(lon)
470 # ax.plot(lon, lat, '.b', ms=2)
470 # ax.plot(lon, lat, '.b', ms=2)
471 ax.text(lon, lat, label.decode('utf8'), ha='center',
471 ax.text(lon, lat, label.decode('utf8'), ha='center',
472 va='bottom', size='8', color='black')
472 va='bottom', size='8', color='black')
473
473
474 # plot limites
474 # plot limites
475 limites = []
475 limites = []
476 tmp = []
476 tmp = []
477 for line in open('/data/workspace/schain_scripts/lima.csv'):
477 for line in open('/data/workspace/schain_scripts/lima.csv'):
478 if '#' in line:
478 if '#' in line:
479 if tmp:
479 if tmp:
480 limites.append(tmp)
480 limites.append(tmp)
481 tmp = []
481 tmp = []
482 continue
482 continue
483 values = line.strip().split(',')
483 values = line.strip().split(',')
484 tmp.append((float(values[0]), float(values[1])))
484 tmp.append((float(values[0]), float(values[1])))
485 for points in limites:
485 for points in limites:
486 ax.add_patch(
486 ax.add_patch(
487 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
487 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
488
488
489 # plot Cuencas
489 # plot Cuencas
490 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
490 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
491 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
491 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
492 values = [line.strip().split(',') for line in f]
492 values = [line.strip().split(',') for line in f]
493 points = [(float(s[0]), float(s[1])) for s in values]
493 points = [(float(s[0]), float(s[1])) for s in values]
494 ax.add_patch(Polygon(points, ec='b', fc='none'))
494 ax.add_patch(Polygon(points, ec='b', fc='none'))
495
495
496 # plot grid
496 # plot grid
497 for r in (15, 30, 45, 60):
497 for r in (15, 30, 45, 60):
498 ax.add_artist(plt.Circle((self.lon, self.lat),
498 ax.add_artist(plt.Circle((self.lon, self.lat),
499 km2deg(r), color='0.6', fill=False, lw=0.2))
499 km2deg(r), color='0.6', fill=False, lw=0.2))
500 ax.text(
500 ax.text(
501 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
501 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
502 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
502 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
503 '{}km'.format(r),
503 '{}km'.format(r),
504 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
504 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
505
505
506 if self.mode == 'E':
506 if self.mode == 'E':
507 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
507 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
508 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
508 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
509 else:
509 else:
510 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
510 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
511 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
511 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
512
512
513 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
513 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
514 self.titles = ['{} {}'.format(
514 self.titles = ['{} {}'.format(
515 self.data.parameters[x], title) for x in self.channels]
515 self.data.parameters[x], title) for x in self.channels]
516
516
517 class WeatherParamsPlot(Plot):
517 class WeatherParamsPlot(Plot):
518 #CODE = 'RHI'
518 #CODE = 'RHI'
519 #plot_name = 'RHI'
519 #plot_name = 'RHI'
520 plot_type = 'scattermap'
520 plot_type = 'scattermap'
521 buffering = False
521 buffering = False
522 projection = ccrs.PlateCarree()
522 projection = ccrs.PlateCarree()
523
523
524 def setup(self):
524 def setup(self):
525
525
526 self.ncols = 1
526 self.ncols = 1
527 self.nrows = 1
527 self.nrows = 1
528 self.nplots= 1
528 self.nplots= 1
529 self.ylabel= 'Height [km]'
529 self.ylabel= 'Height [km]'
530 self.xlabel= 'Distance from radar [km]'
530 self.xlabel= 'Distance from radar [km]'
531
531
532 if self.channels is not None:
532 if self.channels is not None:
533 self.nplots = len(self.channels)
533 self.nplots = len(self.channels)
534 self.ncols = len(self.channels)
534 self.ncols = len(self.channels)
535 else:
535 else:
536 self.nplots = self.data.shape(self.CODE)[0]
536 self.nplots = self.data.shape(self.CODE)[0]
537 self.ncols = self.nplots
537 self.ncols = self.nplots
538 self.channels = list(range(self.nplots))
538 self.channels = list(range(self.nplots))
539
539
540 self.colorbar=True
540 self.colorbar=True
541 if len(self.channels)>1:
541 if len(self.channels)>1:
542 self.width = 12
542 self.width = 12
543 else:
543 else:
544 self.width =8
544 self.width =8
545 self.height =7
545 self.height =7
546 self.ini =0
546 self.ini =0
547 self.len_azi =0
547 self.len_azi =0
548 self.buffer_ini = None
548 self.buffer_ini = None
549 self.buffer_ele = None
549 self.buffer_ele = None
550 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.1})
550 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.1})
551 self.flag =0
551 self.flag =0
552 self.indicador= 0
552 self.indicador= 0
553 self.last_data_ele = None
553 self.last_data_ele = None
554 self.val_mean = None
554 self.val_mean = None
555
555
556 def update(self, dataOut):
556 def update(self, dataOut):
557
557
558 vars = {
558 vars = {
559 'S' : 0,
559 'S' : 0,
560 'V' : 1,
560 'V' : 1,
561 'W' : 2,
561 'W' : 2,
562 'SNR' : 3,
562 'SNR' : 3,
563 'Z' : 4,
563 'Z' : 4,
564 'D' : 5,
564 'D' : 5,
565 'P' : 6,
565 'P' : 6,
566 'R' : 7,
566 'R' : 7,
567 }
567 }
568
568
569 data = {}
569 data = {}
570 meta = {}
570 meta = {}
571
571
572 if hasattr(dataOut, 'nFFTPoints'):
572 if hasattr(dataOut, 'nFFTPoints'):
573 factor = dataOut.normFactor
573 factor = dataOut.normFactor
574 else:
574 else:
575 factor = 1
575 factor = 1
576
576
577 if hasattr(dataOut, 'dparam'):
577 if hasattr(dataOut, 'dparam'):
578 tmp = getattr(dataOut, 'data_param')
578 tmp = getattr(dataOut, 'data_param')
579 else:
579 else:
580
580 #print("-------------------self.attr_data[0]",self.attr_data[0])
581 if 'S' in self.attr_data[0]:
581 if 'S' in self.attr_data[0]:
582 tmp = 10*numpy.log10(10.0*getattr(dataOut, 'data_param')[:,0,:]/(factor))
582 if self.attr_data[0]=='S':
583 tmp = 10*numpy.log10(10.0*getattr(dataOut, 'data_param')[:,0,:]/(factor))
584 if self.attr_data[0]=='SNR':
585 tmp = 10*numpy.log10(getattr(dataOut, 'data_param')[:,3,:])
583 else:
586 else:
584 tmp = getattr(dataOut, 'data_param')[:,vars[self.attr_data[0]],:]
587 tmp = getattr(dataOut, 'data_param')[:,vars[self.attr_data[0]],:]
585
588
586 if self.mask:
589 if self.mask:
587 mask = dataOut.data_param[:,3,:] < self.mask
590 mask = dataOut.data_param[:,3,:] < self.mask
588 tmp = numpy.ma.masked_array(tmp, mask=mask)
591 tmp = numpy.ma.masked_array(tmp, mask=mask)
589
592
590 r = dataOut.heightList
593 r = dataOut.heightList
591 delta_height = r[1]-r[0]
594 delta_height = r[1]-r[0]
592 valid = numpy.where(r>=0)[0]
595 valid = numpy.where(r>=0)[0]
593 data['r'] = numpy.arange(len(valid))*delta_height
596 data['r'] = numpy.arange(len(valid))*delta_height
594
597
595 data['data'] = [0, 0]
598 data['data'] = [0, 0]
596
599
597 try:
600 try:
598 data['data'][0] = tmp[0][:,valid]
601 data['data'][0] = tmp[0][:,valid]
599 data['data'][1] = tmp[1][:,valid]
602 data['data'][1] = tmp[1][:,valid]
600 except:
603 except:
601 data['data'][0] = tmp[0][:,valid]
604 data['data'][0] = tmp[0][:,valid]
602 data['data'][1] = tmp[0][:,valid]
605 data['data'][1] = tmp[0][:,valid]
603
606
604 if dataOut.mode_op == 'PPI':
607 if dataOut.mode_op == 'PPI':
605 self.CODE = 'PPI'
608 self.CODE = 'PPI'
606 self.title = self.CODE
609 self.title = self.CODE
607 elif dataOut.mode_op == 'RHI':
610 elif dataOut.mode_op == 'RHI':
608 self.CODE = 'RHI'
611 self.CODE = 'RHI'
609 self.title = self.CODE
612 self.title = self.CODE
610
613
611 data['azi'] = dataOut.data_azi
614 data['azi'] = dataOut.data_azi
612 data['ele'] = dataOut.data_ele
615 data['ele'] = dataOut.data_ele
616
617 if isinstance(dataOut.mode_op, bytes):
618 try:
619 dataOut.mode_op = dataOut.mode_op.decode()
620 except:
621 dataOut.mode_op = str(dataOut.mode_op, 'utf-8')
613 data['mode_op'] = dataOut.mode_op
622 data['mode_op'] = dataOut.mode_op
614 self.mode = dataOut.mode_op
623 self.mode = dataOut.mode_op
615
624
616 return data, meta
625 return data, meta
617
626
618 def plot(self):
627 def plot(self):
619 data = self.data[-1]
628 data = self.data[-1]
620 z = data['data']
629 z = data['data']
621 r = data['r']
630 r = data['r']
622 self.titles = []
631 self.titles = []
623
632
624 self.ymax = self.ymax if self.ymax else numpy.nanmax(r)
633 self.ymax = self.ymax if self.ymax else numpy.nanmax(r)
625 self.ymin = self.ymin if self.ymin else numpy.nanmin(r)
634 self.ymin = self.ymin if self.ymin else numpy.nanmin(r)
626 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
635 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
627 self.zmin = self.zmin if self.zmin is not None else numpy.nanmin(z)
636 self.zmin = self.zmin if self.zmin is not None else numpy.nanmin(z)
628
637
629 if isinstance(data['mode_op'], bytes):
638 if isinstance(data['mode_op'], bytes):
630 data['mode_op'] = data['mode_op'].decode()
639 data['mode_op'] = data['mode_op'].decode()
631
640
632 if data['mode_op'] == 'RHI':
641 if data['mode_op'] == 'RHI':
633 r, theta = numpy.meshgrid(r, numpy.radians(data['ele']))
642 r, theta = numpy.meshgrid(r, numpy.radians(data['ele']))
634 len_aux = int(data['azi'].shape[0]/4)
643 len_aux = int(data['azi'].shape[0]/4)
635 mean = numpy.mean(data['azi'][len_aux:-len_aux])
644 mean = numpy.mean(data['azi'][len_aux:-len_aux])
636 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
645 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
637 elif data['mode_op'] == 'PPI':
646 elif data['mode_op'] == 'PPI':
638 r, theta = numpy.meshgrid(r, -numpy.radians(data['azi'])+numpy.pi/2)
647 r, theta = numpy.meshgrid(r, -numpy.radians(data['azi'])+numpy.pi/2)
639 len_aux = int(data['ele'].shape[0]/4)
648 len_aux = int(data['ele'].shape[0]/4)
640 mean = numpy.mean(data['ele'][len_aux:-len_aux])
649 mean = numpy.mean(data['ele'][len_aux:-len_aux])
641 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(mean)), r*numpy.sin(
650 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(mean)), r*numpy.sin(
642 theta)*numpy.cos(numpy.radians(mean))
651 theta)*numpy.cos(numpy.radians(mean))
643 x = km2deg(x) + -75.295893
652 x = km2deg(x) + -75.295893
644 y = km2deg(y) + -12.040436
653 y = km2deg(y) + -12.040436
645
654
646 self.clear_figures()
655 self.clear_figures()
647
656
648 if data['mode_op'] == 'PPI':
657 if data['mode_op'] == 'PPI':
649 axes = self.axes['PPI']
658 axes = self.axes['PPI']
650 else:
659 else:
651 axes = self.axes['RHI']
660 axes = self.axes['RHI']
652
661
653 if self.colormap in cb_tables:
662 if self.colormap in cb_tables:
654 norm = cb_tables[self.colormap]['norm']
663 norm = cb_tables[self.colormap]['norm']
655 else:
664 else:
656 norm = None
665 norm = None
657
666
658 for i, ax in enumerate(axes):
667 for i, ax in enumerate(axes):
659 if data['mode_op'] == 'PPI':
668 if data['mode_op'] == 'PPI':
660 ax.set_extent([-75.745893, -74.845893, -12.490436, -11.590436])
669 ax.set_extent([-75.745893, -74.845893, -12.490436, -11.590436])
661
670
662 if norm is None:
671 if norm is None:
663 ax.plt = ax.pcolormesh(x, y, z[i], cmap=self.colormap, vmin=self.zmin, vmax=self.zmax)
672 ax.plt = ax.pcolormesh(x, y, z[i], cmap=self.colormap, vmin=self.zmin, vmax=self.zmax)
664 else:
673 else:
665 ax.plt = ax.pcolormesh(x, y, z[i], cmap=self.colormap, norm=norm)
674 ax.plt = ax.pcolormesh(x, y, z[i], cmap=self.colormap, norm=norm)
666
675
667 if data['mode_op'] == 'RHI':
676 if data['mode_op'] == 'RHI':
668 len_aux = int(data['azi'].shape[0]/4)
677 len_aux = int(data['azi'].shape[0]/4)
669 mean = numpy.mean(data['azi'][len_aux:-len_aux])
678 mean = numpy.mean(data['azi'][len_aux:-len_aux])
670 if len(self.channels) !=1:
679 if len(self.channels) !=1:
671 self.titles = ['RHI {} at AZ: {} CH {}'.format(self.labels[x], str(round(mean,1)), x) for x in self.channels]
680 self.titles = ['RHI {} at AZ: {} CH {}'.format(self.labels[x], str(round(mean,1)), x) for x in self.channels]
672 else:
681 else:
673 self.titles = ['RHI {} at AZ: {} CH {}'.format(self.labels[0], str(round(mean,1)), self.channels[0])]
682 self.titles = ['RHI {} at AZ: {} CH {}'.format(self.labels[0], str(round(mean,1)), self.channels[0])]
674 elif data['mode_op'] == 'PPI':
683 elif data['mode_op'] == 'PPI':
675 len_aux = int(data['ele'].shape[0]/4)
684 len_aux = int(data['ele'].shape[0]/4)
676 mean = numpy.mean(data['ele'][len_aux:-len_aux])
685 mean = numpy.mean(data['ele'][len_aux:-len_aux])
677 if len(self.channels) !=1:
686 if len(self.channels) !=1:
678 self.titles = ['PPI {} at EL: {} CH {}'.format(self.labels[x], str(round(mean,1)), x) for x in self.channels]
687 self.titles = ['PPI {} at EL: {} CH {}'.format(self.labels[x], str(round(mean,1)), x) for x in self.channels]
679 else:
688 else:
680 self.titles = ['PPI {} at EL: {} CH {}'.format(self.labels[0], str(round(mean,1)), self.channels[0])]
689 self.titles = ['PPI {} at EL: {} CH {}'.format(self.labels[0], str(round(mean,1)), self.channels[0])]
681 self.mode_value = round(mean,1)
690 self.mode_value = round(mean,1)
682
691
683 if data['mode_op'] == 'PPI':
692 if data['mode_op'] == 'PPI':
684 gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
693 gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
685 linewidth=1, color='gray', alpha=0.5, linestyle='--')
694 linewidth=1, color='gray', alpha=0.5, linestyle='--')
686 gl.xlabel_style = {'size': 8}
695 gl.xlabel_style = {'size': 8}
687 gl.ylabel_style = {'size': 8}
696 gl.ylabel_style = {'size': 8}
688 gl.xlabels_top = False
697 gl.xlabels_top = False
689 gl.ylabels_right = False
698 gl.ylabels_right = False
699 #self.shapes="/home/soporte/workspace/sirm/volumes/schain/shapes/"
700 #print("self.shapes",self.shapes)
690 shape_p = os.path.join(self.shapes,'PER_ADM2/PER_ADM2.shp')
701 shape_p = os.path.join(self.shapes,'PER_ADM2/PER_ADM2.shp')
691 shape_d = os.path.join(self.shapes,'PER_ADM1/PER_ADM1.shp')
702 shape_d = os.path.join(self.shapes,'PER_ADM1/PER_ADM1.shp')
692 capitales = os.path.join(self.shapes,'CAPITALES/cap_provincia.shp')
703 capitales = os.path.join(self.shapes,'CAPITALES/cap_provincia.shp')
693 vias = os.path.join(self.shapes,'Carreteras/VIAS_NACIONAL_250000.shp')
704 vias = os.path.join(self.shapes,'Carreteras/VIAS_NACIONAL_250000.shp')
694 reader_d = shpreader.BasicReader(shape_p, encoding='latin1')
705 reader_d = shpreader.BasicReader(shape_p, encoding='latin1')
695 reader_p = shpreader.BasicReader(shape_d, encoding='latin1')
706 reader_p = shpreader.BasicReader(shape_d, encoding='latin1')
696 reader_c = shpreader.BasicReader(capitales, encoding='latin1')
707 reader_c = shpreader.BasicReader(capitales, encoding='latin1')
697 reader_v = shpreader.BasicReader(vias, encoding='latin1')
708 reader_v = shpreader.BasicReader(vias, encoding='latin1')
698 caps = [x for x in reader_c.records() if x.attributes["Departa"] in ("JUNIN", "LIMA", "AYACUCHO", "HUANCAVELICA")]
709 caps = [x for x in reader_c.records() if x.attributes["Departa"] in ("JUNIN", "LIMA", "AYACUCHO", "HUANCAVELICA")]
699 districts = [x for x in reader_d.records() if x.attributes["Name"] in ("JUNÍN", "CHANCHAMAYO", "CHUPACA", "CONCEPCIΓ“N", "HUANCAYO", "JAUJA", "SATIPO", "TARMA", "YAUYOS", "HUAROCHIRÍ", "CANTA", "HUANTA", "TAYACAJA")]
710 districts = [x for x in reader_d.records() if x.attributes["Name"] in ("JUNÍN", "CHANCHAMAYO", "CHUPACA", "CONCEPCIΓ“N", "HUANCAYO", "JAUJA", "SATIPO", "TARMA", "YAUYOS", "HUAROCHIRÍ", "CANTA", "HUANTA", "TAYACAJA")]
700 provs = [x for x in reader_p.records() if x.attributes["NAME"] in ("JunΓ­n", "Lima")]
711 provs = [x for x in reader_p.records() if x.attributes["NAME"] in ("JunΓ­n", "Lima")]
701 vias = [x for x in reader_v.records() if x.attributes["DEP"] in ("JUNIN", "LIMA")]
712 vias = [x for x in reader_v.records() if x.attributes["DEP"] in ("JUNIN", "LIMA")]
702
713
703 # Display limits and streets
714 # Display limits and streets
704 shape_feature = ShapelyFeature([x.geometry for x in districts], ccrs.PlateCarree(), facecolor="none", edgecolor='grey', lw=0.5)
715 shape_feature = ShapelyFeature([x.geometry for x in districts], ccrs.PlateCarree(), facecolor="none", edgecolor='grey', lw=0.5)
705 ax.add_feature(shape_feature)
716 ax.add_feature(shape_feature)
706 shape_feature = ShapelyFeature([x.geometry for x in provs], ccrs.PlateCarree(), facecolor="none", edgecolor='white', lw=1)
717 shape_feature = ShapelyFeature([x.geometry for x in provs], ccrs.PlateCarree(), facecolor="none", edgecolor='white', lw=1)
707 ax.add_feature(shape_feature)
718 ax.add_feature(shape_feature)
708 shape_feature = ShapelyFeature([x.geometry for x in vias], ccrs.PlateCarree(), facecolor="none", edgecolor='yellow', lw=1)
719 shape_feature = ShapelyFeature([x.geometry for x in vias], ccrs.PlateCarree(), facecolor="none", edgecolor='yellow', lw=1)
709 ax.add_feature(shape_feature)
720 ax.add_feature(shape_feature)
710
721
711 for cap in caps:
722 for cap in caps:
712 if cap.attributes['Nombre'] in ("LA OROYA", "CONCEPCIΓ“N", "HUANCAYO", "JAUJA", "CHUPACA", "YAUYOS", "HUANTA", "PAMPAS"):
723 if cap.attributes['Nombre'] in ("LA OROYA", "CONCEPCIΓ“N", "HUANCAYO", "JAUJA", "CHUPACA", "YAUYOS", "HUANTA", "PAMPAS"):
713 ax.text(cap.attributes['X'], cap.attributes['Y'], cap.attributes['Nombre'].title(), size=7, color='white')
724 ax.text(cap.attributes['X'], cap.attributes['Y'], cap.attributes['Nombre'].title(), size=7, color='white')
714 ax.text(-75.052003, -11.915552, 'Huaytapallana', size=7, color='cyan')
725 ax.text(-75.052003, -11.915552, 'Huaytapallana', size=7, color='cyan')
715 ax.plot(-75.052003, -11.915552, '*')
726 ax.plot(-75.052003, -11.915552, '*')
716
727
717 for R in (10, 20, 30 , 40, 50):
728 for R in (10, 20, 30 , 40, 50):
718 circle = Circle((-75.295893, -12.040436), km2deg(R), facecolor='none',
729 circle = Circle((-75.295893, -12.040436), km2deg(R), facecolor='none',
719 edgecolor='skyblue', linewidth=1, alpha=0.5)
730 edgecolor='skyblue', linewidth=1, alpha=0.5)
720 ax.add_patch(circle)
731 ax.add_patch(circle)
721 ax.text(km2deg(R)*numpy.cos(numpy.radians(45))-75.295893,
732 ax.text(km2deg(R)*numpy.cos(numpy.radians(45))-75.295893,
722 km2deg(R)*numpy.sin(numpy.radians(45))-12.040436,
733 km2deg(R)*numpy.sin(numpy.radians(45))-12.040436,
723 '{}km'.format(R), color='skyblue', size=7)
734 '{}km'.format(R), color='skyblue', size=7)
724 elif data['mode_op'] == 'RHI':
735 elif data['mode_op'] == 'RHI':
725 ax.grid(color='grey', alpha=0.5, linestyle='--', linewidth=1)
736 ax.grid(color='grey', alpha=0.5, linestyle='--', linewidth=1)
@@ -1,743 +1,743
1 # Copyright (c) 2012-2021 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2021 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Classes to plot Spectra data
5 """Classes to plot Spectra data
6
6
7 """
7 """
8
8
9 import os
9 import os
10 import numpy
10 import numpy
11
11
12 from schainpy.model.graphics.jroplot_base import Plot, plt, log
12 from schainpy.model.graphics.jroplot_base import Plot, plt, log
13
13
14
14
15 class SpectraPlot(Plot):
15 class SpectraPlot(Plot):
16 '''
16 '''
17 Plot for Spectra data
17 Plot for Spectra data
18 '''
18 '''
19
19
20 CODE = 'spc'
20 CODE = 'spc'
21 colormap = 'jet'
21 colormap = 'jet'
22 plot_type = 'pcolor'
22 plot_type = 'pcolor'
23 buffering = False
23 buffering = False
24
24
25 def setup(self):
25 def setup(self):
26 self.nplots = len(self.data.channels)
26 self.nplots = len(self.data.channels)
27 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
27 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
28 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
28 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
29 self.height = 2.6 * self.nrows
29 self.height = 2.6 * self.nrows
30 self.cb_label = 'dB'
30 self.cb_label = 'dB'
31 if self.showprofile:
31 if self.showprofile:
32 self.width = 4 * self.ncols
32 self.width = 4 * self.ncols
33 else:
33 else:
34 self.width = 3.5 * self.ncols
34 self.width = 3.5 * self.ncols
35 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
35 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
36 self.ylabel = 'Range [km]'
36 self.ylabel = 'Range [km]'
37
37
38 def update(self, dataOut):
38 def update(self, dataOut):
39
39
40 data = {}
40 data = {}
41 meta = {}
41 meta = {}
42 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
42 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
43 data['spc'] = spc
43 data['spc'] = spc
44 data['rti'] = dataOut.getPower()
44 data['rti'] = dataOut.getPower()
45 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
45 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
46 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
46 meta['xrange'] = (dataOut.getFreqRange(0)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(0))
47
47
48 if self.CODE == 'spc_moments':
48 if self.CODE == 'spc_moments':
49 data['moments'] = dataOut.moments
49 data['moments'] = dataOut.moments
50 # data['spc'] = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
50 # data['spc'] = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
51 if self.CODE == 'gaussian_fit':
51 if self.CODE == 'gaussian_fit':
52 # data['moments'] = dataOut.moments
52 # data['moments'] = dataOut.moments
53 data['gaussfit'] = dataOut.DGauFitParams
53 data['gaussfit'] = dataOut.DGauFitParams
54 # data['spc'] = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
54 # data['spc'] = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
55
55
56 return data, meta
56 return data, meta
57
57
58 def plot(self):
58 def plot(self):
59 if self.xaxis == "frequency":
59 if self.xaxis == "frequency":
60 x = self.data.xrange[0]
60 x = self.data.xrange[0]
61 self.xlabel = "Frequency (kHz)"
61 self.xlabel = "Frequency (kHz)"
62 elif self.xaxis == "time":
62 elif self.xaxis == "time":
63 x = self.data.xrange[1]
63 x = self.data.xrange[1]
64 self.xlabel = "Time (ms)"
64 self.xlabel = "Time (ms)"
65 else:
65 else:
66 x = self.data.xrange[2]
66 x = self.data.xrange[2]
67 self.xlabel = "Velocity (m/s)"
67 self.xlabel = "Velocity (m/s)"
68
68
69 if (self.CODE == 'spc_moments') | (self.CODE == 'gaussian_fit'):
69 if (self.CODE == 'spc_moments') | (self.CODE == 'gaussian_fit'):
70 x = self.data.xrange[2]
70 x = self.data.xrange[2]
71 self.xlabel = "Velocity (m/s)"
71 self.xlabel = "Velocity (m/s)"
72
72
73 self.titles = []
73 self.titles = []
74
74
75 y = self.data.yrange
75 y = self.data.yrange
76 self.y = y
76 self.y = y
77
77
78 data = self.data[-1]
78 data = self.data[-1]
79 z = data['spc']
79 z = data['spc']
80
80
81 for n, ax in enumerate(self.axes):
81 for n, ax in enumerate(self.axes):
82 noise = data['noise'][n]
82 noise = data['noise'][n]
83 if self.CODE == 'spc_moments':
83 if self.CODE == 'spc_moments':
84 mean = data['moments'][n, 1]
84 mean = data['moments'][n, 1]
85 if self.CODE == 'gaussian_fit':
85 if self.CODE == 'gaussian_fit':
86 # mean = data['moments'][n, 1]
86 # mean = data['moments'][n, 1]
87 gau0 = data['gaussfit'][n][2,:,0]
87 gau0 = data['gaussfit'][n][2,:,0]
88 gau1 = data['gaussfit'][n][2,:,1]
88 gau1 = data['gaussfit'][n][2,:,1]
89 if ax.firsttime:
89 if ax.firsttime:
90 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
90 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
91 self.xmin = self.xmin if self.xmin else -self.xmax
91 self.xmin = self.xmin if self.xmin else -self.xmax
92 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
92 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
93 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
93 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
94 ax.plt = ax.pcolormesh(x, y, z[n].T,
94 ax.plt = ax.pcolormesh(x, y, z[n].T,
95 vmin=self.zmin,
95 vmin=self.zmin,
96 vmax=self.zmax,
96 vmax=self.zmax,
97 cmap=plt.get_cmap(self.colormap)
97 cmap=plt.get_cmap(self.colormap)
98 )
98 )
99
99
100 if self.showprofile:
100 if self.showprofile:
101 ax.plt_profile = self.pf_axes[n].plot(
101 ax.plt_profile = self.pf_axes[n].plot(
102 data['rti'][n], y)[0]
102 data['rti'][n], y)[0]
103 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
103 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
104 color="k", linestyle="dashed", lw=1)[0]
104 color="k", linestyle="dashed", lw=1)[0]
105 if self.CODE == 'spc_moments':
105 if self.CODE == 'spc_moments':
106 ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
106 ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
107 if self.CODE == 'gaussian_fit':
107 if self.CODE == 'gaussian_fit':
108 # ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
108 # ax.plt_mean = ax.plot(mean, y, color='k', lw=1)[0]
109 ax.plt_gau0 = ax.plot(gau0, y, color='r', lw=1)[0]
109 ax.plt_gau0 = ax.plot(gau0, y, color='r', lw=1)[0]
110 ax.plt_gau1 = ax.plot(gau1, y, color='y', lw=1)[0]
110 ax.plt_gau1 = ax.plot(gau1, y, color='y', lw=1)[0]
111 else:
111 else:
112 ax.plt.set_array(z[n].T.ravel())
112 ax.plt.set_array(z[n].T.ravel())
113 if self.showprofile:
113 if self.showprofile:
114 ax.plt_profile.set_data(data['rti'][n], y)
114 ax.plt_profile.set_data(data['rti'][n], y)
115 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
115 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
116 if self.CODE == 'spc_moments':
116 if self.CODE == 'spc_moments':
117 ax.plt_mean.set_data(mean, y)
117 ax.plt_mean.set_data(mean, y)
118 if self.CODE == 'gaussian_fit':
118 if self.CODE == 'gaussian_fit':
119 # ax.plt_mean.set_data(mean, y)
119 # ax.plt_mean.set_data(mean, y)
120 ax.plt_gau0.set_data(gau0, y)
120 ax.plt_gau0.set_data(gau0, y)
121 ax.plt_gau1.set_data(gau1, y)
121 ax.plt_gau1.set_data(gau1, y)
122 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
122 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
123
123
124
124
125 class CrossSpectraPlot(Plot):
125 class CrossSpectraPlot(Plot):
126
126
127 CODE = 'cspc'
127 CODE = 'cspc'
128 colormap = 'jet'
128 colormap = 'jet'
129 plot_type = 'pcolor'
129 plot_type = 'pcolor'
130 zmin_coh = None
130 zmin_coh = None
131 zmax_coh = None
131 zmax_coh = None
132 zmin_phase = None
132 zmin_phase = None
133 zmax_phase = None
133 zmax_phase = None
134
134
135 def setup(self):
135 def setup(self):
136
136
137 self.ncols = 4
137 self.ncols = 4
138 self.nplots = len(self.data.pairs) * 2
138 self.nplots = len(self.data.pairs) * 2
139 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
139 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
140 self.width = 3.1 * self.ncols
140 self.width = 3.1 * self.ncols
141 self.height = 2.6 * self.nrows
141 self.height = 2.6 * self.nrows
142 self.ylabel = 'Range [km]'
142 self.ylabel = 'Range [km]'
143 self.showprofile = False
143 self.showprofile = False
144 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
144 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
145
145
146 def update(self, dataOut):
146 def update(self, dataOut):
147
147
148 data = {}
148 data = {}
149 meta = {}
149 meta = {}
150
150
151 spc = dataOut.data_spc
151 spc = dataOut.data_spc
152 cspc = dataOut.data_cspc
152 cspc = dataOut.data_cspc
153 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
153 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
154 meta['pairs'] = dataOut.pairsList
154 meta['pairs'] = dataOut.pairsList
155
155
156 tmp = []
156 tmp = []
157
157
158 for n, pair in enumerate(meta['pairs']):
158 for n, pair in enumerate(meta['pairs']):
159 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
159 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
160 coh = numpy.abs(out)
160 coh = numpy.abs(out)
161 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
161 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
162 tmp.append(coh)
162 tmp.append(coh)
163 tmp.append(phase)
163 tmp.append(phase)
164
164
165 data['cspc'] = numpy.array(tmp)
165 data['cspc'] = numpy.array(tmp)
166
166
167 return data, meta
167 return data, meta
168
168
169 def plot(self):
169 def plot(self):
170
170
171 if self.xaxis == "frequency":
171 if self.xaxis == "frequency":
172 x = self.data.xrange[0]
172 x = self.data.xrange[0]
173 self.xlabel = "Frequency (kHz)"
173 self.xlabel = "Frequency (kHz)"
174 elif self.xaxis == "time":
174 elif self.xaxis == "time":
175 x = self.data.xrange[1]
175 x = self.data.xrange[1]
176 self.xlabel = "Time (ms)"
176 self.xlabel = "Time (ms)"
177 else:
177 else:
178 x = self.data.xrange[2]
178 x = self.data.xrange[2]
179 self.xlabel = "Velocity (m/s)"
179 self.xlabel = "Velocity (m/s)"
180
180
181 self.titles = []
181 self.titles = []
182
182
183 y = self.data.yrange
183 y = self.data.yrange
184 self.y = y
184 self.y = y
185
185
186 data = self.data[-1]
186 data = self.data[-1]
187 cspc = data['cspc']
187 cspc = data['cspc']
188
188
189 for n in range(len(self.data.pairs)):
189 for n in range(len(self.data.pairs)):
190 pair = self.data.pairs[n]
190 pair = self.data.pairs[n]
191 coh = cspc[n*2]
191 coh = cspc[n*2]
192 phase = cspc[n*2+1]
192 phase = cspc[n*2+1]
193 ax = self.axes[2 * n]
193 ax = self.axes[2 * n]
194 if ax.firsttime:
194 if ax.firsttime:
195 ax.plt = ax.pcolormesh(x, y, coh.T,
195 ax.plt = ax.pcolormesh(x, y, coh.T,
196 vmin=0,
196 vmin=0,
197 vmax=1,
197 vmax=1,
198 cmap=plt.get_cmap(self.colormap_coh)
198 cmap=plt.get_cmap(self.colormap_coh)
199 )
199 )
200 else:
200 else:
201 ax.plt.set_array(coh.T.ravel())
201 ax.plt.set_array(coh.T.ravel())
202 self.titles.append(
202 self.titles.append(
203 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
203 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
204
204
205 ax = self.axes[2 * n + 1]
205 ax = self.axes[2 * n + 1]
206 if ax.firsttime:
206 if ax.firsttime:
207 ax.plt = ax.pcolormesh(x, y, phase.T,
207 ax.plt = ax.pcolormesh(x, y, phase.T,
208 vmin=-180,
208 vmin=-180,
209 vmax=180,
209 vmax=180,
210 cmap=plt.get_cmap(self.colormap_phase)
210 cmap=plt.get_cmap(self.colormap_phase)
211 )
211 )
212 else:
212 else:
213 ax.plt.set_array(phase.T.ravel())
213 ax.plt.set_array(phase.T.ravel())
214 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
214 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
215
215
216
216
217 class RTIPlot(Plot):
217 class RTIPlot(Plot):
218 '''
218 '''
219 Plot for RTI data
219 Plot for RTI data
220 '''
220 '''
221
221
222 CODE = 'rti'
222 CODE = 'rti'
223 colormap = 'jet'
223 colormap = 'jet'
224 plot_type = 'pcolorbuffer'
224 plot_type = 'pcolorbuffer'
225
225
226 def setup(self):
226 def setup(self):
227 self.xaxis = 'time'
227 self.xaxis = 'time'
228 self.ncols = 1
228 self.ncols = 1
229 self.nrows = len(self.data.channels)
229 self.nrows = len(self.data.channels)
230 self.nplots = len(self.data.channels)
230 self.nplots = len(self.data.channels)
231 self.ylabel = 'Range [km]'
231 self.ylabel = 'Range [km]'
232 self.xlabel = 'Time'
232 self.xlabel = 'Time'
233 self.cb_label = 'dB'
233 self.cb_label = 'dB'
234 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
234 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
235 self.titles = ['{} Channel {}'.format(
235 self.titles = ['{} Channel {}'.format(
236 self.CODE.upper(), x) for x in range(self.nrows)]
236 self.CODE.upper(), x) for x in range(self.nrows)]
237
237
238 def update(self, dataOut):
238 def update(self, dataOut):
239
239
240 data = {}
240 data = {}
241 meta = {}
241 meta = {}
242 data['rti'] = dataOut.getPower()
242 data['rti'] = dataOut.getPower()
243 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
243 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
244
244
245 return data, meta
245 return data, meta
246
246
247 def plot(self):
247 def plot(self):
248 self.x = self.data.times
248 self.x = self.data.times
249 self.y = self.data.yrange
249 self.y = self.data.yrange
250 self.z = self.data[self.CODE]
250 self.z = self.data[self.CODE]
251 self.z = numpy.ma.masked_invalid(self.z)
251 self.z = numpy.ma.masked_invalid(self.z)
252
252
253 if self.decimation is None:
253 if self.decimation is None:
254 x, y, z = self.fill_gaps(self.x, self.y, self.z)
254 x, y, z = self.fill_gaps(self.x, self.y, self.z)
255 else:
255 else:
256 x, y, z = self.fill_gaps(*self.decimate())
256 x, y, z = self.fill_gaps(*self.decimate())
257
257
258 for n, ax in enumerate(self.axes):
258 for n, ax in enumerate(self.axes):
259 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
259 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
260 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
260 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
261 data = self.data[-1]
261 data = self.data[-1]
262 if ax.firsttime:
262 if ax.firsttime:
263 ax.plt = ax.pcolormesh(x, y, z[n].T,
263 ax.plt = ax.pcolormesh(x, y, z[n].T,
264 vmin=self.zmin,
264 vmin=self.zmin,
265 vmax=self.zmax,
265 vmax=self.zmax,
266 cmap=plt.get_cmap(self.colormap)
266 cmap=plt.get_cmap(self.colormap)
267 )
267 )
268 if self.showprofile:
268 if self.showprofile:
269 ax.plot_profile = self.pf_axes[n].plot(
269 ax.plot_profile = self.pf_axes[n].plot(
270 data['rti'][n], self.y)[0]
270 data['rti'][n], self.y)[0]
271 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
271 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
272 color="k", linestyle="dashed", lw=1)[0]
272 color="k", linestyle="dashed", lw=1)[0]
273 else:
273 else:
274 ax.collections.remove(ax.collections[0])
274 ax.collections.remove(ax.collections[0])
275 ax.plt = ax.pcolormesh(x, y, z[n].T,
275 ax.plt = ax.pcolormesh(x, y, z[n].T,
276 vmin=self.zmin,
276 vmin=self.zmin,
277 vmax=self.zmax,
277 vmax=self.zmax,
278 cmap=plt.get_cmap(self.colormap)
278 cmap=plt.get_cmap(self.colormap)
279 )
279 )
280 if self.showprofile:
280 if self.showprofile:
281 ax.plot_profile.set_data(data['rti'][n], self.y)
281 ax.plot_profile.set_data(data['rti'][n], self.y)
282 ax.plot_noise.set_data(numpy.repeat(
282 ax.plot_noise.set_data(numpy.repeat(
283 data['noise'][n], len(self.y)), self.y)
283 data['noise'][n], len(self.y)), self.y)
284
284
285
285
286 class CoherencePlot(RTIPlot):
286 class CoherencePlot(RTIPlot):
287 '''
287 '''
288 Plot for Coherence data
288 Plot for Coherence data
289 '''
289 '''
290
290
291 CODE = 'coh'
291 CODE = 'coh'
292
292
293 def setup(self):
293 def setup(self):
294 self.xaxis = 'time'
294 self.xaxis = 'time'
295 self.ncols = 1
295 self.ncols = 1
296 self.nrows = len(self.data.pairs)
296 self.nrows = len(self.data.pairs)
297 self.nplots = len(self.data.pairs)
297 self.nplots = len(self.data.pairs)
298 self.ylabel = 'Range [km]'
298 self.ylabel = 'Range [km]'
299 self.xlabel = 'Time'
299 self.xlabel = 'Time'
300 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
300 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
301 if self.CODE == 'coh':
301 if self.CODE == 'coh':
302 self.cb_label = ''
302 self.cb_label = ''
303 self.titles = [
303 self.titles = [
304 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
304 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
305 else:
305 else:
306 self.cb_label = 'Degrees'
306 self.cb_label = 'Degrees'
307 self.titles = [
307 self.titles = [
308 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
308 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
309
309
310 def update(self, dataOut):
310 def update(self, dataOut):
311
311
312 data = {}
312 data = {}
313 meta = {}
313 meta = {}
314 data['coh'] = dataOut.getCoherence()
314 data['coh'] = dataOut.getCoherence()
315 meta['pairs'] = dataOut.pairsList
315 meta['pairs'] = dataOut.pairsList
316
316
317 return data, meta
317 return data, meta
318
318
319 class PhasePlot(CoherencePlot):
319 class PhasePlot(CoherencePlot):
320 '''
320 '''
321 Plot for Phase map data
321 Plot for Phase map data
322 '''
322 '''
323
323
324 CODE = 'phase'
324 CODE = 'phase'
325 colormap = 'seismic'
325 colormap = 'seismic'
326
326
327 def update(self, dataOut):
327 def update(self, dataOut):
328
328
329 data = {}
329 data = {}
330 meta = {}
330 meta = {}
331 data['phase'] = dataOut.getCoherence(phase=True)
331 data['phase'] = dataOut.getCoherence(phase=True)
332 meta['pairs'] = dataOut.pairsList
332 meta['pairs'] = dataOut.pairsList
333
333
334 return data, meta
334 return data, meta
335
335
336 class NoisePlot(Plot):
336 class NoisePlot(Plot):
337 '''
337 '''
338 Plot for noise
338 Plot for noise
339 '''
339 '''
340
340
341 CODE = 'noise'
341 CODE = 'noise'
342 plot_type = 'scatterbuffer'
342 plot_type = 'scatterbuffer'
343
343
344 def setup(self):
344 def setup(self):
345 self.xaxis = 'time'
345 self.xaxis = 'time'
346 self.ncols = 1
346 self.ncols = 1
347 self.nrows = 1
347 self.nrows = 1
348 self.nplots = 1
348 self.nplots = 1
349 self.ylabel = 'Intensity [dB]'
349 self.ylabel = 'Intensity [dB]'
350 self.xlabel = 'Time'
350 self.xlabel = 'Time'
351 self.titles = ['Noise']
351 self.titles = ['Noise']
352 self.colorbar = False
352 self.colorbar = False
353 self.plots_adjust.update({'right': 0.85 })
353 self.plots_adjust.update({'right': 0.85 })
354
354
355 def update(self, dataOut):
355 def update(self, dataOut):
356
356
357 data = {}
357 data = {}
358 meta = {}
358 meta = {}
359 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
359 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
360 meta['yrange'] = numpy.array([])
360 meta['yrange'] = numpy.array([])
361
361
362 return data, meta
362 return data, meta
363
363
364 def plot(self):
364 def plot(self):
365
365
366 x = self.data.times
366 x = self.data.times
367 xmin = self.data.min_time
367 xmin = self.data.min_time
368 xmax = xmin + self.xrange * 60 * 60
368 xmax = xmin + self.xrange * 60 * 60
369 Y = self.data['noise']
369 Y = self.data['noise']
370
370
371 if self.axes[0].firsttime:
371 if self.axes[0].firsttime:
372 self.ymin = numpy.nanmin(Y) - 5
372 self.ymin = numpy.nanmin(Y) - 5
373 self.ymax = numpy.nanmax(Y) + 5
373 self.ymax = numpy.nanmax(Y) + 5
374 for ch in self.data.channels:
374 for ch in self.data.channels:
375 y = Y[ch]
375 y = Y[ch]
376 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
376 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
377 plt.legend(bbox_to_anchor=(1.18, 1.0))
377 plt.legend(bbox_to_anchor=(1.18, 1.0))
378 else:
378 else:
379 for ch in self.data.channels:
379 for ch in self.data.channels:
380 y = Y[ch]
380 y = Y[ch]
381 self.axes[0].lines[ch].set_data(x, y)
381 self.axes[0].lines[ch].set_data(x, y)
382
382
383
383
384 class PowerProfilePlot(Plot):
384 class PowerProfilePlot(Plot):
385
385
386 CODE = 'pow_profile'
386 CODE = 'pow_profile'
387 plot_type = 'scatter'
387 plot_type = 'scatter'
388
388
389 def setup(self):
389 def setup(self):
390
390
391 self.ncols = 1
391 self.ncols = 1
392 self.nrows = 1
392 self.nrows = 1
393 self.nplots = 1
393 self.nplots = 1
394 self.height = 4
394 self.height = 4
395 self.width = 3
395 self.width = 3
396 self.ylabel = 'Range [km]'
396 self.ylabel = 'Range [km]'
397 self.xlabel = 'Intensity [dB]'
397 self.xlabel = 'Intensity [dB]'
398 self.titles = ['Power Profile']
398 self.titles = ['Power Profile']
399 self.colorbar = False
399 self.colorbar = False
400
400
401 def update(self, dataOut):
401 def update(self, dataOut):
402
402
403 data = {}
403 data = {}
404 meta = {}
404 meta = {}
405 data[self.CODE] = dataOut.getPower()
405 data[self.CODE] = dataOut.getPower()
406
406
407 return data, meta
407 return data, meta
408
408
409 def plot(self):
409 def plot(self):
410
410
411 y = self.data.yrange
411 y = self.data.yrange
412 self.y = y
412 self.y = y
413
413
414 x = self.data[-1][self.CODE]
414 x = self.data[-1][self.CODE]
415
415
416 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
416 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
417 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
417 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
418
418
419 if self.axes[0].firsttime:
419 if self.axes[0].firsttime:
420 for ch in self.data.channels:
420 for ch in self.data.channels:
421 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
421 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
422 plt.legend()
422 plt.legend()
423 else:
423 else:
424 for ch in self.data.channels:
424 for ch in self.data.channels:
425 self.axes[0].lines[ch].set_data(x[ch], y)
425 self.axes[0].lines[ch].set_data(x[ch], y)
426
426
427
427
428 class SpectraCutPlot(Plot):
428 class SpectraCutPlot(Plot):
429
429
430 CODE = 'spc_cut'
430 CODE = 'spc_cut'
431 plot_type = 'scatter'
431 plot_type = 'scatter'
432 buffering = False
432 buffering = False
433
433
434 def setup(self):
434 def setup(self):
435
435
436 self.nplots = len(self.data.channels)
436 self.nplots = len(self.data.channels)
437 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
437 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
438 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
438 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
439 self.width = 3.4 * self.ncols + 1.5
439 self.width = 3.4 * self.ncols + 1.5
440 self.height = 3 * self.nrows
440 self.height = 3 * self.nrows
441 self.ylabel = 'Power [dB]'
441 self.ylabel = 'Power [dB]'
442 self.colorbar = False
442 self.colorbar = False
443 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
443 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
444
444
445 def update(self, dataOut):
445 def update(self, dataOut):
446
446
447 data = {}
447 data = {}
448 meta = {}
448 meta = {}
449 spc = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
449 spc = 10*numpy.log10(dataOut.data_pre[0]/dataOut.normFactor)
450 data['spc'] = spc
450 data['spc'] = spc
451 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
451 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
452 if self.CODE == 'cut_gaussian_fit':
452 if self.CODE == 'cut_gaussian_fit':
453 data['gauss_fit0'] = 10*numpy.log10(dataOut.GaussFit0/dataOut.normFactor)
453 data['gauss_fit0'] = 10*numpy.log10(dataOut.GaussFit0/dataOut.normFactor)
454 data['gauss_fit1'] = 10*numpy.log10(dataOut.GaussFit1/dataOut.normFactor)
454 data['gauss_fit1'] = 10*numpy.log10(dataOut.GaussFit1/dataOut.normFactor)
455 return data, meta
455 return data, meta
456
456
457 def plot(self):
457 def plot(self):
458 if self.xaxis == "frequency":
458 if self.xaxis == "frequency":
459 x = self.data.xrange[0][1:]
459 x = self.data.xrange[0][1:]
460 self.xlabel = "Frequency (kHz)"
460 self.xlabel = "Frequency (kHz)"
461 elif self.xaxis == "time":
461 elif self.xaxis == "time":
462 x = self.data.xrange[1]
462 x = self.data.xrange[1]
463 self.xlabel = "Time (ms)"
463 self.xlabel = "Time (ms)"
464 else:
464 else:
465 x = self.data.xrange[2][:-1]
465 x = self.data.xrange[2][:-1]
466 self.xlabel = "Velocity (m/s)"
466 self.xlabel = "Velocity (m/s)"
467
467
468 if self.CODE == 'cut_gaussian_fit':
468 if self.CODE == 'cut_gaussian_fit':
469 x = self.data.xrange[2][:-1]
469 x = self.data.xrange[2][:-1]
470 self.xlabel = "Velocity (m/s)"
470 self.xlabel = "Velocity (m/s)"
471
471
472 self.titles = []
472 self.titles = []
473
473
474 y = self.data.yrange
474 y = self.data.yrange
475 data = self.data[-1]
475 data = self.data[-1]
476 z = data['spc']
476 z = data['spc']
477
477
478 if self.height_index:
478 if self.height_index:
479 index = numpy.array(self.height_index)
479 index = numpy.array(self.height_index)
480 else:
480 else:
481 index = numpy.arange(0, len(y), int((len(y))/9))
481 index = numpy.arange(0, len(y), int((len(y))/9))
482
482
483 for n, ax in enumerate(self.axes):
483 for n, ax in enumerate(self.axes):
484 if self.CODE == 'cut_gaussian_fit':
484 if self.CODE == 'cut_gaussian_fit':
485 gau0 = data['gauss_fit0']
485 gau0 = data['gauss_fit0']
486 gau1 = data['gauss_fit1']
486 gau1 = data['gauss_fit1']
487 if ax.firsttime:
487 if ax.firsttime:
488 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
488 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
489 self.xmin = self.xmin if self.xmin else -self.xmax
489 self.xmin = self.xmin if self.xmin else -self.xmax
490 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
490 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
491 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
491 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
492 ax.plt = ax.plot(x, z[n, :, index].T, lw=0.25)
492 ax.plt = ax.plot(x, z[n, :, index].T, lw=0.25)
493 if self.CODE == 'cut_gaussian_fit':
493 if self.CODE == 'cut_gaussian_fit':
494 ax.plt_gau0 = ax.plot(x, gau0[n, :, index].T, lw=1, linestyle='-.')
494 ax.plt_gau0 = ax.plot(x, gau0[n, :, index].T, lw=1, linestyle='-.')
495 for i, line in enumerate(ax.plt_gau0):
495 for i, line in enumerate(ax.plt_gau0):
496 line.set_color(ax.plt[i].get_color())
496 line.set_color(ax.plt[i].get_color())
497 ax.plt_gau1 = ax.plot(x, gau1[n, :, index].T, lw=1, linestyle='--')
497 ax.plt_gau1 = ax.plot(x, gau1[n, :, index].T, lw=1, linestyle='--')
498 for i, line in enumerate(ax.plt_gau1):
498 for i, line in enumerate(ax.plt_gau1):
499 line.set_color(ax.plt[i].get_color())
499 line.set_color(ax.plt[i].get_color())
500 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
500 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
501 self.figures[0].legend(ax.plt, labels, loc='center right')
501 self.figures[0].legend(ax.plt, labels, loc='center right')
502 else:
502 else:
503 for i, line in enumerate(ax.plt):
503 for i, line in enumerate(ax.plt):
504 line.set_data(x, z[n, :, index[i]].T)
504 line.set_data(x, z[n, :, index[i]].T)
505 for i, line in enumerate(ax.plt_gau0):
505 for i, line in enumerate(ax.plt_gau0):
506 line.set_data(x, gau0[n, :, index[i]].T)
506 line.set_data(x, gau0[n, :, index[i]].T)
507 line.set_color(ax.plt[i].get_color())
507 line.set_color(ax.plt[i].get_color())
508 for i, line in enumerate(ax.plt_gau1):
508 for i, line in enumerate(ax.plt_gau1):
509 line.set_data(x, gau1[n, :, index[i]].T)
509 line.set_data(x, gau1[n, :, index[i]].T)
510 line.set_color(ax.plt[i].get_color())
510 line.set_color(ax.plt[i].get_color())
511 self.titles.append('CH {}'.format(n))
511 self.titles.append('CH {}'.format(n))
512
512
513
513
514 class BeaconPhase(Plot):
514 class BeaconPhase(Plot):
515
515
516 __isConfig = None
516 __isConfig = None
517 __nsubplots = None
517 __nsubplots = None
518
518
519 PREFIX = 'beacon_phase'
519 PREFIX = 'beacon_phase'
520
520
521 def __init__(self):
521 def __init__(self):
522 Plot.__init__(self)
522 Plot.__init__(self)
523 self.timerange = 24*60*60
523 self.timerange = 24*60*60
524 self.isConfig = False
524 self.isConfig = False
525 self.__nsubplots = 1
525 self.__nsubplots = 1
526 self.counter_imagwr = 0
526 self.counter_imagwr = 0
527 self.WIDTH = 800
527 self.WIDTH = 800
528 self.HEIGHT = 400
528 self.HEIGHT = 400
529 self.WIDTHPROF = 120
529 self.WIDTHPROF = 120
530 self.HEIGHTPROF = 0
530 self.HEIGHTPROF = 0
531 self.xdata = None
531 self.xdata = None
532 self.ydata = None
532 self.ydata = None
533
533
534 self.PLOT_CODE = BEACON_CODE
534 self.PLOT_CODE = BEACON_CODE
535
535
536 self.FTP_WEI = None
536 self.FTP_WEI = None
537 self.EXP_CODE = None
537 self.EXP_CODE = None
538 self.SUB_EXP_CODE = None
538 self.SUB_EXP_CODE = None
539 self.PLOT_POS = None
539 self.PLOT_POS = None
540
540
541 self.filename_phase = None
541 self.filename_phase = None
542
542
543 self.figfile = None
543 self.figfile = None
544
544
545 self.xmin = None
545 self.xmin = None
546 self.xmax = None
546 self.xmax = None
547
547
548 def getSubplots(self):
548 def getSubplots(self):
549
549
550 ncol = 1
550 ncol = 1
551 nrow = 1
551 nrow = 1
552
552
553 return nrow, ncol
553 return nrow, ncol
554
554
555 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
555 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
556
556
557 self.__showprofile = showprofile
557 self.__showprofile = showprofile
558 self.nplots = nplots
558 self.nplots = nplots
559
559
560 ncolspan = 7
560 ncolspan = 7
561 colspan = 6
561 colspan = 6
562 self.__nsubplots = 2
562 self.__nsubplots = 2
563
563
564 self.createFigure(id = id,
564 self.createFigure(id = id,
565 wintitle = wintitle,
565 wintitle = wintitle,
566 widthplot = self.WIDTH+self.WIDTHPROF,
566 widthplot = self.WIDTH+self.WIDTHPROF,
567 heightplot = self.HEIGHT+self.HEIGHTPROF,
567 heightplot = self.HEIGHT+self.HEIGHTPROF,
568 show=show)
568 show=show)
569
569
570 nrow, ncol = self.getSubplots()
570 nrow, ncol = self.getSubplots()
571
571
572 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
572 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
573
573
574 def save_phase(self, filename_phase):
574 def save_phase(self, filename_phase):
575 f = open(filename_phase,'w+')
575 f = open(filename_phase,'w+')
576 f.write('\n\n')
576 f.write('\n\n')
577 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
577 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
578 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
578 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
579 f.close()
579 f.close()
580
580
581 def save_data(self, filename_phase, data, data_datetime):
581 def save_data(self, filename_phase, data, data_datetime):
582 f=open(filename_phase,'a')
582 f=open(filename_phase,'a')
583 timetuple_data = data_datetime.timetuple()
583 timetuple_data = data_datetime.timetuple()
584 day = str(timetuple_data.tm_mday)
584 day = str(timetuple_data.tm_mday)
585 month = str(timetuple_data.tm_mon)
585 month = str(timetuple_data.tm_mon)
586 year = str(timetuple_data.tm_year)
586 year = str(timetuple_data.tm_year)
587 hour = str(timetuple_data.tm_hour)
587 hour = str(timetuple_data.tm_hour)
588 minute = str(timetuple_data.tm_min)
588 minute = str(timetuple_data.tm_min)
589 second = str(timetuple_data.tm_sec)
589 second = str(timetuple_data.tm_sec)
590 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
590 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
591 f.close()
591 f.close()
592
592
593 def plot(self):
593 def plot(self):
594 log.warning('TODO: Not yet implemented...')
594 log.warning('TODO: Not yet implemented...')
595
595
596 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
596 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
597 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
597 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
598 timerange=None,
598 timerange=None,
599 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
599 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
600 server=None, folder=None, username=None, password=None,
600 server=None, folder=None, username=None, password=None,
601 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
601 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
602
602
603 if dataOut.flagNoData:
603 if dataOut.flagNoData:
604 return dataOut
604 return dataOut
605
605
606 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
606 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
607 return
607 return
608
608
609 if pairsList == None:
609 if pairsList == None:
610 pairsIndexList = dataOut.pairsIndexList[:10]
610 pairsIndexList = dataOut.pairsIndexList[:10]
611 else:
611 else:
612 pairsIndexList = []
612 pairsIndexList = []
613 for pair in pairsList:
613 for pair in pairsList:
614 if pair not in dataOut.pairsList:
614 if pair not in dataOut.pairsList:
615 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
615 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
616 pairsIndexList.append(dataOut.pairsList.index(pair))
616 pairsIndexList.append(dataOut.pairsList.index(pair))
617
617
618 if pairsIndexList == []:
618 if pairsIndexList == []:
619 return
619 return
620
620
621 # if len(pairsIndexList) > 4:
621 # if len(pairsIndexList) > 4:
622 # pairsIndexList = pairsIndexList[0:4]
622 # pairsIndexList = pairsIndexList[0:4]
623
623
624 hmin_index = None
624 hmin_index = None
625 hmax_index = None
625 hmax_index = None
626
626
627 if hmin != None and hmax != None:
627 if hmin != None and hmax != None:
628 indexes = numpy.arange(dataOut.nHeights)
628 indexes = numpy.arange(dataOut.nHeights)
629 hmin_list = indexes[dataOut.heightList >= hmin]
629 hmin_list = indexes[dataOut.heightList >= hmin]
630 hmax_list = indexes[dataOut.heightList <= hmax]
630 hmax_list = indexes[dataOut.heightList <= hmax]
631
631
632 if hmin_list.any():
632 if hmin_list.any():
633 hmin_index = hmin_list[0]
633 hmin_index = hmin_list[0]
634
634
635 if hmax_list.any():
635 if hmax_list.any():
636 hmax_index = hmax_list[-1]+1
636 hmax_index = hmax_list[-1]+1
637
637
638 x = dataOut.getTimeRange()
638 x = dataOut.getTimeRange()
639
639
640 thisDatetime = dataOut.datatime
640 thisDatetime = dataOut.datatime
641
641
642 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
642 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
643 xlabel = "Local Time"
643 xlabel = "Local Time"
644 ylabel = "Phase (degrees)"
644 ylabel = "Phase (degrees)"
645
645
646 update_figfile = False
646 update_figfile = False
647
647
648 nplots = len(pairsIndexList)
648 nplots = len(pairsIndexList)
649 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
649 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
650 phase_beacon = numpy.zeros(len(pairsIndexList))
650 phase_beacon = numpy.zeros(len(pairsIndexList))
651 for i in range(nplots):
651 for i in range(nplots):
652 pair = dataOut.pairsList[pairsIndexList[i]]
652 pair = dataOut.pairsList[pairsIndexList[i]]
653 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
653 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
654 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
654 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
655 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
655 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
656 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
656 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
657 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
657 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
658
658
659 if dataOut.beacon_heiIndexList:
659 if dataOut.beacon_heiIndexList:
660 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
660 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
661 else:
661 else:
662 phase_beacon[i] = numpy.average(phase)
662 phase_beacon[i] = numpy.average(phase)
663
663
664 if not self.isConfig:
664 if not self.isConfig:
665
665
666 nplots = len(pairsIndexList)
666 nplots = len(pairsIndexList)
667
667
668 self.setup(id=id,
668 self.setup(id=id,
669 nplots=nplots,
669 nplots=nplots,
670 wintitle=wintitle,
670 wintitle=wintitle,
671 showprofile=showprofile,
671 showprofile=showprofile,
672 show=show)
672 show=show)
673
673
674 if timerange != None:
674 if timerange != None:
675 self.timerange = timerange
675 self.timerange = timerange
676
676
677 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
677 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
678
678
679 if ymin == None: ymin = 0
679 if ymin == None: ymin = 0
680 if ymax == None: ymax = 360
680 if ymax == None: ymax = 360
681
681
682 self.FTP_WEI = ftp_wei
682 self.FTP_WEI = ftp_wei
683 self.EXP_CODE = exp_code
683 self.EXP_CODE = exp_code
684 self.SUB_EXP_CODE = sub_exp_code
684 self.SUB_EXP_CODE = sub_exp_code
685 self.PLOT_POS = plot_pos
685 self.PLOT_POS = plot_pos
686
686
687 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
687 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
688 self.isConfig = True
688 self.isConfig = True
689 self.figfile = figfile
689 self.figfile = figfile
690 self.xdata = numpy.array([])
690 self.xdata = numpy.array([])
691 self.ydata = numpy.array([])
691 self.ydata = numpy.array([])
692
692
693 update_figfile = True
693 update_figfile = True
694
694
695 #open file beacon phase
695 #open file beacon phase
696 path = '%s%03d' %(self.PREFIX, self.id)
696 path = '%s%03d' %(self.PREFIX, self.id)
697 beacon_file = os.path.join(path,'%s.txt'%self.name)
697 beacon_file = os.path.join(path,'%s.txt'%self.name)
698 self.filename_phase = os.path.join(figpath,beacon_file)
698 self.filename_phase = os.path.join(figpath,beacon_file)
699 #self.save_phase(self.filename_phase)
699 #self.save_phase(self.filename_phase)
700
700
701
701
702 #store data beacon phase
702 #store data beacon phase
703 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
703 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
704
704
705 self.setWinTitle(title)
705 self.setWinTitle(title)
706
706
707
707
708 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
708 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
709
709
710 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
710 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
711
711
712 axes = self.axesList[0]
712 axes = self.axesList[0]
713
713
714 self.xdata = numpy.hstack((self.xdata, x[0:1]))
714 self.xdata = numpy.hstack((self.xdata, x[0:1]))
715
715
716 if len(self.ydata)==0:
716 if len(self.ydata)==0:
717 self.ydata = phase_beacon.reshape(-1,1)
717 self.ydata = phase_beacon.reshape(-1,1)
718 else:
718 else:
719 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
719 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
720
720
721
721
722 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
722 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
723 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
723 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
724 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
724 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
725 XAxisAsTime=True, grid='both'
725 XAxisAsTime=True, grid='both'
726 )
726 )
727
727
728 self.draw()
728 self.draw()
729
729
730 if dataOut.ltctime >= self.xmax:
730 if dataOut.ltctime >= self.xmax:
731 self.counter_imagwr = wr_period
731 self.counter_imagwr = wr_period
732 self.isConfig = False
732 self.isConfig = False
733 update_figfile = True
733 update_figfile = True
734
734
735 self.save(figpath=figpath,
735 self.save(figpath=figpath,
736 figfile=figfile,
736 figfile=figfile,
737 save=save,
737 save=save,
738 ftp=ftp,
738 ftp=ftp,
739 wr_period=wr_period,
739 wr_period=wr_period,
740 thisDatetime=thisDatetime,
740 thisDatetime=thisDatetime,
741 update_figfile=update_figfile)
741 update_figfile=update_figfile)
742
742
743 return dataOut
743 return dataOut
@@ -1,844 +1,863
1 '''
1 '''
2 Created on Jul 3, 2014
2 Created on Jul 3, 2014
3
3
4 @author: roj-idl71
4 @author: roj-idl71
5 '''
5 '''
6 # SUBCHANNELS EN VEZ DE CHANNELS
6 # SUBCHANNELS EN VEZ DE CHANNELS
7 # BENCHMARKS -> PROBLEMAS CON ARCHIVOS GRANDES -> INCONSTANTE EN EL TIEMPO
7 # BENCHMARKS -> PROBLEMAS CON ARCHIVOS GRANDES -> INCONSTANTE EN EL TIEMPO
8 # ACTUALIZACION DE VERSION
8 # ACTUALIZACION DE VERSION
9 # HEADERS
9 # HEADERS
10 # MODULO DE ESCRITURA
10 # MODULO DE ESCRITURA
11 # METADATA
11 # METADATA
12
12
13 import os
13 import os
14 import time
14 import time
15 import datetime
15 import datetime
16 import numpy
16 import numpy
17 import timeit
17 import timeit
18 from fractions import Fraction
18 from fractions import Fraction
19 from time import time
19 from time import time
20 from time import sleep
20 from time import sleep
21
21
22 import schainpy.admin
22 import schainpy.admin
23 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
23 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
24 from schainpy.model.data.jrodata import Voltage
24 from schainpy.model.data.jrodata import Voltage
25 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
25 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
26
26
27 import pickle
27 import pickle
28 try:
28 try:
29 os.environ["HDF5_USE_FILE_LOCKING"] = "FALSE"
29 import digital_rf
30 import digital_rf
30 except:
31 except:
31 pass
32 pass
32
33
33
34
34 class DigitalRFReader(ProcessingUnit):
35 class DigitalRFReader(ProcessingUnit):
35 '''
36 '''
36 classdocs
37 classdocs
37 '''
38 '''
38
39
39 def __init__(self):
40 def __init__(self):
40 '''
41 '''
41 Constructor
42 Constructor
42 '''
43 '''
43
44
44 ProcessingUnit.__init__(self)
45 ProcessingUnit.__init__(self)
45
46
46 self.dataOut = Voltage()
47 self.dataOut = Voltage()
47 self.__printInfo = True
48 self.__printInfo = True
48 self.__flagDiscontinuousBlock = False
49 self.__flagDiscontinuousBlock = False
49 self.__bufferIndex = 9999999
50 self.__bufferIndex = 9999999
50 self.__codeType = 0
51 self.__codeType = 0
51 self.__ippKm = None
52 self.__ippKm = None
52 self.__nCode = None
53 self.__nCode = None
53 self.__nBaud = None
54 self.__nBaud = None
54 self.__code = None
55 self.__code = None
55 self.dtype = None
56 self.dtype = None
56 self.oldAverage = None
57 self.oldAverage = None
57 self.path = None
58 self.path = None
58
59
59 def close(self):
60 def close(self):
60 print('Average of writing to digital rf format is ', self.oldAverage * 1000)
61 print('Average of writing to digital rf format is ', self.oldAverage * 1000)
61 return
62 return
62
63
63 def __getCurrentSecond(self):
64 def __getCurrentSecond(self):
64
65
65 return self.__thisUnixSample / self.__sample_rate
66 return self.__thisUnixSample / self.__sample_rate
66
67
67 thisSecond = property(__getCurrentSecond, "I'm the 'thisSecond' property.")
68 thisSecond = property(__getCurrentSecond, "I'm the 'thisSecond' property.")
68
69
69 def __setFileHeader(self):
70 def __setFileHeader(self):
70 '''
71 '''
71 In this method will be initialized every parameter of dataOut object (header, no data)
72 In this method will be initialized every parameter of dataOut object (header, no data)
72 '''
73 '''
73 ippSeconds = 1.0 * self.__nSamples / self.__sample_rate
74 ippSeconds = 1.0 * self.__nSamples / self.__sample_rate
74 if not self.getByBlock:
75 if not self.getByBlock:
75 nProfiles = 1.0 / ippSeconds # Number of profiles in one second
76 nProfiles = 1.0 / ippSeconds # Number of profiles in one second
76 else:
77 else:
77 nProfiles = self.nProfileBlocks # Number of profiles in one block
78 nProfiles = self.nProfileBlocks # Number of profiles in one block
78
79
79 try:
80 try:
80 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(
81 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(
81 self.__radarControllerHeader)
82 self.__radarControllerHeader)
82 except:
83 except:
83 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(
84 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(
84 txA=0,
85 txA=0,
85 txB=0,
86 txB=0,
86 nWindows=1,
87 nWindows=1,
87 nHeights=self.__nSamples,
88 nHeights=self.__nSamples,
88 firstHeight=self.__firstHeigth,
89 firstHeight=self.__firstHeigth,
89 deltaHeight=self.__deltaHeigth,
90 deltaHeight=self.__deltaHeigth,
90 codeType=self.__codeType,
91 codeType=self.__codeType,
91 nCode=self.__nCode, nBaud=self.__nBaud,
92 nCode=self.__nCode, nBaud=self.__nBaud,
92 code=self.__code)
93 code=self.__code)
93
94
94 try:
95 try:
95 self.dataOut.systemHeaderObj = SystemHeader(self.__systemHeader)
96 self.dataOut.systemHeaderObj = SystemHeader(self.__systemHeader)
96 except:
97 except:
97 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
98 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
98 nProfiles=nProfiles,
99 nProfiles=nProfiles,
99 nChannels=len(
100 nChannels=len(
100 self.__channelList),
101 self.__channelList),
101 adcResolution=14)
102 adcResolution=14)
102 self.dataOut.type = "Voltage"
103 self.dataOut.type = "Voltage"
103
104
104 self.dataOut.data = None
105 self.dataOut.data = None
105
106
106 self.dataOut.dtype = self.dtype
107 self.dataOut.dtype = self.dtype
107
108
108 # self.dataOut.nChannels = 0
109 # self.dataOut.nChannels = 0
109
110
110 # self.dataOut.nHeights = 0
111 # self.dataOut.nHeights = 0
111
112
112 self.dataOut.nProfiles = int(nProfiles)
113 self.dataOut.nProfiles = int(nProfiles)
113
114
114 self.dataOut.heightList = self.__firstHeigth + \
115 self.dataOut.heightList = self.__firstHeigth + \
115 numpy.arange(self.__nSamples, dtype=numpy.float) * \
116 numpy.arange(self.__nSamples, dtype=numpy.float) * \
116 self.__deltaHeigth
117 self.__deltaHeigth
117
118
118 #self.dataOut.channelList = list(range(self.__num_subchannels))
119 #self.dataOut.channelList = list(range(self.__num_subchannels))
119 self.dataOut.channelList = list(range(len(self.__channelList)))
120 self.dataOut.channelList = list(range(len(self.__channelList)))
120 if not self.getByBlock:
121 if not self.getByBlock:
121
122
122 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights
123 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights
123 else:
124 else:
124 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights*self.nProfileBlocks
125 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights*self.nProfileBlocks
125
126
126 # self.dataOut.channelIndexList = None
127 # self.dataOut.channelIndexList = None
127
128
128 self.dataOut.flagNoData = True
129 self.dataOut.flagNoData = True
129 if not self.getByBlock:
130 if not self.getByBlock:
130 self.dataOut.flagDataAsBlock = False
131 self.dataOut.flagDataAsBlock = False
131 else:
132 else:
132 self.dataOut.flagDataAsBlock = True
133 self.dataOut.flagDataAsBlock = True
133 # Set to TRUE if the data is discontinuous
134 # Set to TRUE if the data is discontinuous
134 self.dataOut.flagDiscontinuousBlock = False
135 self.dataOut.flagDiscontinuousBlock = False
135
136
136 self.dataOut.utctime = None
137 self.dataOut.utctime = None
137
138
138 # timezone like jroheader, difference in minutes between UTC and localtime
139 # timezone like jroheader, difference in minutes between UTC and localtime
139 self.dataOut.timeZone = self.__timezone / 60
140 self.dataOut.timeZone = self.__timezone / 60
140
141
141 self.dataOut.dstFlag = 0
142 self.dataOut.dstFlag = 0
142
143
143 self.dataOut.errorCount = 0
144 self.dataOut.errorCount = 0
144
145
145 try:
146 try:
146 self.dataOut.nCohInt = self.fixed_metadata_dict.get(
147 self.dataOut.nCohInt = self.fixed_metadata_dict.get(
147 'nCohInt', self.nCohInt)
148 'nCohInt', self.nCohInt)
148
149
149 # asumo que la data esta decodificada
150 # asumo que la data esta decodificada
150 self.dataOut.flagDecodeData = self.fixed_metadata_dict.get(
151 self.dataOut.flagDecodeData = self.fixed_metadata_dict.get(
151 'flagDecodeData', self.flagDecodeData)
152 'flagDecodeData', self.flagDecodeData)
152
153
153 # asumo que la data esta sin flip
154 # asumo que la data esta sin flip
154 self.dataOut.flagDeflipData = self.fixed_metadata_dict['flagDeflipData']
155 self.dataOut.flagDeflipData = self.fixed_metadata_dict['flagDeflipData']
155
156
156 self.dataOut.flagShiftFFT = self.fixed_metadata_dict['flagShiftFFT']
157 self.dataOut.flagShiftFFT = self.fixed_metadata_dict['flagShiftFFT']
157
158
158 self.dataOut.useLocalTime = self.fixed_metadata_dict['useLocalTime']
159 self.dataOut.useLocalTime = self.fixed_metadata_dict['useLocalTime']
159 except:
160 except:
160 pass
161 pass
161
162
162 self.dataOut.ippSeconds = ippSeconds
163 self.dataOut.ippSeconds = ippSeconds
163
164
164 # Time interval between profiles
165 # Time interval between profiles
165 # self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
166 # self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
166
167
167 self.dataOut.frequency = self.__frequency
168 self.dataOut.frequency = self.__frequency
168
169
169 self.dataOut.realtime = self.__online
170 self.dataOut.realtime = self.__online
170
171
171 def findDatafiles(self, path, startDate=None, endDate=None):
172 def findDatafiles(self, path, startDate=None, endDate=None):
172
173
173 if not os.path.isdir(path):
174 if not os.path.isdir(path):
174 return []
175 return []
175
176
176 try:
177 try:
177 digitalReadObj = digital_rf.DigitalRFReader(
178 digitalReadObj = digital_rf.DigitalRFReader(
178 path, load_all_metadata=True)
179 path, load_all_metadata=True)
179 except:
180 except:
180 digitalReadObj = digital_rf.DigitalRFReader(path)
181 digitalReadObj = digital_rf.DigitalRFReader(path)
181
182
182 channelNameList = digitalReadObj.get_channels()
183 channelNameList = digitalReadObj.get_channels()
183
184
184 if not channelNameList:
185 if not channelNameList:
185 return []
186 return []
186
187
187 metadata_dict = digitalReadObj.get_rf_file_metadata(channelNameList[0])
188 metadata_dict = digitalReadObj.get_rf_file_metadata(channelNameList[0])
188
189
189 sample_rate = metadata_dict['sample_rate'][0]
190 sample_rate = metadata_dict['sample_rate'][0]
190
191
191 this_metadata_file = digitalReadObj.get_metadata(channelNameList[0])
192 this_metadata_file = digitalReadObj.get_metadata(channelNameList[0])
192
193
193 try:
194 try:
194 timezone = this_metadata_file['timezone'].value
195 timezone = this_metadata_file['timezone'].value
195 except:
196 except:
196 timezone = 0
197 timezone = 0
197
198
198 startUTCSecond, endUTCSecond = digitalReadObj.get_bounds(
199 startUTCSecond, endUTCSecond = digitalReadObj.get_bounds(
199 channelNameList[0]) / sample_rate - timezone
200 channelNameList[0]) / sample_rate - timezone
200
201
201 startDatetime = datetime.datetime.utcfromtimestamp(startUTCSecond)
202 startDatetime = datetime.datetime.utcfromtimestamp(startUTCSecond)
202 endDatatime = datetime.datetime.utcfromtimestamp(endUTCSecond)
203 endDatatime = datetime.datetime.utcfromtimestamp(endUTCSecond)
203
204
204 if not startDate:
205 if not startDate:
205 startDate = startDatetime.date()
206 startDate = startDatetime.date()
206
207
207 if not endDate:
208 if not endDate:
208 endDate = endDatatime.date()
209 endDate = endDatatime.date()
209
210
210 dateList = []
211 dateList = []
211
212
212 thisDatetime = startDatetime
213 thisDatetime = startDatetime
213
214
214 while(thisDatetime <= endDatatime):
215 while(thisDatetime <= endDatatime):
215
216
216 thisDate = thisDatetime.date()
217 thisDate = thisDatetime.date()
217
218
218 if thisDate < startDate:
219 if thisDate < startDate:
219 continue
220 continue
220
221
221 if thisDate > endDate:
222 if thisDate > endDate:
222 break
223 break
223
224
224 dateList.append(thisDate)
225 dateList.append(thisDate)
225 thisDatetime += datetime.timedelta(1)
226 thisDatetime += datetime.timedelta(1)
226
227
227 return dateList
228 return dateList
228
229
229 def setup(self, path=None,
230 def setup(self, path=None,
230 startDate=None,
231 startDate=None,
231 endDate=None,
232 endDate=None,
232 startTime=datetime.time(0, 0, 0),
233 startTime=datetime.time(0, 0, 0),
233 endTime=datetime.time(23, 59, 59),
234 endTime=datetime.time(23, 59, 59),
234 channelList=None,
235 channelList=None,
235 nSamples=None,
236 nSamples=None,
236 online=False,
237 online=False,
237 delay=60,
238 delay=60,
238 buffer_size=1024,
239 buffer_size=1024,
239 ippKm=None,
240 ippKm=None,
240 nCohInt=1,
241 nCohInt=1,
241 nCode=1,
242 nCode=1,
242 nBaud=1,
243 nBaud=1,
243 flagDecodeData=False,
244 flagDecodeData=False,
244 code=numpy.ones((1, 1), dtype=numpy.int),
245 code=numpy.ones((1, 1), dtype=numpy.int),
245 getByBlock=0,
246 getByBlock=0,
246 nProfileBlocks=1,
247 nProfileBlocks=1,
247 **kwargs):
248 **kwargs):
248 '''
249 '''
249 In this method we should set all initial parameters.
250 In this method we should set all initial parameters.
250
251
251 Inputs:
252 Inputs:
252 path
253 path
253 startDate
254 startDate
254 endDate
255 endDate
255 startTime
256 startTime
256 endTime
257 endTime
257 set
258 set
258 expLabel
259 expLabel
259 ext
260 ext
260 online
261 online
261 delay
262 delay
262 '''
263 '''
263 self.path = path
264 self.path = path
264 self.nCohInt = nCohInt
265 self.nCohInt = nCohInt
265 self.flagDecodeData = flagDecodeData
266 self.flagDecodeData = flagDecodeData
266 self.i = 0
267 self.i = 0
267
268
268 self.getByBlock = getByBlock
269 self.getByBlock = getByBlock
269 self.nProfileBlocks = nProfileBlocks
270 self.nProfileBlocks = nProfileBlocks
271 if online:
272 print('Waiting for RF data..')
273 sleep(40)
274
270 if not os.path.isdir(path):
275 if not os.path.isdir(path):
271 raise ValueError("[Reading] Directory %s does not exist" % path)
276 raise ValueError("[Reading] Directory %s does not exist" % path)
272
277
278 #print("path",path)
273 try:
279 try:
274 self.digitalReadObj = digital_rf.DigitalRFReader(
280 self.digitalReadObj = digital_rf.DigitalRFReader(
275 path, load_all_metadata=True)
281 path, load_all_metadata=True)
276 except:
282 except:
277 self.digitalReadObj = digital_rf.DigitalRFReader(path)
283 self.digitalReadObj = digital_rf.DigitalRFReader(path)
278
284
279 channelNameList = self.digitalReadObj.get_channels()
285 channelNameList = self.digitalReadObj.get_channels()
280
286
281 if not channelNameList:
287 if not channelNameList:
282 raise ValueError("[Reading] Directory %s does not have any files" % path)
288 raise ValueError("[Reading] Directory %s does not have any files" % path)
283
289
284 if not channelList:
290 if not channelList:
285 channelList = list(range(len(channelNameList)))
291 channelList = list(range(len(channelNameList)))
286
292
287 ########## Reading metadata ######################
293 ########## Reading metadata ######################
288
294
289 top_properties = self.digitalReadObj.get_properties(
295 top_properties = self.digitalReadObj.get_properties(
290 channelNameList[channelList[0]])
296 channelNameList[channelList[0]])
291
297
292 self.__num_subchannels = top_properties['num_subchannels']
298 self.__num_subchannels = top_properties['num_subchannels']
293 self.__sample_rate = 1.0 * \
299 self.__sample_rate = 1.0 * \
294 top_properties['sample_rate_numerator'] / \
300 top_properties['sample_rate_numerator'] / \
295 top_properties['sample_rate_denominator']
301 top_properties['sample_rate_denominator']
296 # self.__samples_per_file = top_properties['samples_per_file'][0]
302 # self.__samples_per_file = top_properties['samples_per_file'][0]
297 self.__deltaHeigth = 1e6 * 0.15 / self.__sample_rate # why 0.15?
303 self.__deltaHeigth = 1e6 * 0.15 / self.__sample_rate # why 0.15?
298
304
299 this_metadata_file = self.digitalReadObj.get_digital_metadata(
305 this_metadata_file = self.digitalReadObj.get_digital_metadata(
300 channelNameList[channelList[0]])
306 channelNameList[channelList[0]])
301 metadata_bounds = this_metadata_file.get_bounds()
307 metadata_bounds = this_metadata_file.get_bounds()
302 self.fixed_metadata_dict = this_metadata_file.read(
308 self.fixed_metadata_dict = this_metadata_file.read(
303 metadata_bounds[0])[metadata_bounds[0]] # GET FIRST HEADER
309 metadata_bounds[0])[metadata_bounds[0]] # GET FIRST HEADER
304
310
305 try:
311 try:
306 self.__processingHeader = self.fixed_metadata_dict['processingHeader']
312 self.__processingHeader = self.fixed_metadata_dict['processingHeader']
307 self.__radarControllerHeader = self.fixed_metadata_dict['radarControllerHeader']
313 self.__radarControllerHeader = self.fixed_metadata_dict['radarControllerHeader']
308 self.__systemHeader = self.fixed_metadata_dict['systemHeader']
314 self.__systemHeader = self.fixed_metadata_dict['systemHeader']
309 self.dtype = pickle.loads(self.fixed_metadata_dict['dtype'])
315 self.dtype = pickle.loads(self.fixed_metadata_dict['dtype'])
310 except:
316 except:
311 pass
317 pass
312
318
313 self.__frequency = None
319 self.__frequency = None
314
320
315 self.__frequency = self.fixed_metadata_dict.get('frequency', 1)
321 self.__frequency = self.fixed_metadata_dict.get('frequency', 1)
316
322
317 self.__timezone = self.fixed_metadata_dict.get('timezone', 18000)
323 self.__timezone = self.fixed_metadata_dict.get('timezone', 18000)
318
324
319 try:
325 try:
320 nSamples = self.fixed_metadata_dict['nSamples']
326 nSamples = self.fixed_metadata_dict['nSamples']
321 except:
327 except:
322 nSamples = None
328 nSamples = None
323
329
324 self.__firstHeigth = 0
330 self.__firstHeigth = 0
325
331
326 try:
332 try:
327 codeType = self.__radarControllerHeader['codeType']
333 codeType = self.__radarControllerHeader['codeType']
328 except:
334 except:
329 codeType = 0
335 codeType = 0
330
336
331 try:
337 try:
332 if codeType:
338 if codeType:
333 nCode = self.__radarControllerHeader['nCode']
339 nCode = self.__radarControllerHeader['nCode']
334 nBaud = self.__radarControllerHeader['nBaud']
340 nBaud = self.__radarControllerHeader['nBaud']
335 code = self.__radarControllerHeader['code']
341 code = self.__radarControllerHeader['code']
336 except:
342 except:
337 pass
343 pass
338
344
339 if not ippKm:
345 if not ippKm:
340 try:
346 try:
341 # seconds to km
347 # seconds to km
342 ippKm = self.__radarControllerHeader['ipp']
348 ippKm = self.__radarControllerHeader['ipp']
343 except:
349 except:
344 ippKm = None
350 ippKm = None
345 ####################################################
351 ####################################################
346 self.__ippKm = ippKm
352 self.__ippKm = ippKm
347 startUTCSecond = None
353 startUTCSecond = None
348 endUTCSecond = None
354 endUTCSecond = None
349
355
350 if startDate:
356 if startDate:
351 startDatetime = datetime.datetime.combine(startDate, startTime)
357 startDatetime = datetime.datetime.combine(startDate, startTime)
352 startUTCSecond = (
358 startUTCSecond = (
353 startDatetime - datetime.datetime(1970, 1, 1)).total_seconds() + self.__timezone
359 startDatetime - datetime.datetime(1970, 1, 1)).total_seconds()# + self.__timezone
354
360
355 if endDate:
361 if endDate:
356 endDatetime = datetime.datetime.combine(endDate, endTime)
362 endDatetime = datetime.datetime.combine(endDate, endTime)
357 endUTCSecond = (endDatetime - datetime.datetime(1970,
363 endUTCSecond = (endDatetime - datetime.datetime(1970,
358 1, 1)).total_seconds() + self.__timezone
364 1, 1)).total_seconds()# + self.__timezone
359
365 start_index, end_index = self.digitalReadObj.get_bounds(channelNameList[channelList[0]])
360
366 if start_index==None or end_index==None:
361 #print(startUTCSecond,endUTCSecond)
367 print("Check error No data, start_index: ",start_index,",end_index: ",end_index)
362 start_index, end_index = self.digitalReadObj.get_bounds(
368 #return 0
363 channelNameList[channelList[0]])
364
365 #print("*****",start_index,end_index)
366 if not startUTCSecond:
369 if not startUTCSecond:
367 startUTCSecond = start_index / self.__sample_rate
370 startUTCSecond = start_index / self.__sample_rate
368
369 if start_index > startUTCSecond * self.__sample_rate:
371 if start_index > startUTCSecond * self.__sample_rate:
370 startUTCSecond = start_index / self.__sample_rate
372 startUTCSecond = start_index / self.__sample_rate
371
373
372 if not endUTCSecond:
374 if not endUTCSecond:
373 endUTCSecond = end_index / self.__sample_rate
375 endUTCSecond = end_index / self.__sample_rate
376
374 if end_index < endUTCSecond * self.__sample_rate:
377 if end_index < endUTCSecond * self.__sample_rate:
375 endUTCSecond = end_index / self.__sample_rate #Check UTC and LT time
378 endUTCSecond = end_index / self.__sample_rate #Check UTC and LT time
379
376 if not nSamples:
380 if not nSamples:
377 if not ippKm:
381 if not ippKm:
378 raise ValueError("[Reading] nSamples or ippKm should be defined")
382 raise ValueError("[Reading] nSamples or ippKm should be defined")
379 nSamples = int(ippKm / (1e6 * 0.15 / self.__sample_rate))
383 nSamples = int(ippKm / (1e6 * 0.15 / self.__sample_rate))
380
384
381 channelBoundList = []
385 channelBoundList = []
382 channelNameListFiltered = []
386 channelNameListFiltered = []
383
387
384 for thisIndexChannel in channelList:
388 for thisIndexChannel in channelList:
385 thisChannelName = channelNameList[thisIndexChannel]
389 thisChannelName = channelNameList[thisIndexChannel]
386 start_index, end_index = self.digitalReadObj.get_bounds(
390 start_index, end_index = self.digitalReadObj.get_bounds(
387 thisChannelName)
391 thisChannelName)
388 channelBoundList.append((start_index, end_index))
392 channelBoundList.append((start_index, end_index))
389 channelNameListFiltered.append(thisChannelName)
393 channelNameListFiltered.append(thisChannelName)
390
394
391 self.profileIndex = 0
395 self.profileIndex = 0
392 self.i = 0
396 self.i = 0
393 self.__delay = delay
397 self.__delay = delay
394
398
395 self.__codeType = codeType
399 self.__codeType = codeType
396 self.__nCode = nCode
400 self.__nCode = nCode
397 self.__nBaud = nBaud
401 self.__nBaud = nBaud
398 self.__code = code
402 self.__code = code
399
403
400 self.__datapath = path
404 self.__datapath = path
401 self.__online = online
405 self.__online = online
402 self.__channelList = channelList
406 self.__channelList = channelList
403 self.__channelNameList = channelNameListFiltered
407 self.__channelNameList = channelNameListFiltered
404 self.__channelBoundList = channelBoundList
408 self.__channelBoundList = channelBoundList
405 self.__nSamples = nSamples
409 self.__nSamples = nSamples
406 if self.getByBlock:
410 if self.getByBlock:
407 nSamples = nSamples*nProfileBlocks
411 nSamples = nSamples*nProfileBlocks
408
412
409
413
410 self.__samples_to_read = int(nSamples) # FIJO: AHORA 40
414 self.__samples_to_read = int(nSamples) # FIJO: AHORA 40
411 self.__nChannels = len(self.__channelList)
415 self.__nChannels = len(self.__channelList)
412 #print("------------------------------------------")
416 #print("------------------------------------------")
413 #print("self.__samples_to_read",self.__samples_to_read)
417 #print("self.__samples_to_read",self.__samples_to_read)
414 #print("self.__nSamples",self.__nSamples)
418 #print("self.__nSamples",self.__nSamples)
415 # son iguales y el buffer_index da 0
419 # son iguales y el buffer_index da 0
416 self.__startUTCSecond = startUTCSecond
420 self.__startUTCSecond = startUTCSecond
417 self.__endUTCSecond = endUTCSecond
421 self.__endUTCSecond = endUTCSecond
418
422
419 self.__timeInterval = 1.0 * self.__samples_to_read / \
423 self.__timeInterval = 1.0 * self.__samples_to_read / \
420 self.__sample_rate # Time interval
424 self.__sample_rate # Time interval
421
425
422 if online:
426 if online:
423 # self.__thisUnixSample = int(endUTCSecond*self.__sample_rate - 4*self.__samples_to_read)
427 # self.__thisUnixSample = int(endUTCSecond*self.__sample_rate - 4*self.__samples_to_read)
424 startUTCSecond = numpy.floor(endUTCSecond)
428 startUTCSecond = numpy.floor(endUTCSecond)
425
429
426 # por que en el otro metodo lo primero q se hace es sumar samplestoread
430 # por que en el otro metodo lo primero q se hace es sumar samplestoread
427 self.__thisUnixSample = int(startUTCSecond * self.__sample_rate) - self.__samples_to_read
431 self.__thisUnixSample = int(startUTCSecond * self.__sample_rate) - self.__samples_to_read
428
432
429 #self.__data_buffer = numpy.zeros(
433 #self.__data_buffer = numpy.zeros(
430 # (self.__num_subchannels, self.__samples_to_read), dtype=numpy.complex)
434 # (self.__num_subchannels, self.__samples_to_read), dtype=numpy.complex)
435 print("samplestoread",self.__samples_to_read)
431 self.__data_buffer = numpy.zeros((int(len(channelList)), self.__samples_to_read), dtype=numpy.complex)
436 self.__data_buffer = numpy.zeros((int(len(channelList)), self.__samples_to_read), dtype=numpy.complex)
432
437
433
438
434 self.__setFileHeader()
439 self.__setFileHeader()
435 self.isConfig = True
440 self.isConfig = True
436
441
437 print("[Reading] Digital RF Data was found from %s to %s " % (
442 print("[Reading] Digital RF Data was found from %s to %s " % (
438 datetime.datetime.utcfromtimestamp(
443 datetime.datetime.utcfromtimestamp(
439 self.__startUTCSecond - self.__timezone),
444 self.__startUTCSecond - self.__timezone),
440 datetime.datetime.utcfromtimestamp(
445 datetime.datetime.utcfromtimestamp(
441 self.__endUTCSecond - self.__timezone)
446 self.__endUTCSecond - self.__timezone)
442 ))
447 ))
443
448
444 print("[Reading] Starting process from %s to %s" % (datetime.datetime.utcfromtimestamp(startUTCSecond - self.__timezone),
449 print("[Reading] Starting process from %s to %s" % (datetime.datetime.utcfromtimestamp(startUTCSecond - self.__timezone),
445 datetime.datetime.utcfromtimestamp(
450 datetime.datetime.utcfromtimestamp(endUTCSecond - self.__timezone)))
446 endUTCSecond - self.__timezone)
447 ))
448 self.oldAverage = None
451 self.oldAverage = None
449 self.count = 0
452 self.count = 0
450 self.executionTime = 0
453 self.executionTime = 0
451
454
452 def __reload(self):
455 def __reload(self):
453 # print
456 # print
454 # print "%s not in range [%s, %s]" %(
457 # print "%s not in range [%s, %s]" %(
455 # datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
458 # datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
456 # datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone),
459 # datetime.datetime.utcfromtimestamp(self.__startUTCSecond - self.__timezone),
457 # datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone)
460 # datetime.datetime.utcfromtimestamp(self.__endUTCSecond - self.__timezone)
458 # )
461 # )
459 print("[Reading] reloading metadata ...")
462 print("[Reading] reloading metadata ...")
460
463
461 try:
464 try:
462 self.digitalReadObj.reload(complete_update=True)
465 self.digitalReadObj.reload(complete_update=True)
463 except:
466 except:
464 self.digitalReadObj = digital_rf.DigitalRFReader(self.path)
467 self.digitalReadObj = digital_rf.DigitalRFReader(self.path)
465
468
466 start_index, end_index = self.digitalReadObj.get_bounds(
469 start_index, end_index = self.digitalReadObj.get_bounds(
467 self.__channelNameList[self.__channelList[0]])
470 self.__channelNameList[self.__channelList[0]])
468
471
469 if start_index > self.__startUTCSecond * self.__sample_rate:
472 if start_index > self.__startUTCSecond * self.__sample_rate:
470 self.__startUTCSecond = 1.0 * start_index / self.__sample_rate
473 self.__startUTCSecond = 1.0 * start_index / self.__sample_rate
471
474
472 if end_index > self.__endUTCSecond * self.__sample_rate:
475 if end_index > self.__endUTCSecond * self.__sample_rate:
473 self.__endUTCSecond = 1.0 * end_index / self.__sample_rate
476 self.__endUTCSecond = 1.0 * end_index / self.__sample_rate
474 print()
477 print()
475 print("[Reading] New timerange found [%s, %s] " % (
478 print("[Reading] New timerange found [%s, %s] " % (
476 datetime.datetime.utcfromtimestamp(
479 datetime.datetime.utcfromtimestamp(
477 self.__startUTCSecond - self.__timezone),
480 self.__startUTCSecond - self.__timezone),
478 datetime.datetime.utcfromtimestamp(
481 datetime.datetime.utcfromtimestamp(
479 self.__endUTCSecond - self.__timezone)
482 self.__endUTCSecond - self.__timezone)
480 ))
483 ))
481
484
482 return True
485 return True
483
486
484 return False
487 return False
485
488
486 def timeit(self, toExecute):
489 def timeit(self, toExecute):
487 t0 = time.time()
490 t0 = time.time()
488 toExecute()
491 toExecute()
489 self.executionTime = time.time() - t0
492 self.executionTime = time.time() - t0
490 if self.oldAverage is None:
493 if self.oldAverage is None:
491 self.oldAverage = self.executionTime
494 self.oldAverage = self.executionTime
492 self.oldAverage = (self.executionTime + self.count *
495 self.oldAverage = (self.executionTime + self.count *
493 self.oldAverage) / (self.count + 1.0)
496 self.oldAverage) / (self.count + 1.0)
494 self.count = self.count + 1.0
497 self.count = self.count + 1.0
495 return
498 return
496
499
497 def __readNextBlock(self, seconds=30, volt_scale=1/20000.0):
500 def __readNextBlock(self, seconds=30, volt_scale=1/20000.0):
498 '''
501 '''
499 NOTA: APLICACION RADAR METEOROLOGICO
502 NOTA: APLICACION RADAR METEOROLOGICO
500 VALORES OBTENIDOS CON LA USRP, volt_scale = 1,conexion directa al Ch Rx.
503 VALORES OBTENIDOS CON LA USRP, volt_scale = 1,conexion directa al Ch Rx.
501
504
502 MAXIMO
505 MAXIMO
503 9886 -> 0.980 Voltiospp
506 9886 -> 0.980 Voltiospp
504 4939 -> 0.480 Voltiospp
507 4939 -> 0.480 Voltiospp
505 14825 -> 1.440 Voltiospp
508 14825 -> 1.440 Voltiospp
506 18129 -> 1.940 Voltiospp
509 18129 -> 1.940 Voltiospp
507 Para llevar al valor correspondiente de Voltaje, debemos dividir por 20000
510 Para llevar al valor correspondiente de Voltaje, debemos dividir por 20000
508 y obtenemos la Amplitud correspondiente de entrada IQ.
511 y obtenemos la Amplitud correspondiente de entrada IQ.
509 volt_scale = (1/20000.0)
512 volt_scale = (1/20000.0)
510 '''
513 '''
511 # Set the next data
514 # Set the next data
512 self.__flagDiscontinuousBlock = False
515 self.__flagDiscontinuousBlock = False
513 self.__thisUnixSample += self.__samples_to_read
516 self.__thisUnixSample += self.__samples_to_read
514
517
515 if self.__thisUnixSample + 2 * self.__samples_to_read > self.__endUTCSecond * self.__sample_rate:
518 if self.__thisUnixSample + 2 * self.__samples_to_read > self.__endUTCSecond * self.__sample_rate:
516 print ("[Reading] There are no more data into selected time-range")
519 print ("[Reading] There are no more data into selected time-range")
517 if self.__online:
520 if self.__online:
518 sleep(3)
521 sleep(3)
519 self.__reload()
522 self.__reload()
520 else:
523 else:
521 return False
524 return False
522
525
523 if self.__thisUnixSample + 2 * self.__samples_to_read > self.__endUTCSecond * self.__sample_rate:
526 if self.__thisUnixSample + 2 * self.__samples_to_read > self.__endUTCSecond * self.__sample_rate:
524 return False
527 return False
525 self.__thisUnixSample -= self.__samples_to_read
528 self.__thisUnixSample -= self.__samples_to_read
526
529
527 indexChannel = 0
530 indexChannel = 0
528
531
529 dataOk = False
532 dataOk = False
530
533
531 for thisChannelName in self.__channelNameList: # TODO VARIOS CHANNELS?
534 for thisChannelName in self.__channelNameList: # TODO VARIOS CHANNELS?
532 for indexSubchannel in range(self.__num_subchannels):
535 for indexSubchannel in range(self.__num_subchannels):
533 try:
536 try:
534 t0 = time()
537 t0 = time()
538 #print("thisUNixSample",self.__thisUnixSample)
535 result = self.digitalReadObj.read_vector_c81d(self.__thisUnixSample,
539 result = self.digitalReadObj.read_vector_c81d(self.__thisUnixSample,
536 self.__samples_to_read,
540 self.__samples_to_read,
537 thisChannelName, sub_channel=indexSubchannel)
541 thisChannelName, sub_channel=indexSubchannel)
542 #print("result--------------",result)
538 self.executionTime = time() - t0
543 self.executionTime = time() - t0
539 if self.oldAverage is None:
544 if self.oldAverage is None:
540 self.oldAverage = self.executionTime
545 self.oldAverage = self.executionTime
541 self.oldAverage = (
546 self.oldAverage = (
542 self.executionTime + self.count * self.oldAverage) / (self.count + 1.0)
547 self.executionTime + self.count * self.oldAverage) / (self.count + 1.0)
543 self.count = self.count + 1.0
548 self.count = self.count + 1.0
544
549
545 except IOError as e:
550 except IOError as e:
546 # read next profile
551 # read next profile
547 self.__flagDiscontinuousBlock = True
552 self.__flagDiscontinuousBlock = True
548 print("[Reading] %s" % datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), e)
553 print("[Reading] %s" % datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone), e)
549 break
554 bot = 0
555 while(self.__flagDiscontinuousBlock):
556 bot +=1
557 self.__thisUnixSample += self.__sample_rate
558 try:
559 result = result = self.digitalReadObj.read_vector_c81d(self.__thisUnixSample,self.__samples_to_read,thisChannelName, sub_channel=indexSubchannel)
560 self.__flagDiscontinuousBlock=False
561 print("Searching.. NΒ°: ",bot,"Success",self.__thisUnixSample)
562 except:
563 print("Searching...NΒ°: ",bot,"Fail", self.__thisUnixSample)
564 if self.__flagDiscontinuousBlock==True:
565 break
566 else:
567 print("New data index found...",self.__thisUnixSample)
568 #break
550
569
551 if result.shape[0] != self.__samples_to_read:
570 if result.shape[0] != self.__samples_to_read:
552 self.__flagDiscontinuousBlock = True
571 self.__flagDiscontinuousBlock = True
553 print("[Reading] %s: Too few samples were found, just %d/%d samples" % (datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
572 print("[Reading] %s: Too few samples were found, just %d/%d samples" % (datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
554 result.shape[0],
573 result.shape[0],
555 self.__samples_to_read))
574 self.__samples_to_read))
556 break
575 break
557
576
558 self.__data_buffer[indexChannel, :] = result * volt_scale
577 self.__data_buffer[indexChannel, :] = result * volt_scale
559 indexChannel+=1
578 indexChannel+=1
560
579
561 dataOk = True
580 dataOk = True
562
581
563 self.__utctime = self.__thisUnixSample / self.__sample_rate
582 self.__utctime = self.__thisUnixSample / self.__sample_rate
564
583
565 if not dataOk:
584 if not dataOk:
566 return False
585 return False
567
586
568 print("[Reading] %s: %d samples <> %f sec" % (datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
587 print("[Reading] %s: %d samples <> %f sec" % (datetime.datetime.utcfromtimestamp(self.thisSecond - self.__timezone),
569 self.__samples_to_read,
588 self.__samples_to_read,
570 self.__timeInterval))
589 self.__timeInterval))
571
590
572 self.__bufferIndex = 0
591 self.__bufferIndex = 0
573
592
574 return True
593 return True
575
594
576 def __isBufferEmpty(self):
595 def __isBufferEmpty(self):
577
596
578 return self.__bufferIndex > self.__samples_to_read - self.__nSamples # 40960 - 40
597 return self.__bufferIndex > self.__samples_to_read - self.__nSamples # 40960 - 40
579
598
580 def getData(self, seconds=30, nTries=5):
599 def getData(self, seconds=30, nTries=5):
581 '''
600 '''
582 This method gets the data from files and put the data into the dataOut object
601 This method gets the data from files and put the data into the dataOut object
583
602
584 In addition, increase el the buffer counter in one.
603 In addition, increase el the buffer counter in one.
585
604
586 Return:
605 Return:
587 data : retorna un perfil de voltages (alturas * canales) copiados desde el
606 data : retorna un perfil de voltages (alturas * canales) copiados desde el
588 buffer. Si no hay mas archivos a leer retorna None.
607 buffer. Si no hay mas archivos a leer retorna None.
589
608
590 Affected:
609 Affected:
591 self.dataOut
610 self.dataOut
592 self.profileIndex
611 self.profileIndex
593 self.flagDiscontinuousBlock
612 self.flagDiscontinuousBlock
594 self.flagIsNewBlock
613 self.flagIsNewBlock
595 '''
614 '''
596 #print("getdata")
615 #print("getdata")
597 err_counter = 0
616 err_counter = 0
598 self.dataOut.flagNoData = True
617 self.dataOut.flagNoData = True
599
618
600
619
601 if self.__isBufferEmpty():
620 if self.__isBufferEmpty():
602 #print("hi")
621 #print("hi")
603 self.__flagDiscontinuousBlock = False
622 self.__flagDiscontinuousBlock = False
604
623
605 while True:
624 while True:
606 if self.__readNextBlock():
625 if self.__readNextBlock():
607 break
626 break
608 if self.__thisUnixSample > self.__endUTCSecond * self.__sample_rate:
627 if self.__thisUnixSample > self.__endUTCSecond * self.__sample_rate:
609 raise schainpy.admin.SchainError('Error')
628 raise schainpy.admin.SchainError('Error')
610 return
629 return
611
630
612 if self.__flagDiscontinuousBlock:
631 if self.__flagDiscontinuousBlock:
613 raise schainpy.admin.SchainError('discontinuous block found')
632 raise schainpy.admin.SchainError('discontinuous block found')
614 return
633 return
615
634
616 if not self.__online:
635 if not self.__online:
617 raise schainpy.admin.SchainError('Online?')
636 raise schainpy.admin.SchainError('Online?')
618 return
637 return
619
638
620 err_counter += 1
639 err_counter += 1
621 if err_counter > nTries:
640 if err_counter > nTries:
622 raise schainpy.admin.SchainError('Max retrys reach')
641 raise schainpy.admin.SchainError('Max retrys reach')
623 return
642 return
624
643
625 print('[Reading] waiting %d seconds to read a new block' % seconds)
644 print('[Reading] waiting %d seconds to read a new block' % seconds)
626 sleep(seconds)
645 sleep(seconds)
627
646
628
647
629 if not self.getByBlock:
648 if not self.getByBlock:
630
649
631 #print("self.__bufferIndex",self.__bufferIndex)# este valor siempre es cero aparentemente
650 #print("self.__bufferIndex",self.__bufferIndex)# este valor siempre es cero aparentemente
632 self.dataOut.data = self.__data_buffer[:, self.__bufferIndex:self.__bufferIndex + self.__nSamples]
651 self.dataOut.data = self.__data_buffer[:, self.__bufferIndex:self.__bufferIndex + self.__nSamples]
633 self.dataOut.utctime = ( self.__thisUnixSample + self.__bufferIndex) / self.__sample_rate
652 self.dataOut.utctime = ( self.__thisUnixSample + self.__bufferIndex) / self.__sample_rate
634 self.dataOut.flagNoData = False
653 self.dataOut.flagNoData = False
635 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
654 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
636 self.dataOut.profileIndex = self.profileIndex
655 self.dataOut.profileIndex = self.profileIndex
637
656
638 self.__bufferIndex += self.__nSamples
657 self.__bufferIndex += self.__nSamples
639 self.profileIndex += 1
658 self.profileIndex += 1
640
659
641 if self.profileIndex == self.dataOut.nProfiles:
660 if self.profileIndex == self.dataOut.nProfiles:
642 self.profileIndex = 0
661 self.profileIndex = 0
643 else:
662 else:
644 # ojo debo anadir el readNextBLock y el __isBufferEmpty(
663 # ojo debo anadir el readNextBLock y el __isBufferEmpty(
645 self.dataOut.flagNoData = False
664 self.dataOut.flagNoData = False
646 buffer = self.__data_buffer[:,self.__bufferIndex:self.__bufferIndex + self.__samples_to_read]
665 buffer = self.__data_buffer[:,self.__bufferIndex:self.__bufferIndex + self.__samples_to_read]
647 buffer = buffer.reshape((self.__nChannels, self.nProfileBlocks, int(self.__samples_to_read/self.nProfileBlocks)))
666 buffer = buffer.reshape((self.__nChannels, self.nProfileBlocks, int(self.__samples_to_read/self.nProfileBlocks)))
648 self.dataOut.nProfileBlocks = self.nProfileBlocks
667 self.dataOut.nProfileBlocks = self.nProfileBlocks
649 self.dataOut.data = buffer
668 self.dataOut.data = buffer
650 self.dataOut.utctime = ( self.__thisUnixSample + self.__bufferIndex) / self.__sample_rate
669 self.dataOut.utctime = ( self.__thisUnixSample + self.__bufferIndex) / self.__sample_rate
651 self.profileIndex += self.__samples_to_read
670 self.profileIndex += self.__samples_to_read
652 self.__bufferIndex += self.__samples_to_read
671 self.__bufferIndex += self.__samples_to_read
653 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
672 self.dataOut.flagDiscontinuousBlock = self.__flagDiscontinuousBlock
654 return True
673 return True
655
674
656
675
657 def printInfo(self):
676 def printInfo(self):
658 '''
677 '''
659 '''
678 '''
660 if self.__printInfo == False:
679 if self.__printInfo == False:
661 return
680 return
662
681
663 # self.systemHeaderObj.printInfo()
682 # self.systemHeaderObj.printInfo()
664 # self.radarControllerHeaderObj.printInfo()
683 # self.radarControllerHeaderObj.printInfo()
665
684
666 self.__printInfo = False
685 self.__printInfo = False
667
686
668 def printNumberOfBlock(self):
687 def printNumberOfBlock(self):
669 '''
688 '''
670 '''
689 '''
671 return
690 return
672 # print self.profileIndex
691 # print self.profileIndex
673
692
674 def run(self, **kwargs):
693 def run(self, **kwargs):
675 '''
694 '''
676 This method will be called many times so here you should put all your code
695 This method will be called many times so here you should put all your code
677 '''
696 '''
678
697
679 if not self.isConfig:
698 if not self.isConfig:
680 self.setup(**kwargs)
699 self.setup(**kwargs)
681
700
682 self.getData(seconds=self.__delay)
701 self.getData(seconds=self.__delay)
683
702
684 return
703 return
685
704
686 @MPDecorator
705 @MPDecorator
687 class DigitalRFWriter(Operation):
706 class DigitalRFWriter(Operation):
688 '''
707 '''
689 classdocs
708 classdocs
690 '''
709 '''
691
710
692 def __init__(self, **kwargs):
711 def __init__(self, **kwargs):
693 '''
712 '''
694 Constructor
713 Constructor
695 '''
714 '''
696 Operation.__init__(self, **kwargs)
715 Operation.__init__(self, **kwargs)
697 self.metadata_dict = {}
716 self.metadata_dict = {}
698 self.dataOut = None
717 self.dataOut = None
699 self.dtype = None
718 self.dtype = None
700 self.oldAverage = 0
719 self.oldAverage = 0
701
720
702 def setHeader(self):
721 def setHeader(self):
703
722
704 self.metadata_dict['frequency'] = self.dataOut.frequency
723 self.metadata_dict['frequency'] = self.dataOut.frequency
705 self.metadata_dict['timezone'] = self.dataOut.timeZone
724 self.metadata_dict['timezone'] = self.dataOut.timeZone
706 self.metadata_dict['dtype'] = pickle.dumps(self.dataOut.dtype)
725 self.metadata_dict['dtype'] = pickle.dumps(self.dataOut.dtype)
707 self.metadata_dict['nProfiles'] = self.dataOut.nProfiles
726 self.metadata_dict['nProfiles'] = self.dataOut.nProfiles
708 self.metadata_dict['heightList'] = self.dataOut.heightList
727 self.metadata_dict['heightList'] = self.dataOut.heightList
709 self.metadata_dict['channelList'] = self.dataOut.channelList
728 self.metadata_dict['channelList'] = self.dataOut.channelList
710 self.metadata_dict['flagDecodeData'] = self.dataOut.flagDecodeData
729 self.metadata_dict['flagDecodeData'] = self.dataOut.flagDecodeData
711 self.metadata_dict['flagDeflipData'] = self.dataOut.flagDeflipData
730 self.metadata_dict['flagDeflipData'] = self.dataOut.flagDeflipData
712 self.metadata_dict['flagShiftFFT'] = self.dataOut.flagShiftFFT
731 self.metadata_dict['flagShiftFFT'] = self.dataOut.flagShiftFFT
713 self.metadata_dict['useLocalTime'] = self.dataOut.useLocalTime
732 self.metadata_dict['useLocalTime'] = self.dataOut.useLocalTime
714 self.metadata_dict['nCohInt'] = self.dataOut.nCohInt
733 self.metadata_dict['nCohInt'] = self.dataOut.nCohInt
715 self.metadata_dict['type'] = self.dataOut.type
734 self.metadata_dict['type'] = self.dataOut.type
716 self.metadata_dict['flagDataAsBlock']= getattr(
735 self.metadata_dict['flagDataAsBlock']= getattr(
717 self.dataOut, 'flagDataAsBlock', None) # chequear
736 self.dataOut, 'flagDataAsBlock', None) # chequear
718
737
719 def setup(self, dataOut, path, frequency, fileCadence, dirCadence, metadataCadence, set=0, metadataFile='metadata', ext='.h5'):
738 def setup(self, dataOut, path, frequency, fileCadence, dirCadence, metadataCadence, set=0, metadataFile='metadata', ext='.h5'):
720 '''
739 '''
721 In this method we should set all initial parameters.
740 In this method we should set all initial parameters.
722 Input:
741 Input:
723 dataOut: Input data will also be outputa data
742 dataOut: Input data will also be outputa data
724 '''
743 '''
725 self.setHeader()
744 self.setHeader()
726 self.__ippSeconds = dataOut.ippSeconds
745 self.__ippSeconds = dataOut.ippSeconds
727 self.__deltaH = dataOut.getDeltaH()
746 self.__deltaH = dataOut.getDeltaH()
728 self.__sample_rate = 1e6 * 0.15 / self.__deltaH
747 self.__sample_rate = 1e6 * 0.15 / self.__deltaH
729 self.__dtype = dataOut.dtype
748 self.__dtype = dataOut.dtype
730 if len(dataOut.dtype) == 2:
749 if len(dataOut.dtype) == 2:
731 self.__dtype = dataOut.dtype[0]
750 self.__dtype = dataOut.dtype[0]
732 self.__nSamples = dataOut.systemHeaderObj.nSamples
751 self.__nSamples = dataOut.systemHeaderObj.nSamples
733 self.__nProfiles = dataOut.nProfiles
752 self.__nProfiles = dataOut.nProfiles
734
753
735 if self.dataOut.type != 'Voltage':
754 if self.dataOut.type != 'Voltage':
736 raise 'Digital RF cannot be used with this data type'
755 raise 'Digital RF cannot be used with this data type'
737 self.arr_data = numpy.ones((1, dataOut.nFFTPoints * len(
756 self.arr_data = numpy.ones((1, dataOut.nFFTPoints * len(
738 self.dataOut.channelList)), dtype=[('r', self.__dtype), ('i', self.__dtype)])
757 self.dataOut.channelList)), dtype=[('r', self.__dtype), ('i', self.__dtype)])
739 else:
758 else:
740 self.arr_data = numpy.ones((self.__nSamples, len(
759 self.arr_data = numpy.ones((self.__nSamples, len(
741 self.dataOut.channelList)), dtype=[('r', self.__dtype), ('i', self.__dtype)])
760 self.dataOut.channelList)), dtype=[('r', self.__dtype), ('i', self.__dtype)])
742
761
743 file_cadence_millisecs = 1000
762 file_cadence_millisecs = 1000
744
763
745 sample_rate_fraction = Fraction(self.__sample_rate).limit_denominator()
764 sample_rate_fraction = Fraction(self.__sample_rate).limit_denominator()
746 sample_rate_numerator = int(sample_rate_fraction.numerator)
765 sample_rate_numerator = int(sample_rate_fraction.numerator)
747 sample_rate_denominator = int(sample_rate_fraction.denominator)
766 sample_rate_denominator = int(sample_rate_fraction.denominator)
748 start_global_index = dataOut.utctime * self.__sample_rate
767 start_global_index = dataOut.utctime * self.__sample_rate
749
768
750 uuid = 'prueba'
769 uuid = 'prueba'
751 compression_level = 0
770 compression_level = 0
752 checksum = False
771 checksum = False
753 is_complex = True
772 is_complex = True
754 num_subchannels = len(dataOut.channelList)
773 num_subchannels = len(dataOut.channelList)
755 is_continuous = True
774 is_continuous = True
756 marching_periods = False
775 marching_periods = False
757
776
758 self.digitalWriteObj = digital_rf.DigitalRFWriter(path, self.__dtype, dirCadence,
777 self.digitalWriteObj = digital_rf.DigitalRFWriter(path, self.__dtype, dirCadence,
759 fileCadence, start_global_index,
778 fileCadence, start_global_index,
760 sample_rate_numerator, sample_rate_denominator, uuid, compression_level, checksum,
779 sample_rate_numerator, sample_rate_denominator, uuid, compression_level, checksum,
761 is_complex, num_subchannels, is_continuous, marching_periods)
780 is_complex, num_subchannels, is_continuous, marching_periods)
762 metadata_dir = os.path.join(path, 'metadata')
781 metadata_dir = os.path.join(path, 'metadata')
763 os.system('mkdir %s' % (metadata_dir))
782 os.system('mkdir %s' % (metadata_dir))
764 self.digitalMetadataWriteObj = digital_rf.DigitalMetadataWriter(metadata_dir, dirCadence, 1, # 236, file_cadence_millisecs / 1000
783 self.digitalMetadataWriteObj = digital_rf.DigitalMetadataWriter(metadata_dir, dirCadence, 1, # 236, file_cadence_millisecs / 1000
765 sample_rate_numerator, sample_rate_denominator,
784 sample_rate_numerator, sample_rate_denominator,
766 metadataFile)
785 metadataFile)
767 self.isConfig = True
786 self.isConfig = True
768 self.currentSample = 0
787 self.currentSample = 0
769 self.oldAverage = 0
788 self.oldAverage = 0
770 self.count = 0
789 self.count = 0
771 return
790 return
772
791
773 def writeMetadata(self):
792 def writeMetadata(self):
774 start_idx = self.__sample_rate * self.dataOut.utctime
793 start_idx = self.__sample_rate * self.dataOut.utctime
775
794
776 self.metadata_dict['processingHeader'] = self.dataOut.processingHeaderObj.getAsDict(
795 self.metadata_dict['processingHeader'] = self.dataOut.processingHeaderObj.getAsDict(
777 )
796 )
778 self.metadata_dict['radarControllerHeader'] = self.dataOut.radarControllerHeaderObj.getAsDict(
797 self.metadata_dict['radarControllerHeader'] = self.dataOut.radarControllerHeaderObj.getAsDict(
779 )
798 )
780 self.metadata_dict['systemHeader'] = self.dataOut.systemHeaderObj.getAsDict(
799 self.metadata_dict['systemHeader'] = self.dataOut.systemHeaderObj.getAsDict(
781 )
800 )
782 self.digitalMetadataWriteObj.write(start_idx, self.metadata_dict)
801 self.digitalMetadataWriteObj.write(start_idx, self.metadata_dict)
783 return
802 return
784
803
785 def timeit(self, toExecute):
804 def timeit(self, toExecute):
786 t0 = time()
805 t0 = time()
787 toExecute()
806 toExecute()
788 self.executionTime = time() - t0
807 self.executionTime = time() - t0
789 if self.oldAverage is None:
808 if self.oldAverage is None:
790 self.oldAverage = self.executionTime
809 self.oldAverage = self.executionTime
791 self.oldAverage = (self.executionTime + self.count *
810 self.oldAverage = (self.executionTime + self.count *
792 self.oldAverage) / (self.count + 1.0)
811 self.oldAverage) / (self.count + 1.0)
793 self.count = self.count + 1.0
812 self.count = self.count + 1.0
794 return
813 return
795
814
796 def writeData(self):
815 def writeData(self):
797 if self.dataOut.type != 'Voltage':
816 if self.dataOut.type != 'Voltage':
798 raise 'Digital RF cannot be used with this data type'
817 raise 'Digital RF cannot be used with this data type'
799 for channel in self.dataOut.channelList:
818 for channel in self.dataOut.channelList:
800 for i in range(self.dataOut.nFFTPoints):
819 for i in range(self.dataOut.nFFTPoints):
801 self.arr_data[1][channel * self.dataOut.nFFTPoints +
820 self.arr_data[1][channel * self.dataOut.nFFTPoints +
802 i]['r'] = self.dataOut.data[channel][i].real
821 i]['r'] = self.dataOut.data[channel][i].real
803 self.arr_data[1][channel * self.dataOut.nFFTPoints +
822 self.arr_data[1][channel * self.dataOut.nFFTPoints +
804 i]['i'] = self.dataOut.data[channel][i].imag
823 i]['i'] = self.dataOut.data[channel][i].imag
805 else:
824 else:
806 for i in range(self.dataOut.systemHeaderObj.nSamples):
825 for i in range(self.dataOut.systemHeaderObj.nSamples):
807 for channel in self.dataOut.channelList:
826 for channel in self.dataOut.channelList:
808 self.arr_data[i][channel]['r'] = self.dataOut.data[channel][i].real
827 self.arr_data[i][channel]['r'] = self.dataOut.data[channel][i].real
809 self.arr_data[i][channel]['i'] = self.dataOut.data[channel][i].imag
828 self.arr_data[i][channel]['i'] = self.dataOut.data[channel][i].imag
810
829
811 def f(): return self.digitalWriteObj.rf_write(self.arr_data)
830 def f(): return self.digitalWriteObj.rf_write(self.arr_data)
812 self.timeit(f)
831 self.timeit(f)
813
832
814 return
833 return
815
834
816 def run(self, dataOut, frequency=49.92e6, path=None, fileCadence=1000, dirCadence=36000, metadataCadence=1, **kwargs):
835 def run(self, dataOut, frequency=49.92e6, path=None, fileCadence=1000, dirCadence=36000, metadataCadence=1, **kwargs):
817 '''
836 '''
818 This method will be called many times so here you should put all your code
837 This method will be called many times so here you should put all your code
819 Inputs:
838 Inputs:
820 dataOut: object with the data
839 dataOut: object with the data
821 '''
840 '''
822 # print dataOut.__dict__
841 # print dataOut.__dict__
823 self.dataOut = dataOut
842 self.dataOut = dataOut
824 if not self.isConfig:
843 if not self.isConfig:
825 self.setup(dataOut, path, frequency, fileCadence,
844 self.setup(dataOut, path, frequency, fileCadence,
826 dirCadence, metadataCadence, **kwargs)
845 dirCadence, metadataCadence, **kwargs)
827 self.writeMetadata()
846 self.writeMetadata()
828
847
829 self.writeData()
848 self.writeData()
830
849
831 ## self.currentSample += 1
850 ## self.currentSample += 1
832 # if self.dataOut.flagDataAsBlock or self.currentSample == 1:
851 # if self.dataOut.flagDataAsBlock or self.currentSample == 1:
833 # self.writeMetadata()
852 # self.writeMetadata()
834 ## if self.currentSample == self.__nProfiles: self.currentSample = 0
853 ## if self.currentSample == self.__nProfiles: self.currentSample = 0
835
854
836 return dataOut# en la version 2.7 no aparece este return
855 return dataOut# en la version 2.7 no aparece este return
837
856
838 def close(self):
857 def close(self):
839 print('[Writing] - Closing files ')
858 print('[Writing] - Closing files ')
840 print('Average of writing to digital rf format is ', self.oldAverage * 1000)
859 print('Average of writing to digital rf format is ', self.oldAverage * 1000)
841 try:
860 try:
842 self.digitalWriteObj.close()
861 self.digitalWriteObj.close()
843 except:
862 except:
844 pass
863 pass
@@ -1,4494 +1,4496
1
1
2 import os
2 import os
3 import time
3 import time
4 import math
4 import math
5
5
6 import re
6 import re
7 import datetime
7 import datetime
8 import copy
8 import copy
9 import sys
9 import sys
10 import importlib
10 import importlib
11 import itertools
11 import itertools
12
12
13 from multiprocessing import Pool, TimeoutError
13 from multiprocessing import Pool, TimeoutError
14 from multiprocessing.pool import ThreadPool
14 from multiprocessing.pool import ThreadPool
15 import numpy
15 import numpy
16 import glob
16 import glob
17 import scipy
17 import scipy
18 import h5py
18 import h5py
19 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
19 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
20 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
20 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
21 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
21 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
22 from scipy import asarray as ar,exp
22 from scipy import asarray as ar,exp
23 from scipy.optimize import curve_fit
23 from scipy.optimize import curve_fit
24 from schainpy.utils import log
24 from schainpy.utils import log
25 import schainpy.admin
25 import schainpy.admin
26 import warnings
26 import warnings
27 from scipy import optimize, interpolate, signal, stats, ndimage
27 from scipy import optimize, interpolate, signal, stats, ndimage
28 from scipy.optimize.optimize import OptimizeWarning
28 from scipy.optimize.optimize import OptimizeWarning
29 warnings.filterwarnings('ignore')
29 warnings.filterwarnings('ignore')
30
30
31
31
32 SPEED_OF_LIGHT = 299792458
32 SPEED_OF_LIGHT = 299792458
33
33
34 '''solving pickling issue'''
34 '''solving pickling issue'''
35
35
36 def _pickle_method(method):
36 def _pickle_method(method):
37 func_name = method.__func__.__name__
37 func_name = method.__func__.__name__
38 obj = method.__self__
38 obj = method.__self__
39 cls = method.__self__.__class__
39 cls = method.__self__.__class__
40 return _unpickle_method, (func_name, obj, cls)
40 return _unpickle_method, (func_name, obj, cls)
41
41
42 def _unpickle_method(func_name, obj, cls):
42 def _unpickle_method(func_name, obj, cls):
43 for cls in cls.mro():
43 for cls in cls.mro():
44 try:
44 try:
45 func = cls.__dict__[func_name]
45 func = cls.__dict__[func_name]
46 except KeyError:
46 except KeyError:
47 pass
47 pass
48 else:
48 else:
49 break
49 break
50 return func.__get__(obj, cls)
50 return func.__get__(obj, cls)
51
51
52 def isNumber(str):
52 def isNumber(str):
53 try:
53 try:
54 float(str)
54 float(str)
55 return True
55 return True
56 except:
56 except:
57 return False
57 return False
58
58
59 class ParametersProc(ProcessingUnit):
59 class ParametersProc(ProcessingUnit):
60
60
61 METHODS = {}
61 METHODS = {}
62 nSeconds = None
62 nSeconds = None
63
63
64 def __init__(self):
64 def __init__(self):
65 ProcessingUnit.__init__(self)
65 ProcessingUnit.__init__(self)
66
66
67 # self.objectDict = {}
67 # self.objectDict = {}
68 self.buffer = None
68 self.buffer = None
69 self.firstdatatime = None
69 self.firstdatatime = None
70 self.profIndex = 0
70 self.profIndex = 0
71 self.dataOut = Parameters()
71 self.dataOut = Parameters()
72 self.setupReq = False #Agregar a todas las unidades de proc
72 self.setupReq = False #Agregar a todas las unidades de proc
73
73
74 def __updateObjFromInput(self):
74 def __updateObjFromInput(self):
75
75
76 self.dataOut.inputUnit = self.dataIn.type
76 self.dataOut.inputUnit = self.dataIn.type
77
77
78 self.dataOut.timeZone = self.dataIn.timeZone
78 self.dataOut.timeZone = self.dataIn.timeZone
79 self.dataOut.dstFlag = self.dataIn.dstFlag
79 self.dataOut.dstFlag = self.dataIn.dstFlag
80 self.dataOut.errorCount = self.dataIn.errorCount
80 self.dataOut.errorCount = self.dataIn.errorCount
81 self.dataOut.useLocalTime = self.dataIn.useLocalTime
81 self.dataOut.useLocalTime = self.dataIn.useLocalTime
82
82
83 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
83 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
84 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
84 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
85 self.dataOut.channelList = self.dataIn.channelList
85 self.dataOut.channelList = self.dataIn.channelList
86 self.dataOut.heightList = self.dataIn.heightList
86 self.dataOut.heightList = self.dataIn.heightList
87 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
87 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
88 # self.dataOut.nHeights = self.dataIn.nHeights
88 # self.dataOut.nHeights = self.dataIn.nHeights
89 # self.dataOut.nChannels = self.dataIn.nChannels
89 # self.dataOut.nChannels = self.dataIn.nChannels
90 # self.dataOut.nBaud = self.dataIn.nBaud
90 # self.dataOut.nBaud = self.dataIn.nBaud
91 # self.dataOut.nCode = self.dataIn.nCode
91 # self.dataOut.nCode = self.dataIn.nCode
92 # self.dataOut.code = self.dataIn.code
92 # self.dataOut.code = self.dataIn.code
93 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
93 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
94 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
94 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
95 # self.dataOut.utctime = self.firstdatatime
95 # self.dataOut.utctime = self.firstdatatime
96 self.dataOut.utctime = self.dataIn.utctime
96 self.dataOut.utctime = self.dataIn.utctime
97 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
97 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
98 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
98 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
99 self.dataOut.nCohInt = self.dataIn.nCohInt
99 self.dataOut.nCohInt = self.dataIn.nCohInt
100 # self.dataOut.nIncohInt = 1
100 # self.dataOut.nIncohInt = 1
101 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
101 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
102 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
102 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
103 self.dataOut.timeInterval1 = self.dataIn.timeInterval
103 self.dataOut.timeInterval1 = self.dataIn.timeInterval
104 self.dataOut.heightList = self.dataIn.heightList
104 self.dataOut.heightList = self.dataIn.heightList
105 self.dataOut.frequency = self.dataIn.frequency
105 self.dataOut.frequency = self.dataIn.frequency
106 # self.dataOut.noise = self.dataIn.noise
106 # self.dataOut.noise = self.dataIn.noise
107 self.dataOut.runNextUnit = self.dataIn.runNextUnit
107 self.dataOut.runNextUnit = self.dataIn.runNextUnit
108 self.dataOut.h0 = self.dataIn.h0
108 self.dataOut.h0 = self.dataIn.h0
109
109
110 def run(self, runNextUnit = 0):
110 def run(self, runNextUnit = 0):
111
111
112 self.dataIn.runNextUnit = runNextUnit
112 self.dataIn.runNextUnit = runNextUnit
113 #print("HOLA MUNDO SOY YO")
113 #print("HOLA MUNDO SOY YO")
114 #---------------------- Voltage Data ---------------------------
114 #---------------------- Voltage Data ---------------------------
115
115
116 if self.dataIn.type == "Voltage":
116 if self.dataIn.type == "Voltage":
117
117
118 self.__updateObjFromInput()
118 self.__updateObjFromInput()
119 self.dataOut.data_pre = self.dataIn.data.copy()
119 self.dataOut.data_pre = self.dataIn.data.copy()
120 self.dataOut.flagNoData = False
120 self.dataOut.flagNoData = False
121 self.dataOut.utctimeInit = self.dataIn.utctime
121 self.dataOut.utctimeInit = self.dataIn.utctime
122 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
122 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
123
123
124 if hasattr(self.dataIn, 'flagDataAsBlock'):
124 if hasattr(self.dataIn, 'flagDataAsBlock'):
125 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
125 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
126
126
127 if hasattr(self.dataIn, 'profileIndex'):
127 if hasattr(self.dataIn, 'profileIndex'):
128 self.dataOut.profileIndex = self.dataIn.profileIndex
128 self.dataOut.profileIndex = self.dataIn.profileIndex
129
129
130 if hasattr(self.dataIn, 'dataPP_POW'):
130 if hasattr(self.dataIn, 'dataPP_POW'):
131 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
131 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
132
132
133 if hasattr(self.dataIn, 'dataPP_POWER'):
133 if hasattr(self.dataIn, 'dataPP_POWER'):
134 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
134 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
135
135
136 if hasattr(self.dataIn, 'dataPP_DOP'):
136 if hasattr(self.dataIn, 'dataPP_DOP'):
137 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
137 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
138
138
139 if hasattr(self.dataIn, 'dataPP_SNR'):
139 if hasattr(self.dataIn, 'dataPP_SNR'):
140 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
140 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
141
141
142 if hasattr(self.dataIn, 'dataPP_WIDTH'):
142 if hasattr(self.dataIn, 'dataPP_WIDTH'):
143 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
143 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
144
144
145 if hasattr(self.dataIn, 'dataPP_CCF'):
145 if hasattr(self.dataIn, 'dataPP_CCF'):
146 self.dataOut.dataPP_CCF = self.dataIn.dataPP_CCF
146 self.dataOut.dataPP_CCF = self.dataIn.dataPP_CCF
147
147
148 if hasattr(self.dataIn, 'dataPP_NOISE'):
148 if hasattr(self.dataIn, 'dataPP_NOISE'):
149 self.dataOut.dataPP_NOISE = self.dataIn.dataPP_NOISE
149 self.dataOut.dataPP_NOISE = self.dataIn.dataPP_NOISE
150
150
151 if hasattr(self.dataIn, 'flagAskMode'):
151 if hasattr(self.dataIn, 'flagAskMode'):
152 self.dataOut.flagAskMode = self.dataIn.flagAskMode
152 self.dataOut.flagAskMode = self.dataIn.flagAskMode
153
153
154 return
154 return
155
155
156 #---------------------- Spectra Data ---------------------------
156 #---------------------- Spectra Data ---------------------------
157
157
158 if self.dataIn.type == "Spectra":
158 if self.dataIn.type == "Spectra":
159 #print("que paso en spectra")
159 #print("que paso en spectra")
160 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
160 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
161 self.dataOut.data_spc = self.dataIn.data_spc
161 self.dataOut.data_spc = self.dataIn.data_spc
162 self.dataOut.data_cspc = self.dataIn.data_cspc
162 self.dataOut.data_cspc = self.dataIn.data_cspc
163 self.dataOut.nProfiles = self.dataIn.nProfiles
163 self.dataOut.nProfiles = self.dataIn.nProfiles
164 self.dataOut.nIncohInt = self.dataIn.nIncohInt
164 self.dataOut.nIncohInt = self.dataIn.nIncohInt
165 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
165 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
166 self.dataOut.ippFactor = self.dataIn.ippFactor
166 self.dataOut.ippFactor = self.dataIn.ippFactor
167 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
167 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
168 self.dataOut.spc_noise = self.dataIn.getNoise()
168 self.dataOut.spc_noise = self.dataIn.getNoise()
169 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
169 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
170 # self.dataOut.normFactor = self.dataIn.normFactor
170 # self.dataOut.normFactor = self.dataIn.normFactor
171 self.dataOut.pairsList = self.dataIn.pairsList
171 self.dataOut.pairsList = self.dataIn.pairsList
172 self.dataOut.groupList = self.dataIn.pairsList
172 self.dataOut.groupList = self.dataIn.pairsList
173 self.dataOut.flagNoData = False
173 self.dataOut.flagNoData = False
174
174
175 if hasattr(self.dataIn, 'flagDataAsBlock'):
175 if hasattr(self.dataIn, 'flagDataAsBlock'):
176 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
176 self.dataOut.flagDataAsBlock = self.dataIn.flagDataAsBlock
177
177
178 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
178 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
179 self.dataOut.ChanDist = self.dataIn.ChanDist
179 self.dataOut.ChanDist = self.dataIn.ChanDist
180 else: self.dataOut.ChanDist = None
180 else: self.dataOut.ChanDist = None
181
181
182 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
182 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
183 # self.dataOut.VelRange = self.dataIn.VelRange
183 # self.dataOut.VelRange = self.dataIn.VelRange
184 #else: self.dataOut.VelRange = None
184 #else: self.dataOut.VelRange = None
185
185
186 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
186 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
187 self.dataOut.RadarConst = self.dataIn.RadarConst
187 self.dataOut.RadarConst = self.dataIn.RadarConst
188
188
189 if hasattr(self.dataIn, 'NPW'): #NPW
189 if hasattr(self.dataIn, 'NPW'): #NPW
190 self.dataOut.NPW = self.dataIn.NPW
190 self.dataOut.NPW = self.dataIn.NPW
191
191
192 if hasattr(self.dataIn, 'COFA'): #COFA
192 if hasattr(self.dataIn, 'COFA'): #COFA
193 self.dataOut.COFA = self.dataIn.COFA
193 self.dataOut.COFA = self.dataIn.COFA
194
194
195
195
196
196
197 #---------------------- Correlation Data ---------------------------
197 #---------------------- Correlation Data ---------------------------
198
198
199 if self.dataIn.type == "Correlation":
199 if self.dataIn.type == "Correlation":
200 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
200 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
201
201
202 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
202 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
203 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
203 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
204 self.dataOut.groupList = (acf_pairs, ccf_pairs)
204 self.dataOut.groupList = (acf_pairs, ccf_pairs)
205
205
206 self.dataOut.abscissaList = self.dataIn.lagRange
206 self.dataOut.abscissaList = self.dataIn.lagRange
207 self.dataOut.noise = self.dataIn.noise
207 self.dataOut.noise = self.dataIn.noise
208 self.dataOut.data_snr = self.dataIn.SNR
208 self.dataOut.data_snr = self.dataIn.SNR
209 self.dataOut.flagNoData = False
209 self.dataOut.flagNoData = False
210 self.dataOut.nAvg = self.dataIn.nAvg
210 self.dataOut.nAvg = self.dataIn.nAvg
211
211
212 #---------------------- Parameters Data ---------------------------
212 #---------------------- Parameters Data ---------------------------
213
213
214 if self.dataIn.type == "Parameters":
214 if self.dataIn.type == "Parameters":
215 self.dataOut.copy(self.dataIn)
215 self.dataOut.copy(self.dataIn)
216 self.dataOut.flagNoData = False
216 self.dataOut.flagNoData = False
217 #print("yo si entre")
217 #print("yo si entre")
218
218
219 return True
219 return True
220
220
221 self.__updateObjFromInput()
221 self.__updateObjFromInput()
222 #print("yo si entre2")
222 #print("yo si entre2")
223
223
224 self.dataOut.utctimeInit = self.dataIn.utctime
224 self.dataOut.utctimeInit = self.dataIn.utctime
225 self.dataOut.paramInterval = self.dataIn.timeInterval
225 self.dataOut.paramInterval = self.dataIn.timeInterval
226 #print("soy spectra ",self.dataOut.utctimeInit)
226 #print("soy spectra ",self.dataOut.utctimeInit)
227 return
227 return
228
228
229
229
230 def target(tups):
230 def target(tups):
231
231
232 obj, args = tups
232 obj, args = tups
233
233
234 return obj.FitGau(args)
234 return obj.FitGau(args)
235
235
236 class RemoveWideGC(Operation):
236 class RemoveWideGC(Operation):
237 ''' This class remove the wide clutter and replace it with a simple interpolation points
237 ''' This class remove the wide clutter and replace it with a simple interpolation points
238 This mainly applies to CLAIRE radar
238 This mainly applies to CLAIRE radar
239
239
240 ClutterWidth : Width to look for the clutter peak
240 ClutterWidth : Width to look for the clutter peak
241
241
242 Input:
242 Input:
243
243
244 self.dataOut.data_pre : SPC and CSPC
244 self.dataOut.data_pre : SPC and CSPC
245 self.dataOut.spc_range : To select wind and rainfall velocities
245 self.dataOut.spc_range : To select wind and rainfall velocities
246
246
247 Affected:
247 Affected:
248
248
249 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
249 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
250
250
251 Written by D. ScipiΓ³n 25.02.2021
251 Written by D. ScipiΓ³n 25.02.2021
252 '''
252 '''
253 def __init__(self):
253 def __init__(self):
254 Operation.__init__(self)
254 Operation.__init__(self)
255 self.i = 0
255 self.i = 0
256 self.ich = 0
256 self.ich = 0
257 self.ir = 0
257 self.ir = 0
258
258
259 def run(self, dataOut, ClutterWidth=2.5):
259 def run(self, dataOut, ClutterWidth=2.5):
260 # print ('Entering RemoveWideGC ... ')
260 # print ('Entering RemoveWideGC ... ')
261
261
262 self.spc = dataOut.data_pre[0].copy()
262 self.spc = dataOut.data_pre[0].copy()
263 self.spc_out = dataOut.data_pre[0].copy()
263 self.spc_out = dataOut.data_pre[0].copy()
264 self.Num_Chn = self.spc.shape[0]
264 self.Num_Chn = self.spc.shape[0]
265 self.Num_Hei = self.spc.shape[2]
265 self.Num_Hei = self.spc.shape[2]
266 VelRange = dataOut.spc_range[2][:-1]
266 VelRange = dataOut.spc_range[2][:-1]
267 dv = VelRange[1]-VelRange[0]
267 dv = VelRange[1]-VelRange[0]
268
268
269 # Find the velocities that corresponds to zero
269 # Find the velocities that corresponds to zero
270 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
270 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
271
271
272 # Removing novalid data from the spectra
272 # Removing novalid data from the spectra
273 for ich in range(self.Num_Chn) :
273 for ich in range(self.Num_Chn) :
274 for ir in range(self.Num_Hei) :
274 for ir in range(self.Num_Hei) :
275 # Estimate the noise at each range
275 # Estimate the noise at each range
276 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
276 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
277
277
278 # Removing the noise floor at each range
278 # Removing the noise floor at each range
279 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
279 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
280 self.spc[ich,novalid,ir] = HSn
280 self.spc[ich,novalid,ir] = HSn
281
281
282 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
282 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
283 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
283 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
284 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
284 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
285 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
285 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
286 continue
286 continue
287 junk3 = numpy.squeeze(numpy.diff(j1index))
287 junk3 = numpy.squeeze(numpy.diff(j1index))
288 junk4 = numpy.squeeze(numpy.diff(j2index))
288 junk4 = numpy.squeeze(numpy.diff(j2index))
289
289
290 valleyindex = j2index[numpy.where(junk4>1)]
290 valleyindex = j2index[numpy.where(junk4>1)]
291 peakindex = j1index[numpy.where(junk3>1)]
291 peakindex = j1index[numpy.where(junk3>1)]
292
292
293 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
293 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
294 if numpy.size(isvalid) == 0 :
294 if numpy.size(isvalid) == 0 :
295 continue
295 continue
296 if numpy.size(isvalid) >1 :
296 if numpy.size(isvalid) >1 :
297 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
297 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
298 isvalid = isvalid[vindex]
298 isvalid = isvalid[vindex]
299
299
300 # clutter peak
300 # clutter peak
301 gcpeak = peakindex[isvalid]
301 gcpeak = peakindex[isvalid]
302 vl = numpy.where(valleyindex < gcpeak)
302 vl = numpy.where(valleyindex < gcpeak)
303 if numpy.size(vl) == 0:
303 if numpy.size(vl) == 0:
304 continue
304 continue
305 gcvl = valleyindex[vl[0][-1]]
305 gcvl = valleyindex[vl[0][-1]]
306 vr = numpy.where(valleyindex > gcpeak)
306 vr = numpy.where(valleyindex > gcpeak)
307 if numpy.size(vr) == 0:
307 if numpy.size(vr) == 0:
308 continue
308 continue
309 gcvr = valleyindex[vr[0][0]]
309 gcvr = valleyindex[vr[0][0]]
310
310
311 # Removing the clutter
311 # Removing the clutter
312 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
312 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
313 gcindex = gc_values[gcvl+1:gcvr-1]
313 gcindex = gc_values[gcvl+1:gcvr-1]
314 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
314 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
315
315
316 dataOut.data_pre[0] = self.spc_out
316 dataOut.data_pre[0] = self.spc_out
317 #print ('Leaving RemoveWideGC ... ')
317 #print ('Leaving RemoveWideGC ... ')
318 return dataOut
318 return dataOut
319
319
320 class SpectralFilters(Operation):
320 class SpectralFilters(Operation):
321 ''' This class allows to replace the novalid values with noise for each channel
321 ''' This class allows to replace the novalid values with noise for each channel
322 This applies to CLAIRE RADAR
322 This applies to CLAIRE RADAR
323
323
324 PositiveLimit : RightLimit of novalid data
324 PositiveLimit : RightLimit of novalid data
325 NegativeLimit : LeftLimit of novalid data
325 NegativeLimit : LeftLimit of novalid data
326
326
327 Input:
327 Input:
328
328
329 self.dataOut.data_pre : SPC and CSPC
329 self.dataOut.data_pre : SPC and CSPC
330 self.dataOut.spc_range : To select wind and rainfall velocities
330 self.dataOut.spc_range : To select wind and rainfall velocities
331
331
332 Affected:
332 Affected:
333
333
334 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
334 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
335
335
336 Written by D. ScipiΓ³n 29.01.2021
336 Written by D. ScipiΓ³n 29.01.2021
337 '''
337 '''
338 def __init__(self):
338 def __init__(self):
339 Operation.__init__(self)
339 Operation.__init__(self)
340 self.i = 0
340 self.i = 0
341
341
342 def run(self, dataOut, ):
342 def run(self, dataOut, ):
343
343
344 self.spc = dataOut.data_pre[0].copy()
344 self.spc = dataOut.data_pre[0].copy()
345 self.Num_Chn = self.spc.shape[0]
345 self.Num_Chn = self.spc.shape[0]
346 VelRange = dataOut.spc_range[2]
346 VelRange = dataOut.spc_range[2]
347
347
348 # novalid corresponds to data within the Negative and PositiveLimit
348 # novalid corresponds to data within the Negative and PositiveLimit
349
349
350
350
351 # Removing novalid data from the spectra
351 # Removing novalid data from the spectra
352 for i in range(self.Num_Chn):
352 for i in range(self.Num_Chn):
353 self.spc[i,novalid,:] = dataOut.noise[i]
353 self.spc[i,novalid,:] = dataOut.noise[i]
354 dataOut.data_pre[0] = self.spc
354 dataOut.data_pre[0] = self.spc
355 return dataOut
355 return dataOut
356
356
357 class GaussianFit(Operation):
357 class GaussianFit(Operation):
358
358
359 '''
359 '''
360 Function that fit of one and two generalized gaussians (gg) based
360 Function that fit of one and two generalized gaussians (gg) based
361 on the PSD shape across an "power band" identified from a cumsum of
361 on the PSD shape across an "power band" identified from a cumsum of
362 the measured spectrum - noise.
362 the measured spectrum - noise.
363
363
364 Input:
364 Input:
365 self.dataOut.data_pre : SelfSpectra
365 self.dataOut.data_pre : SelfSpectra
366
366
367 Output:
367 Output:
368 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
368 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
369
369
370 '''
370 '''
371 def __init__(self):
371 def __init__(self):
372 Operation.__init__(self)
372 Operation.__init__(self)
373 self.i=0
373 self.i=0
374
374
375
375
376 # 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
376 # 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
377 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
377 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
378 """This routine will find a couple of generalized Gaussians to a power spectrum
378 """This routine will find a couple of generalized Gaussians to a power spectrum
379 methods: generalized, squared
379 methods: generalized, squared
380 input: spc
380 input: spc
381 output:
381 output:
382 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
382 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
383 """
383 """
384 print ('Entering ',method,' double Gaussian fit')
384 print ('Entering ',method,' double Gaussian fit')
385 self.spc = dataOut.data_pre[0].copy()
385 self.spc = dataOut.data_pre[0].copy()
386 self.Num_Hei = self.spc.shape[2]
386 self.Num_Hei = self.spc.shape[2]
387 self.Num_Bin = self.spc.shape[1]
387 self.Num_Bin = self.spc.shape[1]
388 self.Num_Chn = self.spc.shape[0]
388 self.Num_Chn = self.spc.shape[0]
389
389
390 start_time = time.time()
390 start_time = time.time()
391
391
392 pool = Pool(processes=self.Num_Chn)
392 pool = Pool(processes=self.Num_Chn)
393 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
393 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
394 objs = [self for __ in range(self.Num_Chn)]
394 objs = [self for __ in range(self.Num_Chn)]
395 attrs = list(zip(objs, args))
395 attrs = list(zip(objs, args))
396 DGauFitParam = pool.map(target, attrs)
396 DGauFitParam = pool.map(target, attrs)
397 # Parameters:
397 # Parameters:
398 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
398 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
399 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
399 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
400
400
401 # Double Gaussian Curves
401 # Double Gaussian Curves
402 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
402 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
403 gau0[:] = numpy.NaN
403 gau0[:] = numpy.NaN
404 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
404 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
405 gau1[:] = numpy.NaN
405 gau1[:] = numpy.NaN
406 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
406 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
407 for iCh in range(self.Num_Chn):
407 for iCh in range(self.Num_Chn):
408 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
408 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
409 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
409 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
410 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
410 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
411 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
411 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
412 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
412 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
413 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
413 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
414 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
414 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
415 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
415 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
416 if method == 'genealized':
416 if method == 'genealized':
417 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
417 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
418 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
418 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
419 elif method == 'squared':
419 elif method == 'squared':
420 p0 = 2.
420 p0 = 2.
421 p1 = 2.
421 p1 = 2.
422 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
422 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
423 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
423 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
424 dataOut.GaussFit0 = gau0
424 dataOut.GaussFit0 = gau0
425 dataOut.GaussFit1 = gau1
425 dataOut.GaussFit1 = gau1
426
426
427 print('Leaving ',method ,' double Gaussian fit')
427 print('Leaving ',method ,' double Gaussian fit')
428 return dataOut
428 return dataOut
429
429
430 def FitGau(self, X):
430 def FitGau(self, X):
431 # print('Entering FitGau')
431 # print('Entering FitGau')
432 # Assigning the variables
432 # Assigning the variables
433 Vrange, ch, wnoise, num_intg, SNRlimit = X
433 Vrange, ch, wnoise, num_intg, SNRlimit = X
434 # Noise Limits
434 # Noise Limits
435 noisebl = wnoise * 0.9
435 noisebl = wnoise * 0.9
436 noisebh = wnoise * 1.1
436 noisebh = wnoise * 1.1
437 # Radar Velocity
437 # Radar Velocity
438 Va = max(Vrange)
438 Va = max(Vrange)
439 deltav = Vrange[1] - Vrange[0]
439 deltav = Vrange[1] - Vrange[0]
440 x = numpy.arange(self.Num_Bin)
440 x = numpy.arange(self.Num_Bin)
441
441
442 # print ('stop 0')
442 # print ('stop 0')
443
443
444 # 5 parameters, 2 Gaussians
444 # 5 parameters, 2 Gaussians
445 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
445 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
446 DGauFitParam[:] = numpy.NaN
446 DGauFitParam[:] = numpy.NaN
447
447
448 # SPCparam = []
448 # SPCparam = []
449 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
449 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
450 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
450 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
451 # SPC_ch1[:] = 0 #numpy.NaN
451 # SPC_ch1[:] = 0 #numpy.NaN
452 # SPC_ch2[:] = 0 #numpy.NaN
452 # SPC_ch2[:] = 0 #numpy.NaN
453 # print ('stop 1')
453 # print ('stop 1')
454 for ht in range(self.Num_Hei):
454 for ht in range(self.Num_Hei):
455 # print (ht)
455 # print (ht)
456 # print ('stop 2')
456 # print ('stop 2')
457 # Spectra at each range
457 # Spectra at each range
458 spc = numpy.asarray(self.spc)[ch,:,ht]
458 spc = numpy.asarray(self.spc)[ch,:,ht]
459 snr = ( spc.mean() - wnoise ) / wnoise
459 snr = ( spc.mean() - wnoise ) / wnoise
460 snrdB = 10.*numpy.log10(snr)
460 snrdB = 10.*numpy.log10(snr)
461
461
462 #print ('stop 3')
462 #print ('stop 3')
463 if snrdB < SNRlimit :
463 if snrdB < SNRlimit :
464 # snr = numpy.NaN
464 # snr = numpy.NaN
465 # SPC_ch1[:,ht] = 0#numpy.NaN
465 # SPC_ch1[:,ht] = 0#numpy.NaN
466 # SPC_ch1[:,ht] = 0#numpy.NaN
466 # SPC_ch1[:,ht] = 0#numpy.NaN
467 # SPCparam = (SPC_ch1,SPC_ch2)
467 # SPCparam = (SPC_ch1,SPC_ch2)
468 # print ('SNR less than SNRth')
468 # print ('SNR less than SNRth')
469 continue
469 continue
470 # wnoise = hildebrand_sekhon(spc,num_intg)
470 # wnoise = hildebrand_sekhon(spc,num_intg)
471 # print ('stop 2.01')
471 # print ('stop 2.01')
472 #############################################
472 #############################################
473 # normalizing spc and noise
473 # normalizing spc and noise
474 # This part differs from gg1
474 # This part differs from gg1
475 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
475 # spc_norm_max = max(spc) #commented by D. ScipiΓ³n 19.03.2021
476 #spc = spc / spc_norm_max
476 #spc = spc / spc_norm_max
477 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
477 # pnoise = pnoise #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
478 #############################################
478 #############################################
479
479
480 # print ('stop 2.1')
480 # print ('stop 2.1')
481 fatspectra=1.0
481 fatspectra=1.0
482 # noise per channel.... we might want to use the noise at each range
482 # noise per channel.... we might want to use the noise at each range
483
483
484 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
484 # wnoise = noise_ #/ spc_norm_max #commented by D. ScipiΓ³n 19.03.2021
485 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
485 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
486 #if wnoise>1.1*pnoise: # to be tested later
486 #if wnoise>1.1*pnoise: # to be tested later
487 # wnoise=pnoise
487 # wnoise=pnoise
488 # noisebl = wnoise*0.9
488 # noisebl = wnoise*0.9
489 # noisebh = wnoise*1.1
489 # noisebh = wnoise*1.1
490 spc = spc - wnoise # signal
490 spc = spc - wnoise # signal
491
491
492 # print ('stop 2.2')
492 # print ('stop 2.2')
493 minx = numpy.argmin(spc)
493 minx = numpy.argmin(spc)
494 #spcs=spc.copy()
494 #spcs=spc.copy()
495 spcs = numpy.roll(spc,-minx)
495 spcs = numpy.roll(spc,-minx)
496 cum = numpy.cumsum(spcs)
496 cum = numpy.cumsum(spcs)
497 # tot_noise = wnoise * self.Num_Bin #64;
497 # tot_noise = wnoise * self.Num_Bin #64;
498
498
499 # print ('stop 2.3')
499 # print ('stop 2.3')
500 # snr = sum(spcs) / tot_noise
500 # snr = sum(spcs) / tot_noise
501 # snrdB = 10.*numpy.log10(snr)
501 # snrdB = 10.*numpy.log10(snr)
502 #print ('stop 3')
502 #print ('stop 3')
503 # if snrdB < SNRlimit :
503 # if snrdB < SNRlimit :
504 # snr = numpy.NaN
504 # snr = numpy.NaN
505 # SPC_ch1[:,ht] = 0#numpy.NaN
505 # SPC_ch1[:,ht] = 0#numpy.NaN
506 # SPC_ch1[:,ht] = 0#numpy.NaN
506 # SPC_ch1[:,ht] = 0#numpy.NaN
507 # SPCparam = (SPC_ch1,SPC_ch2)
507 # SPCparam = (SPC_ch1,SPC_ch2)
508 # print ('SNR less than SNRth')
508 # print ('SNR less than SNRth')
509 # continue
509 # continue
510
510
511
511
512 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
512 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
513 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
513 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
514 # print ('stop 4')
514 # print ('stop 4')
515 cummax = max(cum)
515 cummax = max(cum)
516 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
516 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
517 cumlo = cummax * epsi
517 cumlo = cummax * epsi
518 cumhi = cummax * (1-epsi)
518 cumhi = cummax * (1-epsi)
519 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
519 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
520
520
521 # print ('stop 5')
521 # print ('stop 5')
522 if len(powerindex) < 1:# case for powerindex 0
522 if len(powerindex) < 1:# case for powerindex 0
523 # print ('powerindex < 1')
523 # print ('powerindex < 1')
524 continue
524 continue
525 powerlo = powerindex[0]
525 powerlo = powerindex[0]
526 powerhi = powerindex[-1]
526 powerhi = powerindex[-1]
527 powerwidth = powerhi-powerlo
527 powerwidth = powerhi-powerlo
528 if powerwidth <= 1:
528 if powerwidth <= 1:
529 # print('powerwidth <= 1')
529 # print('powerwidth <= 1')
530 continue
530 continue
531
531
532 # print ('stop 6')
532 # print ('stop 6')
533 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
533 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
534 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
534 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
535 midpeak = (firstpeak + secondpeak)/2.
535 midpeak = (firstpeak + secondpeak)/2.
536 firstamp = spcs[int(firstpeak)]
536 firstamp = spcs[int(firstpeak)]
537 secondamp = spcs[int(secondpeak)]
537 secondamp = spcs[int(secondpeak)]
538 midamp = spcs[int(midpeak)]
538 midamp = spcs[int(midpeak)]
539
539
540 y_data = spc + wnoise
540 y_data = spc + wnoise
541
541
542 ''' single Gaussian '''
542 ''' single Gaussian '''
543 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
543 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
544 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
544 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
545 power0 = 2.
545 power0 = 2.
546 amplitude0 = midamp
546 amplitude0 = midamp
547 state0 = [shift0,width0,amplitude0,power0,wnoise]
547 state0 = [shift0,width0,amplitude0,power0,wnoise]
548 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
548 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
549 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
549 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
550 # print ('stop 7.1')
550 # print ('stop 7.1')
551 # print (bnds)
551 # print (bnds)
552
552
553 chiSq1=lsq1[1]
553 chiSq1=lsq1[1]
554
554
555 # print ('stop 8')
555 # print ('stop 8')
556 if fatspectra<1.0 and powerwidth<4:
556 if fatspectra<1.0 and powerwidth<4:
557 choice=0
557 choice=0
558 Amplitude0=lsq1[0][2]
558 Amplitude0=lsq1[0][2]
559 shift0=lsq1[0][0]
559 shift0=lsq1[0][0]
560 width0=lsq1[0][1]
560 width0=lsq1[0][1]
561 p0=lsq1[0][3]
561 p0=lsq1[0][3]
562 Amplitude1=0.
562 Amplitude1=0.
563 shift1=0.
563 shift1=0.
564 width1=0.
564 width1=0.
565 p1=0.
565 p1=0.
566 noise=lsq1[0][4]
566 noise=lsq1[0][4]
567 #return (numpy.array([shift0,width0,Amplitude0,p0]),
567 #return (numpy.array([shift0,width0,Amplitude0,p0]),
568 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
568 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
569
569
570 # print ('stop 9')
570 # print ('stop 9')
571 ''' two Gaussians '''
571 ''' two Gaussians '''
572 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
572 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
573 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
573 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
574 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
574 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
575 width0 = powerwidth/6.
575 width0 = powerwidth/6.
576 width1 = width0
576 width1 = width0
577 power0 = 2.
577 power0 = 2.
578 power1 = power0
578 power1 = power0
579 amplitude0 = firstamp
579 amplitude0 = firstamp
580 amplitude1 = secondamp
580 amplitude1 = secondamp
581 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
581 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
582 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
582 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
583 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))
583 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))
584 #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))
584 #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))
585
585
586 # print ('stop 10')
586 # print ('stop 10')
587 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
587 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
588
588
589 # print ('stop 11')
589 # print ('stop 11')
590 chiSq2 = lsq2[1]
590 chiSq2 = lsq2[1]
591
591
592 # print ('stop 12')
592 # print ('stop 12')
593
593
594 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)
594 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)
595
595
596 # print ('stop 13')
596 # print ('stop 13')
597 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
597 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
598 if oneG:
598 if oneG:
599 choice = 0
599 choice = 0
600 else:
600 else:
601 w1 = lsq2[0][1]; w2 = lsq2[0][5]
601 w1 = lsq2[0][1]; w2 = lsq2[0][5]
602 a1 = lsq2[0][2]; a2 = lsq2[0][6]
602 a1 = lsq2[0][2]; a2 = lsq2[0][6]
603 p1 = lsq2[0][3]; p2 = lsq2[0][7]
603 p1 = lsq2[0][3]; p2 = lsq2[0][7]
604 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
604 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
605 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
605 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
606 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
606 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
607
607
608 if gp1>gp2:
608 if gp1>gp2:
609 if a1>0.7*a2:
609 if a1>0.7*a2:
610 choice = 1
610 choice = 1
611 else:
611 else:
612 choice = 2
612 choice = 2
613 elif gp2>gp1:
613 elif gp2>gp1:
614 if a2>0.7*a1:
614 if a2>0.7*a1:
615 choice = 2
615 choice = 2
616 else:
616 else:
617 choice = 1
617 choice = 1
618 else:
618 else:
619 choice = numpy.argmax([a1,a2])+1
619 choice = numpy.argmax([a1,a2])+1
620 #else:
620 #else:
621 #choice=argmin([std2a,std2b])+1
621 #choice=argmin([std2a,std2b])+1
622
622
623 else: # with low SNR go to the most energetic peak
623 else: # with low SNR go to the most energetic peak
624 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
624 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
625
625
626 # print ('stop 14')
626 # print ('stop 14')
627 shift0 = lsq2[0][0]
627 shift0 = lsq2[0][0]
628 vel0 = Vrange[0] + shift0 * deltav
628 vel0 = Vrange[0] + shift0 * deltav
629 shift1 = lsq2[0][4]
629 shift1 = lsq2[0][4]
630 # vel1=Vrange[0] + shift1 * deltav
630 # vel1=Vrange[0] + shift1 * deltav
631
631
632 # max_vel = 1.0
632 # max_vel = 1.0
633 # Va = max(Vrange)
633 # Va = max(Vrange)
634 # deltav = Vrange[1]-Vrange[0]
634 # deltav = Vrange[1]-Vrange[0]
635 # print ('stop 15')
635 # print ('stop 15')
636 #first peak will be 0, second peak will be 1
636 #first peak will be 0, second peak will be 1
637 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
637 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.ScipiΓ³n 19.03.2021
638 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
638 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
639 shift0 = lsq2[0][0]
639 shift0 = lsq2[0][0]
640 width0 = lsq2[0][1]
640 width0 = lsq2[0][1]
641 Amplitude0 = lsq2[0][2]
641 Amplitude0 = lsq2[0][2]
642 p0 = lsq2[0][3]
642 p0 = lsq2[0][3]
643
643
644 shift1 = lsq2[0][4]
644 shift1 = lsq2[0][4]
645 width1 = lsq2[0][5]
645 width1 = lsq2[0][5]
646 Amplitude1 = lsq2[0][6]
646 Amplitude1 = lsq2[0][6]
647 p1 = lsq2[0][7]
647 p1 = lsq2[0][7]
648 noise = lsq2[0][8]
648 noise = lsq2[0][8]
649 else:
649 else:
650 shift1 = lsq2[0][0]
650 shift1 = lsq2[0][0]
651 width1 = lsq2[0][1]
651 width1 = lsq2[0][1]
652 Amplitude1 = lsq2[0][2]
652 Amplitude1 = lsq2[0][2]
653 p1 = lsq2[0][3]
653 p1 = lsq2[0][3]
654
654
655 shift0 = lsq2[0][4]
655 shift0 = lsq2[0][4]
656 width0 = lsq2[0][5]
656 width0 = lsq2[0][5]
657 Amplitude0 = lsq2[0][6]
657 Amplitude0 = lsq2[0][6]
658 p0 = lsq2[0][7]
658 p0 = lsq2[0][7]
659 noise = lsq2[0][8]
659 noise = lsq2[0][8]
660
660
661 if Amplitude0<0.05: # in case the peak is noise
661 if Amplitude0<0.05: # in case the peak is noise
662 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
662 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
663 if Amplitude1<0.05:
663 if Amplitude1<0.05:
664 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
664 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
665
665
666 # print ('stop 16 ')
666 # print ('stop 16 ')
667 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
667 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
668 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
668 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
669 # SPCparam = (SPC_ch1,SPC_ch2)
669 # SPCparam = (SPC_ch1,SPC_ch2)
670
670
671 DGauFitParam[0,ht,0] = noise
671 DGauFitParam[0,ht,0] = noise
672 DGauFitParam[0,ht,1] = noise
672 DGauFitParam[0,ht,1] = noise
673 DGauFitParam[1,ht,0] = Amplitude0
673 DGauFitParam[1,ht,0] = Amplitude0
674 DGauFitParam[1,ht,1] = Amplitude1
674 DGauFitParam[1,ht,1] = Amplitude1
675 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
675 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
676 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
676 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
677 DGauFitParam[3,ht,0] = width0 * deltav
677 DGauFitParam[3,ht,0] = width0 * deltav
678 DGauFitParam[3,ht,1] = width1 * deltav
678 DGauFitParam[3,ht,1] = width1 * deltav
679 DGauFitParam[4,ht,0] = p0
679 DGauFitParam[4,ht,0] = p0
680 DGauFitParam[4,ht,1] = p1
680 DGauFitParam[4,ht,1] = p1
681
681
682 # print (DGauFitParam.shape)
682 # print (DGauFitParam.shape)
683 # print ('Leaving FitGau')
683 # print ('Leaving FitGau')
684 return DGauFitParam
684 return DGauFitParam
685 # return SPCparam
685 # return SPCparam
686 # return GauSPC
686 # return GauSPC
687
687
688 def y_model1(self,x,state):
688 def y_model1(self,x,state):
689 shift0, width0, amplitude0, power0, noise = state
689 shift0, width0, amplitude0, power0, noise = state
690 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
690 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
691 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
691 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
692 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
692 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
693 return model0 + model0u + model0d + noise
693 return model0 + model0u + model0d + noise
694
694
695 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
695 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
696 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
696 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
697 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
697 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
698 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
698 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
699 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
699 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
700
700
701 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
701 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
702 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
702 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
703 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
703 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
704 return model0 + model0u + model0d + model1 + model1u + model1d + noise
704 return model0 + model0u + model0d + model1 + model1u + model1d + noise
705
705
706 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.
706 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.
707
707
708 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
708 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
709
709
710 def misfit2(self,state,y_data,x,num_intg):
710 def misfit2(self,state,y_data,x,num_intg):
711 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
711 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
712
712
713
713
714
714
715 class PrecipitationProc(Operation):
715 class PrecipitationProc(Operation):
716
716
717 '''
717 '''
718 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
718 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
719
719
720 Input:
720 Input:
721 self.dataOut.data_pre : SelfSpectra
721 self.dataOut.data_pre : SelfSpectra
722
722
723 Output:
723 Output:
724
724
725 self.dataOut.data_output : Reflectivity factor, rainfall Rate
725 self.dataOut.data_output : Reflectivity factor, rainfall Rate
726
726
727
727
728 Parameters affected:
728 Parameters affected:
729 '''
729 '''
730
730
731 def __init__(self):
731 def __init__(self):
732 Operation.__init__(self)
732 Operation.__init__(self)
733 self.i=0
733 self.i=0
734
734
735 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
735 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
736 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
736 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
737
737
738 # print ('Entering PrecepitationProc ... ')
738 # print ('Entering PrecepitationProc ... ')
739
739
740 if radar == "MIRA35C" :
740 if radar == "MIRA35C" :
741
741
742 self.spc = dataOut.data_pre[0].copy()
742 self.spc = dataOut.data_pre[0].copy()
743 self.Num_Hei = self.spc.shape[2]
743 self.Num_Hei = self.spc.shape[2]
744 self.Num_Bin = self.spc.shape[1]
744 self.Num_Bin = self.spc.shape[1]
745 self.Num_Chn = self.spc.shape[0]
745 self.Num_Chn = self.spc.shape[0]
746 Ze = self.dBZeMODE2(dataOut)
746 Ze = self.dBZeMODE2(dataOut)
747
747
748 else:
748 else:
749
749
750 self.spc = dataOut.data_pre[0].copy()
750 self.spc = dataOut.data_pre[0].copy()
751
751
752 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
752 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
753 self.spc[:,:,0:7]= numpy.NaN
753 self.spc[:,:,0:7]= numpy.NaN
754
754
755 self.Num_Hei = self.spc.shape[2]
755 self.Num_Hei = self.spc.shape[2]
756 self.Num_Bin = self.spc.shape[1]
756 self.Num_Bin = self.spc.shape[1]
757 self.Num_Chn = self.spc.shape[0]
757 self.Num_Chn = self.spc.shape[0]
758
758
759 VelRange = dataOut.spc_range[2]
759 VelRange = dataOut.spc_range[2]
760
760
761 ''' Se obtiene la constante del RADAR '''
761 ''' Se obtiene la constante del RADAR '''
762
762
763 self.Pt = Pt
763 self.Pt = Pt
764 self.Gt = Gt
764 self.Gt = Gt
765 self.Gr = Gr
765 self.Gr = Gr
766 self.Lambda = Lambda
766 self.Lambda = Lambda
767 self.aL = aL
767 self.aL = aL
768 self.tauW = tauW
768 self.tauW = tauW
769 self.ThetaT = ThetaT
769 self.ThetaT = ThetaT
770 self.ThetaR = ThetaR
770 self.ThetaR = ThetaR
771 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
771 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
772 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
772 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
773 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
773 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
774
774
775 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
775 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
776 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
776 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
777 RadarConstant = 10e-26 * Numerator / Denominator #
777 RadarConstant = 10e-26 * Numerator / Denominator #
778 ExpConstant = 10**(40/10) #Constante Experimental
778 ExpConstant = 10**(40/10) #Constante Experimental
779
779
780 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
780 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
781 for i in range(self.Num_Chn):
781 for i in range(self.Num_Chn):
782 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
782 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
783 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
783 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
784
784
785 SPCmean = numpy.mean(SignalPower, 0)
785 SPCmean = numpy.mean(SignalPower, 0)
786 Pr = SPCmean[:,:]/dataOut.normFactor
786 Pr = SPCmean[:,:]/dataOut.normFactor
787
787
788 # Declaring auxiliary variables
788 # Declaring auxiliary variables
789 Range = dataOut.heightList*1000. #Range in m
789 Range = dataOut.heightList*1000. #Range in m
790 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
790 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
791 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
791 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
792 zMtrx = rMtrx+Altitude
792 zMtrx = rMtrx+Altitude
793 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
793 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
794 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
794 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
795
795
796 # height dependence to air density Foote and Du Toit (1969)
796 # height dependence to air density Foote and Du Toit (1969)
797 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
797 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
798 VMtrx = VelMtrx / delv_z #Normalized velocity
798 VMtrx = VelMtrx / delv_z #Normalized velocity
799 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
799 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
800 # Diameter is related to the fall speed of falling drops
800 # Diameter is related to the fall speed of falling drops
801 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
801 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
802 # Only valid for D>= 0.16 mm
802 # Only valid for D>= 0.16 mm
803 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
803 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
804
804
805 #Calculate Radar Reflectivity ETAn
805 #Calculate Radar Reflectivity ETAn
806 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
806 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
807 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
807 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
808 # Radar Cross Section
808 # Radar Cross Section
809 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
809 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
810 # Drop Size Distribution
810 # Drop Size Distribution
811 DSD = ETAn / sigmaD
811 DSD = ETAn / sigmaD
812 # Equivalente Reflectivy
812 # Equivalente Reflectivy
813 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
813 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
814 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
814 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
815 # RainFall Rate
815 # RainFall Rate
816 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
816 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
817
817
818 # Censoring the data
818 # Censoring the data
819 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
819 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
820 SNRth = 10**(SNRdBlimit/10) #-30dB
820 SNRth = 10**(SNRdBlimit/10) #-30dB
821 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
821 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
822 W = numpy.nanmean(dataOut.data_dop,0)
822 W = numpy.nanmean(dataOut.data_dop,0)
823 W[novalid] = numpy.NaN
823 W[novalid] = numpy.NaN
824 Ze_org[novalid] = numpy.NaN
824 Ze_org[novalid] = numpy.NaN
825 RR[novalid] = numpy.NaN
825 RR[novalid] = numpy.NaN
826
826
827 dataOut.data_output = RR[8]
827 dataOut.data_output = RR[8]
828 dataOut.data_param = numpy.ones([3,self.Num_Hei])
828 dataOut.data_param = numpy.ones([3,self.Num_Hei])
829 dataOut.channelList = [0,1,2]
829 dataOut.channelList = [0,1,2]
830
830
831 dataOut.data_param[0]=10*numpy.log10(Ze_org)
831 dataOut.data_param[0]=10*numpy.log10(Ze_org)
832 dataOut.data_param[1]=-W
832 dataOut.data_param[1]=-W
833 dataOut.data_param[2]=RR
833 dataOut.data_param[2]=RR
834
834
835 # print ('Leaving PrecepitationProc ... ')
835 # print ('Leaving PrecepitationProc ... ')
836 return dataOut
836 return dataOut
837
837
838 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
838 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
839
839
840 NPW = dataOut.NPW
840 NPW = dataOut.NPW
841 COFA = dataOut.COFA
841 COFA = dataOut.COFA
842
842
843 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
843 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
844 RadarConst = dataOut.RadarConst
844 RadarConst = dataOut.RadarConst
845 #frequency = 34.85*10**9
845 #frequency = 34.85*10**9
846
846
847 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
847 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
848 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
848 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
849
849
850 ETA = numpy.sum(SNR,1)
850 ETA = numpy.sum(SNR,1)
851
851
852 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
852 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
853
853
854 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
854 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
855
855
856 for r in range(self.Num_Hei):
856 for r in range(self.Num_Hei):
857
857
858 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
858 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
859 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
859 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
860
860
861 return Ze
861 return Ze
862
862
863 # def GetRadarConstant(self):
863 # def GetRadarConstant(self):
864 #
864 #
865 # """
865 # """
866 # Constants:
866 # Constants:
867 #
867 #
868 # Pt: Transmission Power dB 5kW 5000
868 # Pt: Transmission Power dB 5kW 5000
869 # Gt: Transmission Gain dB 24.7 dB 295.1209
869 # Gt: Transmission Gain dB 24.7 dB 295.1209
870 # Gr: Reception Gain dB 18.5 dB 70.7945
870 # Gr: Reception Gain dB 18.5 dB 70.7945
871 # Lambda: Wavelenght m 0.6741 m 0.6741
871 # Lambda: Wavelenght m 0.6741 m 0.6741
872 # aL: Attenuation loses dB 4dB 2.5118
872 # aL: Attenuation loses dB 4dB 2.5118
873 # tauW: Width of transmission pulse s 4us 4e-6
873 # tauW: Width of transmission pulse s 4us 4e-6
874 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
874 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
875 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
875 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
876 #
876 #
877 # """
877 # """
878 #
878 #
879 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
879 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
880 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
880 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
881 # RadarConstant = Numerator / Denominator
881 # RadarConstant = Numerator / Denominator
882 #
882 #
883 # return RadarConstant
883 # return RadarConstant
884
884
885
885
886
886
887 class FullSpectralAnalysis(Operation):
887 class FullSpectralAnalysis(Operation):
888
888
889 """
889 """
890 Function that implements Full Spectral Analysis technique.
890 Function that implements Full Spectral Analysis technique.
891
891
892 Input:
892 Input:
893 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
893 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
894 self.dataOut.groupList : Pairlist of channels
894 self.dataOut.groupList : Pairlist of channels
895 self.dataOut.ChanDist : Physical distance between receivers
895 self.dataOut.ChanDist : Physical distance between receivers
896
896
897
897
898 Output:
898 Output:
899
899
900 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
900 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
901
901
902
902
903 Parameters affected: Winds, height range, SNR
903 Parameters affected: Winds, height range, SNR
904
904
905 """
905 """
906 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
906 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
907 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
907 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
908
908
909 spc = dataOut.data_pre[0].copy()
909 spc = dataOut.data_pre[0].copy()
910 cspc = dataOut.data_pre[1]
910 cspc = dataOut.data_pre[1]
911 nHeights = spc.shape[2]
911 nHeights = spc.shape[2]
912
912
913 # first_height = 0.75 #km (ref: data header 20170822)
913 # first_height = 0.75 #km (ref: data header 20170822)
914 # resolution_height = 0.075 #km
914 # resolution_height = 0.075 #km
915 '''
915 '''
916 finding height range. check this when radar parameters are changed!
916 finding height range. check this when radar parameters are changed!
917 '''
917 '''
918 if maxheight is not None:
918 if maxheight is not None:
919 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
919 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
920 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
920 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
921 else:
921 else:
922 range_max = nHeights
922 range_max = nHeights
923 if minheight is not None:
923 if minheight is not None:
924 # range_min = int((minheight - first_height) / resolution_height) # theoretical
924 # range_min = int((minheight - first_height) / resolution_height) # theoretical
925 range_min = int(13.26 * minheight - 5) # empirical, works better
925 range_min = int(13.26 * minheight - 5) # empirical, works better
926 if range_min < 0:
926 if range_min < 0:
927 range_min = 0
927 range_min = 0
928 else:
928 else:
929 range_min = 0
929 range_min = 0
930
930
931 pairsList = dataOut.groupList
931 pairsList = dataOut.groupList
932 if dataOut.ChanDist is not None :
932 if dataOut.ChanDist is not None :
933 ChanDist = dataOut.ChanDist
933 ChanDist = dataOut.ChanDist
934 else:
934 else:
935 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
935 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
936
936
937 # 4 variables: zonal, meridional, vertical, and average SNR
937 # 4 variables: zonal, meridional, vertical, and average SNR
938 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
938 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
939 velocityX = numpy.zeros([nHeights]) * numpy.NaN
939 velocityX = numpy.zeros([nHeights]) * numpy.NaN
940 velocityY = numpy.zeros([nHeights]) * numpy.NaN
940 velocityY = numpy.zeros([nHeights]) * numpy.NaN
941 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
941 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
942
942
943 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
943 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
944
944
945 '''***********************************************WIND ESTIMATION**************************************'''
945 '''***********************************************WIND ESTIMATION**************************************'''
946 for Height in range(nHeights):
946 for Height in range(nHeights):
947
947
948 if Height >= range_min and Height < range_max:
948 if Height >= range_min and Height < range_max:
949 # error_code will be useful in future analysis
949 # error_code will be useful in future analysis
950 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
950 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
951 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
951 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
952
952
953 if abs(Vzon) < 100. and abs(Vmer) < 100.:
953 if abs(Vzon) < 100. and abs(Vmer) < 100.:
954 velocityX[Height] = Vzon
954 velocityX[Height] = Vzon
955 velocityY[Height] = -Vmer
955 velocityY[Height] = -Vmer
956 velocityZ[Height] = Vver
956 velocityZ[Height] = Vver
957
957
958 # Censoring data with SNR threshold
958 # Censoring data with SNR threshold
959 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
959 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
960
960
961 data_param[0] = velocityX
961 data_param[0] = velocityX
962 data_param[1] = velocityY
962 data_param[1] = velocityY
963 data_param[2] = velocityZ
963 data_param[2] = velocityZ
964 data_param[3] = dbSNR
964 data_param[3] = dbSNR
965 dataOut.data_param = data_param
965 dataOut.data_param = data_param
966 return dataOut
966 return dataOut
967
967
968 def moving_average(self,x, N=2):
968 def moving_average(self,x, N=2):
969 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
969 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
970 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
970 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
971
971
972 def gaus(self,xSamples,Amp,Mu,Sigma):
972 def gaus(self,xSamples,Amp,Mu,Sigma):
973 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
973 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
974
974
975 def Moments(self, ySamples, xSamples):
975 def Moments(self, ySamples, xSamples):
976 Power = numpy.nanmean(ySamples) # Power, 0th Moment
976 Power = numpy.nanmean(ySamples) # Power, 0th Moment
977 yNorm = ySamples / numpy.nansum(ySamples)
977 yNorm = ySamples / numpy.nansum(ySamples)
978 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
978 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
979 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
979 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
980 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
980 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
981 return numpy.array([Power,RadVel,StdDev])
981 return numpy.array([Power,RadVel,StdDev])
982
982
983 def StopWindEstimation(self, error_code):
983 def StopWindEstimation(self, error_code):
984 Vzon = numpy.NaN
984 Vzon = numpy.NaN
985 Vmer = numpy.NaN
985 Vmer = numpy.NaN
986 Vver = numpy.NaN
986 Vver = numpy.NaN
987 return Vzon, Vmer, Vver, error_code
987 return Vzon, Vmer, Vver, error_code
988
988
989 def AntiAliasing(self, interval, maxstep):
989 def AntiAliasing(self, interval, maxstep):
990 """
990 """
991 function to prevent errors from aliased values when computing phaseslope
991 function to prevent errors from aliased values when computing phaseslope
992 """
992 """
993 antialiased = numpy.zeros(len(interval))
993 antialiased = numpy.zeros(len(interval))
994 copyinterval = interval.copy()
994 copyinterval = interval.copy()
995
995
996 antialiased[0] = copyinterval[0]
996 antialiased[0] = copyinterval[0]
997
997
998 for i in range(1,len(antialiased)):
998 for i in range(1,len(antialiased)):
999 step = interval[i] - interval[i-1]
999 step = interval[i] - interval[i-1]
1000 if step > maxstep:
1000 if step > maxstep:
1001 copyinterval -= 2*numpy.pi
1001 copyinterval -= 2*numpy.pi
1002 antialiased[i] = copyinterval[i]
1002 antialiased[i] = copyinterval[i]
1003 elif step < maxstep*(-1):
1003 elif step < maxstep*(-1):
1004 copyinterval += 2*numpy.pi
1004 copyinterval += 2*numpy.pi
1005 antialiased[i] = copyinterval[i]
1005 antialiased[i] = copyinterval[i]
1006 else:
1006 else:
1007 antialiased[i] = copyinterval[i].copy()
1007 antialiased[i] = copyinterval[i].copy()
1008
1008
1009 return antialiased
1009 return antialiased
1010
1010
1011 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1011 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
1012 """
1012 """
1013 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1013 Function that Calculates Zonal, Meridional and Vertical wind velocities.
1014 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1014 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
1015
1015
1016 Input:
1016 Input:
1017 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1017 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
1018 pairsList : Pairlist of channels
1018 pairsList : Pairlist of channels
1019 ChanDist : array of xi_ij and eta_ij
1019 ChanDist : array of xi_ij and eta_ij
1020 Height : height at which data is processed
1020 Height : height at which data is processed
1021 noise : noise in [channels] format for specific height
1021 noise : noise in [channels] format for specific height
1022 Abbsisarange : range of the frequencies or velocities
1022 Abbsisarange : range of the frequencies or velocities
1023 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1023 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
1024
1024
1025 Output:
1025 Output:
1026 Vzon, Vmer, Vver : wind velocities
1026 Vzon, Vmer, Vver : wind velocities
1027 error_code : int that states where code is terminated
1027 error_code : int that states where code is terminated
1028
1028
1029 0 : no error detected
1029 0 : no error detected
1030 1 : Gaussian of mean spc exceeds widthlimit
1030 1 : Gaussian of mean spc exceeds widthlimit
1031 2 : no Gaussian of mean spc found
1031 2 : no Gaussian of mean spc found
1032 3 : SNR to low or velocity to high -> prec. e.g.
1032 3 : SNR to low or velocity to high -> prec. e.g.
1033 4 : at least one Gaussian of cspc exceeds widthlimit
1033 4 : at least one Gaussian of cspc exceeds widthlimit
1034 5 : zero out of three cspc Gaussian fits converged
1034 5 : zero out of three cspc Gaussian fits converged
1035 6 : phase slope fit could not be found
1035 6 : phase slope fit could not be found
1036 7 : arrays used to fit phase have different length
1036 7 : arrays used to fit phase have different length
1037 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1037 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1038
1038
1039 """
1039 """
1040
1040
1041 error_code = 0
1041 error_code = 0
1042
1042
1043 nChan = spc.shape[0]
1043 nChan = spc.shape[0]
1044 nProf = spc.shape[1]
1044 nProf = spc.shape[1]
1045 nPair = cspc.shape[0]
1045 nPair = cspc.shape[0]
1046
1046
1047 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1047 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1048 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1048 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1049 phase = numpy.zeros([nPair, nProf]) # phase between channels
1049 phase = numpy.zeros([nPair, nProf]) # phase between channels
1050 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1050 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1051 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1051 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1052 xFrec = AbbsisaRange[0][:-1] # frequency range
1052 xFrec = AbbsisaRange[0][:-1] # frequency range
1053 xVel = AbbsisaRange[2][:-1] # velocity range
1053 xVel = AbbsisaRange[2][:-1] # velocity range
1054 xSamples = xFrec # the frequency range is taken
1054 xSamples = xFrec # the frequency range is taken
1055 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1055 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1056
1056
1057 # only consider velocities with in NegativeLimit and PositiveLimit
1057 # only consider velocities with in NegativeLimit and PositiveLimit
1058 if (NegativeLimit is None):
1058 if (NegativeLimit is None):
1059 NegativeLimit = numpy.min(xVel)
1059 NegativeLimit = numpy.min(xVel)
1060 if (PositiveLimit is None):
1060 if (PositiveLimit is None):
1061 PositiveLimit = numpy.max(xVel)
1061 PositiveLimit = numpy.max(xVel)
1062 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1062 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1063 xSamples_zoom = xSamples[xvalid]
1063 xSamples_zoom = xSamples[xvalid]
1064
1064
1065 '''Getting Eij and Nij'''
1065 '''Getting Eij and Nij'''
1066 Xi01, Xi02, Xi12 = ChanDist[:,0]
1066 Xi01, Xi02, Xi12 = ChanDist[:,0]
1067 Eta01, Eta02, Eta12 = ChanDist[:,1]
1067 Eta01, Eta02, Eta12 = ChanDist[:,1]
1068
1068
1069 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1069 # spwd limit - updated by D. ScipiΓ³n 30.03.2021
1070 widthlimit = 10
1070 widthlimit = 10
1071 '''************************* SPC is normalized ********************************'''
1071 '''************************* SPC is normalized ********************************'''
1072 spc_norm = spc.copy()
1072 spc_norm = spc.copy()
1073 # For each channel
1073 # For each channel
1074 for i in range(nChan):
1074 for i in range(nChan):
1075 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1075 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1076 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1076 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1077
1077
1078 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1078 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1079
1079
1080 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1080 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1081 you only fit the curve and don't need the absolute value of height for calculation,
1081 you only fit the curve and don't need the absolute value of height for calculation,
1082 only for estimation of width. for normalization of cross spectra, you need initial,
1082 only for estimation of width. for normalization of cross spectra, you need initial,
1083 unnormalized self-spectra With noise.
1083 unnormalized self-spectra With noise.
1084
1084
1085 Technically, you don't even need to normalize the self-spectra, as you only need the
1085 Technically, you don't even need to normalize the self-spectra, as you only need the
1086 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1086 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1087 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1087 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1088 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1088 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1089 """
1089 """
1090 # initial conditions
1090 # initial conditions
1091 popt = [1e-10,0,1e-10]
1091 popt = [1e-10,0,1e-10]
1092 # Spectra average
1092 # Spectra average
1093 SPCMean = numpy.average(SPC_Samples,0)
1093 SPCMean = numpy.average(SPC_Samples,0)
1094 # Moments in frequency
1094 # Moments in frequency
1095 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1095 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1096
1096
1097 # Gauss Fit SPC in frequency domain
1097 # Gauss Fit SPC in frequency domain
1098 if dbSNR > SNRlimit: # only if SNR > SNRth
1098 if dbSNR > SNRlimit: # only if SNR > SNRth
1099 try:
1099 try:
1100 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1100 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1101 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1101 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1102 return self.StopWindEstimation(error_code = 1)
1102 return self.StopWindEstimation(error_code = 1)
1103 FitGauss = self.gaus(xSamples_zoom,*popt)
1103 FitGauss = self.gaus(xSamples_zoom,*popt)
1104 except :#RuntimeError:
1104 except :#RuntimeError:
1105 return self.StopWindEstimation(error_code = 2)
1105 return self.StopWindEstimation(error_code = 2)
1106 else:
1106 else:
1107 return self.StopWindEstimation(error_code = 3)
1107 return self.StopWindEstimation(error_code = 3)
1108
1108
1109 '''***************************** CSPC Normalization *************************
1109 '''***************************** CSPC Normalization *************************
1110 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1110 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1111 influence the norm which is not desired. First, a range is identified where the
1111 influence the norm which is not desired. First, a range is identified where the
1112 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1112 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1113 around it gets cut off and values replaced by mean determined by the boundary
1113 around it gets cut off and values replaced by mean determined by the boundary
1114 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1114 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1115
1115
1116 The sums are then added and multiplied by range/datapoints, because you need
1116 The sums are then added and multiplied by range/datapoints, because you need
1117 an integral and not a sum for normalization.
1117 an integral and not a sum for normalization.
1118
1118
1119 A norm is found according to Briggs 92.
1119 A norm is found according to Briggs 92.
1120 '''
1120 '''
1121 # for each pair
1121 # for each pair
1122 for i in range(nPair):
1122 for i in range(nPair):
1123 cspc_norm = cspc[i,:].copy()
1123 cspc_norm = cspc[i,:].copy()
1124 chan_index0 = pairsList[i][0]
1124 chan_index0 = pairsList[i][0]
1125 chan_index1 = pairsList[i][1]
1125 chan_index1 = pairsList[i][1]
1126 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1126 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1127 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1127 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1128
1128
1129 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1129 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1130 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1130 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1131 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1131 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1132
1132
1133 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1133 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1134 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1134 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1135
1135
1136 '''*******************************FIT GAUSS CSPC************************************'''
1136 '''*******************************FIT GAUSS CSPC************************************'''
1137 try:
1137 try:
1138 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1138 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1139 if popt01[2] > widthlimit: # CONDITION
1139 if popt01[2] > widthlimit: # CONDITION
1140 return self.StopWindEstimation(error_code = 4)
1140 return self.StopWindEstimation(error_code = 4)
1141 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1141 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1142 if popt02[2] > widthlimit: # CONDITION
1142 if popt02[2] > widthlimit: # CONDITION
1143 return self.StopWindEstimation(error_code = 4)
1143 return self.StopWindEstimation(error_code = 4)
1144 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1144 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1145 if popt12[2] > widthlimit: # CONDITION
1145 if popt12[2] > widthlimit: # CONDITION
1146 return self.StopWindEstimation(error_code = 4)
1146 return self.StopWindEstimation(error_code = 4)
1147
1147
1148 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1148 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1149 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1149 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1150 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1150 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1151 except:
1151 except:
1152 return self.StopWindEstimation(error_code = 5)
1152 return self.StopWindEstimation(error_code = 5)
1153
1153
1154
1154
1155 '''************* Getting Fij ***************'''
1155 '''************* Getting Fij ***************'''
1156 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1156 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1157 GaussCenter = popt[1]
1157 GaussCenter = popt[1]
1158 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1158 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1159 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1159 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1160
1160
1161 # Point where e^-1 is located in the gaussian
1161 # Point where e^-1 is located in the gaussian
1162 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1162 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1163 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1163 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1164 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1164 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1165 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1165 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1166
1166
1167 '''********** Taking frequency ranges from mean SPCs **********'''
1167 '''********** Taking frequency ranges from mean SPCs **********'''
1168 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1168 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1169 Range = numpy.empty(2)
1169 Range = numpy.empty(2)
1170 Range[0] = GaussCenter - GauWidth
1170 Range[0] = GaussCenter - GauWidth
1171 Range[1] = GaussCenter + GauWidth
1171 Range[1] = GaussCenter + GauWidth
1172 # Point in x-axis where the bandwidth is located (min:max)
1172 # Point in x-axis where the bandwidth is located (min:max)
1173 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1173 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1174 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1174 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1175 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1175 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1176 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1176 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1177 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1177 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1178 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1178 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1179
1179
1180 '''************************** Getting Phase Slope ***************************'''
1180 '''************************** Getting Phase Slope ***************************'''
1181 for i in range(nPair):
1181 for i in range(nPair):
1182 if len(FrecRange) > 5:
1182 if len(FrecRange) > 5:
1183 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1183 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1184 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1184 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1185 if len(FrecRange) == len(PhaseRange):
1185 if len(FrecRange) == len(PhaseRange):
1186 try:
1186 try:
1187 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1187 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1188 PhaseSlope[i] = slope
1188 PhaseSlope[i] = slope
1189 PhaseInter[i] = intercept
1189 PhaseInter[i] = intercept
1190 except:
1190 except:
1191 return self.StopWindEstimation(error_code = 6)
1191 return self.StopWindEstimation(error_code = 6)
1192 else:
1192 else:
1193 return self.StopWindEstimation(error_code = 7)
1193 return self.StopWindEstimation(error_code = 7)
1194 else:
1194 else:
1195 return self.StopWindEstimation(error_code = 8)
1195 return self.StopWindEstimation(error_code = 8)
1196
1196
1197 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1197 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1198
1198
1199 '''Getting constant C'''
1199 '''Getting constant C'''
1200 cC=(Fij*numpy.pi)**2
1200 cC=(Fij*numpy.pi)**2
1201
1201
1202 '''****** Getting constants F and G ******'''
1202 '''****** Getting constants F and G ******'''
1203 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1203 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1204 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1204 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1205 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1205 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1206 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1206 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1207 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1207 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1208 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1208 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1209 MijResults = numpy.array([MijResult1, MijResult2])
1209 MijResults = numpy.array([MijResult1, MijResult2])
1210 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1210 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1211
1211
1212 '''****** Getting constants A, B and H ******'''
1212 '''****** Getting constants A, B and H ******'''
1213 W01 = numpy.nanmax( FitGauss01 )
1213 W01 = numpy.nanmax( FitGauss01 )
1214 W02 = numpy.nanmax( FitGauss02 )
1214 W02 = numpy.nanmax( FitGauss02 )
1215 W12 = numpy.nanmax( FitGauss12 )
1215 W12 = numpy.nanmax( FitGauss12 )
1216
1216
1217 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1217 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1218 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1218 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1219 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1219 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1220 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1220 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1221
1221
1222 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1222 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1223 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1223 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1224
1224
1225 VxVy = numpy.array([[cA,cH],[cH,cB]])
1225 VxVy = numpy.array([[cA,cH],[cH,cB]])
1226 VxVyResults = numpy.array([-cF,-cG])
1226 VxVyResults = numpy.array([-cF,-cG])
1227 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1227 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1228 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1228 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1229 error_code = 0
1229 error_code = 0
1230
1230
1231 return Vzon, Vmer, Vver, error_code
1231 return Vzon, Vmer, Vver, error_code
1232
1232
1233 class SpectralMoments(Operation):
1233 class SpectralMoments(Operation):
1234
1234
1235 '''
1235 '''
1236 Function SpectralMoments()
1236 Function SpectralMoments()
1237
1237
1238 Calculates moments (power, mean, standard deviation) and SNR of the signal
1238 Calculates moments (power, mean, standard deviation) and SNR of the signal
1239
1239
1240 Type of dataIn: Spectra
1240 Type of dataIn: Spectra
1241
1241
1242 Configuration Parameters:
1242 Configuration Parameters:
1243
1243
1244 dirCosx : Cosine director in X axis
1244 dirCosx : Cosine director in X axis
1245 dirCosy : Cosine director in Y axis
1245 dirCosy : Cosine director in Y axis
1246
1246
1247 elevation :
1247 elevation :
1248 azimuth :
1248 azimuth :
1249
1249
1250 Input:
1250 Input:
1251 channelList : simple channel list to select e.g. [2,3,7]
1251 channelList : simple channel list to select e.g. [2,3,7]
1252 self.dataOut.data_pre : Spectral data
1252 self.dataOut.data_pre : Spectral data
1253 self.dataOut.abscissaList : List of frequencies
1253 self.dataOut.abscissaList : List of frequencies
1254 self.dataOut.noise : Noise level per channel
1254 self.dataOut.noise : Noise level per channel
1255
1255
1256 Affected:
1256 Affected:
1257 self.dataOut.moments : Parameters per channel
1257 self.dataOut.moments : Parameters per channel
1258 self.dataOut.data_snr : SNR per channel
1258 self.dataOut.data_snr : SNR per channel
1259
1259
1260 '''
1260 '''
1261
1261
1262 def run(self, dataOut,wradar=False):
1262 def run(self, dataOut,wradar=False):
1263
1263
1264 data = dataOut.data_pre[0]
1264 data = dataOut.data_pre[0]
1265 absc = dataOut.abscissaList[:-1]
1265 absc = dataOut.abscissaList[:-1]
1266 noise = dataOut.noise
1266 noise = dataOut.noise
1267 nChannel = data.shape[0]
1267 nChannel = data.shape[0]
1268 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1268 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1269
1269
1270 for ind in range(nChannel):
1270 for ind in range(nChannel):
1271 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind],wradar=wradar )
1271 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind],wradar=wradar )
1272
1272
1273 dataOut.moments = data_param[:,1:,:]
1273 dataOut.moments = data_param[:,1:,:]
1274 dataOut.data_snr = data_param[:,0]
1274 dataOut.data_snr = data_param[:,0]
1275 dataOut.data_pow = data_param[:,1]
1275 dataOut.data_pow = data_param[:,1]
1276 dataOut.data_dop = data_param[:,2]
1276 dataOut.data_dop = data_param[:,2]
1277 dataOut.data_width = data_param[:,3]
1277 dataOut.data_width = data_param[:,3]
1278 return dataOut
1278 return dataOut
1279
1279
1280 def __calculateMoments(self, oldspec, oldfreq, n0,
1280 def __calculateMoments(self, oldspec, oldfreq, n0,
1281 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None,wradar=None):
1281 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None,wradar=None):
1282
1282
1283 if (nicoh is None): nicoh = 1
1283 if (nicoh is None): nicoh = 1
1284 if (graph is None): graph = 0
1284 if (graph is None): graph = 0
1285 if (smooth is None): smooth = 0
1285 if (smooth is None): smooth = 0
1286 elif (self.smooth < 3): smooth = 0
1286 elif (self.smooth < 3): smooth = 0
1287
1287
1288 if (type1 is None): type1 = 0
1288 if (type1 is None): type1 = 0
1289 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1289 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1290 if (snrth is None): snrth = -3
1290 if (snrth is None): snrth = -3
1291 if (dc is None): dc = 0
1291 if (dc is None): dc = 0
1292 if (aliasing is None): aliasing = 0
1292 if (aliasing is None): aliasing = 0
1293 if (oldfd is None): oldfd = 0
1293 if (oldfd is None): oldfd = 0
1294 if (wwauto is None): wwauto = 0
1294 if (wwauto is None): wwauto = 0
1295
1295
1296 if (n0 < 1.e-20): n0 = 1.e-20
1296 if (n0 < 1.e-20): n0 = 1.e-20
1297
1297
1298 freq = oldfreq
1298 freq = oldfreq
1299 vec_power = numpy.zeros(oldspec.shape[1])
1299 vec_power = numpy.zeros(oldspec.shape[1])
1300 vec_fd = numpy.zeros(oldspec.shape[1])
1300 vec_fd = numpy.zeros(oldspec.shape[1])
1301 vec_w = numpy.zeros(oldspec.shape[1])
1301 vec_w = numpy.zeros(oldspec.shape[1])
1302 vec_snr = numpy.zeros(oldspec.shape[1])
1302 vec_snr = numpy.zeros(oldspec.shape[1])
1303
1303
1304 # oldspec = numpy.ma.masked_invalid(oldspec)
1304 # oldspec = numpy.ma.masked_invalid(oldspec)
1305 for ind in range(oldspec.shape[1]):
1305 for ind in range(oldspec.shape[1]):
1306
1306
1307 spec = oldspec[:,ind]
1307 spec = oldspec[:,ind]
1308 aux = spec*fwindow
1308 aux = spec*fwindow
1309 max_spec = aux.max()
1309 max_spec = aux.max()
1310 m = aux.tolist().index(max_spec)
1310 m = aux.tolist().index(max_spec)
1311
1311
1312 # Smooth
1312 # Smooth
1313 if (smooth == 0):
1313 if (smooth == 0):
1314 spec2 = spec
1314 spec2 = spec
1315 else:
1315 else:
1316 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1316 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1317
1317
1318 # Moments Estimation
1318 # Moments Estimation
1319 bb = spec2[numpy.arange(m,spec2.size)]
1319 bb = spec2[numpy.arange(m,spec2.size)]
1320 bb = (bb<n0).nonzero()
1320 bb = (bb<n0).nonzero()
1321 bb = bb[0]
1321 bb = bb[0]
1322
1322
1323 ss = spec2[numpy.arange(0,m + 1)]
1323 ss = spec2[numpy.arange(0,m + 1)]
1324 ss = (ss<n0).nonzero()
1324 ss = (ss<n0).nonzero()
1325 ss = ss[0]
1325 ss = ss[0]
1326
1326
1327 if (bb.size == 0):
1327 if (bb.size == 0):
1328 bb0 = spec.size - 1 - m
1328 bb0 = spec.size - 1 - m
1329 else:
1329 else:
1330 bb0 = bb[0] - 1
1330 bb0 = bb[0] - 1
1331 if (bb0 < 0):
1331 if (bb0 < 0):
1332 bb0 = 0
1332 bb0 = 0
1333
1333
1334 if (ss.size == 0):
1334 if (ss.size == 0):
1335 ss1 = 1
1335 ss1 = 1
1336 else:
1336 else:
1337 ss1 = max(ss) + 1
1337 ss1 = max(ss) + 1
1338
1338
1339 if (ss1 > m):
1339 if (ss1 > m):
1340 ss1 = m
1340 ss1 = m
1341
1341
1342 #valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1342 #valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1343 valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1343 valid = numpy.arange(1,oldspec.shape[0])# valid perfil completo igual pulsepair
1344 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1344 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1345 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1345 total_power = (spec2[valid] * fwindow[valid]).mean() # D. ScipiΓ³n added with correct definition
1346 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1346 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1347 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1347 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1348 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1348 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1349 snr = (spec2.mean()-n0)/n0
1349 snr = (spec2.mean()-n0)/n0
1350 if (snr < 1.e-20) :
1350 if (snr < 1.e-20) :
1351 snr = 1.e-20
1351 snr = 1.e-20
1352
1352
1353 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1353 # vec_power[ind] = power #D. ScipiΓ³n replaced with the line below
1354 if wradar ==False:
1354 if wradar ==False:
1355 vec_power[ind] = total_power
1355 vec_power[ind] = total_power
1356 else:
1356 else:
1357 vec_power[ind] = signal_power
1357 vec_power[ind] = signal_power
1358
1358
1359 vec_fd[ind] = fd
1359 vec_fd[ind] = fd
1360 vec_w[ind] = w
1360 vec_w[ind] = w
1361 vec_snr[ind] = snr
1361 vec_snr[ind] = snr
1362 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1362 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1363
1363
1364 #------------------ Get SA Parameters --------------------------
1364 #------------------ Get SA Parameters --------------------------
1365
1365
1366 def GetSAParameters(self):
1366 def GetSAParameters(self):
1367 #SA en frecuencia
1367 #SA en frecuencia
1368 pairslist = self.dataOut.groupList
1368 pairslist = self.dataOut.groupList
1369 num_pairs = len(pairslist)
1369 num_pairs = len(pairslist)
1370
1370
1371 vel = self.dataOut.abscissaList
1371 vel = self.dataOut.abscissaList
1372 spectra = self.dataOut.data_pre
1372 spectra = self.dataOut.data_pre
1373 cspectra = self.dataIn.data_cspc
1373 cspectra = self.dataIn.data_cspc
1374 delta_v = vel[1] - vel[0]
1374 delta_v = vel[1] - vel[0]
1375
1375
1376 #Calculating the power spectrum
1376 #Calculating the power spectrum
1377 spc_pow = numpy.sum(spectra, 3)*delta_v
1377 spc_pow = numpy.sum(spectra, 3)*delta_v
1378 #Normalizing Spectra
1378 #Normalizing Spectra
1379 norm_spectra = spectra/spc_pow
1379 norm_spectra = spectra/spc_pow
1380 #Calculating the norm_spectra at peak
1380 #Calculating the norm_spectra at peak
1381 max_spectra = numpy.max(norm_spectra, 3)
1381 max_spectra = numpy.max(norm_spectra, 3)
1382
1382
1383 #Normalizing Cross Spectra
1383 #Normalizing Cross Spectra
1384 norm_cspectra = numpy.zeros(cspectra.shape)
1384 norm_cspectra = numpy.zeros(cspectra.shape)
1385
1385
1386 for i in range(num_chan):
1386 for i in range(num_chan):
1387 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1387 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1388
1388
1389 max_cspectra = numpy.max(norm_cspectra,2)
1389 max_cspectra = numpy.max(norm_cspectra,2)
1390 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1390 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1391
1391
1392 for i in range(num_pairs):
1392 for i in range(num_pairs):
1393 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1393 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1394 #------------------- Get Lags ----------------------------------
1394 #------------------- Get Lags ----------------------------------
1395
1395
1396 class SALags(Operation):
1396 class SALags(Operation):
1397 '''
1397 '''
1398 Function GetMoments()
1398 Function GetMoments()
1399
1399
1400 Input:
1400 Input:
1401 self.dataOut.data_pre
1401 self.dataOut.data_pre
1402 self.dataOut.abscissaList
1402 self.dataOut.abscissaList
1403 self.dataOut.noise
1403 self.dataOut.noise
1404 self.dataOut.normFactor
1404 self.dataOut.normFactor
1405 self.dataOut.data_snr
1405 self.dataOut.data_snr
1406 self.dataOut.groupList
1406 self.dataOut.groupList
1407 self.dataOut.nChannels
1407 self.dataOut.nChannels
1408
1408
1409 Affected:
1409 Affected:
1410 self.dataOut.data_param
1410 self.dataOut.data_param
1411
1411
1412 '''
1412 '''
1413 def run(self, dataOut):
1413 def run(self, dataOut):
1414 data_acf = dataOut.data_pre[0]
1414 data_acf = dataOut.data_pre[0]
1415 data_ccf = dataOut.data_pre[1]
1415 data_ccf = dataOut.data_pre[1]
1416 normFactor_acf = dataOut.normFactor[0]
1416 normFactor_acf = dataOut.normFactor[0]
1417 normFactor_ccf = dataOut.normFactor[1]
1417 normFactor_ccf = dataOut.normFactor[1]
1418 pairs_acf = dataOut.groupList[0]
1418 pairs_acf = dataOut.groupList[0]
1419 pairs_ccf = dataOut.groupList[1]
1419 pairs_ccf = dataOut.groupList[1]
1420
1420
1421 nHeights = dataOut.nHeights
1421 nHeights = dataOut.nHeights
1422 absc = dataOut.abscissaList
1422 absc = dataOut.abscissaList
1423 noise = dataOut.noise
1423 noise = dataOut.noise
1424 SNR = dataOut.data_snr
1424 SNR = dataOut.data_snr
1425 nChannels = dataOut.nChannels
1425 nChannels = dataOut.nChannels
1426 # pairsList = dataOut.groupList
1426 # pairsList = dataOut.groupList
1427 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1427 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1428
1428
1429 for l in range(len(pairs_acf)):
1429 for l in range(len(pairs_acf)):
1430 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1430 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1431
1431
1432 for l in range(len(pairs_ccf)):
1432 for l in range(len(pairs_ccf)):
1433 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1433 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1434
1434
1435 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1435 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1436 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1436 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1437 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1437 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1438 return
1438 return
1439
1439
1440 # def __getPairsAutoCorr(self, pairsList, nChannels):
1440 # def __getPairsAutoCorr(self, pairsList, nChannels):
1441 #
1441 #
1442 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1442 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1443 #
1443 #
1444 # for l in range(len(pairsList)):
1444 # for l in range(len(pairsList)):
1445 # firstChannel = pairsList[l][0]
1445 # firstChannel = pairsList[l][0]
1446 # secondChannel = pairsList[l][1]
1446 # secondChannel = pairsList[l][1]
1447 #
1447 #
1448 # #Obteniendo pares de Autocorrelacion
1448 # #Obteniendo pares de Autocorrelacion
1449 # if firstChannel == secondChannel:
1449 # if firstChannel == secondChannel:
1450 # pairsAutoCorr[firstChannel] = int(l)
1450 # pairsAutoCorr[firstChannel] = int(l)
1451 #
1451 #
1452 # pairsAutoCorr = pairsAutoCorr.astype(int)
1452 # pairsAutoCorr = pairsAutoCorr.astype(int)
1453 #
1453 #
1454 # pairsCrossCorr = range(len(pairsList))
1454 # pairsCrossCorr = range(len(pairsList))
1455 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1455 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1456 #
1456 #
1457 # return pairsAutoCorr, pairsCrossCorr
1457 # return pairsAutoCorr, pairsCrossCorr
1458
1458
1459 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1459 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1460
1460
1461 lag0 = data_acf.shape[1]/2
1461 lag0 = data_acf.shape[1]/2
1462 #Funcion de Autocorrelacion
1462 #Funcion de Autocorrelacion
1463 mean_acf = stats.nanmean(data_acf, axis = 0)
1463 mean_acf = stats.nanmean(data_acf, axis = 0)
1464
1464
1465 #Obtencion Indice de TauCross
1465 #Obtencion Indice de TauCross
1466 ind_ccf = data_ccf.argmax(axis = 1)
1466 ind_ccf = data_ccf.argmax(axis = 1)
1467 #Obtencion Indice de TauAuto
1467 #Obtencion Indice de TauAuto
1468 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1468 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1469 ccf_lag0 = data_ccf[:,lag0,:]
1469 ccf_lag0 = data_ccf[:,lag0,:]
1470
1470
1471 for i in range(ccf_lag0.shape[0]):
1471 for i in range(ccf_lag0.shape[0]):
1472 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1472 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1473
1473
1474 #Obtencion de TauCross y TauAuto
1474 #Obtencion de TauCross y TauAuto
1475 tau_ccf = lagRange[ind_ccf]
1475 tau_ccf = lagRange[ind_ccf]
1476 tau_acf = lagRange[ind_acf]
1476 tau_acf = lagRange[ind_acf]
1477
1477
1478 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1478 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1479
1479
1480 tau_ccf[Nan1,Nan2] = numpy.nan
1480 tau_ccf[Nan1,Nan2] = numpy.nan
1481 tau_acf[Nan1,Nan2] = numpy.nan
1481 tau_acf[Nan1,Nan2] = numpy.nan
1482 tau = numpy.vstack((tau_ccf,tau_acf))
1482 tau = numpy.vstack((tau_ccf,tau_acf))
1483
1483
1484 return tau
1484 return tau
1485
1485
1486 def __calculateLag1Phase(self, data, lagTRange):
1486 def __calculateLag1Phase(self, data, lagTRange):
1487 data1 = stats.nanmean(data, axis = 0)
1487 data1 = stats.nanmean(data, axis = 0)
1488 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1488 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1489
1489
1490 phase = numpy.angle(data1[lag1,:])
1490 phase = numpy.angle(data1[lag1,:])
1491
1491
1492 return phase
1492 return phase
1493
1493
1494 class SpectralFitting(Operation):
1494 class SpectralFitting(Operation):
1495 '''
1495 '''
1496 Function GetMoments()
1496 Function GetMoments()
1497
1497
1498 Input:
1498 Input:
1499 Output:
1499 Output:
1500 Variables modified:
1500 Variables modified:
1501 '''
1501 '''
1502
1502
1503 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1503 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1504
1504
1505
1505
1506 if path != None:
1506 if path != None:
1507 sys.path.append(path)
1507 sys.path.append(path)
1508 self.dataOut.library = importlib.import_module(file)
1508 self.dataOut.library = importlib.import_module(file)
1509
1509
1510 #To be inserted as a parameter
1510 #To be inserted as a parameter
1511 groupArray = numpy.array(groupList)
1511 groupArray = numpy.array(groupList)
1512 # groupArray = numpy.array([[0,1],[2,3]])
1512 # groupArray = numpy.array([[0,1],[2,3]])
1513 self.dataOut.groupList = groupArray
1513 self.dataOut.groupList = groupArray
1514
1514
1515 nGroups = groupArray.shape[0]
1515 nGroups = groupArray.shape[0]
1516 nChannels = self.dataIn.nChannels
1516 nChannels = self.dataIn.nChannels
1517 nHeights=self.dataIn.heightList.size
1517 nHeights=self.dataIn.heightList.size
1518
1518
1519 #Parameters Array
1519 #Parameters Array
1520 self.dataOut.data_param = None
1520 self.dataOut.data_param = None
1521
1521
1522 #Set constants
1522 #Set constants
1523 constants = self.dataOut.library.setConstants(self.dataIn)
1523 constants = self.dataOut.library.setConstants(self.dataIn)
1524 self.dataOut.constants = constants
1524 self.dataOut.constants = constants
1525 M = self.dataIn.normFactor
1525 M = self.dataIn.normFactor
1526 N = self.dataIn.nFFTPoints
1526 N = self.dataIn.nFFTPoints
1527 ippSeconds = self.dataIn.ippSeconds
1527 ippSeconds = self.dataIn.ippSeconds
1528 K = self.dataIn.nIncohInt
1528 K = self.dataIn.nIncohInt
1529 pairsArray = numpy.array(self.dataIn.pairsList)
1529 pairsArray = numpy.array(self.dataIn.pairsList)
1530
1530
1531 #List of possible combinations
1531 #List of possible combinations
1532 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1532 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1533 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1533 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1534
1534
1535 if getSNR:
1535 if getSNR:
1536 listChannels = groupArray.reshape((groupArray.size))
1536 listChannels = groupArray.reshape((groupArray.size))
1537 listChannels.sort()
1537 listChannels.sort()
1538 noise = self.dataIn.getNoise()
1538 noise = self.dataIn.getNoise()
1539 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1539 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1540
1540
1541 for i in range(nGroups):
1541 for i in range(nGroups):
1542 coord = groupArray[i,:]
1542 coord = groupArray[i,:]
1543
1543
1544 #Input data array
1544 #Input data array
1545 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1545 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1546 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1546 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1547
1547
1548 #Cross Spectra data array for Covariance Matrixes
1548 #Cross Spectra data array for Covariance Matrixes
1549 ind = 0
1549 ind = 0
1550 for pairs in listComb:
1550 for pairs in listComb:
1551 pairsSel = numpy.array([coord[x],coord[y]])
1551 pairsSel = numpy.array([coord[x],coord[y]])
1552 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1552 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1553 ind += 1
1553 ind += 1
1554 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1554 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1555 dataCross = dataCross**2/K
1555 dataCross = dataCross**2/K
1556
1556
1557 for h in range(nHeights):
1557 for h in range(nHeights):
1558
1558
1559 #Input
1559 #Input
1560 d = data[:,h]
1560 d = data[:,h]
1561
1561
1562 #Covariance Matrix
1562 #Covariance Matrix
1563 D = numpy.diag(d**2/K)
1563 D = numpy.diag(d**2/K)
1564 ind = 0
1564 ind = 0
1565 for pairs in listComb:
1565 for pairs in listComb:
1566 #Coordinates in Covariance Matrix
1566 #Coordinates in Covariance Matrix
1567 x = pairs[0]
1567 x = pairs[0]
1568 y = pairs[1]
1568 y = pairs[1]
1569 #Channel Index
1569 #Channel Index
1570 S12 = dataCross[ind,:,h]
1570 S12 = dataCross[ind,:,h]
1571 D12 = numpy.diag(S12)
1571 D12 = numpy.diag(S12)
1572 #Completing Covariance Matrix with Cross Spectras
1572 #Completing Covariance Matrix with Cross Spectras
1573 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1573 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1574 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1574 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1575 ind += 1
1575 ind += 1
1576 Dinv=numpy.linalg.inv(D)
1576 Dinv=numpy.linalg.inv(D)
1577 L=numpy.linalg.cholesky(Dinv)
1577 L=numpy.linalg.cholesky(Dinv)
1578 LT=L.T
1578 LT=L.T
1579
1579
1580 dp = numpy.dot(LT,d)
1580 dp = numpy.dot(LT,d)
1581
1581
1582 #Initial values
1582 #Initial values
1583 data_spc = self.dataIn.data_spc[coord,:,h]
1583 data_spc = self.dataIn.data_spc[coord,:,h]
1584
1584
1585 if (h>0)and(error1[3]<5):
1585 if (h>0)and(error1[3]<5):
1586 p0 = self.dataOut.data_param[i,:,h-1]
1586 p0 = self.dataOut.data_param[i,:,h-1]
1587 else:
1587 else:
1588 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1588 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1589
1589
1590 try:
1590 try:
1591 #Least Squares
1591 #Least Squares
1592 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1592 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1593 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1593 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1594 #Chi square error
1594 #Chi square error
1595 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1595 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1596 #Error with Jacobian
1596 #Error with Jacobian
1597 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1597 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1598 except:
1598 except:
1599 minp = p0*numpy.nan
1599 minp = p0*numpy.nan
1600 error0 = numpy.nan
1600 error0 = numpy.nan
1601 error1 = p0*numpy.nan
1601 error1 = p0*numpy.nan
1602
1602
1603 #Save
1603 #Save
1604 if self.dataOut.data_param is None:
1604 if self.dataOut.data_param is None:
1605 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1605 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1606 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1606 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1607
1607
1608 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1608 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1609 self.dataOut.data_param[i,:,h] = minp
1609 self.dataOut.data_param[i,:,h] = minp
1610 return
1610 return
1611
1611
1612 def __residFunction(self, p, dp, LT, constants):
1612 def __residFunction(self, p, dp, LT, constants):
1613
1613
1614 fm = self.dataOut.library.modelFunction(p, constants)
1614 fm = self.dataOut.library.modelFunction(p, constants)
1615 fmp=numpy.dot(LT,fm)
1615 fmp=numpy.dot(LT,fm)
1616
1616
1617 return dp-fmp
1617 return dp-fmp
1618
1618
1619 def __getSNR(self, z, noise):
1619 def __getSNR(self, z, noise):
1620
1620
1621 avg = numpy.average(z, axis=1)
1621 avg = numpy.average(z, axis=1)
1622 SNR = (avg.T-noise)/noise
1622 SNR = (avg.T-noise)/noise
1623 SNR = SNR.T
1623 SNR = SNR.T
1624 return SNR
1624 return SNR
1625
1625
1626 def __chisq(p,chindex,hindex):
1626 def __chisq(p,chindex,hindex):
1627 #similar to Resid but calculates CHI**2
1627 #similar to Resid but calculates CHI**2
1628 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1628 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1629 dp=numpy.dot(LT,d)
1629 dp=numpy.dot(LT,d)
1630 fmp=numpy.dot(LT,fm)
1630 fmp=numpy.dot(LT,fm)
1631 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1631 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1632 return chisq
1632 return chisq
1633
1633
1634 class WindProfiler(Operation):
1634 class WindProfiler(Operation):
1635
1635
1636 __isConfig = False
1636 __isConfig = False
1637
1637
1638 __initime = None
1638 __initime = None
1639 __lastdatatime = None
1639 __lastdatatime = None
1640 __integrationtime = None
1640 __integrationtime = None
1641
1641
1642 __buffer = None
1642 __buffer = None
1643
1643
1644 __dataReady = False
1644 __dataReady = False
1645
1645
1646 __firstdata = None
1646 __firstdata = None
1647
1647
1648 n = None
1648 n = None
1649
1649
1650 def __init__(self):
1650 def __init__(self):
1651 Operation.__init__(self)
1651 Operation.__init__(self)
1652
1652
1653 def __calculateCosDir(self, elev, azim):
1653 def __calculateCosDir(self, elev, azim):
1654 zen = (90 - elev)*numpy.pi/180
1654 zen = (90 - elev)*numpy.pi/180
1655 azim = azim*numpy.pi/180
1655 azim = azim*numpy.pi/180
1656 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1656 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1657 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1657 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1658
1658
1659 signX = numpy.sign(numpy.cos(azim))
1659 signX = numpy.sign(numpy.cos(azim))
1660 signY = numpy.sign(numpy.sin(azim))
1660 signY = numpy.sign(numpy.sin(azim))
1661
1661
1662 cosDirX = numpy.copysign(cosDirX, signX)
1662 cosDirX = numpy.copysign(cosDirX, signX)
1663 cosDirY = numpy.copysign(cosDirY, signY)
1663 cosDirY = numpy.copysign(cosDirY, signY)
1664 return cosDirX, cosDirY
1664 return cosDirX, cosDirY
1665
1665
1666 def __calculateAngles(self, theta_x, theta_y, azimuth):
1666 def __calculateAngles(self, theta_x, theta_y, azimuth):
1667
1667
1668 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1668 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1669 zenith_arr = numpy.arccos(dir_cosw)
1669 zenith_arr = numpy.arccos(dir_cosw)
1670 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1670 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1671
1671
1672 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1672 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1673 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1673 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1674
1674
1675 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1675 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1676
1676
1677 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1677 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1678
1678
1679 #
1679 #
1680 if horOnly:
1680 if horOnly:
1681 A = numpy.c_[dir_cosu,dir_cosv]
1681 A = numpy.c_[dir_cosu,dir_cosv]
1682 else:
1682 else:
1683 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1683 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1684 A = numpy.asmatrix(A)
1684 A = numpy.asmatrix(A)
1685 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1685 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1686
1686
1687 return A1
1687 return A1
1688
1688
1689 def __correctValues(self, heiRang, phi, velRadial, SNR):
1689 def __correctValues(self, heiRang, phi, velRadial, SNR):
1690 listPhi = phi.tolist()
1690 listPhi = phi.tolist()
1691 maxid = listPhi.index(max(listPhi))
1691 maxid = listPhi.index(max(listPhi))
1692 minid = listPhi.index(min(listPhi))
1692 minid = listPhi.index(min(listPhi))
1693
1693
1694 rango = list(range(len(phi)))
1694 rango = list(range(len(phi)))
1695 # rango = numpy.delete(rango,maxid)
1695 # rango = numpy.delete(rango,maxid)
1696
1696
1697 heiRang1 = heiRang*math.cos(phi[maxid])
1697 heiRang1 = heiRang*math.cos(phi[maxid])
1698 heiRangAux = heiRang*math.cos(phi[minid])
1698 heiRangAux = heiRang*math.cos(phi[minid])
1699 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1699 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1700 heiRang1 = numpy.delete(heiRang1,indOut)
1700 heiRang1 = numpy.delete(heiRang1,indOut)
1701
1701
1702 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1702 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1703 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1703 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1704
1704
1705 for i in rango:
1705 for i in rango:
1706 x = heiRang*math.cos(phi[i])
1706 x = heiRang*math.cos(phi[i])
1707 y1 = velRadial[i,:]
1707 y1 = velRadial[i,:]
1708 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1708 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1709
1709
1710 x1 = heiRang1
1710 x1 = heiRang1
1711 y11 = f1(x1)
1711 y11 = f1(x1)
1712
1712
1713 y2 = SNR[i,:]
1713 y2 = SNR[i,:]
1714 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1714 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1715 y21 = f2(x1)
1715 y21 = f2(x1)
1716
1716
1717 velRadial1[i,:] = y11
1717 velRadial1[i,:] = y11
1718 SNR1[i,:] = y21
1718 SNR1[i,:] = y21
1719
1719
1720 return heiRang1, velRadial1, SNR1
1720 return heiRang1, velRadial1, SNR1
1721
1721
1722 def __calculateVelUVW(self, A, velRadial):
1722 def __calculateVelUVW(self, A, velRadial):
1723
1723
1724 #Operacion Matricial
1724 #Operacion Matricial
1725 # velUVW = numpy.zeros((velRadial.shape[1],3))
1725 # velUVW = numpy.zeros((velRadial.shape[1],3))
1726 # for ind in range(velRadial.shape[1]):
1726 # for ind in range(velRadial.shape[1]):
1727 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1727 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1728 # velUVW = velUVW.transpose()
1728 # velUVW = velUVW.transpose()
1729 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1729 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1730 velUVW[:,:] = numpy.dot(A,velRadial)
1730 velUVW[:,:] = numpy.dot(A,velRadial)
1731
1731
1732
1732
1733 return velUVW
1733 return velUVW
1734
1734
1735 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1735 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1736
1736
1737 def techniqueDBS(self, kwargs):
1737 def techniqueDBS(self, kwargs):
1738 """
1738 """
1739 Function that implements Doppler Beam Swinging (DBS) technique.
1739 Function that implements Doppler Beam Swinging (DBS) technique.
1740
1740
1741 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1741 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1742 Direction correction (if necessary), Ranges and SNR
1742 Direction correction (if necessary), Ranges and SNR
1743
1743
1744 Output: Winds estimation (Zonal, Meridional and Vertical)
1744 Output: Winds estimation (Zonal, Meridional and Vertical)
1745
1745
1746 Parameters affected: Winds, height range, SNR
1746 Parameters affected: Winds, height range, SNR
1747 """
1747 """
1748 velRadial0 = kwargs['velRadial']
1748 velRadial0 = kwargs['velRadial']
1749 heiRang = kwargs['heightList']
1749 heiRang = kwargs['heightList']
1750 SNR0 = kwargs['SNR']
1750 SNR0 = kwargs['SNR']
1751
1751
1752 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1752 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1753 theta_x = numpy.array(kwargs['dirCosx'])
1753 theta_x = numpy.array(kwargs['dirCosx'])
1754 theta_y = numpy.array(kwargs['dirCosy'])
1754 theta_y = numpy.array(kwargs['dirCosy'])
1755 else:
1755 else:
1756 elev = numpy.array(kwargs['elevation'])
1756 elev = numpy.array(kwargs['elevation'])
1757 azim = numpy.array(kwargs['azimuth'])
1757 azim = numpy.array(kwargs['azimuth'])
1758 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1758 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1759 azimuth = kwargs['correctAzimuth']
1759 azimuth = kwargs['correctAzimuth']
1760 if 'horizontalOnly' in kwargs:
1760 if 'horizontalOnly' in kwargs:
1761 horizontalOnly = kwargs['horizontalOnly']
1761 horizontalOnly = kwargs['horizontalOnly']
1762 else: horizontalOnly = False
1762 else: horizontalOnly = False
1763 if 'correctFactor' in kwargs:
1763 if 'correctFactor' in kwargs:
1764 correctFactor = kwargs['correctFactor']
1764 correctFactor = kwargs['correctFactor']
1765 else: correctFactor = 1
1765 else: correctFactor = 1
1766 if 'channelList' in kwargs:
1766 if 'channelList' in kwargs:
1767 channelList = kwargs['channelList']
1767 channelList = kwargs['channelList']
1768 if len(channelList) == 2:
1768 if len(channelList) == 2:
1769 horizontalOnly = True
1769 horizontalOnly = True
1770 arrayChannel = numpy.array(channelList)
1770 arrayChannel = numpy.array(channelList)
1771 param = param[arrayChannel,:,:]
1771 param = param[arrayChannel,:,:]
1772 theta_x = theta_x[arrayChannel]
1772 theta_x = theta_x[arrayChannel]
1773 theta_y = theta_y[arrayChannel]
1773 theta_y = theta_y[arrayChannel]
1774
1774
1775 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1775 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1776 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1776 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1777 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1777 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1778
1778
1779 #Calculo de Componentes de la velocidad con DBS
1779 #Calculo de Componentes de la velocidad con DBS
1780 winds = self.__calculateVelUVW(A,velRadial1)
1780 winds = self.__calculateVelUVW(A,velRadial1)
1781
1781
1782 return winds, heiRang1, SNR1
1782 return winds, heiRang1, SNR1
1783
1783
1784 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1784 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1785
1785
1786 nPairs = len(pairs_ccf)
1786 nPairs = len(pairs_ccf)
1787 posx = numpy.asarray(posx)
1787 posx = numpy.asarray(posx)
1788 posy = numpy.asarray(posy)
1788 posy = numpy.asarray(posy)
1789
1789
1790 #Rotacion Inversa para alinear con el azimuth
1790 #Rotacion Inversa para alinear con el azimuth
1791 if azimuth!= None:
1791 if azimuth!= None:
1792 azimuth = azimuth*math.pi/180
1792 azimuth = azimuth*math.pi/180
1793 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1793 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1794 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1794 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1795 else:
1795 else:
1796 posx1 = posx
1796 posx1 = posx
1797 posy1 = posy
1797 posy1 = posy
1798
1798
1799 #Calculo de Distancias
1799 #Calculo de Distancias
1800 distx = numpy.zeros(nPairs)
1800 distx = numpy.zeros(nPairs)
1801 disty = numpy.zeros(nPairs)
1801 disty = numpy.zeros(nPairs)
1802 dist = numpy.zeros(nPairs)
1802 dist = numpy.zeros(nPairs)
1803 ang = numpy.zeros(nPairs)
1803 ang = numpy.zeros(nPairs)
1804
1804
1805 for i in range(nPairs):
1805 for i in range(nPairs):
1806 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1806 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1807 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1807 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1808 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1808 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1809 ang[i] = numpy.arctan2(disty[i],distx[i])
1809 ang[i] = numpy.arctan2(disty[i],distx[i])
1810
1810
1811 return distx, disty, dist, ang
1811 return distx, disty, dist, ang
1812 #Calculo de Matrices
1812 #Calculo de Matrices
1813 # nPairs = len(pairs)
1813 # nPairs = len(pairs)
1814 # ang1 = numpy.zeros((nPairs, 2, 1))
1814 # ang1 = numpy.zeros((nPairs, 2, 1))
1815 # dist1 = numpy.zeros((nPairs, 2, 1))
1815 # dist1 = numpy.zeros((nPairs, 2, 1))
1816 #
1816 #
1817 # for j in range(nPairs):
1817 # for j in range(nPairs):
1818 # dist1[j,0,0] = dist[pairs[j][0]]
1818 # dist1[j,0,0] = dist[pairs[j][0]]
1819 # dist1[j,1,0] = dist[pairs[j][1]]
1819 # dist1[j,1,0] = dist[pairs[j][1]]
1820 # ang1[j,0,0] = ang[pairs[j][0]]
1820 # ang1[j,0,0] = ang[pairs[j][0]]
1821 # ang1[j,1,0] = ang[pairs[j][1]]
1821 # ang1[j,1,0] = ang[pairs[j][1]]
1822 #
1822 #
1823 # return distx,disty, dist1,ang1
1823 # return distx,disty, dist1,ang1
1824
1824
1825
1825
1826 def __calculateVelVer(self, phase, lagTRange, _lambda):
1826 def __calculateVelVer(self, phase, lagTRange, _lambda):
1827
1827
1828 Ts = lagTRange[1] - lagTRange[0]
1828 Ts = lagTRange[1] - lagTRange[0]
1829 velW = -_lambda*phase/(4*math.pi*Ts)
1829 velW = -_lambda*phase/(4*math.pi*Ts)
1830
1830
1831 return velW
1831 return velW
1832
1832
1833 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1833 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1834 nPairs = tau1.shape[0]
1834 nPairs = tau1.shape[0]
1835 nHeights = tau1.shape[1]
1835 nHeights = tau1.shape[1]
1836 vel = numpy.zeros((nPairs,3,nHeights))
1836 vel = numpy.zeros((nPairs,3,nHeights))
1837 dist1 = numpy.reshape(dist, (dist.size,1))
1837 dist1 = numpy.reshape(dist, (dist.size,1))
1838
1838
1839 angCos = numpy.cos(ang)
1839 angCos = numpy.cos(ang)
1840 angSin = numpy.sin(ang)
1840 angSin = numpy.sin(ang)
1841
1841
1842 vel0 = dist1*tau1/(2*tau2**2)
1842 vel0 = dist1*tau1/(2*tau2**2)
1843 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1843 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1844 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1844 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1845
1845
1846 ind = numpy.where(numpy.isinf(vel))
1846 ind = numpy.where(numpy.isinf(vel))
1847 vel[ind] = numpy.nan
1847 vel[ind] = numpy.nan
1848
1848
1849 return vel
1849 return vel
1850
1850
1851 # def __getPairsAutoCorr(self, pairsList, nChannels):
1851 # def __getPairsAutoCorr(self, pairsList, nChannels):
1852 #
1852 #
1853 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1853 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1854 #
1854 #
1855 # for l in range(len(pairsList)):
1855 # for l in range(len(pairsList)):
1856 # firstChannel = pairsList[l][0]
1856 # firstChannel = pairsList[l][0]
1857 # secondChannel = pairsList[l][1]
1857 # secondChannel = pairsList[l][1]
1858 #
1858 #
1859 # #Obteniendo pares de Autocorrelacion
1859 # #Obteniendo pares de Autocorrelacion
1860 # if firstChannel == secondChannel:
1860 # if firstChannel == secondChannel:
1861 # pairsAutoCorr[firstChannel] = int(l)
1861 # pairsAutoCorr[firstChannel] = int(l)
1862 #
1862 #
1863 # pairsAutoCorr = pairsAutoCorr.astype(int)
1863 # pairsAutoCorr = pairsAutoCorr.astype(int)
1864 #
1864 #
1865 # pairsCrossCorr = range(len(pairsList))
1865 # pairsCrossCorr = range(len(pairsList))
1866 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1866 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1867 #
1867 #
1868 # return pairsAutoCorr, pairsCrossCorr
1868 # return pairsAutoCorr, pairsCrossCorr
1869
1869
1870 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1870 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1871 def techniqueSA(self, kwargs):
1871 def techniqueSA(self, kwargs):
1872
1872
1873 """
1873 """
1874 Function that implements Spaced Antenna (SA) technique.
1874 Function that implements Spaced Antenna (SA) technique.
1875
1875
1876 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1876 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1877 Direction correction (if necessary), Ranges and SNR
1877 Direction correction (if necessary), Ranges and SNR
1878
1878
1879 Output: Winds estimation (Zonal, Meridional and Vertical)
1879 Output: Winds estimation (Zonal, Meridional and Vertical)
1880
1880
1881 Parameters affected: Winds
1881 Parameters affected: Winds
1882 """
1882 """
1883 position_x = kwargs['positionX']
1883 position_x = kwargs['positionX']
1884 position_y = kwargs['positionY']
1884 position_y = kwargs['positionY']
1885 azimuth = kwargs['azimuth']
1885 azimuth = kwargs['azimuth']
1886
1886
1887 if 'correctFactor' in kwargs:
1887 if 'correctFactor' in kwargs:
1888 correctFactor = kwargs['correctFactor']
1888 correctFactor = kwargs['correctFactor']
1889 else:
1889 else:
1890 correctFactor = 1
1890 correctFactor = 1
1891
1891
1892 groupList = kwargs['groupList']
1892 groupList = kwargs['groupList']
1893 pairs_ccf = groupList[1]
1893 pairs_ccf = groupList[1]
1894 tau = kwargs['tau']
1894 tau = kwargs['tau']
1895 _lambda = kwargs['_lambda']
1895 _lambda = kwargs['_lambda']
1896
1896
1897 #Cross Correlation pairs obtained
1897 #Cross Correlation pairs obtained
1898 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1898 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1899 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1899 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1900 # pairsSelArray = numpy.array(pairsSelected)
1900 # pairsSelArray = numpy.array(pairsSelected)
1901 # pairs = []
1901 # pairs = []
1902 #
1902 #
1903 # #Wind estimation pairs obtained
1903 # #Wind estimation pairs obtained
1904 # for i in range(pairsSelArray.shape[0]/2):
1904 # for i in range(pairsSelArray.shape[0]/2):
1905 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1905 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1906 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1906 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1907 # pairs.append((ind1,ind2))
1907 # pairs.append((ind1,ind2))
1908
1908
1909 indtau = tau.shape[0]/2
1909 indtau = tau.shape[0]/2
1910 tau1 = tau[:indtau,:]
1910 tau1 = tau[:indtau,:]
1911 tau2 = tau[indtau:-1,:]
1911 tau2 = tau[indtau:-1,:]
1912 # tau1 = tau1[pairs,:]
1912 # tau1 = tau1[pairs,:]
1913 # tau2 = tau2[pairs,:]
1913 # tau2 = tau2[pairs,:]
1914 phase1 = tau[-1,:]
1914 phase1 = tau[-1,:]
1915
1915
1916 #---------------------------------------------------------------------
1916 #---------------------------------------------------------------------
1917 #Metodo Directo
1917 #Metodo Directo
1918 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1918 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1919 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1919 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1920 winds = stats.nanmean(winds, axis=0)
1920 winds = stats.nanmean(winds, axis=0)
1921 #---------------------------------------------------------------------
1921 #---------------------------------------------------------------------
1922 #Metodo General
1922 #Metodo General
1923 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1923 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1924 # #Calculo Coeficientes de Funcion de Correlacion
1924 # #Calculo Coeficientes de Funcion de Correlacion
1925 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1925 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1926 # #Calculo de Velocidades
1926 # #Calculo de Velocidades
1927 # winds = self.calculateVelUV(F,G,A,B,H)
1927 # winds = self.calculateVelUV(F,G,A,B,H)
1928
1928
1929 #---------------------------------------------------------------------
1929 #---------------------------------------------------------------------
1930 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1930 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1931 winds = correctFactor*winds
1931 winds = correctFactor*winds
1932 return winds
1932 return winds
1933
1933
1934 def __checkTime(self, currentTime, paramInterval, outputInterval):
1934 def __checkTime(self, currentTime, paramInterval, outputInterval):
1935
1935
1936 dataTime = currentTime + paramInterval
1936 dataTime = currentTime + paramInterval
1937 deltaTime = dataTime - self.__initime
1937 deltaTime = dataTime - self.__initime
1938
1938
1939 if deltaTime >= outputInterval or deltaTime < 0:
1939 if deltaTime >= outputInterval or deltaTime < 0:
1940 self.__dataReady = True
1940 self.__dataReady = True
1941 return
1941 return
1942
1942
1943 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1943 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1944 '''
1944 '''
1945 Function that implements winds estimation technique with detected meteors.
1945 Function that implements winds estimation technique with detected meteors.
1946
1946
1947 Input: Detected meteors, Minimum meteor quantity to wind estimation
1947 Input: Detected meteors, Minimum meteor quantity to wind estimation
1948
1948
1949 Output: Winds estimation (Zonal and Meridional)
1949 Output: Winds estimation (Zonal and Meridional)
1950
1950
1951 Parameters affected: Winds
1951 Parameters affected: Winds
1952 '''
1952 '''
1953 #Settings
1953 #Settings
1954 nInt = (heightMax - heightMin)/2
1954 nInt = (heightMax - heightMin)/2
1955 nInt = int(nInt)
1955 nInt = int(nInt)
1956 winds = numpy.zeros((2,nInt))*numpy.nan
1956 winds = numpy.zeros((2,nInt))*numpy.nan
1957
1957
1958 #Filter errors
1958 #Filter errors
1959 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1959 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1960 finalMeteor = arrayMeteor[error,:]
1960 finalMeteor = arrayMeteor[error,:]
1961
1961
1962 #Meteor Histogram
1962 #Meteor Histogram
1963 finalHeights = finalMeteor[:,2]
1963 finalHeights = finalMeteor[:,2]
1964 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1964 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1965 nMeteorsPerI = hist[0]
1965 nMeteorsPerI = hist[0]
1966 heightPerI = hist[1]
1966 heightPerI = hist[1]
1967
1967
1968 #Sort of meteors
1968 #Sort of meteors
1969 indSort = finalHeights.argsort()
1969 indSort = finalHeights.argsort()
1970 finalMeteor2 = finalMeteor[indSort,:]
1970 finalMeteor2 = finalMeteor[indSort,:]
1971
1971
1972 # Calculating winds
1972 # Calculating winds
1973 ind1 = 0
1973 ind1 = 0
1974 ind2 = 0
1974 ind2 = 0
1975
1975
1976 for i in range(nInt):
1976 for i in range(nInt):
1977 nMet = nMeteorsPerI[i]
1977 nMet = nMeteorsPerI[i]
1978 ind1 = ind2
1978 ind1 = ind2
1979 ind2 = ind1 + nMet
1979 ind2 = ind1 + nMet
1980
1980
1981 meteorAux = finalMeteor2[ind1:ind2,:]
1981 meteorAux = finalMeteor2[ind1:ind2,:]
1982
1982
1983 if meteorAux.shape[0] >= meteorThresh:
1983 if meteorAux.shape[0] >= meteorThresh:
1984 vel = meteorAux[:, 6]
1984 vel = meteorAux[:, 6]
1985 zen = meteorAux[:, 4]*numpy.pi/180
1985 zen = meteorAux[:, 4]*numpy.pi/180
1986 azim = meteorAux[:, 3]*numpy.pi/180
1986 azim = meteorAux[:, 3]*numpy.pi/180
1987
1987
1988 n = numpy.cos(zen)
1988 n = numpy.cos(zen)
1989 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1989 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1990 # l = m*numpy.tan(azim)
1990 # l = m*numpy.tan(azim)
1991 l = numpy.sin(zen)*numpy.sin(azim)
1991 l = numpy.sin(zen)*numpy.sin(azim)
1992 m = numpy.sin(zen)*numpy.cos(azim)
1992 m = numpy.sin(zen)*numpy.cos(azim)
1993
1993
1994 A = numpy.vstack((l, m)).transpose()
1994 A = numpy.vstack((l, m)).transpose()
1995 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1995 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1996 windsAux = numpy.dot(A1, vel)
1996 windsAux = numpy.dot(A1, vel)
1997
1997
1998 winds[0,i] = windsAux[0]
1998 winds[0,i] = windsAux[0]
1999 winds[1,i] = windsAux[1]
1999 winds[1,i] = windsAux[1]
2000
2000
2001 return winds, heightPerI[:-1]
2001 return winds, heightPerI[:-1]
2002
2002
2003 def techniqueNSM_SA(self, **kwargs):
2003 def techniqueNSM_SA(self, **kwargs):
2004 metArray = kwargs['metArray']
2004 metArray = kwargs['metArray']
2005 heightList = kwargs['heightList']
2005 heightList = kwargs['heightList']
2006 timeList = kwargs['timeList']
2006 timeList = kwargs['timeList']
2007
2007
2008 rx_location = kwargs['rx_location']
2008 rx_location = kwargs['rx_location']
2009 groupList = kwargs['groupList']
2009 groupList = kwargs['groupList']
2010 azimuth = kwargs['azimuth']
2010 azimuth = kwargs['azimuth']
2011 dfactor = kwargs['dfactor']
2011 dfactor = kwargs['dfactor']
2012 k = kwargs['k']
2012 k = kwargs['k']
2013
2013
2014 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
2014 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
2015 d = dist*dfactor
2015 d = dist*dfactor
2016 #Phase calculation
2016 #Phase calculation
2017 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2017 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
2018
2018
2019 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2019 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
2020
2020
2021 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2021 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2022 azimuth1 = azimuth1*numpy.pi/180
2022 azimuth1 = azimuth1*numpy.pi/180
2023
2023
2024 for i in range(heightList.size):
2024 for i in range(heightList.size):
2025 h = heightList[i]
2025 h = heightList[i]
2026 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2026 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
2027 metHeight = metArray1[indH,:]
2027 metHeight = metArray1[indH,:]
2028 if metHeight.shape[0] >= 2:
2028 if metHeight.shape[0] >= 2:
2029 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2029 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
2030 iazim = metHeight[:,1].astype(int)
2030 iazim = metHeight[:,1].astype(int)
2031 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2031 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
2032 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2032 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2033 A = numpy.asmatrix(A)
2033 A = numpy.asmatrix(A)
2034 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2034 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2035 velHor = numpy.dot(A1,velAux)
2035 velHor = numpy.dot(A1,velAux)
2036
2036
2037 velEst[i,:] = numpy.squeeze(velHor)
2037 velEst[i,:] = numpy.squeeze(velHor)
2038 return velEst
2038 return velEst
2039
2039
2040 def __getPhaseSlope(self, metArray, heightList, timeList):
2040 def __getPhaseSlope(self, metArray, heightList, timeList):
2041 meteorList = []
2041 meteorList = []
2042 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2042 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2043 #Putting back together the meteor matrix
2043 #Putting back together the meteor matrix
2044 utctime = metArray[:,0]
2044 utctime = metArray[:,0]
2045 uniqueTime = numpy.unique(utctime)
2045 uniqueTime = numpy.unique(utctime)
2046
2046
2047 phaseDerThresh = 0.5
2047 phaseDerThresh = 0.5
2048 ippSeconds = timeList[1] - timeList[0]
2048 ippSeconds = timeList[1] - timeList[0]
2049 sec = numpy.where(timeList>1)[0][0]
2049 sec = numpy.where(timeList>1)[0][0]
2050 nPairs = metArray.shape[1] - 6
2050 nPairs = metArray.shape[1] - 6
2051 nHeights = len(heightList)
2051 nHeights = len(heightList)
2052
2052
2053 for t in uniqueTime:
2053 for t in uniqueTime:
2054 metArray1 = metArray[utctime==t,:]
2054 metArray1 = metArray[utctime==t,:]
2055 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2055 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2056 tmet = metArray1[:,1].astype(int)
2056 tmet = metArray1[:,1].astype(int)
2057 hmet = metArray1[:,2].astype(int)
2057 hmet = metArray1[:,2].astype(int)
2058
2058
2059 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2059 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2060 metPhase[:,:] = numpy.nan
2060 metPhase[:,:] = numpy.nan
2061 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2061 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2062
2062
2063 #Delete short trails
2063 #Delete short trails
2064 metBool = ~numpy.isnan(metPhase[0,:,:])
2064 metBool = ~numpy.isnan(metPhase[0,:,:])
2065 heightVect = numpy.sum(metBool, axis = 1)
2065 heightVect = numpy.sum(metBool, axis = 1)
2066 metBool[heightVect<sec,:] = False
2066 metBool[heightVect<sec,:] = False
2067 metPhase[:,heightVect<sec,:] = numpy.nan
2067 metPhase[:,heightVect<sec,:] = numpy.nan
2068
2068
2069 #Derivative
2069 #Derivative
2070 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2070 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2071 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2071 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2072 metPhase[phDerAux] = numpy.nan
2072 metPhase[phDerAux] = numpy.nan
2073
2073
2074 #--------------------------METEOR DETECTION -----------------------------------------
2074 #--------------------------METEOR DETECTION -----------------------------------------
2075 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2075 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2076
2076
2077 for p in numpy.arange(nPairs):
2077 for p in numpy.arange(nPairs):
2078 phase = metPhase[p,:,:]
2078 phase = metPhase[p,:,:]
2079 phDer = metDer[p,:,:]
2079 phDer = metDer[p,:,:]
2080
2080
2081 for h in indMet:
2081 for h in indMet:
2082 height = heightList[h]
2082 height = heightList[h]
2083 phase1 = phase[h,:] #82
2083 phase1 = phase[h,:] #82
2084 phDer1 = phDer[h,:]
2084 phDer1 = phDer[h,:]
2085
2085
2086 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2086 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2087
2087
2088 indValid = numpy.where(~numpy.isnan(phase1))[0]
2088 indValid = numpy.where(~numpy.isnan(phase1))[0]
2089 initMet = indValid[0]
2089 initMet = indValid[0]
2090 endMet = 0
2090 endMet = 0
2091
2091
2092 for i in range(len(indValid)-1):
2092 for i in range(len(indValid)-1):
2093
2093
2094 #Time difference
2094 #Time difference
2095 inow = indValid[i]
2095 inow = indValid[i]
2096 inext = indValid[i+1]
2096 inext = indValid[i+1]
2097 idiff = inext - inow
2097 idiff = inext - inow
2098 #Phase difference
2098 #Phase difference
2099 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2099 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2100
2100
2101 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2101 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2102 sizeTrail = inow - initMet + 1
2102 sizeTrail = inow - initMet + 1
2103 if sizeTrail>3*sec: #Too short meteors
2103 if sizeTrail>3*sec: #Too short meteors
2104 x = numpy.arange(initMet,inow+1)*ippSeconds
2104 x = numpy.arange(initMet,inow+1)*ippSeconds
2105 y = phase1[initMet:inow+1]
2105 y = phase1[initMet:inow+1]
2106 ynnan = ~numpy.isnan(y)
2106 ynnan = ~numpy.isnan(y)
2107 x = x[ynnan]
2107 x = x[ynnan]
2108 y = y[ynnan]
2108 y = y[ynnan]
2109 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2109 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2110 ylin = x*slope + intercept
2110 ylin = x*slope + intercept
2111 rsq = r_value**2
2111 rsq = r_value**2
2112 if rsq > 0.5:
2112 if rsq > 0.5:
2113 vel = slope#*height*1000/(k*d)
2113 vel = slope#*height*1000/(k*d)
2114 estAux = numpy.array([utctime,p,height, vel, rsq])
2114 estAux = numpy.array([utctime,p,height, vel, rsq])
2115 meteorList.append(estAux)
2115 meteorList.append(estAux)
2116 initMet = inext
2116 initMet = inext
2117 metArray2 = numpy.array(meteorList)
2117 metArray2 = numpy.array(meteorList)
2118
2118
2119 return metArray2
2119 return metArray2
2120
2120
2121 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2121 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2122
2122
2123 azimuth1 = numpy.zeros(len(pairslist))
2123 azimuth1 = numpy.zeros(len(pairslist))
2124 dist = numpy.zeros(len(pairslist))
2124 dist = numpy.zeros(len(pairslist))
2125
2125
2126 for i in range(len(rx_location)):
2126 for i in range(len(rx_location)):
2127 ch0 = pairslist[i][0]
2127 ch0 = pairslist[i][0]
2128 ch1 = pairslist[i][1]
2128 ch1 = pairslist[i][1]
2129
2129
2130 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2130 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2131 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2131 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2132 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2132 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2133 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2133 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2134
2134
2135 azimuth1 -= azimuth0
2135 azimuth1 -= azimuth0
2136 return azimuth1, dist
2136 return azimuth1, dist
2137
2137
2138 def techniqueNSM_DBS(self, **kwargs):
2138 def techniqueNSM_DBS(self, **kwargs):
2139 metArray = kwargs['metArray']
2139 metArray = kwargs['metArray']
2140 heightList = kwargs['heightList']
2140 heightList = kwargs['heightList']
2141 timeList = kwargs['timeList']
2141 timeList = kwargs['timeList']
2142 azimuth = kwargs['azimuth']
2142 azimuth = kwargs['azimuth']
2143 theta_x = numpy.array(kwargs['theta_x'])
2143 theta_x = numpy.array(kwargs['theta_x'])
2144 theta_y = numpy.array(kwargs['theta_y'])
2144 theta_y = numpy.array(kwargs['theta_y'])
2145
2145
2146 utctime = metArray[:,0]
2146 utctime = metArray[:,0]
2147 cmet = metArray[:,1].astype(int)
2147 cmet = metArray[:,1].astype(int)
2148 hmet = metArray[:,3].astype(int)
2148 hmet = metArray[:,3].astype(int)
2149 SNRmet = metArray[:,4]
2149 SNRmet = metArray[:,4]
2150 vmet = metArray[:,5]
2150 vmet = metArray[:,5]
2151 spcmet = metArray[:,6]
2151 spcmet = metArray[:,6]
2152
2152
2153 nChan = numpy.max(cmet) + 1
2153 nChan = numpy.max(cmet) + 1
2154 nHeights = len(heightList)
2154 nHeights = len(heightList)
2155
2155
2156 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2156 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2157 hmet = heightList[hmet]
2157 hmet = heightList[hmet]
2158 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2158 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2159
2159
2160 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2160 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2161
2161
2162 for i in range(nHeights - 1):
2162 for i in range(nHeights - 1):
2163 hmin = heightList[i]
2163 hmin = heightList[i]
2164 hmax = heightList[i + 1]
2164 hmax = heightList[i + 1]
2165
2165
2166 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2166 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2167 indthisH = numpy.where(thisH)
2167 indthisH = numpy.where(thisH)
2168
2168
2169 if numpy.size(indthisH) > 3:
2169 if numpy.size(indthisH) > 3:
2170
2170
2171 vel_aux = vmet[thisH]
2171 vel_aux = vmet[thisH]
2172 chan_aux = cmet[thisH]
2172 chan_aux = cmet[thisH]
2173 cosu_aux = dir_cosu[chan_aux]
2173 cosu_aux = dir_cosu[chan_aux]
2174 cosv_aux = dir_cosv[chan_aux]
2174 cosv_aux = dir_cosv[chan_aux]
2175 cosw_aux = dir_cosw[chan_aux]
2175 cosw_aux = dir_cosw[chan_aux]
2176
2176
2177 nch = numpy.size(numpy.unique(chan_aux))
2177 nch = numpy.size(numpy.unique(chan_aux))
2178 if nch > 1:
2178 if nch > 1:
2179 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2179 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2180 velEst[i,:] = numpy.dot(A,vel_aux)
2180 velEst[i,:] = numpy.dot(A,vel_aux)
2181
2181
2182 return velEst
2182 return velEst
2183
2183
2184 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2184 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2185
2185
2186 param = dataOut.data_param
2186 param = dataOut.data_param
2187 if dataOut.abscissaList != None:
2187 if dataOut.abscissaList != None:
2188 absc = dataOut.abscissaList[:-1]
2188 absc = dataOut.abscissaList[:-1]
2189 # noise = dataOut.noise
2189 # noise = dataOut.noise
2190 heightList = dataOut.heightList
2190 heightList = dataOut.heightList
2191 SNR = dataOut.data_snr
2191 SNR = dataOut.data_snr
2192
2192
2193 if technique == 'DBS':
2193 if technique == 'DBS':
2194
2194
2195 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2195 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2196 kwargs['heightList'] = heightList
2196 kwargs['heightList'] = heightList
2197 kwargs['SNR'] = SNR
2197 kwargs['SNR'] = SNR
2198
2198
2199 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2199 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2200 dataOut.utctimeInit = dataOut.utctime
2200 dataOut.utctimeInit = dataOut.utctime
2201 dataOut.outputInterval = dataOut.paramInterval
2201 dataOut.outputInterval = dataOut.paramInterval
2202
2202
2203 elif technique == 'SA':
2203 elif technique == 'SA':
2204
2204
2205 #Parameters
2205 #Parameters
2206 # position_x = kwargs['positionX']
2206 # position_x = kwargs['positionX']
2207 # position_y = kwargs['positionY']
2207 # position_y = kwargs['positionY']
2208 # azimuth = kwargs['azimuth']
2208 # azimuth = kwargs['azimuth']
2209 #
2209 #
2210 # if kwargs.has_key('crosspairsList'):
2210 # if kwargs.has_key('crosspairsList'):
2211 # pairs = kwargs['crosspairsList']
2211 # pairs = kwargs['crosspairsList']
2212 # else:
2212 # else:
2213 # pairs = None
2213 # pairs = None
2214 #
2214 #
2215 # if kwargs.has_key('correctFactor'):
2215 # if kwargs.has_key('correctFactor'):
2216 # correctFactor = kwargs['correctFactor']
2216 # correctFactor = kwargs['correctFactor']
2217 # else:
2217 # else:
2218 # correctFactor = 1
2218 # correctFactor = 1
2219
2219
2220 # tau = dataOut.data_param
2220 # tau = dataOut.data_param
2221 # _lambda = dataOut.C/dataOut.frequency
2221 # _lambda = dataOut.C/dataOut.frequency
2222 # pairsList = dataOut.groupList
2222 # pairsList = dataOut.groupList
2223 # nChannels = dataOut.nChannels
2223 # nChannels = dataOut.nChannels
2224
2224
2225 kwargs['groupList'] = dataOut.groupList
2225 kwargs['groupList'] = dataOut.groupList
2226 kwargs['tau'] = dataOut.data_param
2226 kwargs['tau'] = dataOut.data_param
2227 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2227 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2228 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2228 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2229 dataOut.data_output = self.techniqueSA(kwargs)
2229 dataOut.data_output = self.techniqueSA(kwargs)
2230 dataOut.utctimeInit = dataOut.utctime
2230 dataOut.utctimeInit = dataOut.utctime
2231 dataOut.outputInterval = dataOut.timeInterval
2231 dataOut.outputInterval = dataOut.timeInterval
2232
2232
2233 elif technique == 'Meteors':
2233 elif technique == 'Meteors':
2234 dataOut.flagNoData = True
2234 dataOut.flagNoData = True
2235 self.__dataReady = False
2235 self.__dataReady = False
2236
2236
2237 if 'nHours' in kwargs:
2237 if 'nHours' in kwargs:
2238 nHours = kwargs['nHours']
2238 nHours = kwargs['nHours']
2239 else:
2239 else:
2240 nHours = 1
2240 nHours = 1
2241
2241
2242 if 'meteorsPerBin' in kwargs:
2242 if 'meteorsPerBin' in kwargs:
2243 meteorThresh = kwargs['meteorsPerBin']
2243 meteorThresh = kwargs['meteorsPerBin']
2244 else:
2244 else:
2245 meteorThresh = 6
2245 meteorThresh = 6
2246
2246
2247 if 'hmin' in kwargs:
2247 if 'hmin' in kwargs:
2248 hmin = kwargs['hmin']
2248 hmin = kwargs['hmin']
2249 else: hmin = 70
2249 else: hmin = 70
2250 if 'hmax' in kwargs:
2250 if 'hmax' in kwargs:
2251 hmax = kwargs['hmax']
2251 hmax = kwargs['hmax']
2252 else: hmax = 110
2252 else: hmax = 110
2253
2253
2254 dataOut.outputInterval = nHours*3600
2254 dataOut.outputInterval = nHours*3600
2255
2255
2256 if self.__isConfig == False:
2256 if self.__isConfig == False:
2257 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2257 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2258 #Get Initial LTC time
2258 #Get Initial LTC time
2259 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2259 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2260 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2260 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2261
2261
2262 self.__isConfig = True
2262 self.__isConfig = True
2263
2263
2264 if self.__buffer is None:
2264 if self.__buffer is None:
2265 self.__buffer = dataOut.data_param
2265 self.__buffer = dataOut.data_param
2266 self.__firstdata = copy.copy(dataOut)
2266 self.__firstdata = copy.copy(dataOut)
2267
2267
2268 else:
2268 else:
2269 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2269 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2270
2270
2271 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2271 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2272
2272
2273 if self.__dataReady:
2273 if self.__dataReady:
2274 dataOut.utctimeInit = self.__initime
2274 dataOut.utctimeInit = self.__initime
2275
2275
2276 self.__initime += dataOut.outputInterval #to erase time offset
2276 self.__initime += dataOut.outputInterval #to erase time offset
2277
2277
2278 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2278 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2279 dataOut.flagNoData = False
2279 dataOut.flagNoData = False
2280 self.__buffer = None
2280 self.__buffer = None
2281
2281
2282 elif technique == 'Meteors1':
2282 elif technique == 'Meteors1':
2283 dataOut.flagNoData = True
2283 dataOut.flagNoData = True
2284 self.__dataReady = False
2284 self.__dataReady = False
2285
2285
2286 if 'nMins' in kwargs:
2286 if 'nMins' in kwargs:
2287 nMins = kwargs['nMins']
2287 nMins = kwargs['nMins']
2288 else: nMins = 20
2288 else: nMins = 20
2289 if 'rx_location' in kwargs:
2289 if 'rx_location' in kwargs:
2290 rx_location = kwargs['rx_location']
2290 rx_location = kwargs['rx_location']
2291 else: rx_location = [(0,1),(1,1),(1,0)]
2291 else: rx_location = [(0,1),(1,1),(1,0)]
2292 if 'azimuth' in kwargs:
2292 if 'azimuth' in kwargs:
2293 azimuth = kwargs['azimuth']
2293 azimuth = kwargs['azimuth']
2294 else: azimuth = 51.06
2294 else: azimuth = 51.06
2295 if 'dfactor' in kwargs:
2295 if 'dfactor' in kwargs:
2296 dfactor = kwargs['dfactor']
2296 dfactor = kwargs['dfactor']
2297 if 'mode' in kwargs:
2297 if 'mode' in kwargs:
2298 mode = kwargs['mode']
2298 mode = kwargs['mode']
2299 if 'theta_x' in kwargs:
2299 if 'theta_x' in kwargs:
2300 theta_x = kwargs['theta_x']
2300 theta_x = kwargs['theta_x']
2301 if 'theta_y' in kwargs:
2301 if 'theta_y' in kwargs:
2302 theta_y = kwargs['theta_y']
2302 theta_y = kwargs['theta_y']
2303 else: mode = 'SA'
2303 else: mode = 'SA'
2304
2304
2305 #Borrar luego esto
2305 #Borrar luego esto
2306 if dataOut.groupList is None:
2306 if dataOut.groupList is None:
2307 dataOut.groupList = [(0,1),(0,2),(1,2)]
2307 dataOut.groupList = [(0,1),(0,2),(1,2)]
2308 groupList = dataOut.groupList
2308 groupList = dataOut.groupList
2309 C = 3e8
2309 C = 3e8
2310 freq = 50e6
2310 freq = 50e6
2311 lamb = C/freq
2311 lamb = C/freq
2312 k = 2*numpy.pi/lamb
2312 k = 2*numpy.pi/lamb
2313
2313
2314 timeList = dataOut.abscissaList
2314 timeList = dataOut.abscissaList
2315 heightList = dataOut.heightList
2315 heightList = dataOut.heightList
2316
2316
2317 if self.__isConfig == False:
2317 if self.__isConfig == False:
2318 dataOut.outputInterval = nMins*60
2318 dataOut.outputInterval = nMins*60
2319 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2319 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2320 #Get Initial LTC time
2320 #Get Initial LTC time
2321 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2321 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2322 minuteAux = initime.minute
2322 minuteAux = initime.minute
2323 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2323 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2324 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2324 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2325
2325
2326 self.__isConfig = True
2326 self.__isConfig = True
2327
2327
2328 if self.__buffer is None:
2328 if self.__buffer is None:
2329 self.__buffer = dataOut.data_param
2329 self.__buffer = dataOut.data_param
2330 self.__firstdata = copy.copy(dataOut)
2330 self.__firstdata = copy.copy(dataOut)
2331
2331
2332 else:
2332 else:
2333 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2333 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2334
2334
2335 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2335 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2336
2336
2337 if self.__dataReady:
2337 if self.__dataReady:
2338 dataOut.utctimeInit = self.__initime
2338 dataOut.utctimeInit = self.__initime
2339 self.__initime += dataOut.outputInterval #to erase time offset
2339 self.__initime += dataOut.outputInterval #to erase time offset
2340
2340
2341 metArray = self.__buffer
2341 metArray = self.__buffer
2342 if mode == 'SA':
2342 if mode == 'SA':
2343 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2343 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2344 elif mode == 'DBS':
2344 elif mode == 'DBS':
2345 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2345 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2346 dataOut.data_output = dataOut.data_output.T
2346 dataOut.data_output = dataOut.data_output.T
2347 dataOut.flagNoData = False
2347 dataOut.flagNoData = False
2348 self.__buffer = None
2348 self.__buffer = None
2349
2349
2350 return
2350 return
2351
2351
2352 class EWDriftsEstimation(Operation):
2352 class EWDriftsEstimation(Operation):
2353
2353
2354 def __init__(self):
2354 def __init__(self):
2355 Operation.__init__(self)
2355 Operation.__init__(self)
2356
2356
2357 def __correctValues(self, heiRang, phi, velRadial, SNR):
2357 def __correctValues(self, heiRang, phi, velRadial, SNR):
2358 listPhi = phi.tolist()
2358 listPhi = phi.tolist()
2359 maxid = listPhi.index(max(listPhi))
2359 maxid = listPhi.index(max(listPhi))
2360 minid = listPhi.index(min(listPhi))
2360 minid = listPhi.index(min(listPhi))
2361
2361
2362 rango = list(range(len(phi)))
2362 rango = list(range(len(phi)))
2363 # rango = numpy.delete(rango,maxid)
2363 # rango = numpy.delete(rango,maxid)
2364
2364
2365 heiRang1 = heiRang*math.cos(phi[maxid])
2365 heiRang1 = heiRang*math.cos(phi[maxid])
2366 heiRangAux = heiRang*math.cos(phi[minid])
2366 heiRangAux = heiRang*math.cos(phi[minid])
2367 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2367 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2368 heiRang1 = numpy.delete(heiRang1,indOut)
2368 heiRang1 = numpy.delete(heiRang1,indOut)
2369
2369
2370 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2370 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2371 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2371 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2372
2372
2373 for i in rango:
2373 for i in rango:
2374 x = heiRang*math.cos(phi[i])
2374 x = heiRang*math.cos(phi[i])
2375 y1 = velRadial[i,:]
2375 y1 = velRadial[i,:]
2376 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2376 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2377
2377
2378 x1 = heiRang1
2378 x1 = heiRang1
2379 y11 = f1(x1)
2379 y11 = f1(x1)
2380
2380
2381 y2 = SNR[i,:]
2381 y2 = SNR[i,:]
2382 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2382 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2383 y21 = f2(x1)
2383 y21 = f2(x1)
2384
2384
2385 velRadial1[i,:] = y11
2385 velRadial1[i,:] = y11
2386 SNR1[i,:] = y21
2386 SNR1[i,:] = y21
2387
2387
2388 return heiRang1, velRadial1, SNR1
2388 return heiRang1, velRadial1, SNR1
2389
2389
2390 def run(self, dataOut, zenith, zenithCorrection):
2390 def run(self, dataOut, zenith, zenithCorrection):
2391 heiRang = dataOut.heightList
2391 heiRang = dataOut.heightList
2392 velRadial = dataOut.data_param[:,3,:]
2392 velRadial = dataOut.data_param[:,3,:]
2393 SNR = dataOut.data_snr
2393 SNR = dataOut.data_snr
2394
2394
2395 zenith = numpy.array(zenith)
2395 zenith = numpy.array(zenith)
2396 zenith -= zenithCorrection
2396 zenith -= zenithCorrection
2397 zenith *= numpy.pi/180
2397 zenith *= numpy.pi/180
2398
2398
2399 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2399 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2400
2400
2401 alp = zenith[0]
2401 alp = zenith[0]
2402 bet = zenith[1]
2402 bet = zenith[1]
2403
2403
2404 w_w = velRadial1[0,:]
2404 w_w = velRadial1[0,:]
2405 w_e = velRadial1[1,:]
2405 w_e = velRadial1[1,:]
2406
2406
2407 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2407 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2408 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2408 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2409
2409
2410 winds = numpy.vstack((u,w))
2410 winds = numpy.vstack((u,w))
2411
2411
2412 dataOut.heightList = heiRang1
2412 dataOut.heightList = heiRang1
2413 dataOut.data_output = winds
2413 dataOut.data_output = winds
2414 dataOut.data_snr = SNR1
2414 dataOut.data_snr = SNR1
2415
2415
2416 dataOut.utctimeInit = dataOut.utctime
2416 dataOut.utctimeInit = dataOut.utctime
2417 dataOut.outputInterval = dataOut.timeInterval
2417 dataOut.outputInterval = dataOut.timeInterval
2418 return
2418 return
2419
2419
2420 #--------------- Non Specular Meteor ----------------
2420 #--------------- Non Specular Meteor ----------------
2421
2421
2422 class NonSpecularMeteorDetection(Operation):
2422 class NonSpecularMeteorDetection(Operation):
2423
2423
2424 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2424 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2425 data_acf = dataOut.data_pre[0]
2425 data_acf = dataOut.data_pre[0]
2426 data_ccf = dataOut.data_pre[1]
2426 data_ccf = dataOut.data_pre[1]
2427 pairsList = dataOut.groupList[1]
2427 pairsList = dataOut.groupList[1]
2428
2428
2429 lamb = dataOut.C/dataOut.frequency
2429 lamb = dataOut.C/dataOut.frequency
2430 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2430 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2431 paramInterval = dataOut.paramInterval
2431 paramInterval = dataOut.paramInterval
2432
2432
2433 nChannels = data_acf.shape[0]
2433 nChannels = data_acf.shape[0]
2434 nLags = data_acf.shape[1]
2434 nLags = data_acf.shape[1]
2435 nProfiles = data_acf.shape[2]
2435 nProfiles = data_acf.shape[2]
2436 nHeights = dataOut.nHeights
2436 nHeights = dataOut.nHeights
2437 nCohInt = dataOut.nCohInt
2437 nCohInt = dataOut.nCohInt
2438 sec = numpy.round(nProfiles/dataOut.paramInterval)
2438 sec = numpy.round(nProfiles/dataOut.paramInterval)
2439 heightList = dataOut.heightList
2439 heightList = dataOut.heightList
2440 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2440 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2441 utctime = dataOut.utctime
2441 utctime = dataOut.utctime
2442
2442
2443 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2443 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2444
2444
2445 #------------------------ SNR --------------------------------------
2445 #------------------------ SNR --------------------------------------
2446 power = data_acf[:,0,:,:].real
2446 power = data_acf[:,0,:,:].real
2447 noise = numpy.zeros(nChannels)
2447 noise = numpy.zeros(nChannels)
2448 SNR = numpy.zeros(power.shape)
2448 SNR = numpy.zeros(power.shape)
2449 for i in range(nChannels):
2449 for i in range(nChannels):
2450 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2450 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2451 SNR[i] = (power[i]-noise[i])/noise[i]
2451 SNR[i] = (power[i]-noise[i])/noise[i]
2452 SNRm = numpy.nanmean(SNR, axis = 0)
2452 SNRm = numpy.nanmean(SNR, axis = 0)
2453 SNRdB = 10*numpy.log10(SNR)
2453 SNRdB = 10*numpy.log10(SNR)
2454
2454
2455 if mode == 'SA':
2455 if mode == 'SA':
2456 dataOut.groupList = dataOut.groupList[1]
2456 dataOut.groupList = dataOut.groupList[1]
2457 nPairs = data_ccf.shape[0]
2457 nPairs = data_ccf.shape[0]
2458 #---------------------- Coherence and Phase --------------------------
2458 #---------------------- Coherence and Phase --------------------------
2459 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2459 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2460 # phase1 = numpy.copy(phase)
2460 # phase1 = numpy.copy(phase)
2461 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2461 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2462
2462
2463 for p in range(nPairs):
2463 for p in range(nPairs):
2464 ch0 = pairsList[p][0]
2464 ch0 = pairsList[p][0]
2465 ch1 = pairsList[p][1]
2465 ch1 = pairsList[p][1]
2466 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2466 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2467 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2467 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2468 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2468 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2469 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2469 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2470 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2470 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2471 coh = numpy.nanmax(coh1, axis = 0)
2471 coh = numpy.nanmax(coh1, axis = 0)
2472 # struc = numpy.ones((5,1))
2472 # struc = numpy.ones((5,1))
2473 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2473 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2474 #---------------------- Radial Velocity ----------------------------
2474 #---------------------- Radial Velocity ----------------------------
2475 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2475 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2476 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2476 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2477
2477
2478 if allData:
2478 if allData:
2479 boolMetFin = ~numpy.isnan(SNRm)
2479 boolMetFin = ~numpy.isnan(SNRm)
2480 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2480 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2481 else:
2481 else:
2482 #------------------------ Meteor mask ---------------------------------
2482 #------------------------ Meteor mask ---------------------------------
2483 # #SNR mask
2483 # #SNR mask
2484 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2484 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2485 #
2485 #
2486 # #Erase small objects
2486 # #Erase small objects
2487 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2487 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2488 #
2488 #
2489 # auxEEJ = numpy.sum(boolMet1,axis=0)
2489 # auxEEJ = numpy.sum(boolMet1,axis=0)
2490 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2490 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2491 # indEEJ = numpy.where(indOver)[0]
2491 # indEEJ = numpy.where(indOver)[0]
2492 # indNEEJ = numpy.where(~indOver)[0]
2492 # indNEEJ = numpy.where(~indOver)[0]
2493 #
2493 #
2494 # boolMetFin = boolMet1
2494 # boolMetFin = boolMet1
2495 #
2495 #
2496 # if indEEJ.size > 0:
2496 # if indEEJ.size > 0:
2497 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2497 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2498 #
2498 #
2499 # boolMet2 = coh > cohThresh
2499 # boolMet2 = coh > cohThresh
2500 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2500 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2501 #
2501 #
2502 # #Final Meteor mask
2502 # #Final Meteor mask
2503 # boolMetFin = boolMet1|boolMet2
2503 # boolMetFin = boolMet1|boolMet2
2504
2504
2505 #Coherence mask
2505 #Coherence mask
2506 boolMet1 = coh > 0.75
2506 boolMet1 = coh > 0.75
2507 struc = numpy.ones((30,1))
2507 struc = numpy.ones((30,1))
2508 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2508 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2509
2509
2510 #Derivative mask
2510 #Derivative mask
2511 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2511 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2512 boolMet2 = derPhase < 0.2
2512 boolMet2 = derPhase < 0.2
2513 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2513 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2514 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2514 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2515 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2515 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2516 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2516 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2517 # #Final mask
2517 # #Final mask
2518 # boolMetFin = boolMet2
2518 # boolMetFin = boolMet2
2519 boolMetFin = boolMet1&boolMet2
2519 boolMetFin = boolMet1&boolMet2
2520 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2520 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2521 #Creating data_param
2521 #Creating data_param
2522 coordMet = numpy.where(boolMetFin)
2522 coordMet = numpy.where(boolMetFin)
2523
2523
2524 tmet = coordMet[0]
2524 tmet = coordMet[0]
2525 hmet = coordMet[1]
2525 hmet = coordMet[1]
2526
2526
2527 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2527 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2528 data_param[:,0] = utctime
2528 data_param[:,0] = utctime
2529 data_param[:,1] = tmet
2529 data_param[:,1] = tmet
2530 data_param[:,2] = hmet
2530 data_param[:,2] = hmet
2531 data_param[:,3] = SNRm[tmet,hmet]
2531 data_param[:,3] = SNRm[tmet,hmet]
2532 data_param[:,4] = velRad[tmet,hmet]
2532 data_param[:,4] = velRad[tmet,hmet]
2533 data_param[:,5] = coh[tmet,hmet]
2533 data_param[:,5] = coh[tmet,hmet]
2534 data_param[:,6:] = phase[:,tmet,hmet].T
2534 data_param[:,6:] = phase[:,tmet,hmet].T
2535
2535
2536 elif mode == 'DBS':
2536 elif mode == 'DBS':
2537 dataOut.groupList = numpy.arange(nChannels)
2537 dataOut.groupList = numpy.arange(nChannels)
2538
2538
2539 #Radial Velocities
2539 #Radial Velocities
2540 phase = numpy.angle(data_acf[:,1,:,:])
2540 phase = numpy.angle(data_acf[:,1,:,:])
2541 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2541 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2542 velRad = phase*lamb/(4*numpy.pi*tSamp)
2542 velRad = phase*lamb/(4*numpy.pi*tSamp)
2543
2543
2544 #Spectral width
2544 #Spectral width
2545 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2545 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2546 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2546 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2547 acf1 = data_acf[:,1,:,:]
2547 acf1 = data_acf[:,1,:,:]
2548 acf2 = data_acf[:,2,:,:]
2548 acf2 = data_acf[:,2,:,:]
2549
2549
2550 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2550 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2551 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2551 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2552 if allData:
2552 if allData:
2553 boolMetFin = ~numpy.isnan(SNRdB)
2553 boolMetFin = ~numpy.isnan(SNRdB)
2554 else:
2554 else:
2555 #SNR
2555 #SNR
2556 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2556 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2557 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2557 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2558
2558
2559 #Radial velocity
2559 #Radial velocity
2560 boolMet2 = numpy.abs(velRad) < 20
2560 boolMet2 = numpy.abs(velRad) < 20
2561 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2561 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2562
2562
2563 #Spectral Width
2563 #Spectral Width
2564 boolMet3 = spcWidth < 30
2564 boolMet3 = spcWidth < 30
2565 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2565 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2566 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2566 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2567 boolMetFin = boolMet1&boolMet2&boolMet3
2567 boolMetFin = boolMet1&boolMet2&boolMet3
2568
2568
2569 #Creating data_param
2569 #Creating data_param
2570 coordMet = numpy.where(boolMetFin)
2570 coordMet = numpy.where(boolMetFin)
2571
2571
2572 cmet = coordMet[0]
2572 cmet = coordMet[0]
2573 tmet = coordMet[1]
2573 tmet = coordMet[1]
2574 hmet = coordMet[2]
2574 hmet = coordMet[2]
2575
2575
2576 data_param = numpy.zeros((tmet.size, 7))
2576 data_param = numpy.zeros((tmet.size, 7))
2577 data_param[:,0] = utctime
2577 data_param[:,0] = utctime
2578 data_param[:,1] = cmet
2578 data_param[:,1] = cmet
2579 data_param[:,2] = tmet
2579 data_param[:,2] = tmet
2580 data_param[:,3] = hmet
2580 data_param[:,3] = hmet
2581 data_param[:,4] = SNR[cmet,tmet,hmet].T
2581 data_param[:,4] = SNR[cmet,tmet,hmet].T
2582 data_param[:,5] = velRad[cmet,tmet,hmet].T
2582 data_param[:,5] = velRad[cmet,tmet,hmet].T
2583 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2583 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2584
2584
2585 # self.dataOut.data_param = data_int
2585 # self.dataOut.data_param = data_int
2586 if len(data_param) == 0:
2586 if len(data_param) == 0:
2587 dataOut.flagNoData = True
2587 dataOut.flagNoData = True
2588 else:
2588 else:
2589 dataOut.data_param = data_param
2589 dataOut.data_param = data_param
2590
2590
2591 def __erase_small(self, binArray, threshX, threshY):
2591 def __erase_small(self, binArray, threshX, threshY):
2592 labarray, numfeat = ndimage.measurements.label(binArray)
2592 labarray, numfeat = ndimage.measurements.label(binArray)
2593 binArray1 = numpy.copy(binArray)
2593 binArray1 = numpy.copy(binArray)
2594
2594
2595 for i in range(1,numfeat + 1):
2595 for i in range(1,numfeat + 1):
2596 auxBin = (labarray==i)
2596 auxBin = (labarray==i)
2597 auxSize = auxBin.sum()
2597 auxSize = auxBin.sum()
2598
2598
2599 x,y = numpy.where(auxBin)
2599 x,y = numpy.where(auxBin)
2600 widthX = x.max() - x.min()
2600 widthX = x.max() - x.min()
2601 widthY = y.max() - y.min()
2601 widthY = y.max() - y.min()
2602
2602
2603 #width X: 3 seg -> 12.5*3
2603 #width X: 3 seg -> 12.5*3
2604 #width Y:
2604 #width Y:
2605
2605
2606 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2606 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2607 binArray1[auxBin] = False
2607 binArray1[auxBin] = False
2608
2608
2609 return binArray1
2609 return binArray1
2610
2610
2611 #--------------- Specular Meteor ----------------
2611 #--------------- Specular Meteor ----------------
2612
2612
2613 class SMDetection(Operation):
2613 class SMDetection(Operation):
2614 '''
2614 '''
2615 Function DetectMeteors()
2615 Function DetectMeteors()
2616 Project developed with paper:
2616 Project developed with paper:
2617 HOLDSWORTH ET AL. 2004
2617 HOLDSWORTH ET AL. 2004
2618
2618
2619 Input:
2619 Input:
2620 self.dataOut.data_pre
2620 self.dataOut.data_pre
2621
2621
2622 centerReceiverIndex: From the channels, which is the center receiver
2622 centerReceiverIndex: From the channels, which is the center receiver
2623
2623
2624 hei_ref: Height reference for the Beacon signal extraction
2624 hei_ref: Height reference for the Beacon signal extraction
2625 tauindex:
2625 tauindex:
2626 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2626 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2627
2627
2628 cohDetection: Whether to user Coherent detection or not
2628 cohDetection: Whether to user Coherent detection or not
2629 cohDet_timeStep: Coherent Detection calculation time step
2629 cohDet_timeStep: Coherent Detection calculation time step
2630 cohDet_thresh: Coherent Detection phase threshold to correct phases
2630 cohDet_thresh: Coherent Detection phase threshold to correct phases
2631
2631
2632 noise_timeStep: Noise calculation time step
2632 noise_timeStep: Noise calculation time step
2633 noise_multiple: Noise multiple to define signal threshold
2633 noise_multiple: Noise multiple to define signal threshold
2634
2634
2635 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2635 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2636 multDet_rangeLimit: Multiple Detection Removal range limit in km
2636 multDet_rangeLimit: Multiple Detection Removal range limit in km
2637
2637
2638 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2638 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2639 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2639 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2640
2640
2641 hmin: Minimum Height of the meteor to use it in the further wind estimations
2641 hmin: Minimum Height of the meteor to use it in the further wind estimations
2642 hmax: Maximum Height of the meteor to use it in the further wind estimations
2642 hmax: Maximum Height of the meteor to use it in the further wind estimations
2643 azimuth: Azimuth angle correction
2643 azimuth: Azimuth angle correction
2644
2644
2645 Affected:
2645 Affected:
2646 self.dataOut.data_param
2646 self.dataOut.data_param
2647
2647
2648 Rejection Criteria (Errors):
2648 Rejection Criteria (Errors):
2649 0: No error; analysis OK
2649 0: No error; analysis OK
2650 1: SNR < SNR threshold
2650 1: SNR < SNR threshold
2651 2: angle of arrival (AOA) ambiguously determined
2651 2: angle of arrival (AOA) ambiguously determined
2652 3: AOA estimate not feasible
2652 3: AOA estimate not feasible
2653 4: Large difference in AOAs obtained from different antenna baselines
2653 4: Large difference in AOAs obtained from different antenna baselines
2654 5: echo at start or end of time series
2654 5: echo at start or end of time series
2655 6: echo less than 5 examples long; too short for analysis
2655 6: echo less than 5 examples long; too short for analysis
2656 7: echo rise exceeds 0.3s
2656 7: echo rise exceeds 0.3s
2657 8: echo decay time less than twice rise time
2657 8: echo decay time less than twice rise time
2658 9: large power level before echo
2658 9: large power level before echo
2659 10: large power level after echo
2659 10: large power level after echo
2660 11: poor fit to amplitude for estimation of decay time
2660 11: poor fit to amplitude for estimation of decay time
2661 12: poor fit to CCF phase variation for estimation of radial drift velocity
2661 12: poor fit to CCF phase variation for estimation of radial drift velocity
2662 13: height unresolvable echo: not valid height within 70 to 110 km
2662 13: height unresolvable echo: not valid height within 70 to 110 km
2663 14: height ambiguous echo: more then one possible height within 70 to 110 km
2663 14: height ambiguous echo: more then one possible height within 70 to 110 km
2664 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2664 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2665 16: oscilatory echo, indicating event most likely not an underdense echo
2665 16: oscilatory echo, indicating event most likely not an underdense echo
2666
2666
2667 17: phase difference in meteor Reestimation
2667 17: phase difference in meteor Reestimation
2668
2668
2669 Data Storage:
2669 Data Storage:
2670 Meteors for Wind Estimation (8):
2670 Meteors for Wind Estimation (8):
2671 Utc Time | Range Height
2671 Utc Time | Range Height
2672 Azimuth Zenith errorCosDir
2672 Azimuth Zenith errorCosDir
2673 VelRad errorVelRad
2673 VelRad errorVelRad
2674 Phase0 Phase1 Phase2 Phase3
2674 Phase0 Phase1 Phase2 Phase3
2675 TypeError
2675 TypeError
2676
2676
2677 '''
2677 '''
2678
2678
2679 def run(self, dataOut, hei_ref = None, tauindex = 0,
2679 def run(self, dataOut, hei_ref = None, tauindex = 0,
2680 phaseOffsets = None,
2680 phaseOffsets = None,
2681 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2681 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2682 noise_timeStep = 4, noise_multiple = 4,
2682 noise_timeStep = 4, noise_multiple = 4,
2683 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2683 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2684 phaseThresh = 20, SNRThresh = 5,
2684 phaseThresh = 20, SNRThresh = 5,
2685 hmin = 50, hmax=150, azimuth = 0,
2685 hmin = 50, hmax=150, azimuth = 0,
2686 channelPositions = None) :
2686 channelPositions = None) :
2687
2687
2688
2688
2689 #Getting Pairslist
2689 #Getting Pairslist
2690 if channelPositions is None:
2690 if channelPositions is None:
2691 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2691 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2692 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2692 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2693 meteorOps = SMOperations()
2693 meteorOps = SMOperations()
2694 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2694 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2695 heiRang = dataOut.heightList
2695 heiRang = dataOut.heightList
2696 #Get Beacon signal - No Beacon signal anymore
2696 #Get Beacon signal - No Beacon signal anymore
2697 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2697 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2698 #
2698 #
2699 # if hei_ref != None:
2699 # if hei_ref != None:
2700 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2700 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2701 #
2701 #
2702
2702
2703
2703
2704 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2704 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2705 # see if the user put in pre defined phase shifts
2705 # see if the user put in pre defined phase shifts
2706 voltsPShift = dataOut.data_pre.copy()
2706 voltsPShift = dataOut.data_pre.copy()
2707
2707
2708 # if predefinedPhaseShifts != None:
2708 # if predefinedPhaseShifts != None:
2709 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2709 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2710 #
2710 #
2711 # # elif beaconPhaseShifts:
2711 # # elif beaconPhaseShifts:
2712 # # #get hardware phase shifts using beacon signal
2712 # # #get hardware phase shifts using beacon signal
2713 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2713 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2714 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2714 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2715 #
2715 #
2716 # else:
2716 # else:
2717 # hardwarePhaseShifts = numpy.zeros(5)
2717 # hardwarePhaseShifts = numpy.zeros(5)
2718 #
2718 #
2719 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2719 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2720 # for i in range(self.dataOut.data_pre.shape[0]):
2720 # for i in range(self.dataOut.data_pre.shape[0]):
2721 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2721 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2722
2722
2723 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2723 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2724
2724
2725 #Remove DC
2725 #Remove DC
2726 voltsDC = numpy.mean(voltsPShift,1)
2726 voltsDC = numpy.mean(voltsPShift,1)
2727 voltsDC = numpy.mean(voltsDC,1)
2727 voltsDC = numpy.mean(voltsDC,1)
2728 for i in range(voltsDC.shape[0]):
2728 for i in range(voltsDC.shape[0]):
2729 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2729 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2730
2730
2731 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2731 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2732 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2732 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2733
2733
2734 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2734 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2735 #Coherent Detection
2735 #Coherent Detection
2736 if cohDetection:
2736 if cohDetection:
2737 #use coherent detection to get the net power
2737 #use coherent detection to get the net power
2738 cohDet_thresh = cohDet_thresh*numpy.pi/180
2738 cohDet_thresh = cohDet_thresh*numpy.pi/180
2739 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2739 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2740
2740
2741 #Non-coherent detection!
2741 #Non-coherent detection!
2742 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2742 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2743 #********** END OF COH/NON-COH POWER CALCULATION**********************
2743 #********** END OF COH/NON-COH POWER CALCULATION**********************
2744
2744
2745 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2745 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2746 #Get noise
2746 #Get noise
2747 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2747 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2748 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2748 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2749 #Get signal threshold
2749 #Get signal threshold
2750 signalThresh = noise_multiple*noise
2750 signalThresh = noise_multiple*noise
2751 #Meteor echoes detection
2751 #Meteor echoes detection
2752 listMeteors = self.__findMeteors(powerNet, signalThresh)
2752 listMeteors = self.__findMeteors(powerNet, signalThresh)
2753 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2753 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2754
2754
2755 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2755 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2756 #Parameters
2756 #Parameters
2757 heiRange = dataOut.heightList
2757 heiRange = dataOut.heightList
2758 rangeInterval = heiRange[1] - heiRange[0]
2758 rangeInterval = heiRange[1] - heiRange[0]
2759 rangeLimit = multDet_rangeLimit/rangeInterval
2759 rangeLimit = multDet_rangeLimit/rangeInterval
2760 timeLimit = multDet_timeLimit/dataOut.timeInterval
2760 timeLimit = multDet_timeLimit/dataOut.timeInterval
2761 #Multiple detection removals
2761 #Multiple detection removals
2762 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2762 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2763 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2763 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2764
2764
2765 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2765 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2766 #Parameters
2766 #Parameters
2767 phaseThresh = phaseThresh*numpy.pi/180
2767 phaseThresh = phaseThresh*numpy.pi/180
2768 thresh = [phaseThresh, noise_multiple, SNRThresh]
2768 thresh = [phaseThresh, noise_multiple, SNRThresh]
2769 #Meteor reestimation (Errors N 1, 6, 12, 17)
2769 #Meteor reestimation (Errors N 1, 6, 12, 17)
2770 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2770 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2771 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2771 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2772 #Estimation of decay times (Errors N 7, 8, 11)
2772 #Estimation of decay times (Errors N 7, 8, 11)
2773 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2773 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2774 #******************* END OF METEOR REESTIMATION *******************
2774 #******************* END OF METEOR REESTIMATION *******************
2775
2775
2776 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2776 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2777 #Calculating Radial Velocity (Error N 15)
2777 #Calculating Radial Velocity (Error N 15)
2778 radialStdThresh = 10
2778 radialStdThresh = 10
2779 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2779 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2780
2780
2781 if len(listMeteors4) > 0:
2781 if len(listMeteors4) > 0:
2782 #Setting New Array
2782 #Setting New Array
2783 date = dataOut.utctime
2783 date = dataOut.utctime
2784 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2784 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2785
2785
2786 #Correcting phase offset
2786 #Correcting phase offset
2787 if phaseOffsets != None:
2787 if phaseOffsets != None:
2788 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2788 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2789 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2789 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2790
2790
2791 #Second Pairslist
2791 #Second Pairslist
2792 pairsList = []
2792 pairsList = []
2793 pairx = (0,1)
2793 pairx = (0,1)
2794 pairy = (2,3)
2794 pairy = (2,3)
2795 pairsList.append(pairx)
2795 pairsList.append(pairx)
2796 pairsList.append(pairy)
2796 pairsList.append(pairy)
2797
2797
2798 jph = numpy.array([0,0,0,0])
2798 jph = numpy.array([0,0,0,0])
2799 h = (hmin,hmax)
2799 h = (hmin,hmax)
2800 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2800 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2801
2801
2802 # #Calculate AOA (Error N 3, 4)
2802 # #Calculate AOA (Error N 3, 4)
2803 # #JONES ET AL. 1998
2803 # #JONES ET AL. 1998
2804 # error = arrayParameters[:,-1]
2804 # error = arrayParameters[:,-1]
2805 # AOAthresh = numpy.pi/8
2805 # AOAthresh = numpy.pi/8
2806 # phases = -arrayParameters[:,9:13]
2806 # phases = -arrayParameters[:,9:13]
2807 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2807 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2808 #
2808 #
2809 # #Calculate Heights (Error N 13 and 14)
2809 # #Calculate Heights (Error N 13 and 14)
2810 # error = arrayParameters[:,-1]
2810 # error = arrayParameters[:,-1]
2811 # Ranges = arrayParameters[:,2]
2811 # Ranges = arrayParameters[:,2]
2812 # zenith = arrayParameters[:,5]
2812 # zenith = arrayParameters[:,5]
2813 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2813 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2814 # error = arrayParameters[:,-1]
2814 # error = arrayParameters[:,-1]
2815 #********************* END OF PARAMETERS CALCULATION **************************
2815 #********************* END OF PARAMETERS CALCULATION **************************
2816
2816
2817 #***************************+ PASS DATA TO NEXT STEP **********************
2817 #***************************+ PASS DATA TO NEXT STEP **********************
2818 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2818 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2819 dataOut.data_param = arrayParameters
2819 dataOut.data_param = arrayParameters
2820
2820
2821 if arrayParameters is None:
2821 if arrayParameters is None:
2822 dataOut.flagNoData = True
2822 dataOut.flagNoData = True
2823 else:
2823 else:
2824 dataOut.flagNoData = True
2824 dataOut.flagNoData = True
2825
2825
2826 return
2826 return
2827
2827
2828 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2828 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2829
2829
2830 minIndex = min(newheis[0])
2830 minIndex = min(newheis[0])
2831 maxIndex = max(newheis[0])
2831 maxIndex = max(newheis[0])
2832
2832
2833 voltage = voltage0[:,:,minIndex:maxIndex+1]
2833 voltage = voltage0[:,:,minIndex:maxIndex+1]
2834 nLength = voltage.shape[1]/n
2834 nLength = voltage.shape[1]/n
2835 nMin = 0
2835 nMin = 0
2836 nMax = 0
2836 nMax = 0
2837 phaseOffset = numpy.zeros((len(pairslist),n))
2837 phaseOffset = numpy.zeros((len(pairslist),n))
2838
2838
2839 for i in range(n):
2839 for i in range(n):
2840 nMax += nLength
2840 nMax += nLength
2841 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2841 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2842 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2842 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2843 phaseOffset[:,i] = phaseCCF.transpose()
2843 phaseOffset[:,i] = phaseCCF.transpose()
2844 nMin = nMax
2844 nMin = nMax
2845 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2845 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2846
2846
2847 #Remove Outliers
2847 #Remove Outliers
2848 factor = 2
2848 factor = 2
2849 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2849 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2850 dw = numpy.std(wt,axis = 1)
2850 dw = numpy.std(wt,axis = 1)
2851 dw = dw.reshape((dw.size,1))
2851 dw = dw.reshape((dw.size,1))
2852 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2852 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2853 phaseOffset[ind] = numpy.nan
2853 phaseOffset[ind] = numpy.nan
2854 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2854 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2855
2855
2856 return phaseOffset
2856 return phaseOffset
2857
2857
2858 def __shiftPhase(self, data, phaseShift):
2858 def __shiftPhase(self, data, phaseShift):
2859 #this will shift the phase of a complex number
2859 #this will shift the phase of a complex number
2860 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2860 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2861 return dataShifted
2861 return dataShifted
2862
2862
2863 def __estimatePhaseDifference(self, array, pairslist):
2863 def __estimatePhaseDifference(self, array, pairslist):
2864 nChannel = array.shape[0]
2864 nChannel = array.shape[0]
2865 nHeights = array.shape[2]
2865 nHeights = array.shape[2]
2866 numPairs = len(pairslist)
2866 numPairs = len(pairslist)
2867 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2867 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2868 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2868 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2869
2869
2870 #Correct phases
2870 #Correct phases
2871 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2871 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2872 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2872 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2873
2873
2874 if indDer[0].shape[0] > 0:
2874 if indDer[0].shape[0] > 0:
2875 for i in range(indDer[0].shape[0]):
2875 for i in range(indDer[0].shape[0]):
2876 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2876 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2877 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2877 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2878
2878
2879 # for j in range(numSides):
2879 # for j in range(numSides):
2880 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2880 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2881 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2881 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2882 #
2882 #
2883 #Linear
2883 #Linear
2884 phaseInt = numpy.zeros((numPairs,1))
2884 phaseInt = numpy.zeros((numPairs,1))
2885 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2885 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2886 for j in range(numPairs):
2886 for j in range(numPairs):
2887 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2887 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2888 phaseInt[j] = fit[1]
2888 phaseInt[j] = fit[1]
2889 #Phase Differences
2889 #Phase Differences
2890 phaseDiff = phaseInt - phaseCCF[:,2,:]
2890 phaseDiff = phaseInt - phaseCCF[:,2,:]
2891 phaseArrival = phaseInt.reshape(phaseInt.size)
2891 phaseArrival = phaseInt.reshape(phaseInt.size)
2892
2892
2893 #Dealias
2893 #Dealias
2894 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2894 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2895 # indAlias = numpy.where(phaseArrival > numpy.pi)
2895 # indAlias = numpy.where(phaseArrival > numpy.pi)
2896 # phaseArrival[indAlias] -= 2*numpy.pi
2896 # phaseArrival[indAlias] -= 2*numpy.pi
2897 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2897 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2898 # phaseArrival[indAlias] += 2*numpy.pi
2898 # phaseArrival[indAlias] += 2*numpy.pi
2899
2899
2900 return phaseDiff, phaseArrival
2900 return phaseDiff, phaseArrival
2901
2901
2902 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2902 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2903 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2903 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2904 #find the phase shifts of each channel over 1 second intervals
2904 #find the phase shifts of each channel over 1 second intervals
2905 #only look at ranges below the beacon signal
2905 #only look at ranges below the beacon signal
2906 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2906 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2907 numBlocks = int(volts.shape[1]/numProfPerBlock)
2907 numBlocks = int(volts.shape[1]/numProfPerBlock)
2908 numHeights = volts.shape[2]
2908 numHeights = volts.shape[2]
2909 nChannel = volts.shape[0]
2909 nChannel = volts.shape[0]
2910 voltsCohDet = volts.copy()
2910 voltsCohDet = volts.copy()
2911
2911
2912 pairsarray = numpy.array(pairslist)
2912 pairsarray = numpy.array(pairslist)
2913 indSides = pairsarray[:,1]
2913 indSides = pairsarray[:,1]
2914 # indSides = numpy.array(range(nChannel))
2914 # indSides = numpy.array(range(nChannel))
2915 # indSides = numpy.delete(indSides, indCenter)
2915 # indSides = numpy.delete(indSides, indCenter)
2916 #
2916 #
2917 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2917 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2918 listBlocks = numpy.array_split(volts, numBlocks, 1)
2918 listBlocks = numpy.array_split(volts, numBlocks, 1)
2919
2919
2920 startInd = 0
2920 startInd = 0
2921 endInd = 0
2921 endInd = 0
2922
2922
2923 for i in range(numBlocks):
2923 for i in range(numBlocks):
2924 startInd = endInd
2924 startInd = endInd
2925 endInd = endInd + listBlocks[i].shape[1]
2925 endInd = endInd + listBlocks[i].shape[1]
2926
2926
2927 arrayBlock = listBlocks[i]
2927 arrayBlock = listBlocks[i]
2928 # arrayBlockCenter = listCenter[i]
2928 # arrayBlockCenter = listCenter[i]
2929
2929
2930 #Estimate the Phase Difference
2930 #Estimate the Phase Difference
2931 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2931 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2932 #Phase Difference RMS
2932 #Phase Difference RMS
2933 arrayPhaseRMS = numpy.abs(phaseDiff)
2933 arrayPhaseRMS = numpy.abs(phaseDiff)
2934 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2934 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2935 indPhase = numpy.where(phaseRMSaux==4)
2935 indPhase = numpy.where(phaseRMSaux==4)
2936 #Shifting
2936 #Shifting
2937 if indPhase[0].shape[0] > 0:
2937 if indPhase[0].shape[0] > 0:
2938 for j in range(indSides.size):
2938 for j in range(indSides.size):
2939 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2939 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2940 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2940 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2941
2941
2942 return voltsCohDet
2942 return voltsCohDet
2943
2943
2944 def __calculateCCF(self, volts, pairslist ,laglist):
2944 def __calculateCCF(self, volts, pairslist ,laglist):
2945
2945
2946 nHeights = volts.shape[2]
2946 nHeights = volts.shape[2]
2947 nPoints = volts.shape[1]
2947 nPoints = volts.shape[1]
2948 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2948 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2949
2949
2950 for i in range(len(pairslist)):
2950 for i in range(len(pairslist)):
2951 volts1 = volts[pairslist[i][0]]
2951 volts1 = volts[pairslist[i][0]]
2952 volts2 = volts[pairslist[i][1]]
2952 volts2 = volts[pairslist[i][1]]
2953
2953
2954 for t in range(len(laglist)):
2954 for t in range(len(laglist)):
2955 idxT = laglist[t]
2955 idxT = laglist[t]
2956 if idxT >= 0:
2956 if idxT >= 0:
2957 vStacked = numpy.vstack((volts2[idxT:,:],
2957 vStacked = numpy.vstack((volts2[idxT:,:],
2958 numpy.zeros((idxT, nHeights),dtype='complex')))
2958 numpy.zeros((idxT, nHeights),dtype='complex')))
2959 else:
2959 else:
2960 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2960 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2961 volts2[:(nPoints + idxT),:]))
2961 volts2[:(nPoints + idxT),:]))
2962 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2962 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2963
2963
2964 vStacked = None
2964 vStacked = None
2965 return voltsCCF
2965 return voltsCCF
2966
2966
2967 def __getNoise(self, power, timeSegment, timeInterval):
2967 def __getNoise(self, power, timeSegment, timeInterval):
2968 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2968 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2969 numBlocks = int(power.shape[0]/numProfPerBlock)
2969 numBlocks = int(power.shape[0]/numProfPerBlock)
2970 numHeights = power.shape[1]
2970 numHeights = power.shape[1]
2971
2971
2972 listPower = numpy.array_split(power, numBlocks, 0)
2972 listPower = numpy.array_split(power, numBlocks, 0)
2973 noise = numpy.zeros((power.shape[0], power.shape[1]))
2973 noise = numpy.zeros((power.shape[0], power.shape[1]))
2974 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2974 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2975
2975
2976 startInd = 0
2976 startInd = 0
2977 endInd = 0
2977 endInd = 0
2978
2978
2979 for i in range(numBlocks): #split por canal
2979 for i in range(numBlocks): #split por canal
2980 startInd = endInd
2980 startInd = endInd
2981 endInd = endInd + listPower[i].shape[0]
2981 endInd = endInd + listPower[i].shape[0]
2982
2982
2983 arrayBlock = listPower[i]
2983 arrayBlock = listPower[i]
2984 noiseAux = numpy.mean(arrayBlock, 0)
2984 noiseAux = numpy.mean(arrayBlock, 0)
2985 # noiseAux = numpy.median(noiseAux)
2985 # noiseAux = numpy.median(noiseAux)
2986 # noiseAux = numpy.mean(arrayBlock)
2986 # noiseAux = numpy.mean(arrayBlock)
2987 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2987 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2988
2988
2989 noiseAux1 = numpy.mean(arrayBlock)
2989 noiseAux1 = numpy.mean(arrayBlock)
2990 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2990 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2991
2991
2992 return noise, noise1
2992 return noise, noise1
2993
2993
2994 def __findMeteors(self, power, thresh):
2994 def __findMeteors(self, power, thresh):
2995 nProf = power.shape[0]
2995 nProf = power.shape[0]
2996 nHeights = power.shape[1]
2996 nHeights = power.shape[1]
2997 listMeteors = []
2997 listMeteors = []
2998
2998
2999 for i in range(nHeights):
2999 for i in range(nHeights):
3000 powerAux = power[:,i]
3000 powerAux = power[:,i]
3001 threshAux = thresh[:,i]
3001 threshAux = thresh[:,i]
3002
3002
3003 indUPthresh = numpy.where(powerAux > threshAux)[0]
3003 indUPthresh = numpy.where(powerAux > threshAux)[0]
3004 indDNthresh = numpy.where(powerAux <= threshAux)[0]
3004 indDNthresh = numpy.where(powerAux <= threshAux)[0]
3005
3005
3006 j = 0
3006 j = 0
3007
3007
3008 while (j < indUPthresh.size - 2):
3008 while (j < indUPthresh.size - 2):
3009 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
3009 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
3010 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
3010 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
3011 indDNthresh = indDNthresh[indDNAux]
3011 indDNthresh = indDNthresh[indDNAux]
3012
3012
3013 if (indDNthresh.size > 0):
3013 if (indDNthresh.size > 0):
3014 indEnd = indDNthresh[0] - 1
3014 indEnd = indDNthresh[0] - 1
3015 indInit = indUPthresh[j]
3015 indInit = indUPthresh[j]
3016
3016
3017 meteor = powerAux[indInit:indEnd + 1]
3017 meteor = powerAux[indInit:indEnd + 1]
3018 indPeak = meteor.argmax() + indInit
3018 indPeak = meteor.argmax() + indInit
3019 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3019 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
3020
3020
3021 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3021 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
3022 j = numpy.where(indUPthresh == indEnd)[0] + 1
3022 j = numpy.where(indUPthresh == indEnd)[0] + 1
3023 else: j+=1
3023 else: j+=1
3024 else: j+=1
3024 else: j+=1
3025
3025
3026 return listMeteors
3026 return listMeteors
3027
3027
3028 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3028 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
3029
3029
3030 arrayMeteors = numpy.asarray(listMeteors)
3030 arrayMeteors = numpy.asarray(listMeteors)
3031 listMeteors1 = []
3031 listMeteors1 = []
3032
3032
3033 while arrayMeteors.shape[0] > 0:
3033 while arrayMeteors.shape[0] > 0:
3034 FLAs = arrayMeteors[:,4]
3034 FLAs = arrayMeteors[:,4]
3035 maxFLA = FLAs.argmax()
3035 maxFLA = FLAs.argmax()
3036 listMeteors1.append(arrayMeteors[maxFLA,:])
3036 listMeteors1.append(arrayMeteors[maxFLA,:])
3037
3037
3038 MeteorInitTime = arrayMeteors[maxFLA,1]
3038 MeteorInitTime = arrayMeteors[maxFLA,1]
3039 MeteorEndTime = arrayMeteors[maxFLA,3]
3039 MeteorEndTime = arrayMeteors[maxFLA,3]
3040 MeteorHeight = arrayMeteors[maxFLA,0]
3040 MeteorHeight = arrayMeteors[maxFLA,0]
3041
3041
3042 #Check neighborhood
3042 #Check neighborhood
3043 maxHeightIndex = MeteorHeight + rangeLimit
3043 maxHeightIndex = MeteorHeight + rangeLimit
3044 minHeightIndex = MeteorHeight - rangeLimit
3044 minHeightIndex = MeteorHeight - rangeLimit
3045 minTimeIndex = MeteorInitTime - timeLimit
3045 minTimeIndex = MeteorInitTime - timeLimit
3046 maxTimeIndex = MeteorEndTime + timeLimit
3046 maxTimeIndex = MeteorEndTime + timeLimit
3047
3047
3048 #Check Heights
3048 #Check Heights
3049 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3049 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3050 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3050 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3051 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3051 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3052
3052
3053 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3053 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3054
3054
3055 return listMeteors1
3055 return listMeteors1
3056
3056
3057 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3057 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3058 numHeights = volts.shape[2]
3058 numHeights = volts.shape[2]
3059 nChannel = volts.shape[0]
3059 nChannel = volts.shape[0]
3060
3060
3061 thresholdPhase = thresh[0]
3061 thresholdPhase = thresh[0]
3062 thresholdNoise = thresh[1]
3062 thresholdNoise = thresh[1]
3063 thresholdDB = float(thresh[2])
3063 thresholdDB = float(thresh[2])
3064
3064
3065 thresholdDB1 = 10**(thresholdDB/10)
3065 thresholdDB1 = 10**(thresholdDB/10)
3066 pairsarray = numpy.array(pairslist)
3066 pairsarray = numpy.array(pairslist)
3067 indSides = pairsarray[:,1]
3067 indSides = pairsarray[:,1]
3068
3068
3069 pairslist1 = list(pairslist)
3069 pairslist1 = list(pairslist)
3070 pairslist1.append((0,1))
3070 pairslist1.append((0,1))
3071 pairslist1.append((3,4))
3071 pairslist1.append((3,4))
3072
3072
3073 listMeteors1 = []
3073 listMeteors1 = []
3074 listPowerSeries = []
3074 listPowerSeries = []
3075 listVoltageSeries = []
3075 listVoltageSeries = []
3076 #volts has the war data
3076 #volts has the war data
3077
3077
3078 if frequency == 30e6:
3078 if frequency == 30e6:
3079 timeLag = 45*10**-3
3079 timeLag = 45*10**-3
3080 else:
3080 else:
3081 timeLag = 15*10**-3
3081 timeLag = 15*10**-3
3082 lag = numpy.ceil(timeLag/timeInterval)
3082 lag = numpy.ceil(timeLag/timeInterval)
3083
3083
3084 for i in range(len(listMeteors)):
3084 for i in range(len(listMeteors)):
3085
3085
3086 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3086 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3087 meteorAux = numpy.zeros(16)
3087 meteorAux = numpy.zeros(16)
3088
3088
3089 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3089 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3090 mHeight = listMeteors[i][0]
3090 mHeight = listMeteors[i][0]
3091 mStart = listMeteors[i][1]
3091 mStart = listMeteors[i][1]
3092 mPeak = listMeteors[i][2]
3092 mPeak = listMeteors[i][2]
3093 mEnd = listMeteors[i][3]
3093 mEnd = listMeteors[i][3]
3094
3094
3095 #get the volt data between the start and end times of the meteor
3095 #get the volt data between the start and end times of the meteor
3096 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3096 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3097 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3097 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3098
3098
3099 #3.6. Phase Difference estimation
3099 #3.6. Phase Difference estimation
3100 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3100 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3101
3101
3102 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3102 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3103 #meteorVolts0.- all Channels, all Profiles
3103 #meteorVolts0.- all Channels, all Profiles
3104 meteorVolts0 = volts[:,:,mHeight]
3104 meteorVolts0 = volts[:,:,mHeight]
3105 meteorThresh = noise[:,mHeight]*thresholdNoise
3105 meteorThresh = noise[:,mHeight]*thresholdNoise
3106 meteorNoise = noise[:,mHeight]
3106 meteorNoise = noise[:,mHeight]
3107 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3107 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3108 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3108 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3109
3109
3110 #Times reestimation
3110 #Times reestimation
3111 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3111 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3112 if mStart1.size > 0:
3112 if mStart1.size > 0:
3113 mStart1 = mStart1[-1] + 1
3113 mStart1 = mStart1[-1] + 1
3114
3114
3115 else:
3115 else:
3116 mStart1 = mPeak
3116 mStart1 = mPeak
3117
3117
3118 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3118 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3119 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3119 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3120 if mEndDecayTime1.size == 0:
3120 if mEndDecayTime1.size == 0:
3121 mEndDecayTime1 = powerNet0.size
3121 mEndDecayTime1 = powerNet0.size
3122 else:
3122 else:
3123 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3123 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3124 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3124 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3125
3125
3126 #meteorVolts1.- all Channels, from start to end
3126 #meteorVolts1.- all Channels, from start to end
3127 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3127 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3128 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3128 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3129 if meteorVolts2.shape[1] == 0:
3129 if meteorVolts2.shape[1] == 0:
3130 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3130 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3131 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3131 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3132 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3132 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3133 ##################### END PARAMETERS REESTIMATION #########################
3133 ##################### END PARAMETERS REESTIMATION #########################
3134
3134
3135 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3135 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3136 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3136 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3137 if meteorVolts2.shape[1] > 0:
3137 if meteorVolts2.shape[1] > 0:
3138 #Phase Difference re-estimation
3138 #Phase Difference re-estimation
3139 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3139 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3140 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3140 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3141 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3141 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3142 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3142 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3143 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3143 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3144
3144
3145 #Phase Difference RMS
3145 #Phase Difference RMS
3146 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3146 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3147 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3147 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3148 #Data from Meteor
3148 #Data from Meteor
3149 mPeak1 = powerNet1.argmax() + mStart1
3149 mPeak1 = powerNet1.argmax() + mStart1
3150 mPeakPower1 = powerNet1.max()
3150 mPeakPower1 = powerNet1.max()
3151 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3151 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3152 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3152 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3153 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3153 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3154 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3154 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3155 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3155 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3156 #Vectorize
3156 #Vectorize
3157 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3157 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3158 meteorAux[7:11] = phaseDiffint[0:4]
3158 meteorAux[7:11] = phaseDiffint[0:4]
3159
3159
3160 #Rejection Criterions
3160 #Rejection Criterions
3161 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3161 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3162 meteorAux[-1] = 17
3162 meteorAux[-1] = 17
3163 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3163 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3164 meteorAux[-1] = 1
3164 meteorAux[-1] = 1
3165
3165
3166
3166
3167 else:
3167 else:
3168 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3168 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3169 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3169 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3170 PowerSeries = 0
3170 PowerSeries = 0
3171
3171
3172 listMeteors1.append(meteorAux)
3172 listMeteors1.append(meteorAux)
3173 listPowerSeries.append(PowerSeries)
3173 listPowerSeries.append(PowerSeries)
3174 listVoltageSeries.append(meteorVolts1)
3174 listVoltageSeries.append(meteorVolts1)
3175
3175
3176 return listMeteors1, listPowerSeries, listVoltageSeries
3176 return listMeteors1, listPowerSeries, listVoltageSeries
3177
3177
3178 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3178 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3179
3179
3180 threshError = 10
3180 threshError = 10
3181 #Depending if it is 30 or 50 MHz
3181 #Depending if it is 30 or 50 MHz
3182 if frequency == 30e6:
3182 if frequency == 30e6:
3183 timeLag = 45*10**-3
3183 timeLag = 45*10**-3
3184 else:
3184 else:
3185 timeLag = 15*10**-3
3185 timeLag = 15*10**-3
3186 lag = numpy.ceil(timeLag/timeInterval)
3186 lag = numpy.ceil(timeLag/timeInterval)
3187
3187
3188 listMeteors1 = []
3188 listMeteors1 = []
3189
3189
3190 for i in range(len(listMeteors)):
3190 for i in range(len(listMeteors)):
3191 meteorPower = listPower[i]
3191 meteorPower = listPower[i]
3192 meteorAux = listMeteors[i]
3192 meteorAux = listMeteors[i]
3193
3193
3194 if meteorAux[-1] == 0:
3194 if meteorAux[-1] == 0:
3195
3195
3196 try:
3196 try:
3197 indmax = meteorPower.argmax()
3197 indmax = meteorPower.argmax()
3198 indlag = indmax + lag
3198 indlag = indmax + lag
3199
3199
3200 y = meteorPower[indlag:]
3200 y = meteorPower[indlag:]
3201 x = numpy.arange(0, y.size)*timeLag
3201 x = numpy.arange(0, y.size)*timeLag
3202
3202
3203 #first guess
3203 #first guess
3204 a = y[0]
3204 a = y[0]
3205 tau = timeLag
3205 tau = timeLag
3206 #exponential fit
3206 #exponential fit
3207 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3207 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3208 y1 = self.__exponential_function(x, *popt)
3208 y1 = self.__exponential_function(x, *popt)
3209 #error estimation
3209 #error estimation
3210 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3210 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3211
3211
3212 decayTime = popt[1]
3212 decayTime = popt[1]
3213 riseTime = indmax*timeInterval
3213 riseTime = indmax*timeInterval
3214 meteorAux[11:13] = [decayTime, error]
3214 meteorAux[11:13] = [decayTime, error]
3215
3215
3216 #Table items 7, 8 and 11
3216 #Table items 7, 8 and 11
3217 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3217 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3218 meteorAux[-1] = 7
3218 meteorAux[-1] = 7
3219 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3219 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3220 meteorAux[-1] = 8
3220 meteorAux[-1] = 8
3221 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3221 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3222 meteorAux[-1] = 11
3222 meteorAux[-1] = 11
3223
3223
3224
3224
3225 except:
3225 except:
3226 meteorAux[-1] = 11
3226 meteorAux[-1] = 11
3227
3227
3228
3228
3229 listMeteors1.append(meteorAux)
3229 listMeteors1.append(meteorAux)
3230
3230
3231 return listMeteors1
3231 return listMeteors1
3232
3232
3233 #Exponential Function
3233 #Exponential Function
3234
3234
3235 def __exponential_function(self, x, a, tau):
3235 def __exponential_function(self, x, a, tau):
3236 y = a*numpy.exp(-x/tau)
3236 y = a*numpy.exp(-x/tau)
3237 return y
3237 return y
3238
3238
3239 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3239 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3240
3240
3241 pairslist1 = list(pairslist)
3241 pairslist1 = list(pairslist)
3242 pairslist1.append((0,1))
3242 pairslist1.append((0,1))
3243 pairslist1.append((3,4))
3243 pairslist1.append((3,4))
3244 numPairs = len(pairslist1)
3244 numPairs = len(pairslist1)
3245 #Time Lag
3245 #Time Lag
3246 timeLag = 45*10**-3
3246 timeLag = 45*10**-3
3247 c = 3e8
3247 c = 3e8
3248 lag = numpy.ceil(timeLag/timeInterval)
3248 lag = numpy.ceil(timeLag/timeInterval)
3249 freq = 30e6
3249 freq = 30e6
3250
3250
3251 listMeteors1 = []
3251 listMeteors1 = []
3252
3252
3253 for i in range(len(listMeteors)):
3253 for i in range(len(listMeteors)):
3254 meteorAux = listMeteors[i]
3254 meteorAux = listMeteors[i]
3255 if meteorAux[-1] == 0:
3255 if meteorAux[-1] == 0:
3256 mStart = listMeteors[i][1]
3256 mStart = listMeteors[i][1]
3257 mPeak = listMeteors[i][2]
3257 mPeak = listMeteors[i][2]
3258 mLag = mPeak - mStart + lag
3258 mLag = mPeak - mStart + lag
3259
3259
3260 #get the volt data between the start and end times of the meteor
3260 #get the volt data between the start and end times of the meteor
3261 meteorVolts = listVolts[i]
3261 meteorVolts = listVolts[i]
3262 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3262 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3263
3263
3264 #Get CCF
3264 #Get CCF
3265 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3265 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3266
3266
3267 #Method 2
3267 #Method 2
3268 slopes = numpy.zeros(numPairs)
3268 slopes = numpy.zeros(numPairs)
3269 time = numpy.array([-2,-1,1,2])*timeInterval
3269 time = numpy.array([-2,-1,1,2])*timeInterval
3270 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3270 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3271
3271
3272 #Correct phases
3272 #Correct phases
3273 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3273 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3274 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3274 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3275
3275
3276 if indDer[0].shape[0] > 0:
3276 if indDer[0].shape[0] > 0:
3277 for i in range(indDer[0].shape[0]):
3277 for i in range(indDer[0].shape[0]):
3278 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3278 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3279 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3279 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3280
3280
3281 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3281 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3282 for j in range(numPairs):
3282 for j in range(numPairs):
3283 fit = stats.linregress(time, angAllCCF[j,:])
3283 fit = stats.linregress(time, angAllCCF[j,:])
3284 slopes[j] = fit[0]
3284 slopes[j] = fit[0]
3285
3285
3286 #Remove Outlier
3286 #Remove Outlier
3287 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3287 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3288 # slopes = numpy.delete(slopes,indOut)
3288 # slopes = numpy.delete(slopes,indOut)
3289 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3289 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3290 # slopes = numpy.delete(slopes,indOut)
3290 # slopes = numpy.delete(slopes,indOut)
3291
3291
3292 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3292 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3293 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3293 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3294 meteorAux[-2] = radialError
3294 meteorAux[-2] = radialError
3295 meteorAux[-3] = radialVelocity
3295 meteorAux[-3] = radialVelocity
3296
3296
3297 #Setting Error
3297 #Setting Error
3298 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3298 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3299 if numpy.abs(radialVelocity) > 200:
3299 if numpy.abs(radialVelocity) > 200:
3300 meteorAux[-1] = 15
3300 meteorAux[-1] = 15
3301 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3301 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3302 elif radialError > radialStdThresh:
3302 elif radialError > radialStdThresh:
3303 meteorAux[-1] = 12
3303 meteorAux[-1] = 12
3304
3304
3305 listMeteors1.append(meteorAux)
3305 listMeteors1.append(meteorAux)
3306 return listMeteors1
3306 return listMeteors1
3307
3307
3308 def __setNewArrays(self, listMeteors, date, heiRang):
3308 def __setNewArrays(self, listMeteors, date, heiRang):
3309
3309
3310 #New arrays
3310 #New arrays
3311 arrayMeteors = numpy.array(listMeteors)
3311 arrayMeteors = numpy.array(listMeteors)
3312 arrayParameters = numpy.zeros((len(listMeteors), 13))
3312 arrayParameters = numpy.zeros((len(listMeteors), 13))
3313
3313
3314 #Date inclusion
3314 #Date inclusion
3315 # date = re.findall(r'\((.*?)\)', date)
3315 # date = re.findall(r'\((.*?)\)', date)
3316 # date = date[0].split(',')
3316 # date = date[0].split(',')
3317 # date = map(int, date)
3317 # date = map(int, date)
3318 #
3318 #
3319 # if len(date)<6:
3319 # if len(date)<6:
3320 # date.append(0)
3320 # date.append(0)
3321 #
3321 #
3322 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3322 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3323 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3323 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3324 arrayDate = numpy.tile(date, (len(listMeteors)))
3324 arrayDate = numpy.tile(date, (len(listMeteors)))
3325
3325
3326 #Meteor array
3326 #Meteor array
3327 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3327 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3328 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3328 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3329
3329
3330 #Parameters Array
3330 #Parameters Array
3331 arrayParameters[:,0] = arrayDate #Date
3331 arrayParameters[:,0] = arrayDate #Date
3332 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3332 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3333 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3333 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3334 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3334 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3335 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3335 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3336
3336
3337
3337
3338 return arrayParameters
3338 return arrayParameters
3339
3339
3340 class CorrectSMPhases(Operation):
3340 class CorrectSMPhases(Operation):
3341
3341
3342 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3342 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3343
3343
3344 arrayParameters = dataOut.data_param
3344 arrayParameters = dataOut.data_param
3345 pairsList = []
3345 pairsList = []
3346 pairx = (0,1)
3346 pairx = (0,1)
3347 pairy = (2,3)
3347 pairy = (2,3)
3348 pairsList.append(pairx)
3348 pairsList.append(pairx)
3349 pairsList.append(pairy)
3349 pairsList.append(pairy)
3350 jph = numpy.zeros(4)
3350 jph = numpy.zeros(4)
3351
3351
3352 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3352 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3353 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3353 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3354 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3354 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3355
3355
3356 meteorOps = SMOperations()
3356 meteorOps = SMOperations()
3357 if channelPositions is None:
3357 if channelPositions is None:
3358 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3358 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3359 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3359 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3360
3360
3361 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3361 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3362 h = (hmin,hmax)
3362 h = (hmin,hmax)
3363
3363
3364 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3364 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3365
3365
3366 dataOut.data_param = arrayParameters
3366 dataOut.data_param = arrayParameters
3367 return
3367 return
3368
3368
3369 class SMPhaseCalibration(Operation):
3369 class SMPhaseCalibration(Operation):
3370
3370
3371 __buffer = None
3371 __buffer = None
3372
3372
3373 __initime = None
3373 __initime = None
3374
3374
3375 __dataReady = False
3375 __dataReady = False
3376
3376
3377 __isConfig = False
3377 __isConfig = False
3378
3378
3379 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3379 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3380
3380
3381 dataTime = currentTime + paramInterval
3381 dataTime = currentTime + paramInterval
3382 deltaTime = dataTime - initTime
3382 deltaTime = dataTime - initTime
3383
3383
3384 if deltaTime >= outputInterval or deltaTime < 0:
3384 if deltaTime >= outputInterval or deltaTime < 0:
3385 return True
3385 return True
3386
3386
3387 return False
3387 return False
3388
3388
3389 def __getGammas(self, pairs, d, phases):
3389 def __getGammas(self, pairs, d, phases):
3390 gammas = numpy.zeros(2)
3390 gammas = numpy.zeros(2)
3391
3391
3392 for i in range(len(pairs)):
3392 for i in range(len(pairs)):
3393
3393
3394 pairi = pairs[i]
3394 pairi = pairs[i]
3395
3395
3396 phip3 = phases[:,pairi[0]]
3396 phip3 = phases[:,pairi[0]]
3397 d3 = d[pairi[0]]
3397 d3 = d[pairi[0]]
3398 phip2 = phases[:,pairi[1]]
3398 phip2 = phases[:,pairi[1]]
3399 d2 = d[pairi[1]]
3399 d2 = d[pairi[1]]
3400 #Calculating gamma
3400 #Calculating gamma
3401 # jdcos = alp1/(k*d1)
3401 # jdcos = alp1/(k*d1)
3402 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3402 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3403 jgamma = -phip2*d3/d2 - phip3
3403 jgamma = -phip2*d3/d2 - phip3
3404 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3404 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3405 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3405 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3406 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3406 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3407
3407
3408 #Revised distribution
3408 #Revised distribution
3409 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3409 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3410
3410
3411 #Histogram
3411 #Histogram
3412 nBins = 64
3412 nBins = 64
3413 rmin = -0.5*numpy.pi
3413 rmin = -0.5*numpy.pi
3414 rmax = 0.5*numpy.pi
3414 rmax = 0.5*numpy.pi
3415 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3415 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3416
3416
3417 meteorsY = phaseHisto[0]
3417 meteorsY = phaseHisto[0]
3418 phasesX = phaseHisto[1][:-1]
3418 phasesX = phaseHisto[1][:-1]
3419 width = phasesX[1] - phasesX[0]
3419 width = phasesX[1] - phasesX[0]
3420 phasesX += width/2
3420 phasesX += width/2
3421
3421
3422 #Gaussian aproximation
3422 #Gaussian aproximation
3423 bpeak = meteorsY.argmax()
3423 bpeak = meteorsY.argmax()
3424 peak = meteorsY.max()
3424 peak = meteorsY.max()
3425 jmin = bpeak - 5
3425 jmin = bpeak - 5
3426 jmax = bpeak + 5 + 1
3426 jmax = bpeak + 5 + 1
3427
3427
3428 if jmin<0:
3428 if jmin<0:
3429 jmin = 0
3429 jmin = 0
3430 jmax = 6
3430 jmax = 6
3431 elif jmax > meteorsY.size:
3431 elif jmax > meteorsY.size:
3432 jmin = meteorsY.size - 6
3432 jmin = meteorsY.size - 6
3433 jmax = meteorsY.size
3433 jmax = meteorsY.size
3434
3434
3435 x0 = numpy.array([peak,bpeak,50])
3435 x0 = numpy.array([peak,bpeak,50])
3436 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3436 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3437
3437
3438 #Gammas
3438 #Gammas
3439 gammas[i] = coeff[0][1]
3439 gammas[i] = coeff[0][1]
3440
3440
3441 return gammas
3441 return gammas
3442
3442
3443 def __residualFunction(self, coeffs, y, t):
3443 def __residualFunction(self, coeffs, y, t):
3444
3444
3445 return y - self.__gauss_function(t, coeffs)
3445 return y - self.__gauss_function(t, coeffs)
3446
3446
3447 def __gauss_function(self, t, coeffs):
3447 def __gauss_function(self, t, coeffs):
3448
3448
3449 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3449 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3450
3450
3451 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3451 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3452 meteorOps = SMOperations()
3452 meteorOps = SMOperations()
3453 nchan = 4
3453 nchan = 4
3454 pairx = pairsList[0] #x es 0
3454 pairx = pairsList[0] #x es 0
3455 pairy = pairsList[1] #y es 1
3455 pairy = pairsList[1] #y es 1
3456 center_xangle = 0
3456 center_xangle = 0
3457 center_yangle = 0
3457 center_yangle = 0
3458 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3458 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3459 ntimes = len(range_angle)
3459 ntimes = len(range_angle)
3460
3460
3461 nstepsx = 20
3461 nstepsx = 20
3462 nstepsy = 20
3462 nstepsy = 20
3463
3463
3464 for iz in range(ntimes):
3464 for iz in range(ntimes):
3465 min_xangle = -range_angle[iz]/2 + center_xangle
3465 min_xangle = -range_angle[iz]/2 + center_xangle
3466 max_xangle = range_angle[iz]/2 + center_xangle
3466 max_xangle = range_angle[iz]/2 + center_xangle
3467 min_yangle = -range_angle[iz]/2 + center_yangle
3467 min_yangle = -range_angle[iz]/2 + center_yangle
3468 max_yangle = range_angle[iz]/2 + center_yangle
3468 max_yangle = range_angle[iz]/2 + center_yangle
3469
3469
3470 inc_x = (max_xangle-min_xangle)/nstepsx
3470 inc_x = (max_xangle-min_xangle)/nstepsx
3471 inc_y = (max_yangle-min_yangle)/nstepsy
3471 inc_y = (max_yangle-min_yangle)/nstepsy
3472
3472
3473 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3473 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3474 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3474 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3475 penalty = numpy.zeros((nstepsx,nstepsy))
3475 penalty = numpy.zeros((nstepsx,nstepsy))
3476 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3476 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3477 jph = numpy.zeros(nchan)
3477 jph = numpy.zeros(nchan)
3478
3478
3479 # Iterations looking for the offset
3479 # Iterations looking for the offset
3480 for iy in range(int(nstepsy)):
3480 for iy in range(int(nstepsy)):
3481 for ix in range(int(nstepsx)):
3481 for ix in range(int(nstepsx)):
3482 d3 = d[pairsList[1][0]]
3482 d3 = d[pairsList[1][0]]
3483 d2 = d[pairsList[1][1]]
3483 d2 = d[pairsList[1][1]]
3484 d5 = d[pairsList[0][0]]
3484 d5 = d[pairsList[0][0]]
3485 d4 = d[pairsList[0][1]]
3485 d4 = d[pairsList[0][1]]
3486
3486
3487 alp2 = alpha_y[iy] #gamma 1
3487 alp2 = alpha_y[iy] #gamma 1
3488 alp4 = alpha_x[ix] #gamma 0
3488 alp4 = alpha_x[ix] #gamma 0
3489
3489
3490 alp3 = -alp2*d3/d2 - gammas[1]
3490 alp3 = -alp2*d3/d2 - gammas[1]
3491 alp5 = -alp4*d5/d4 - gammas[0]
3491 alp5 = -alp4*d5/d4 - gammas[0]
3492 # jph[pairy[1]] = alpha_y[iy]
3492 # jph[pairy[1]] = alpha_y[iy]
3493 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3493 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3494
3494
3495 # jph[pairx[1]] = alpha_x[ix]
3495 # jph[pairx[1]] = alpha_x[ix]
3496 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3496 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3497 jph[pairsList[0][1]] = alp4
3497 jph[pairsList[0][1]] = alp4
3498 jph[pairsList[0][0]] = alp5
3498 jph[pairsList[0][0]] = alp5
3499 jph[pairsList[1][0]] = alp3
3499 jph[pairsList[1][0]] = alp3
3500 jph[pairsList[1][1]] = alp2
3500 jph[pairsList[1][1]] = alp2
3501 jph_array[:,ix,iy] = jph
3501 jph_array[:,ix,iy] = jph
3502 # d = [2.0,2.5,2.5,2.0]
3502 # d = [2.0,2.5,2.5,2.0]
3503 #falta chequear si va a leer bien los meteoros
3503 #falta chequear si va a leer bien los meteoros
3504 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3504 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3505 error = meteorsArray1[:,-1]
3505 error = meteorsArray1[:,-1]
3506 ind1 = numpy.where(error==0)[0]
3506 ind1 = numpy.where(error==0)[0]
3507 penalty[ix,iy] = ind1.size
3507 penalty[ix,iy] = ind1.size
3508
3508
3509 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3509 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3510 phOffset = jph_array[:,i,j]
3510 phOffset = jph_array[:,i,j]
3511
3511
3512 center_xangle = phOffset[pairx[1]]
3512 center_xangle = phOffset[pairx[1]]
3513 center_yangle = phOffset[pairy[1]]
3513 center_yangle = phOffset[pairy[1]]
3514
3514
3515 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3515 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3516 phOffset = phOffset*180/numpy.pi
3516 phOffset = phOffset*180/numpy.pi
3517 return phOffset
3517 return phOffset
3518
3518
3519
3519
3520 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3520 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3521
3521
3522 dataOut.flagNoData = True
3522 dataOut.flagNoData = True
3523 self.__dataReady = False
3523 self.__dataReady = False
3524 dataOut.outputInterval = nHours*3600
3524 dataOut.outputInterval = nHours*3600
3525
3525
3526 if self.__isConfig == False:
3526 if self.__isConfig == False:
3527 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3527 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3528 #Get Initial LTC time
3528 #Get Initial LTC time
3529 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3529 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3530 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3530 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3531
3531
3532 self.__isConfig = True
3532 self.__isConfig = True
3533
3533
3534 if self.__buffer is None:
3534 if self.__buffer is None:
3535 self.__buffer = dataOut.data_param.copy()
3535 self.__buffer = dataOut.data_param.copy()
3536
3536
3537 else:
3537 else:
3538 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3538 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3539
3539
3540 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3540 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3541
3541
3542 if self.__dataReady:
3542 if self.__dataReady:
3543 dataOut.utctimeInit = self.__initime
3543 dataOut.utctimeInit = self.__initime
3544 self.__initime += dataOut.outputInterval #to erase time offset
3544 self.__initime += dataOut.outputInterval #to erase time offset
3545
3545
3546 freq = dataOut.frequency
3546 freq = dataOut.frequency
3547 c = dataOut.C #m/s
3547 c = dataOut.C #m/s
3548 lamb = c/freq
3548 lamb = c/freq
3549 k = 2*numpy.pi/lamb
3549 k = 2*numpy.pi/lamb
3550 azimuth = 0
3550 azimuth = 0
3551 h = (hmin, hmax)
3551 h = (hmin, hmax)
3552 # pairs = ((0,1),(2,3)) #Estrella
3552 # pairs = ((0,1),(2,3)) #Estrella
3553 # pairs = ((1,0),(2,3)) #T
3553 # pairs = ((1,0),(2,3)) #T
3554
3554
3555 if channelPositions is None:
3555 if channelPositions is None:
3556 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3556 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3557 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3557 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3558 meteorOps = SMOperations()
3558 meteorOps = SMOperations()
3559 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3559 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3560
3560
3561 #Checking correct order of pairs
3561 #Checking correct order of pairs
3562 pairs = []
3562 pairs = []
3563 if distances[1] > distances[0]:
3563 if distances[1] > distances[0]:
3564 pairs.append((1,0))
3564 pairs.append((1,0))
3565 else:
3565 else:
3566 pairs.append((0,1))
3566 pairs.append((0,1))
3567
3567
3568 if distances[3] > distances[2]:
3568 if distances[3] > distances[2]:
3569 pairs.append((3,2))
3569 pairs.append((3,2))
3570 else:
3570 else:
3571 pairs.append((2,3))
3571 pairs.append((2,3))
3572 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3572 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3573
3573
3574 meteorsArray = self.__buffer
3574 meteorsArray = self.__buffer
3575 error = meteorsArray[:,-1]
3575 error = meteorsArray[:,-1]
3576 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3576 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3577 ind1 = numpy.where(boolError)[0]
3577 ind1 = numpy.where(boolError)[0]
3578 meteorsArray = meteorsArray[ind1,:]
3578 meteorsArray = meteorsArray[ind1,:]
3579 meteorsArray[:,-1] = 0
3579 meteorsArray[:,-1] = 0
3580 phases = meteorsArray[:,8:12]
3580 phases = meteorsArray[:,8:12]
3581
3581
3582 #Calculate Gammas
3582 #Calculate Gammas
3583 gammas = self.__getGammas(pairs, distances, phases)
3583 gammas = self.__getGammas(pairs, distances, phases)
3584 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3584 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3585 #Calculate Phases
3585 #Calculate Phases
3586 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3586 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3587 phasesOff = phasesOff.reshape((1,phasesOff.size))
3587 phasesOff = phasesOff.reshape((1,phasesOff.size))
3588 dataOut.data_output = -phasesOff
3588 dataOut.data_output = -phasesOff
3589 dataOut.flagNoData = False
3589 dataOut.flagNoData = False
3590 self.__buffer = None
3590 self.__buffer = None
3591
3591
3592
3592
3593 return
3593 return
3594
3594
3595 class SMOperations():
3595 class SMOperations():
3596
3596
3597 def __init__(self):
3597 def __init__(self):
3598
3598
3599 return
3599 return
3600
3600
3601 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3601 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3602
3602
3603 arrayParameters = arrayParameters0.copy()
3603 arrayParameters = arrayParameters0.copy()
3604 hmin = h[0]
3604 hmin = h[0]
3605 hmax = h[1]
3605 hmax = h[1]
3606
3606
3607 #Calculate AOA (Error N 3, 4)
3607 #Calculate AOA (Error N 3, 4)
3608 #JONES ET AL. 1998
3608 #JONES ET AL. 1998
3609 AOAthresh = numpy.pi/8
3609 AOAthresh = numpy.pi/8
3610 error = arrayParameters[:,-1]
3610 error = arrayParameters[:,-1]
3611 phases = -arrayParameters[:,8:12] + jph
3611 phases = -arrayParameters[:,8:12] + jph
3612 # phases = numpy.unwrap(phases)
3612 # phases = numpy.unwrap(phases)
3613 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3613 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3614
3614
3615 #Calculate Heights (Error N 13 and 14)
3615 #Calculate Heights (Error N 13 and 14)
3616 error = arrayParameters[:,-1]
3616 error = arrayParameters[:,-1]
3617 Ranges = arrayParameters[:,1]
3617 Ranges = arrayParameters[:,1]
3618 zenith = arrayParameters[:,4]
3618 zenith = arrayParameters[:,4]
3619 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3619 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3620
3620
3621 #----------------------- Get Final data ------------------------------------
3621 #----------------------- Get Final data ------------------------------------
3622 # error = arrayParameters[:,-1]
3622 # error = arrayParameters[:,-1]
3623 # ind1 = numpy.where(error==0)[0]
3623 # ind1 = numpy.where(error==0)[0]
3624 # arrayParameters = arrayParameters[ind1,:]
3624 # arrayParameters = arrayParameters[ind1,:]
3625
3625
3626 return arrayParameters
3626 return arrayParameters
3627
3627
3628 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3628 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3629
3629
3630 arrayAOA = numpy.zeros((phases.shape[0],3))
3630 arrayAOA = numpy.zeros((phases.shape[0],3))
3631 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3631 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3632
3632
3633 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3633 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3634 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3634 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3635 arrayAOA[:,2] = cosDirError
3635 arrayAOA[:,2] = cosDirError
3636
3636
3637 azimuthAngle = arrayAOA[:,0]
3637 azimuthAngle = arrayAOA[:,0]
3638 zenithAngle = arrayAOA[:,1]
3638 zenithAngle = arrayAOA[:,1]
3639
3639
3640 #Setting Error
3640 #Setting Error
3641 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3641 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3642 error[indError] = 0
3642 error[indError] = 0
3643 #Number 3: AOA not fesible
3643 #Number 3: AOA not fesible
3644 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3644 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3645 error[indInvalid] = 3
3645 error[indInvalid] = 3
3646 #Number 4: Large difference in AOAs obtained from different antenna baselines
3646 #Number 4: Large difference in AOAs obtained from different antenna baselines
3647 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3647 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3648 error[indInvalid] = 4
3648 error[indInvalid] = 4
3649 return arrayAOA, error
3649 return arrayAOA, error
3650
3650
3651 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3651 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3652
3652
3653 #Initializing some variables
3653 #Initializing some variables
3654 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3654 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3655 ang_aux = ang_aux.reshape(1,ang_aux.size)
3655 ang_aux = ang_aux.reshape(1,ang_aux.size)
3656
3656
3657 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3657 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3658 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3658 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3659
3659
3660
3660
3661 for i in range(2):
3661 for i in range(2):
3662 ph0 = arrayPhase[:,pairsList[i][0]]
3662 ph0 = arrayPhase[:,pairsList[i][0]]
3663 ph1 = arrayPhase[:,pairsList[i][1]]
3663 ph1 = arrayPhase[:,pairsList[i][1]]
3664 d0 = distances[pairsList[i][0]]
3664 d0 = distances[pairsList[i][0]]
3665 d1 = distances[pairsList[i][1]]
3665 d1 = distances[pairsList[i][1]]
3666
3666
3667 ph0_aux = ph0 + ph1
3667 ph0_aux = ph0 + ph1
3668 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3668 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3669 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3669 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3670 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3670 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3671 #First Estimation
3671 #First Estimation
3672 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3672 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3673
3673
3674 #Most-Accurate Second Estimation
3674 #Most-Accurate Second Estimation
3675 phi1_aux = ph0 - ph1
3675 phi1_aux = ph0 - ph1
3676 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3676 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3677 #Direction Cosine 1
3677 #Direction Cosine 1
3678 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3678 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3679
3679
3680 #Searching the correct Direction Cosine
3680 #Searching the correct Direction Cosine
3681 cosdir0_aux = cosdir0[:,i]
3681 cosdir0_aux = cosdir0[:,i]
3682 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3682 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3683 #Minimum Distance
3683 #Minimum Distance
3684 cosDiff = (cosdir1 - cosdir0_aux)**2
3684 cosDiff = (cosdir1 - cosdir0_aux)**2
3685 indcos = cosDiff.argmin(axis = 1)
3685 indcos = cosDiff.argmin(axis = 1)
3686 #Saving Value obtained
3686 #Saving Value obtained
3687 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3687 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3688
3688
3689 return cosdir0, cosdir
3689 return cosdir0, cosdir
3690
3690
3691 def __calculateAOA(self, cosdir, azimuth):
3691 def __calculateAOA(self, cosdir, azimuth):
3692 cosdirX = cosdir[:,0]
3692 cosdirX = cosdir[:,0]
3693 cosdirY = cosdir[:,1]
3693 cosdirY = cosdir[:,1]
3694
3694
3695 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3695 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3696 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3696 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3697 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3697 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3698
3698
3699 return angles
3699 return angles
3700
3700
3701 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3701 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3702
3702
3703 Ramb = 375 #Ramb = c/(2*PRF)
3703 Ramb = 375 #Ramb = c/(2*PRF)
3704 Re = 6371 #Earth Radius
3704 Re = 6371 #Earth Radius
3705 heights = numpy.zeros(Ranges.shape)
3705 heights = numpy.zeros(Ranges.shape)
3706
3706
3707 R_aux = numpy.array([0,1,2])*Ramb
3707 R_aux = numpy.array([0,1,2])*Ramb
3708 R_aux = R_aux.reshape(1,R_aux.size)
3708 R_aux = R_aux.reshape(1,R_aux.size)
3709
3709
3710 Ranges = Ranges.reshape(Ranges.size,1)
3710 Ranges = Ranges.reshape(Ranges.size,1)
3711
3711
3712 Ri = Ranges + R_aux
3712 Ri = Ranges + R_aux
3713 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3713 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3714
3714
3715 #Check if there is a height between 70 and 110 km
3715 #Check if there is a height between 70 and 110 km
3716 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3716 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3717 ind_h = numpy.where(h_bool == 1)[0]
3717 ind_h = numpy.where(h_bool == 1)[0]
3718
3718
3719 hCorr = hi[ind_h, :]
3719 hCorr = hi[ind_h, :]
3720 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3720 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3721
3721
3722 hCorr = hi[ind_hCorr][:len(ind_h)]
3722 hCorr = hi[ind_hCorr][:len(ind_h)]
3723 heights[ind_h] = hCorr
3723 heights[ind_h] = hCorr
3724
3724
3725 #Setting Error
3725 #Setting Error
3726 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3726 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3727 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3727 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3728 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3728 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3729 error[indError] = 0
3729 error[indError] = 0
3730 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3730 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3731 error[indInvalid2] = 14
3731 error[indInvalid2] = 14
3732 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3732 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3733 error[indInvalid1] = 13
3733 error[indInvalid1] = 13
3734
3734
3735 return heights, error
3735 return heights, error
3736
3736
3737 def getPhasePairs(self, channelPositions):
3737 def getPhasePairs(self, channelPositions):
3738 chanPos = numpy.array(channelPositions)
3738 chanPos = numpy.array(channelPositions)
3739 listOper = list(itertools.combinations(list(range(5)),2))
3739 listOper = list(itertools.combinations(list(range(5)),2))
3740
3740
3741 distances = numpy.zeros(4)
3741 distances = numpy.zeros(4)
3742 axisX = []
3742 axisX = []
3743 axisY = []
3743 axisY = []
3744 distX = numpy.zeros(3)
3744 distX = numpy.zeros(3)
3745 distY = numpy.zeros(3)
3745 distY = numpy.zeros(3)
3746 ix = 0
3746 ix = 0
3747 iy = 0
3747 iy = 0
3748
3748
3749 pairX = numpy.zeros((2,2))
3749 pairX = numpy.zeros((2,2))
3750 pairY = numpy.zeros((2,2))
3750 pairY = numpy.zeros((2,2))
3751
3751
3752 for i in range(len(listOper)):
3752 for i in range(len(listOper)):
3753 pairi = listOper[i]
3753 pairi = listOper[i]
3754
3754
3755 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3755 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3756
3756
3757 if posDif[0] == 0:
3757 if posDif[0] == 0:
3758 axisY.append(pairi)
3758 axisY.append(pairi)
3759 distY[iy] = posDif[1]
3759 distY[iy] = posDif[1]
3760 iy += 1
3760 iy += 1
3761 elif posDif[1] == 0:
3761 elif posDif[1] == 0:
3762 axisX.append(pairi)
3762 axisX.append(pairi)
3763 distX[ix] = posDif[0]
3763 distX[ix] = posDif[0]
3764 ix += 1
3764 ix += 1
3765
3765
3766 for i in range(2):
3766 for i in range(2):
3767 if i==0:
3767 if i==0:
3768 dist0 = distX
3768 dist0 = distX
3769 axis0 = axisX
3769 axis0 = axisX
3770 else:
3770 else:
3771 dist0 = distY
3771 dist0 = distY
3772 axis0 = axisY
3772 axis0 = axisY
3773
3773
3774 side = numpy.argsort(dist0)[:-1]
3774 side = numpy.argsort(dist0)[:-1]
3775 axis0 = numpy.array(axis0)[side,:]
3775 axis0 = numpy.array(axis0)[side,:]
3776 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3776 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3777 axis1 = numpy.unique(numpy.reshape(axis0,4))
3777 axis1 = numpy.unique(numpy.reshape(axis0,4))
3778 side = axis1[axis1 != chanC]
3778 side = axis1[axis1 != chanC]
3779 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3779 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3780 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3780 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3781 if diff1<0:
3781 if diff1<0:
3782 chan2 = side[0]
3782 chan2 = side[0]
3783 d2 = numpy.abs(diff1)
3783 d2 = numpy.abs(diff1)
3784 chan1 = side[1]
3784 chan1 = side[1]
3785 d1 = numpy.abs(diff2)
3785 d1 = numpy.abs(diff2)
3786 else:
3786 else:
3787 chan2 = side[1]
3787 chan2 = side[1]
3788 d2 = numpy.abs(diff2)
3788 d2 = numpy.abs(diff2)
3789 chan1 = side[0]
3789 chan1 = side[0]
3790 d1 = numpy.abs(diff1)
3790 d1 = numpy.abs(diff1)
3791
3791
3792 if i==0:
3792 if i==0:
3793 chanCX = chanC
3793 chanCX = chanC
3794 chan1X = chan1
3794 chan1X = chan1
3795 chan2X = chan2
3795 chan2X = chan2
3796 distances[0:2] = numpy.array([d1,d2])
3796 distances[0:2] = numpy.array([d1,d2])
3797 else:
3797 else:
3798 chanCY = chanC
3798 chanCY = chanC
3799 chan1Y = chan1
3799 chan1Y = chan1
3800 chan2Y = chan2
3800 chan2Y = chan2
3801 distances[2:4] = numpy.array([d1,d2])
3801 distances[2:4] = numpy.array([d1,d2])
3802 # axisXsides = numpy.reshape(axisX[ix,:],4)
3802 # axisXsides = numpy.reshape(axisX[ix,:],4)
3803 #
3803 #
3804 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3804 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3805 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3805 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3806 #
3806 #
3807 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3807 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3808 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3808 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3809 # channel25X = int(pairX[0,ind25X])
3809 # channel25X = int(pairX[0,ind25X])
3810 # channel20X = int(pairX[1,ind20X])
3810 # channel20X = int(pairX[1,ind20X])
3811 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3811 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3812 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3812 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3813 # channel25Y = int(pairY[0,ind25Y])
3813 # channel25Y = int(pairY[0,ind25Y])
3814 # channel20Y = int(pairY[1,ind20Y])
3814 # channel20Y = int(pairY[1,ind20Y])
3815
3815
3816 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3816 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3817 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3817 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3818
3818
3819 return pairslist, distances
3819 return pairslist, distances
3820 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3820 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3821 #
3821 #
3822 # arrayAOA = numpy.zeros((phases.shape[0],3))
3822 # arrayAOA = numpy.zeros((phases.shape[0],3))
3823 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3823 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3824 #
3824 #
3825 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3825 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3826 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3826 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3827 # arrayAOA[:,2] = cosDirError
3827 # arrayAOA[:,2] = cosDirError
3828 #
3828 #
3829 # azimuthAngle = arrayAOA[:,0]
3829 # azimuthAngle = arrayAOA[:,0]
3830 # zenithAngle = arrayAOA[:,1]
3830 # zenithAngle = arrayAOA[:,1]
3831 #
3831 #
3832 # #Setting Error
3832 # #Setting Error
3833 # #Number 3: AOA not fesible
3833 # #Number 3: AOA not fesible
3834 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3834 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3835 # error[indInvalid] = 3
3835 # error[indInvalid] = 3
3836 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3836 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3837 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3837 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3838 # error[indInvalid] = 4
3838 # error[indInvalid] = 4
3839 # return arrayAOA, error
3839 # return arrayAOA, error
3840 #
3840 #
3841 # def __getDirectionCosines(self, arrayPhase, pairsList):
3841 # def __getDirectionCosines(self, arrayPhase, pairsList):
3842 #
3842 #
3843 # #Initializing some variables
3843 # #Initializing some variables
3844 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3844 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3845 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3845 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3846 #
3846 #
3847 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3847 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3848 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3848 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3849 #
3849 #
3850 #
3850 #
3851 # for i in range(2):
3851 # for i in range(2):
3852 # #First Estimation
3852 # #First Estimation
3853 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3853 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3854 # #Dealias
3854 # #Dealias
3855 # indcsi = numpy.where(phi0_aux > numpy.pi)
3855 # indcsi = numpy.where(phi0_aux > numpy.pi)
3856 # phi0_aux[indcsi] -= 2*numpy.pi
3856 # phi0_aux[indcsi] -= 2*numpy.pi
3857 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3857 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3858 # phi0_aux[indcsi] += 2*numpy.pi
3858 # phi0_aux[indcsi] += 2*numpy.pi
3859 # #Direction Cosine 0
3859 # #Direction Cosine 0
3860 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3860 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3861 #
3861 #
3862 # #Most-Accurate Second Estimation
3862 # #Most-Accurate Second Estimation
3863 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3863 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3864 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3864 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3865 # #Direction Cosine 1
3865 # #Direction Cosine 1
3866 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3866 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3867 #
3867 #
3868 # #Searching the correct Direction Cosine
3868 # #Searching the correct Direction Cosine
3869 # cosdir0_aux = cosdir0[:,i]
3869 # cosdir0_aux = cosdir0[:,i]
3870 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3870 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3871 # #Minimum Distance
3871 # #Minimum Distance
3872 # cosDiff = (cosdir1 - cosdir0_aux)**2
3872 # cosDiff = (cosdir1 - cosdir0_aux)**2
3873 # indcos = cosDiff.argmin(axis = 1)
3873 # indcos = cosDiff.argmin(axis = 1)
3874 # #Saving Value obtained
3874 # #Saving Value obtained
3875 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3875 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3876 #
3876 #
3877 # return cosdir0, cosdir
3877 # return cosdir0, cosdir
3878 #
3878 #
3879 # def __calculateAOA(self, cosdir, azimuth):
3879 # def __calculateAOA(self, cosdir, azimuth):
3880 # cosdirX = cosdir[:,0]
3880 # cosdirX = cosdir[:,0]
3881 # cosdirY = cosdir[:,1]
3881 # cosdirY = cosdir[:,1]
3882 #
3882 #
3883 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3883 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3884 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3884 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3885 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3885 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3886 #
3886 #
3887 # return angles
3887 # return angles
3888 #
3888 #
3889 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3889 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3890 #
3890 #
3891 # Ramb = 375 #Ramb = c/(2*PRF)
3891 # Ramb = 375 #Ramb = c/(2*PRF)
3892 # Re = 6371 #Earth Radius
3892 # Re = 6371 #Earth Radius
3893 # heights = numpy.zeros(Ranges.shape)
3893 # heights = numpy.zeros(Ranges.shape)
3894 #
3894 #
3895 # R_aux = numpy.array([0,1,2])*Ramb
3895 # R_aux = numpy.array([0,1,2])*Ramb
3896 # R_aux = R_aux.reshape(1,R_aux.size)
3896 # R_aux = R_aux.reshape(1,R_aux.size)
3897 #
3897 #
3898 # Ranges = Ranges.reshape(Ranges.size,1)
3898 # Ranges = Ranges.reshape(Ranges.size,1)
3899 #
3899 #
3900 # Ri = Ranges + R_aux
3900 # Ri = Ranges + R_aux
3901 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3901 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3902 #
3902 #
3903 # #Check if there is a height between 70 and 110 km
3903 # #Check if there is a height between 70 and 110 km
3904 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3904 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3905 # ind_h = numpy.where(h_bool == 1)[0]
3905 # ind_h = numpy.where(h_bool == 1)[0]
3906 #
3906 #
3907 # hCorr = hi[ind_h, :]
3907 # hCorr = hi[ind_h, :]
3908 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3908 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3909 #
3909 #
3910 # hCorr = hi[ind_hCorr]
3910 # hCorr = hi[ind_hCorr]
3911 # heights[ind_h] = hCorr
3911 # heights[ind_h] = hCorr
3912 #
3912 #
3913 # #Setting Error
3913 # #Setting Error
3914 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3914 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3915 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3915 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3916 #
3916 #
3917 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3917 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3918 # error[indInvalid2] = 14
3918 # error[indInvalid2] = 14
3919 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3919 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3920 # error[indInvalid1] = 13
3920 # error[indInvalid1] = 13
3921 #
3921 #
3922 # return heights, error
3922 # return heights, error
3923
3923
3924
3924
3925 class WeatherRadar(Operation):
3925 class WeatherRadar(Operation):
3926 '''
3926 '''
3927 Function tat implements Weather Radar operations-
3927 Function tat implements Weather Radar operations-
3928 Input:
3928 Input:
3929 Output:
3929 Output:
3930 Parameters affected:
3930 Parameters affected:
3931
3931
3932 Conversion Watt
3932 Conversion Watt
3933 Referencia
3933 Referencia
3934 https://www.tek.com/en/blog/calculating-rf-power-iq-samples
3934 https://www.tek.com/en/blog/calculating-rf-power-iq-samples
3935
3935
3936 data_param = (nCh, 8, nHeis)
3936 data_param = (nCh, 8, nHeis)
3937 S, V, W, SNR, Z, D, P, R
3937 S, V, W, SNR, Z, D, P, R
3938 Power, Velocity, Spectral width, SNR, Reflectivity, Differential reflectivity, PHI DP, RHO HV
3938 Power, Velocity, Spectral width, SNR, Reflectivity, Differential reflectivity, PHI DP, RHO HV
3939 '''
3939 '''
3940 isConfig = False
3940 isConfig = False
3941 variableList = None
3941 variableList = None
3942
3942
3943 def __init__(self):
3943 def __init__(self):
3944 Operation.__init__(self)
3944 Operation.__init__(self)
3945
3945
3946 def setup(self,dataOut,variableList= None,Pt=0,Gt=0,Gr=0,Glna=0,lambda_=0, aL=0,
3946 def setup(self,dataOut,variableList= None,Pt=0,Gt=0,Gr=0,Glna=0,lambda_=0, aL=0,
3947 tauW= 0,thetaT=0,thetaR=0,Km =0,CR_Flag=False,min_index=0,sesgoZD=0):
3947 tauW= 0,thetaT=0,thetaR=0,Km =0,CR_Flag=False,min_index=0,sesgoZD=0):
3948
3948
3949 self.nCh = dataOut.nChannels
3949 self.nCh = dataOut.nChannels
3950 self.nHeis = dataOut.nHeights
3950 self.nHeis = dataOut.nHeights
3951 self.min_index= min_index
3951 self.min_index= min_index
3952 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3952 deltaHeight = dataOut.heightList[1] - dataOut.heightList[0]
3953 self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]+min_index*deltaHeight
3953 #self.Range = numpy.arange(dataOut.nHeights)*deltaHeight + dataOut.heightList[0]+min_index*deltaHeight
3954 self.Range = dataOut.heightList
3955 print(self.Range, flush=True)
3954 self.Range = self.Range.reshape(1,self.nHeis)
3956 self.Range = self.Range.reshape(1,self.nHeis)
3955 self.Range = numpy.tile(self.Range,[self.nCh,1])
3957 self.Range = numpy.tile(self.Range,[self.nCh,1])
3956 '''-----------1 Constante del Radar----------'''
3958 '''-----------1 Constante del Radar----------'''
3957 self.Pt = Pt # Pmax =200 W x DC=(0.2 useg/400useg)
3959 self.Pt = Pt # Pmax =200 W x DC=(0.2 useg/400useg)
3958 self.Gt = Gt # 38 db
3960 self.Gt = Gt # 38 db
3959 self.Gr = Gr # 38 dB
3961 self.Gr = Gr # 38 dB
3960 self.Glna = Glna # 60 dB
3962 self.Glna = Glna # 60 dB
3961 self.lambda_ = lambda_ # 3.2 cm 0.032 m.
3963 self.lambda_ = lambda_ # 3.2 cm 0.032 m.
3962 self.aL = aL # Perdidas
3964 self.aL = aL # Perdidas
3963 self.tauW = tauW #ancho de pulso 0.2useg pulso corto.
3965 self.tauW = tauW #ancho de pulso 0.2useg pulso corto.
3964 self.thetaT = thetaT # 1.8ΒΊ -- 0.0314 rad
3966 self.thetaT = thetaT # 1.8ΒΊ -- 0.0314 rad
3965 self.thetaR = thetaR # 1.8Βͺ --0.0314 rad
3967 self.thetaR = thetaR # 1.8Βͺ --0.0314 rad
3966 self.Km = Km
3968 self.Km = Km
3967 self.CR_Flag = CR_Flag
3969 self.CR_Flag = CR_Flag
3968 self.sesgoZD = sesgoZD
3970 self.sesgoZD = sesgoZD
3969 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2)*(10**18))
3971 Numerator = ((4*numpy.pi)**3 * aL**2 * 16 *numpy.log(2)*(10**18))
3970 Denominator = (Pt *(10**(Gt/10.0))*(10**(Gr/10.0))*(10**(Glna/10.0))* lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3972 Denominator = (Pt *(10**(Gt/10.0))*(10**(Gr/10.0))*(10**(Glna/10.0))* lambda_**2 * SPEED_OF_LIGHT * tauW * numpy.pi*thetaT*thetaR)
3971 self.RadarConstant = Numerator/Denominator
3973 self.RadarConstant = Numerator/Denominator
3972 self.variableList = variableList
3974 self.variableList = variableList
3973 if self.variableList== None:
3975 if self.variableList== None:
3974 self.variableList= ['Z','D','R','P']
3976 self.variableList= ['Z','D','R','P']
3975
3977
3976 def setMoments(self, dataOut):
3978 def setMoments(self, dataOut):
3977 # S, V, W, SNR, Z, D, P, R
3979 # S, V, W, SNR, Z, D, P, R
3978 type = dataOut.inputUnit
3980 type = dataOut.inputUnit
3979 nCh = dataOut.nChannels
3981 nCh = dataOut.nChannels
3980 nHeis = dataOut.nHeights
3982 nHeis = dataOut.nHeights
3981 data_param = numpy.zeros((nCh, 8, nHeis))
3983 data_param = numpy.zeros((nCh, 8, nHeis))
3982 if type == "Voltage":
3984 if type == "Voltage":
3983 factor = 1
3985 factor = 1
3984 data_param[:,0,:] = dataOut.dataPP_POW/(factor)#dataOut.dataPP_POWER/(factor)
3986 data_param[:,0,:] = dataOut.dataPP_POW/(factor)#dataOut.dataPP_POWER/(factor)
3985 data_param[:,1,:] = dataOut.dataPP_DOP
3987 data_param[:,1,:] = dataOut.dataPP_DOP
3986 data_param[:,2,:] = dataOut.dataPP_WIDTH
3988 data_param[:,2,:] = dataOut.dataPP_WIDTH
3987 data_param[:,3,:] = dataOut.dataPP_SNR
3989 data_param[:,3,:] = dataOut.dataPP_SNR
3988 if type == "Spectra":
3990 if type == "Spectra":
3989 factor = dataOut.normFactor
3991 factor = dataOut.normFactor
3990 data_param[:,0,:] = dataOut.data_pow/(factor)
3992 data_param[:,0,:] = dataOut.data_pow/(factor)
3991 data_param[:,1,:] = dataOut.data_dop
3993 data_param[:,1,:] = dataOut.data_dop
3992 data_param[:,2,:] = dataOut.data_width
3994 data_param[:,2,:] = dataOut.data_width
3993 data_param[:,3,:] = dataOut.data_snr
3995 data_param[:,3,:] = dataOut.data_snr
3994 return data_param
3996 return data_param
3995
3997
3996 def getCoeficienteCorrelacionROhv_R(self,dataOut):
3998 def getCoeficienteCorrelacionROhv_R(self,dataOut):
3997 type = dataOut.inputUnit
3999 type = dataOut.inputUnit
3998 nHeis = dataOut.nHeights
4000 nHeis = dataOut.nHeights
3999 data_RhoHV_R = numpy.zeros((nHeis))
4001 data_RhoHV_R = numpy.zeros((nHeis))
4000 if type == "Voltage":
4002 if type == "Voltage":
4001 avgcoherenceComplex= dataOut.dataPP_CCF
4003 avgcoherenceComplex= dataOut.dataPP_CCF
4002 data_RhoHV_R = numpy.abs(avgcoherenceComplex)
4004 data_RhoHV_R = numpy.abs(avgcoherenceComplex)
4003 if type == "Spectra":
4005 if type == "Spectra":
4004 data_RhoHV_R = dataOut.getCoherence()
4006 data_RhoHV_R = dataOut.getCoherence()
4005
4007
4006 return data_RhoHV_R
4008 return data_RhoHV_R
4007
4009
4008 def getFasediferencialPhiD_P(self,dataOut,phase= True):
4010 def getFasediferencialPhiD_P(self,dataOut,phase= True):
4009 type = dataOut.inputUnit
4011 type = dataOut.inputUnit
4010 nHeis = dataOut.nHeights
4012 nHeis = dataOut.nHeights
4011 data_PhiD_P = numpy.zeros((nHeis))
4013 data_PhiD_P = numpy.zeros((nHeis))
4012 if type == "Voltage":
4014 if type == "Voltage":
4013 avgcoherenceComplex= dataOut.dataPP_CCF
4015 avgcoherenceComplex= dataOut.dataPP_CCF
4014 if phase:
4016 if phase:
4015 data_PhiD_P = numpy.arctan2(avgcoherenceComplex.imag,
4017 data_PhiD_P = numpy.arctan2(avgcoherenceComplex.imag,
4016 avgcoherenceComplex.real) * 180 / numpy.pi
4018 avgcoherenceComplex.real) * 180 / numpy.pi
4017 if type == "Spectra":
4019 if type == "Spectra":
4018 data_PhiD_P = dataOut.getCoherence(phase = phase)
4020 data_PhiD_P = dataOut.getCoherence(phase = phase)
4019
4021
4020 return data_PhiD_P
4022 return data_PhiD_P
4021
4023
4022 def getReflectividad_D(self,dataOut,type):
4024 def getReflectividad_D(self,dataOut,type):
4023 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
4025 '''-----------------------------Potencia de Radar -Signal S-----------------------------'''
4024
4026
4025 Pr = dataOut.data_param[:,0,:]
4027 Pr = dataOut.data_param[:,0,:]
4026 '''---------------------------- Calculo de Noise y threshold para Reflectividad---------'''
4028 '''---------------------------- Calculo de Noise y threshold para Reflectividad---------'''
4027
4029
4028 Pr = Pr/100.0 # Conversion Watt
4030 Pr = Pr/100.0 # Conversion Watt
4029 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
4031 '''-----------2 Reflectividad del Radar y Factor de Reflectividad------'''
4030 if not self.CR_Flag:
4032 if not self.CR_Flag:
4031 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
4033 self.n_radar = numpy.zeros((self.nCh,self.nHeis))
4032 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
4034 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
4033 for R in range(self.nHeis):
4035 for R in range(self.nHeis):
4034 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R]*(10**3))**2
4036 self.n_radar[:,R] = self.RadarConstant*Pr[:,R]* (self.Range[:,R]*(10**3))**2
4035
4037
4036 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
4038 self.Z_radar[:,R] = self.n_radar[:,R]* self.lambda_**4/( numpy.pi**5 * self.Km**2)
4037
4039
4038 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
4040 '''----------- Factor de Reflectividad Equivalente lamda_ < 10 cm , lamda_= 3.2cm-------'''
4039 Zeh = self.Z_radar
4041 Zeh = self.Z_radar
4040
4042
4041 if self.Pt<0.3:
4043 if self.Pt<0.3:
4042 factor=1
4044 factor=1
4043 else:
4045 else:
4044 factor=28#23.072
4046 factor=28#23.072
4045
4047
4046 dBZeh = 10*numpy.log10(Zeh) + factor
4048 dBZeh = 10*numpy.log10(Zeh) + factor
4047 else:
4049 else:
4048 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
4050 self.Z_radar = numpy.zeros((self.nCh,self.nHeis))
4049
4051
4050 for R in range(self.nHeis):
4052 for R in range(self.nHeis):
4051 self.Z_radar[0,R]= 10*numpy.log10(Pr[0,R])+20*numpy.log10(self.Range[0,R]*10**3)+67.41-10*numpy.log10(self.Pt)-59-10*numpy.log10(self.tauW)#63.58,65.26,68.91
4053 self.Z_radar[0,R]= 10*numpy.log10(Pr[0,R])+20*numpy.log10(self.Range[0,R]*10**3)+67.41-10*numpy.log10(self.Pt)-59-10*numpy.log10(self.tauW)#63.58,65.26,68.91
4052 self.Z_radar[1,R]= 10*numpy.log10(Pr[1,R])+20*numpy.log10(self.Range[1,R]*10**3)+67.17-10*numpy.log10(self.Pt)-59-10*numpy.log10(self.tauW)#64.26,65.79,62.33
4054 self.Z_radar[1,R]= 10*numpy.log10(Pr[1,R])+20*numpy.log10(self.Range[1,R]*10**3)+67.17-10*numpy.log10(self.Pt)-59-10*numpy.log10(self.tauW)#64.26,65.79,62.33
4053 dBZeh= self.Z_radar
4055 dBZeh= self.Z_radar
4054
4056
4055 if type=='N':
4057 if type=='N':
4056 return dBZeh
4058 return dBZeh
4057 elif type=='D':
4059 elif type=='D':
4058 Zdb_D = dBZeh[0] - dBZeh[1]- self.sesgoZD
4060 Zdb_D = dBZeh[0] - dBZeh[1]- self.sesgoZD
4059 return Zdb_D
4061 return Zdb_D
4060
4062
4061 def getRadialVelocity_V(self,dataOut):
4063 def getRadialVelocity_V(self,dataOut):
4062 velRadial_V = dataOut.data_param[:,1,:]
4064 velRadial_V = dataOut.data_param[:,1,:]
4063 return velRadial_V
4065 return velRadial_V
4064
4066
4065 def getAnchoEspectral_W(self,dataOut):
4067 def getAnchoEspectral_W(self,dataOut):
4066 Sigmav_W = dataOut.data_param[:,2,:]
4068 Sigmav_W = dataOut.data_param[:,2,:]
4067 return Sigmav_W
4069 return Sigmav_W
4068
4070
4069
4071
4070 def run(self,dataOut,variableList=None,Pt=1.58,Gt=38.5,Gr=38.5,Glna=59.0,lambda_=0.032, aL=1,
4072 def run(self,dataOut,variableList=None,Pt=1.58,Gt=38.5,Gr=38.5,Glna=59.0,lambda_=0.032, aL=1,
4071 tauW= 0.2,thetaT=0.0314,thetaR=0.0314,Km =0.93,CR_Flag=0,min_index=0,sesgoZD=0):
4073 tauW= 0.2,thetaT=0.0314,thetaR=0.0314,Km =0.93,CR_Flag=0,min_index=0,sesgoZD=0):
4072 if not self.isConfig:
4074 if not self.isConfig:
4073 self.setup(dataOut= dataOut, variableList=variableList,Pt=Pt,Gt=Gt,Gr=Gr,Glna=Glna,lambda_=lambda_, aL=aL,
4075 self.setup(dataOut= dataOut, variableList=variableList,Pt=Pt,Gt=Gt,Gr=Gr,Glna=Glna,lambda_=lambda_, aL=aL,
4074 tauW= tauW,thetaT=thetaT,thetaR=thetaR,Km =Km,CR_Flag=CR_Flag,min_index=min_index,sesgoZD=sesgoZD)
4076 tauW= tauW,thetaT=thetaT,thetaR=thetaR,Km =Km,CR_Flag=CR_Flag,min_index=min_index,sesgoZD=sesgoZD)
4075 self.isConfig = True
4077 self.isConfig = True
4076
4078
4077 dataOut.data_param = self.setMoments(dataOut)
4079 dataOut.data_param = self.setMoments(dataOut)
4078
4080
4079 for i in range(len(self.variableList)):
4081 for i in range(len(self.variableList)):
4080 if self.variableList[i] == 'Z':
4082 if self.variableList[i] == 'Z':
4081 dataOut.data_param[:,4,:] =self.getReflectividad_D(dataOut=dataOut,type='N')
4083 dataOut.data_param[:,4,:] =self.getReflectividad_D(dataOut=dataOut,type='N')
4082 if self.variableList[i] == 'D' and dataOut.nChannels>1:
4084 if self.variableList[i] == 'D' and dataOut.nChannels>1:
4083 dataOut.data_param[:,5,:] =self.getReflectividad_D(dataOut=dataOut,type='D')
4085 dataOut.data_param[:,5,:] =self.getReflectividad_D(dataOut=dataOut,type='D')
4084 if self.variableList[i] == 'P' and dataOut.nChannels>1:
4086 if self.variableList[i] == 'P' and dataOut.nChannels>1:
4085 dataOut.data_param[:,6,:] =self.getFasediferencialPhiD_P(dataOut=dataOut, phase=True)
4087 dataOut.data_param[:,6,:] =self.getFasediferencialPhiD_P(dataOut=dataOut, phase=True)
4086 if self.variableList[i] == 'R' and dataOut.nChannels>1:
4088 if self.variableList[i] == 'R' and dataOut.nChannels>1:
4087 dataOut.data_param[:,7,:] = self.getCoeficienteCorrelacionROhv_R(dataOut)
4089 dataOut.data_param[:,7,:] = self.getCoeficienteCorrelacionROhv_R(dataOut)
4088
4090
4089 return dataOut
4091 return dataOut
4090
4092
4091 class PedestalInformation(Operation):
4093 class PedestalInformation(Operation):
4092
4094
4093 def __init__(self):
4095 def __init__(self):
4094 Operation.__init__(self)
4096 Operation.__init__(self)
4095 self.filename = False
4097 self.filename = False
4096 self.delay = 32
4098 self.delay = 32
4097 self.nTries = 3
4099 self.nTries = 3
4098 self.nFiles = 5
4100 self.nFiles = 5
4099 self.flagAskMode = False
4101 self.flagAskMode = False
4100
4102
4101 def find_file(self, timestamp):
4103 def find_file(self, timestamp):
4102
4104
4103 dt = datetime.datetime.utcfromtimestamp(timestamp)
4105 dt = datetime.datetime.utcfromtimestamp(timestamp)
4104 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4106 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4105
4107
4106 if not os.path.exists(path):
4108 if not os.path.exists(path):
4107 return False
4109 return False
4108 fileList = glob.glob(os.path.join(path, '*.h5'))
4110 fileList = glob.glob(os.path.join(path, '*.h5'))
4109 fileList.sort()
4111 fileList.sort()
4110 return fileList
4112 return fileList
4111
4113
4112 def find_next_file(self):
4114 def find_next_file(self):
4113
4115
4114 while True:
4116 while True:
4115 if self.utctime < self.utcfile:
4117 if self.utctime < self.utcfile:
4116 self.flagNoData = True
4118 self.flagNoData = True
4117 break
4119 break
4118 self.flagNoData = False
4120 self.flagNoData = False
4119 file_size = len(self.fp['Data']['utc'])
4121 file_size = len(self.fp['Data']['utc'])
4120 if self.utctime < self.utcfile+file_size*self.interval:
4122 if self.utctime < self.utcfile+file_size*self.interval:
4121 break
4123 break
4122 dt = datetime.datetime.utcfromtimestamp(self.utcfile)
4124 dt = datetime.datetime.utcfromtimestamp(self.utcfile)
4123 if dt.second > 0:
4125 if dt.second > 0:
4124 self.utcfile -= dt.second
4126 self.utcfile -= dt.second
4125 self.utcfile += self.samples*self.interval
4127 self.utcfile += self.samples*self.interval
4126 dt = datetime.datetime.utcfromtimestamp(self.utcfile)
4128 dt = datetime.datetime.utcfromtimestamp(self.utcfile)
4127 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4129 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4128 self.filename = os.path.join(path, 'pos@{}.000.h5'.format(int(self.utcfile)))
4130 self.filename = os.path.join(path, 'pos@{}.000.h5'.format(int(self.utcfile)))
4129
4131
4130 for i in range(self.nFiles):
4132 for i in range(self.nFiles):
4131 ok = False
4133 ok = False
4132 for j in range(self.nTries):
4134 for j in range(self.nTries):
4133 ok = False
4135 ok = False
4134 try:
4136 try:
4135 if not os.path.exists(self.filename):
4137 if not os.path.exists(self.filename):
4136 log.warning('Waiting {}s for position files...'.format(self.delay), self.name)
4138 log.warning('Waiting {}s for position files...'.format(self.delay), self.name)
4137 time.sleep(1)
4139 time.sleep(1)
4138 continue
4140 continue
4139 self.fp.close()
4141 self.fp.close()
4140 self.fp = h5py.File(self.filename, 'r')
4142 self.fp = h5py.File(self.filename, 'r')
4141 self.ele = self.fp['Data']['ele_pos'][:]
4143 self.ele = self.fp['Data']['ele_pos'][:]
4142 self.azi = self.fp['Data']['azi_pos'][:] + 26.27
4144 self.azi = self.fp['Data']['azi_pos'][:] + 26.27
4143 self.azi[self.azi>360] = self.azi[self.azi>360] - 360
4145 self.azi[self.azi>360] = self.azi[self.azi>360] - 360
4144 log.log('Opening file: {}'.format(self.filename), self.name)
4146 log.log('Opening file: {}'.format(self.filename), self.name)
4145 ok = True
4147 ok = True
4146 break
4148 break
4147 except Exception as e:
4149 except Exception as e:
4148 log.warning('Waiting {}s for position file to be ready...'.format(self.delay), self.name)
4150 log.warning('Waiting {}s for position file to be ready...'.format(self.delay), self.name)
4149 time.sleep(self.delay)
4151 time.sleep(self.delay)
4150 continue
4152 continue
4151 if ok:
4153 if ok:
4152 break
4154 break
4153 log.warning('Trying next file...', self.name)
4155 log.warning('Trying next file...', self.name)
4154 self.utcfile += self.samples*self.interval
4156 self.utcfile += self.samples*self.interval
4155 dt = datetime.datetime.utcfromtimestamp(self.utcfile)
4157 dt = datetime.datetime.utcfromtimestamp(self.utcfile)
4156 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4158 path = os.path.join(self.path, dt.strftime('%Y-%m-%dT%H-00-00'))
4157 self.filename = os.path.join(path, 'pos@{}.000.h5'.format(int(self.utcfile)))
4159 self.filename = os.path.join(path, 'pos@{}.000.h5'.format(int(self.utcfile)))
4158 if not ok:
4160 if not ok:
4159 log.error('No new position files found in {}'.format(path))
4161 log.error('No new position files found in {}'.format(path))
4160 raise IOError('No new position files found in {}'.format(path))
4162 raise IOError('No new position files found in {}'.format(path))
4161
4163
4162 def get_values(self):
4164 def get_values(self):
4163
4165
4164 if self.flagNoData:
4166 if self.flagNoData:
4165 return numpy.nan, numpy.nan, numpy.nan #Should be self.mode?
4167 return numpy.nan, numpy.nan, numpy.nan #Should be self.mode?
4166 else:
4168 else:
4167 index = int((self.utctime-self.utcfile)/self.interval)
4169 index = int((self.utctime-self.utcfile)/self.interval)
4168 try:
4170 try:
4169 return self.azi[index], self.ele[index], None
4171 return self.azi[index], self.ele[index], None
4170 except:
4172 except:
4171 return numpy.nan, numpy.nan, numpy.nan
4173 return numpy.nan, numpy.nan, numpy.nan
4172
4174
4173 def setup(self, dataOut, path, conf, samples, interval, mode):
4175 def setup(self, dataOut, path, conf, samples, interval, mode):
4174
4176
4175 self.path = path
4177 self.path = path
4176 self.conf = conf
4178 self.conf = conf
4177 self.samples = samples
4179 self.samples = samples
4178 self.interval = interval
4180 self.interval = interval
4179 self.mode = mode
4181 self.mode = mode
4180 if mode is None:
4182 if mode is None:
4181 self.flagAskMode = True
4183 self.flagAskMode = True
4182 N = 0
4184 N = 0
4183 while True:
4185 while True:
4184 if N == self.nTries+1:
4186 if N == self.nTries+1:
4185 log.error('No position files found in {}'.format(path), self.name)
4187 log.error('No position files found in {}'.format(path), self.name)
4186 raise IOError('No position files found in {}'.format(path))
4188 raise IOError('No position files found in {}'.format(path))
4187 filelist = self.find_file(dataOut.utctime)
4189 filelist = self.find_file(dataOut.utctime)
4188
4190
4189 if filelist == 0:
4191 if filelist == 0:
4190 N += 1
4192 N += 1
4191 log.warning('Waiting {}s for position files...'.format(self.delay), self.name)
4193 log.warning('Waiting {}s for position files...'.format(self.delay), self.name)
4192 time.sleep(self.delay)
4194 time.sleep(self.delay)
4193 continue
4195 continue
4194 self.filename = filelist[0]
4196 self.filename = filelist[0]
4195 try:
4197 try:
4196 self.fp = h5py.File(self.filename, 'r')
4198 self.fp = h5py.File(self.filename, 'r')
4197 self.utcfile = int(self.filename.split('/')[-1][4:14])
4199 self.utcfile = int(self.filename.split('/')[-1][4:14])
4198
4200
4199 self.ele = self.fp['Data']['ele_pos'][:]
4201 self.ele = self.fp['Data']['ele_pos'][:]
4200 self.azi = self.fp['Data']['azi_pos'][:] + 26.27
4202 self.azi = self.fp['Data']['azi_pos'][:] + 26.27
4201 self.azi[self.azi>360] = self.azi[self.azi>360] - 360
4203 self.azi[self.azi>360] = self.azi[self.azi>360] - 360
4202 break
4204 break
4203 except:
4205 except:
4204 log.warning('Waiting {}s for position file to be ready...'.format(self.delay), self.name)
4206 log.warning('Waiting {}s for position file to be ready...'.format(self.delay), self.name)
4205 time.sleep(self.delay)
4207 time.sleep(self.delay)
4206
4208
4207 def run(self, dataOut, path, conf=None, samples=1500, interval=0.04, time_offset=0, mode=None):
4209 def run(self, dataOut, path, conf=None, samples=1500, interval=0.04, time_offset=0, mode=None):
4208
4210
4209 if not self.isConfig:
4211 if not self.isConfig:
4210 self.setup(dataOut, path, conf, samples, interval, mode)
4212 self.setup(dataOut, path, conf, samples, interval, mode)
4211 self.isConfig = True
4213 self.isConfig = True
4212
4214
4213 self.utctime = dataOut.utctime + time_offset
4215 self.utctime = dataOut.utctime + time_offset
4214
4216
4215 self.find_next_file()
4217 self.find_next_file()
4216
4218
4217 az, el, scan = self.get_values()
4219 az, el, scan = self.get_values()
4218
4220
4219 dataOut.flagNoData = False
4221 dataOut.flagNoData = False
4220 if numpy.isnan(az) or numpy.isnan(el) :
4222 if numpy.isnan(az) or numpy.isnan(el) :
4221 dataOut.flagNoData = True
4223 dataOut.flagNoData = True
4222 return dataOut
4224 return dataOut
4223
4225
4224 dataOut.azimuth = round(az, 2)
4226 dataOut.azimuth = round(az, 2)
4225 dataOut.elevation = round(el, 2)
4227 dataOut.elevation = round(el, 2)
4226 dataOut.mode_op = scan
4228 dataOut.mode_op = scan
4227
4229
4228 return dataOut
4230 return dataOut
4229
4231
4230 class Block360(Operation):
4232 class Block360(Operation):
4231 '''
4233 '''
4232 '''
4234 '''
4233 isConfig = False
4235 isConfig = False
4234 __profIndex = 0
4236 __profIndex = 0
4235 __initime = None
4237 __initime = None
4236 __lastdatatime = None
4238 __lastdatatime = None
4237 __buffer = None
4239 __buffer = None
4238 __dataReady = False
4240 __dataReady = False
4239 n = None
4241 n = None
4240 index = 0
4242 index = 0
4241 mode = None
4243 mode = None
4242
4244
4243 def __init__(self,**kwargs):
4245 def __init__(self,**kwargs):
4244 Operation.__init__(self,**kwargs)
4246 Operation.__init__(self,**kwargs)
4245
4247
4246 def setup(self, dataOut, attr, angles,horario):
4248 def setup(self, dataOut, attr, angles,horario):
4247 '''
4249 '''
4248 n= Numero de PRF's de entrada
4250 n= Numero de PRF's de entrada
4249 '''
4251 '''
4250 self.__initime = None
4252 self.__initime = None
4251 self.__lastdatatime = 0
4253 self.__lastdatatime = 0
4252 self.__dataReady = False
4254 self.__dataReady = False
4253 self.__buffer = 0
4255 self.__buffer = 0
4254 self.index = 0
4256 self.index = 0
4255 self.attr = attr
4257 self.attr = attr
4256 self.__buffer = []
4258 self.__buffer = []
4257 self.azi = []
4259 self.azi = []
4258 self.ele = []
4260 self.ele = []
4259 self.angles = angles
4261 self.angles = angles
4260 self.horario= horario
4262 self.horario= horario
4261
4263
4262 def putData(self, data, attr):
4264 def putData(self, data, attr):
4263 '''
4265 '''
4264 Add a profile to he __buffer and increase in one the __profiel Index
4266 Add a profile to he __buffer and increase in one the __profiel Index
4265 '''
4267 '''
4266 tmp= getattr(data, attr)
4268 tmp= getattr(data, attr)
4267 self.__buffer.append(tmp)
4269 self.__buffer.append(tmp)
4268 self.azi.append(data.azimuth)
4270 self.azi.append(data.azimuth)
4269 self.ele.append(data.elevation)
4271 self.ele.append(data.elevation)
4270 self.__profIndex += 1
4272 self.__profIndex += 1
4271
4273
4272 def pushData(self, data, case_flag):
4274 def pushData(self, data, case_flag):
4273 '''
4275 '''
4274 '''
4276 '''
4275
4277
4276 data_360 = numpy.array(self.__buffer).transpose(1, 2, 0, 3)
4278 data_360 = numpy.array(self.__buffer).transpose(1, 2, 0, 3)
4277 data_p = numpy.array(self.azi)
4279 data_p = numpy.array(self.azi)
4278 data_e = numpy.array(self.ele)
4280 data_e = numpy.array(self.ele)
4279 n = self.__profIndex
4281 n = self.__profIndex
4280
4282
4281 self.__buffer = []
4283 self.__buffer = []
4282 self.azi = []
4284 self.azi = []
4283 self.ele = []
4285 self.ele = []
4284 self.__profIndex = 0
4286 self.__profIndex = 0
4285
4287
4286 if case_flag in (0, 1, -1):
4288 if case_flag in (0, 1, -1):
4287 self.putData(data=data, attr = self.attr)
4289 self.putData(data=data, attr = self.attr)
4288
4290
4289 return data_360, n, data_p, data_e
4291 return data_360, n, data_p, data_e
4290
4292
4291 def byProfiles(self, dataOut):
4293 def byProfiles(self, dataOut):
4292
4294
4293 self.__dataReady = False
4295 self.__dataReady = False
4294 data_360 = []
4296 data_360 = []
4295 data_p = None
4297 data_p = None
4296 data_e = None
4298 data_e = None
4297
4299
4298 self.putData(data=dataOut, attr = self.attr)
4300 self.putData(data=dataOut, attr = self.attr)
4299
4301
4300 if self.__profIndex > 5:
4302 if self.__profIndex > 5:
4301 case_flag = self.checkcase()
4303 case_flag = self.checkcase()
4302
4304
4303 if self.flagMode == 1: #'AZI':
4305 if self.flagMode == 1: #'AZI':
4304 if case_flag == 0: #Ya girΓ³
4306 if case_flag == 0: #Ya girΓ³
4305 self.__buffer.pop() #Erase last data
4307 self.__buffer.pop() #Erase last data
4306 self.azi.pop()
4308 self.azi.pop()
4307 self.ele.pop()
4309 self.ele.pop()
4308 data_360 ,n,data_p,data_e = self.pushData(dataOut, case_flag)
4310 data_360 ,n,data_p,data_e = self.pushData(dataOut, case_flag)
4309 if len(data_p)>350:
4311 if len(data_p)>350:
4310 self.__dataReady = True
4312 self.__dataReady = True
4311 elif self.flagMode == 0: #'ELE'
4313 elif self.flagMode == 0: #'ELE'
4312 if case_flag == 1: #Bajada
4314 if case_flag == 1: #Bajada
4313 self.__buffer.pop() #Erase last data
4315 self.__buffer.pop() #Erase last data
4314 self.azi.pop()
4316 self.azi.pop()
4315 self.ele.pop()
4317 self.ele.pop()
4316 data_360, n, data_p, data_e = self.pushData(dataOut, case_flag)
4318 data_360, n, data_p, data_e = self.pushData(dataOut, case_flag)
4317 self.__dataReady = True
4319 self.__dataReady = True
4318 if case_flag == -1: #Subida
4320 if case_flag == -1: #Subida
4319 self.__buffer.pop() #Erase last data
4321 self.__buffer.pop() #Erase last data
4320 self.azi.pop()
4322 self.azi.pop()
4321 self.ele.pop()
4323 self.ele.pop()
4322 data_360, n, data_p, data_e = self.pushData(dataOut, case_flag)
4324 data_360, n, data_p, data_e = self.pushData(dataOut, case_flag)
4323 #self.__dataReady = True
4325 #self.__dataReady = True
4324
4326
4325 return data_360, data_p, data_e
4327 return data_360, data_p, data_e
4326
4328
4327
4329
4328 def blockOp(self, dataOut, datatime= None):
4330 def blockOp(self, dataOut, datatime= None):
4329 if self.__initime == None:
4331 if self.__initime == None:
4330 self.__initime = datatime
4332 self.__initime = datatime
4331 data_360, data_p, data_e = self.byProfiles(dataOut)
4333 data_360, data_p, data_e = self.byProfiles(dataOut)
4332 self.__lastdatatime = datatime
4334 self.__lastdatatime = datatime
4333
4335
4334 avgdatatime = self.__initime
4336 avgdatatime = self.__initime
4335 if self.n==1:
4337 if self.n==1:
4336 avgdatatime = datatime
4338 avgdatatime = datatime
4337
4339
4338 self.__initime = datatime
4340 self.__initime = datatime
4339 return data_360, avgdatatime, data_p, data_e
4341 return data_360, avgdatatime, data_p, data_e
4340
4342
4341 def checkcase(self):
4343 def checkcase(self):
4342
4344
4343 sigma_ele = numpy.nanstd(self.ele[-5:])
4345 sigma_ele = numpy.nanstd(self.ele[-5:])
4344 sigma_azi = numpy.nanstd(self.azi[-5:])
4346 sigma_azi = numpy.nanstd(self.azi[-5:])
4345
4347
4346 if sigma_ele<.5 and sigma_azi<.5:
4348 if sigma_ele<.5 and sigma_azi<.5:
4347 if sigma_ele<sigma_azi:
4349 if sigma_ele<sigma_azi:
4348 self.flagMode = 1
4350 self.flagMode = 1
4349 self.mode_op = 'PPI'
4351 self.mode_op = 'PPI'
4350 else:
4352 else:
4351 self.flagMode = 0
4353 self.flagMode = 0
4352 self.mode_op = 'RHI'
4354 self.mode_op = 'RHI'
4353 elif sigma_ele < .5:
4355 elif sigma_ele < .5:
4354 self.flagMode = 1
4356 self.flagMode = 1
4355 self.mode_op = 'PPI'
4357 self.mode_op = 'PPI'
4356 elif sigma_azi < .5:
4358 elif sigma_azi < .5:
4357 self.flagMode = 0
4359 self.flagMode = 0
4358 self.mode_op = 'RHI'
4360 self.mode_op = 'RHI'
4359 else:
4361 else:
4360 self.flagMode = None
4362 self.flagMode = None
4361 self.mode_op = 'None'
4363 self.mode_op = 'None'
4362
4364
4363 if self.flagMode == 1: #'AZI'
4365 if self.flagMode == 1: #'AZI'
4364 start = self.azi[-2]
4366 start = self.azi[-2]
4365 end = self.azi[-1]
4367 end = self.azi[-1]
4366 diff_angle = (end-start)
4368 diff_angle = (end-start)
4367 if self.horario== True:
4369 if self.horario== True:
4368 if diff_angle < 0: #Ya girΓ³
4370 if diff_angle < 0: #Ya girΓ³
4369 return 0
4371 return 0
4370 else:
4372 else:
4371 if diff_angle > 0: #Ya girΓ³
4373 if diff_angle > 0: #Ya girΓ³
4372 return 0
4374 return 0
4373 elif self.flagMode == 0: #'ELE'
4375 elif self.flagMode == 0: #'ELE'
4374
4376
4375 start = self.ele[-3]
4377 start = self.ele[-3]
4376 middle = self.ele[-2]
4378 middle = self.ele[-2]
4377 end = self.ele[-1]
4379 end = self.ele[-1]
4378
4380
4379 if end < 0:
4381 if end < 0:
4380 return 1
4382 return 1
4381 elif (middle>start and end<middle):
4383 elif (middle>start and end<middle):
4382 return -1
4384 return -1
4383
4385
4384 def run(self, dataOut, attr_data='dataPP_POWER', runNextOp = False, angles=[],horario=True,**kwargs):
4386 def run(self, dataOut, attr_data='dataPP_POWER', runNextOp = False, angles=[],horario=True,**kwargs):
4385
4387
4386 dataOut.attr_data = attr_data
4388 dataOut.attr_data = attr_data
4387 dataOut.runNextOp = runNextOp
4389 dataOut.runNextOp = runNextOp
4388
4390
4389 if not self.isConfig:
4391 if not self.isConfig:
4390 self.setup(dataOut=dataOut, attr=attr_data, angles=angles,horario=horario, **kwargs)
4392 self.setup(dataOut=dataOut, attr=attr_data, angles=angles,horario=horario, **kwargs)
4391 self.isConfig = True
4393 self.isConfig = True
4392
4394
4393 data_360, avgdatatime, data_p, data_e = self.blockOp(dataOut, dataOut.utctime)
4395 data_360, avgdatatime, data_p, data_e = self.blockOp(dataOut, dataOut.utctime)
4394
4396
4395 dataOut.flagNoData = True
4397 dataOut.flagNoData = True
4396 if self.__dataReady:
4398 if self.__dataReady:
4397 mean_az = numpy.mean(data_p[25:-25])
4399 mean_az = numpy.mean(data_p[25:-25])
4398 mean_el = numpy.mean(data_e[25:-25])
4400 mean_el = numpy.mean(data_e[25:-25])
4399 if round(mean_az,1) in angles or round(mean_el,1) in angles:
4401 if round(mean_az,1) in angles or round(mean_el,1) in angles:
4400 setattr(dataOut, attr_data, data_360 )
4402 setattr(dataOut, attr_data, data_360 )
4401 dataOut.data_azi = data_p
4403 dataOut.data_azi = data_p
4402 dataOut.data_ele = data_e
4404 dataOut.data_ele = data_e
4403 dataOut.utctime = avgdatatime
4405 dataOut.utctime = avgdatatime
4404 dataOut.flagNoData = False
4406 dataOut.flagNoData = False
4405 dataOut.flagMode = self.flagMode
4407 dataOut.flagMode = self.flagMode
4406 dataOut.mode_op = self.mode_op
4408 dataOut.mode_op = self.mode_op
4407 else:
4409 else:
4408 log.warning('Skipping angle {} / {}'.format(round(mean_az,1), round(mean_el,1)))
4410 log.warning('Skipping angle {} / {}'.format(round(mean_az,1), round(mean_el,1)))
4409
4411
4410 return dataOut
4412 return dataOut
4411
4413
4412 class MergeProc(ProcessingUnit):
4414 class MergeProc(ProcessingUnit):
4413
4415
4414 def __init__(self):
4416 def __init__(self):
4415 ProcessingUnit.__init__(self)
4417 ProcessingUnit.__init__(self)
4416
4418
4417 def run(self, attr_data, mode=0):
4419 def run(self, attr_data, mode=0):
4418
4420
4419 #exit(1)
4421 #exit(1)
4420 self.dataOut = getattr(self, self.inputs[0])
4422 self.dataOut = getattr(self, self.inputs[0])
4421 data_inputs = [getattr(self, attr) for attr in self.inputs]
4423 data_inputs = [getattr(self, attr) for attr in self.inputs]
4422 #print(data_inputs)
4424 #print(data_inputs)
4423 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
4425 #print(numpy.shape([getattr(data, attr_data) for data in data_inputs][1]))
4424 #exit(1)
4426 #exit(1)
4425 if mode==0:
4427 if mode==0:
4426 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
4428 data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs])
4427 setattr(self.dataOut, attr_data, data)
4429 setattr(self.dataOut, attr_data, data)
4428
4430
4429 if mode==1: #Hybrid
4431 if mode==1: #Hybrid
4430 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
4432 #data = numpy.concatenate([getattr(data, attr_data) for data in data_inputs],axis=1)
4431 #setattr(self.dataOut, attr_data, data)
4433 #setattr(self.dataOut, attr_data, data)
4432 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
4434 setattr(self.dataOut, 'dataLag_spc', [getattr(data, attr_data) for data in data_inputs][0])
4433 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
4435 setattr(self.dataOut, 'dataLag_spc_LP', [getattr(data, attr_data) for data in data_inputs][1])
4434 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
4436 setattr(self.dataOut, 'dataLag_cspc', [getattr(data, attr_data_2) for data in data_inputs][0])
4435 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
4437 setattr(self.dataOut, 'dataLag_cspc_LP', [getattr(data, attr_data_2) for data in data_inputs][1])
4436 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
4438 #setattr(self.dataOut, 'nIncohInt', [getattr(data, attr_data_3) for data in data_inputs][0])
4437 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
4439 #setattr(self.dataOut, 'nIncohInt_LP', [getattr(data, attr_data_3) for data in data_inputs][1])
4438 '''
4440 '''
4439 print(self.dataOut.dataLag_spc_LP.shape)
4441 print(self.dataOut.dataLag_spc_LP.shape)
4440 print(self.dataOut.dataLag_cspc_LP.shape)
4442 print(self.dataOut.dataLag_cspc_LP.shape)
4441 exit(1)
4443 exit(1)
4442 '''
4444 '''
4443
4445
4444 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
4446 #self.dataOut.dataLag_spc_LP = numpy.transpose(self.dataOut.dataLag_spc_LP[0],(2,0,1))
4445 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
4447 #self.dataOut.dataLag_cspc_LP = numpy.transpose(self.dataOut.dataLag_cspc_LP,(3,1,2,0))
4446 '''
4448 '''
4447 print("Merge")
4449 print("Merge")
4448 print(numpy.shape(self.dataOut.dataLag_spc))
4450 print(numpy.shape(self.dataOut.dataLag_spc))
4449 print(numpy.shape(self.dataOut.dataLag_spc_LP))
4451 print(numpy.shape(self.dataOut.dataLag_spc_LP))
4450 print(numpy.shape(self.dataOut.dataLag_cspc))
4452 print(numpy.shape(self.dataOut.dataLag_cspc))
4451 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
4453 print(numpy.shape(self.dataOut.dataLag_cspc_LP))
4452 exit(1)
4454 exit(1)
4453 '''
4455 '''
4454 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
4456 #print(numpy.sum(self.dataOut.dataLag_spc_LP[2,:,164])/128)
4455 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
4457 #print(numpy.sum(self.dataOut.dataLag_cspc_LP[0,:,30,1])/128)
4456 #exit(1)
4458 #exit(1)
4457 #print(self.dataOut.NDP)
4459 #print(self.dataOut.NDP)
4458 #print(self.dataOut.nNoiseProfiles)
4460 #print(self.dataOut.nNoiseProfiles)
4459
4461
4460 #self.dataOut.nIncohInt_LP = 128
4462 #self.dataOut.nIncohInt_LP = 128
4461 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
4463 self.dataOut.nProfiles_LP = 128#self.dataOut.nIncohInt_LP
4462 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
4464 self.dataOut.nIncohInt_LP = self.dataOut.nIncohInt
4463 self.dataOut.NLAG = 16
4465 self.dataOut.NLAG = 16
4464 self.dataOut.NRANGE = 200
4466 self.dataOut.NRANGE = 200
4465 self.dataOut.NSCAN = 128
4467 self.dataOut.NSCAN = 128
4466 #print(numpy.shape(self.dataOut.data_spc))
4468 #print(numpy.shape(self.dataOut.data_spc))
4467
4469
4468 #exit(1)
4470 #exit(1)
4469
4471
4470 if mode==2: #HAE 2022
4472 if mode==2: #HAE 2022
4471 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
4473 data = numpy.sum([getattr(data, attr_data) for data in data_inputs],axis=0)
4472 setattr(self.dataOut, attr_data, data)
4474 setattr(self.dataOut, attr_data, data)
4473
4475
4474 self.dataOut.nIncohInt *= 2
4476 self.dataOut.nIncohInt *= 2
4475 #meta = self.dataOut.getFreqRange(1)/1000.
4477 #meta = self.dataOut.getFreqRange(1)/1000.
4476 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
4478 self.dataOut.freqRange = self.dataOut.getFreqRange(1)/1000.
4477
4479
4478 #exit(1)
4480 #exit(1)
4479
4481
4480 if mode==7: #RM
4482 if mode==7: #RM
4481
4483
4482 f = [getattr(data, attr_data) for data in data_inputs][0]
4484 f = [getattr(data, attr_data) for data in data_inputs][0]
4483 g = [getattr(data, attr_data) for data in data_inputs][1]
4485 g = [getattr(data, attr_data) for data in data_inputs][1]
4484 data = numpy.concatenate((f,g),axis=3)
4486 data = numpy.concatenate((f,g),axis=3)
4485 setattr(self.dataOut, attr_data, data)
4487 setattr(self.dataOut, attr_data, data)
4486
4488
4487 # snr
4489 # snr
4488 # self.dataOut.data_snr = numpy.concatenate((data_inputs[0].data_snr, data_inputs[1].data_snr), axis=2)
4490 # self.dataOut.data_snr = numpy.concatenate((data_inputs[0].data_snr, data_inputs[1].data_snr), axis=2)
4489
4491
4490 # ranges
4492 # ranges
4491 dh = self.dataOut.heightList[1]-self.dataOut.heightList[0]
4493 dh = self.dataOut.heightList[1]-self.dataOut.heightList[0]
4492 heightList_2 = (self.dataOut.heightList[-1]+dh) + numpy.arange(g.shape[-1], dtype=numpy.float) * dh
4494 heightList_2 = (self.dataOut.heightList[-1]+dh) + numpy.arange(g.shape[-1], dtype=numpy.float) * dh
4493
4495
4494 self.dataOut.heightList = numpy.concatenate((self.dataOut.heightList,heightList_2))
4496 self.dataOut.heightList = numpy.concatenate((self.dataOut.heightList,heightList_2))
@@ -1,375 +1,375
1 # SOPHY PROC script
1 # SOPHY PROC script
2 import os, sys, json, argparse
2 import os, sys, json, argparse
3 import datetime
3 import datetime
4 import time
4 import time
5
5
6 PATH = '/DATA_RM/DATA'
6 PATH = '/DATA_RM/DATA'
7 PATH = '/media/jespinoza/Elements'
7 PATH = '/media/jespinoza/Elements'
8 PATH = '/media/jespinoza/data/SOPHY'
8 PATH = '/media/jespinoza/data/SOPHY'
9 PATH = '/home/soporte/Documents/EVENTO'
9 PATH = '/home/soporte/Documents/EVENTO'
10
10
11 PARAM = {
11 PARAM = {
12 'S': {'zmin': -45, 'zmax': -25, 'colormap': 'jet', 'label': 'Power', 'wrname': 'power','cb_label': 'dBm', 'ch':0},
12 'S': {'zmin': -45, 'zmax': -25, 'colormap': 'jet', 'label': 'Power', 'wrname': 'power','cb_label': 'dBm', 'ch':0},
13 'SNR': {'zmin': -40, 'zmax': -20, 'colormap': 'jet', 'label': 'SNR', 'wrname': 'snr','cb_label': 'dB', 'ch':0},
13 'SNR': {'zmin': -40, 'zmax': -20, 'colormap': 'jet', 'label': 'SNR', 'wrname': 'snr','cb_label': 'dB', 'ch':0},
14 'V': {'zmin': -12, 'zmax': 12, 'colormap': 'sophy_v', 'label': 'Velocity', 'wrname': 'velocity', 'cb_label': 'm/s', 'ch':0},
14 'V': {'zmin': -12, 'zmax': 12, 'colormap': 'sophy_v', 'label': 'Velocity', 'wrname': 'velocity', 'cb_label': 'm/s', 'ch':0},
15 'R': {'zmin': 0, 'zmax': 1, 'colormap': 'jet', 'label': 'RhoHV', 'wrname':'rhoHV', 'cb_label': '*', 'ch':0},
15 'R': {'zmin': 0, 'zmax': 1, 'colormap': 'jet', 'label': 'RhoHV', 'wrname':'rhoHV', 'cb_label': '*', 'ch':0},
16 'P': {'zmin': -180,'zmax': 180,'colormap': 'RdBu_r', 'label': 'PhiDP', 'wrname':'phiDP' , 'cb_label': 'ΒΊ', 'ch':0},
16 'P': {'zmin': -180,'zmax': 180,'colormap': 'RdBu_r', 'label': 'PhiDP', 'wrname':'phiDP' , 'cb_label': 'ΒΊ', 'ch':0},
17 'D': {'zmin': -30, 'zmax': 80, 'colormap': 'sophy_r','label': 'ZDR','wrname':'differential_reflectivity' , 'cb_label': 'dBz','ch':0},
17 'D': {'zmin': -30, 'zmax': 80, 'colormap': 'sophy_r','label': 'ZDR','wrname':'differential_reflectivity' , 'cb_label': 'dBz','ch':0},
18 'Z': {'zmin': -30, 'zmax': 80, 'colormap': 'sophy_r','label': 'Reflectivity ', 'wrname':'reflectivity', 'cb_label': 'dBz','ch':0},
18 'Z': {'zmin': -30, 'zmax': 80, 'colormap': 'sophy_r','label': 'Reflectivity ', 'wrname':'reflectivity', 'cb_label': 'dBz','ch':0},
19 'W': {'zmin': 0, 'zmax': 15, 'colormap': 'sophy_w','label': 'Spectral Width', 'wrname':'spectral_width', 'cb_label': 'm/s', 'ch':0}
19 'W': {'zmin': 0, 'zmax': 15, 'colormap': 'sophy_w','label': 'Spectral Width', 'wrname':'spectral_width', 'cb_label': 'm/s', 'ch':0}
20 }
20 }
21
21
22 def max_index(r, sample_rate, ipp):
22 def max_index(r, sample_rate, ipp):
23
23
24 return int(sample_rate*ipp*1e6 * r / 60) + int(sample_rate*ipp*1e6 * 1.2 / 60)
24 return int(sample_rate*ipp*1e6 * r / 60) + int(sample_rate*ipp*1e6 * 1.2 / 60)
25
25
26 def main(args):
26 def main(args):
27
27
28 experiment = args.experiment
28 experiment = args.experiment
29 fp = open(os.path.join(PATH, experiment, 'experiment.conf'))
29 fp = open(os.path.join(PATH, experiment, 'experiment.conf'))
30 conf = json.loads(fp.read())
30 conf = json.loads(fp.read())
31
31
32 ipp_km = conf['usrp_tx']['ipp']
32 ipp_km = conf['usrp_tx']['ipp']
33 ipp = ipp_km * 2 /300000
33 ipp = ipp_km * 2 /300000
34 sample_rate = conf['usrp_rx']['sample_rate']
34 sample_rate = conf['usrp_rx']['sample_rate']
35 axis = ['0' if x=='elevation' else '1' for x in conf['pedestal']['axis']] # AZIMUTH 1 ELEVACION 0
35 axis = ['0' if x=='elevation' else '1' for x in conf['pedestal']['axis']] # AZIMUTH 1 ELEVACION 0
36 speed_axis = conf['pedestal']['speed']
36 speed_axis = conf['pedestal']['speed']
37 steps = conf['pedestal']['table']
37 steps = conf['pedestal']['table']
38 time_offset = args.time_offset
38 time_offset = args.time_offset
39 parameters = args.parameters
39 parameters = args.parameters
40 start_date = experiment.split('@')[1].split('T')[0].replace('-', '/')
40 start_date = experiment.split('@')[1].split('T')[0].replace('-', '/')
41 end_date = start_date
41 end_date = start_date
42 if args.start_time:
42 if args.start_time:
43 start_time = args.start_time
43 start_time = args.start_time
44 else:
44 else:
45 start_time = experiment.split('@')[1].split('T')[1].replace('-', ':')
45 start_time = experiment.split('@')[1].split('T')[1].replace('-', ':')
46 end_time = '23:59:59'
46 end_time = '23:59:59'
47 N = int(1/(speed_axis[0]*ipp)) # 1 GRADO DE RESOLUCION
47 N = int(1/(speed_axis[0]*ipp)) # 1 GRADO DE RESOLUCION
48 path = os.path.join(PATH, experiment, 'rawdata')
48 path = os.path.join(PATH, experiment, 'rawdata')
49 path_ped = os.path.join(PATH, experiment, 'position')
49 path_ped = os.path.join(PATH, experiment, 'position')
50 path_plots = os.path.join(PATH, experiment, 'plotsC0N'+str(args.range))
50 path_plots = os.path.join(PATH, experiment, 'plotsC0N'+str(args.range))
51 path_save = os.path.join(PATH, experiment, 'paramC0N'+str(args.range))
51 path_save = os.path.join(PATH, experiment, 'paramC0N'+str(args.range))
52 RMIX = 1.62
52 RMIX = 1.62
53 H0 = -1.68
53 H0 = -1.68
54 MASK = 0.3
54 MASK = 0.3
55
55
56 from schainpy.controller import Project
56 from schainpy.controller import Project
57
57
58 project = Project()
58 project = Project()
59 project.setup(id='1', name='Sophy', description='sophy proc')
59 project.setup(id='1', name='Sophy', description='sophy proc')
60
60
61 reader = project.addReadUnit(datatype='DigitalRFReader',
61 reader = project.addReadUnit(datatype='DigitalRFReader',
62 path=path,
62 path=path,
63 startDate=start_date,
63 startDate=start_date,
64 endDate=end_date,
64 endDate=end_date,
65 startTime=start_time,
65 startTime=start_time,
66 endTime=end_time,
66 endTime=end_time,
67 delay=30,
67 delay=30,
68 online=args.online,
68 online=args.online,
69 walk=1,
69 walk=1,
70 ippKm = ipp_km,
70 ippKm = ipp_km,
71 getByBlock = 1,
71 getByBlock = 1,
72 nProfileBlocks = N,
72 nProfileBlocks = N,
73 )
73 )
74
74
75 if not conf['usrp_tx']['enable_2']: # One Pulse
75 if not conf['usrp_tx']['enable_2']: # One Pulse
76 voltage = project.addProcUnit(datatype='VoltageProc', inputId=reader.getId())
76 voltage = project.addProcUnit(datatype='VoltageProc', inputId=reader.getId())
77
77
78 if conf['usrp_tx']['code_type_1'] != 'None':
78 if conf['usrp_tx']['code_type_1'] != 'None':
79 codes = [ c.strip() for c in conf['usrp_tx']['code_1'].split(',')]
79 codes = [ c.strip() for c in conf['usrp_tx']['code_1'].split(',')]
80 code = []
80 code = []
81 for c in codes:
81 for c in codes:
82 code.append([int(x) for x in c])
82 code.append([int(x) for x in c])
83 op = voltage.addOperation(name='Decoder', optype='other')
83 op = voltage.addOperation(name='Decoder', optype='other')
84 op.addParameter(name='code', value=code)
84 op.addParameter(name='code', value=code)
85 op.addParameter(name='nCode', value=len(code), format='int')
85 op.addParameter(name='nCode', value=len(code), format='int')
86 op.addParameter(name='nBaud', value=len(code[0]), format='int')
86 op.addParameter(name='nBaud', value=len(code[0]), format='int')
87
87
88 op = voltage.addOperation(name='CohInt', optype='other') #Minimo integrar 2 perfiles por ser codigo complementario
88 op = voltage.addOperation(name='CohInt', optype='other') #Minimo integrar 2 perfiles por ser codigo complementario
89 op.addParameter(name='n', value=len(code), format='int')
89 op.addParameter(name='n', value=len(code), format='int')
90 ncode = len(code)
90 ncode = len(code)
91 else:
91 else:
92 ncode = 1
92 ncode = 1
93 code = ['0']
93 code = ['0']
94
94
95 op = voltage.addOperation(name='setH0')
95 op = voltage.addOperation(name='setH0')
96 op.addParameter(name='h0', value=H0)
96 op.addParameter(name='h0', value=H0)
97
97
98 if args.range > 0:
98 if args.range > 0:
99 op = voltage.addOperation(name='selectHeights')
99 op = voltage.addOperation(name='selectHeights')
100 op.addParameter(name='minIndex', value='0', format='int')
100 op.addParameter(name='minIndex', value='0', format='int')
101 op.addParameter(name='maxIndex', value=max_index(args.range, sample_rate, ipp), format='int')
101 op.addParameter(name='maxIndex', value=max_index(args.range, sample_rate, ipp), format='int')
102
102
103 op = voltage.addOperation(name='PulsePair_vRF', optype='other')
103 op = voltage.addOperation(name='PulsePair_vRF', optype='other')
104 op.addParameter(name='n', value=int(N)/ncode, format='int')
104 op.addParameter(name='n', value=int(N)/ncode, format='int')
105 #op.addParameter(name='removeDC', value=1, format='int')
105 #op.addParameter(name='removeDC', value=1, format='int')
106
106
107
107
108 proc = project.addProcUnit(datatype='ParametersProc', inputId=voltage.getId())
108 proc = project.addProcUnit(datatype='ParametersProc', inputId=voltage.getId())
109
109
110 opObj10 = proc.addOperation(name="WeatherRadar")
110 opObj10 = proc.addOperation(name="WeatherRadar")
111 opObj10.addParameter(name='tauW',value=(1e-6/sample_rate)*len(code[0]))
111 opObj10.addParameter(name='tauW',value=(1e-6/sample_rate)*len(code[0]))
112 opObj10.addParameter(name='Pt',value=((1e-6/sample_rate)*len(code[0])/ipp)*200)
112 opObj10.addParameter(name='Pt',value=((1e-6/sample_rate)*len(code[0])/ipp)*200)
113
113
114 op = proc.addOperation(name='PedestalInformation')
114 op = proc.addOperation(name='PedestalInformation')
115 op.addParameter(name='path', value=path_ped, format='str')
115 op.addParameter(name='path', value=path_ped, format='str')
116 op.addParameter(name='interval', value='0.04')
116 op.addParameter(name='interval', value='0.04')
117 op.addParameter(name='time_offset', value=time_offset)
117 op.addParameter(name='time_offset', value=time_offset)
118 op.addParameter(name='mode', value='PPI')
118 op.addParameter(name='mode', value='PPI')
119
119
120 for param in parameters:
120 for param in parameters:
121 op = proc.addOperation(name='Block360')
121 op = proc.addOperation(name='Block360')
122 op.addParameter(name='runNextOp', value=True)
122 op.addParameter(name='runNextOp', value=True)
123
123
124 op= proc.addOperation(name='WeatherParamsPlot')
124 op= proc.addOperation(name='WeatherParamsPlot')
125 if args.save: op.addParameter(name='save', value=path_plots, format='str')
125 if args.save: op.addParameter(name='save', value=path_plots, format='str')
126 op.addParameter(name='save_period', value=-1)
126 op.addParameter(name='save_period', value=-1)
127 op.addParameter(name='show', value=args.show)
127 op.addParameter(name='show', value=args.show)
128 op.addParameter(name='channels', value='1,')
128 op.addParameter(name='channels', value='1,')
129 op.addParameter(name='zmin', value=PARAM[param]['zmin'])
129 op.addParameter(name='zmin', value=PARAM[param]['zmin'])
130 op.addParameter(name='zmax', value=PARAM[param]['zmax'])
130 op.addParameter(name='zmax', value=PARAM[param]['zmax'])
131 op.addParameter(name='attr_data', value=param, format='str')
131 op.addParameter(name='attr_data', value=param, format='str')
132 op.addParameter(name='labels', value=[PARAM[param]['label']])
132 op.addParameter(name='labels', value=[PARAM[param]['label']])
133 op.addParameter(name='save_code', value=param)
133 op.addParameter(name='save_code', value=param)
134 op.addParameter(name='cb_label', value=PARAM[param]['cb_label'])
134 op.addParameter(name='cb_label', value=PARAM[param]['cb_label'])
135 op.addParameter(name='colormap', value=PARAM[param]['colormap'])
135 op.addParameter(name='colormap', value=PARAM[param]['colormap'])
136 op.addParameter(name='bgcolor', value='black')
136 op.addParameter(name='bgcolor', value='black')
137 if MASK: op.addParameter(name='mask', value=MASK, format='float')
137 if MASK: op.addParameter(name='mask', value=MASK, format='float')
138 if args.server:
138 if args.server:
139 op.addParameter(name='server', value='0.0.0.0:4444')
139 op.addParameter(name='server', value='0.0.0.0:4444')
140 op.addParameter(name='exp_code', value='400')
140 op.addParameter(name='exp_code', value='400')
141
141
142 desc = {
142 desc = {
143 'Data': {
143 'Data': {
144 param: PARAM[param]['wrname'],
144 param: PARAM[param]['wrname'],
145 'utctime': 'time'
145 'utctime': 'time'
146 },
146 },
147 'Metadata': {
147 'Metadata': {
148 'heightList': 'range',
148 'heightList': 'range',
149 'data_azi': 'azimuth',
149 'data_azi': 'azimuth',
150 'data_ele': 'elevation',
150 'data_ele': 'elevation',
151 'mode_op': 'scan_type',
151 'mode_op': 'scan_type',
152 'h0': 'range_correction',
152 'h0': 'range_correction',
153 }
153 }
154 }
154 }
155
155
156 if args.save:
156 if args.save:
157 opObj10 = proc.addOperation(name='HDFWriter')
157 opObj10 = proc.addOperation(name='HDFWriter')
158 writer.addParameter(name='path', value=path_save, format='str')
158 writer.addParameter(name='path', value=path_save, format='str')
159 writer.addParameter(name='Reset', value=True)
159 writer.addParameter(name='Reset', value=True)
160 writer.addParameter(name='setType', value='weather')
160 writer.addParameter(name='setType', value='weather')
161 writer.addParameter(name='description', value=json.dumps(desc))
161 writer.addParameter(name='description', value=json.dumps(desc))
162 writer.addParameter(name='blocksPerFile', value='1',format='int')
162 writer.addParameter(name='blocksPerFile', value='1',format='int')
163 writer.addParameter(name='metadataList', value='heightList,data_azi,data_ele,mode_op,latitude,longitude,altitude,heading,radar_name,institution,contact,h0,range_unit')
163 writer.addParameter(name='metadataList', value='heightList,data_azi,data_ele,mode_op,latitude,longitude,altitude,heading,radar_name,institution,contact,h0,range_unit')
164 writer.addParameter(name='dataList', value='{},utctime'.format(param))
164 writer.addParameter(name='dataList', value='{},utctime'.format(param))
165 writer.addParameter(name='mask', value=MASK, format='float')
165 writer.addParameter(name='mask', value=MASK, format='float')
166 # meta
166 # meta
167 writer.addParameter(name='latitude', value='-12.040436')
167 writer.addParameter(name='latitude', value='-12.040436')
168 writer.addParameter(name='longitude', value='-75.295893')
168 writer.addParameter(name='longitude', value='-75.295893')
169 writer.addParameter(name='altitude', value='3379.2147')
169 writer.addParameter(name='altitude', value='3379.2147')
170 writer.addParameter(name='heading', value='0')
170 writer.addParameter(name='heading', value='0')
171 writer.addParameter(name='radar_name', value='SOPHy')
171 writer.addParameter(name='radar_name', value='SOPHy')
172 writer.addParameter(name='institution', value='IGP')
172 writer.addParameter(name='institution', value='IGP')
173 writer.addParameter(name='contact', value='dscipion@igp.gob.pe')
173 writer.addParameter(name='contact', value='dscipion@igp.gob.pe')
174 writer.addParameter(name='created_by', value='Signal Chain (https://pypi.org/project/schainpy/)')
174 writer.addParameter(name='created_by', value='Signal Chain (https://pypi.org/project/schainpy/)')
175 writer.addParameter(name='range_unit', value='km')
175 writer.addParameter(name='range_unit', value='km')
176
176
177 else: #Two pulses
177 else: #Two pulses
178
178
179 voltage1 = project.addProcUnit(datatype='VoltageProc', inputId=reader.getId())
179 voltage1 = project.addProcUnit(datatype='VoltageProc', inputId=reader.getId())
180
180
181 op = voltage1.addOperation(name='ProfileSelector')
181 op = voltage1.addOperation(name='ProfileSelector')
182 op.addParameter(name='profileRangeList', value='0,{}'.format(conf['usrp_tx']['repetitions_1']-1))
182 op.addParameter(name='profileRangeList', value='0,{}'.format(conf['usrp_tx']['repetitions_1']-1))
183
183
184 if conf['usrp_tx']['code_type_1'] != 'None':
184 if conf['usrp_tx']['code_type_1'] != 'None':
185 codes = [ c.strip() for c in conf['usrp_tx']['code_1'].split(',')]
185 codes = [ c.strip() for c in conf['usrp_tx']['code_1'].split(',')]
186 code = []
186 code = []
187 for c in codes:
187 for c in codes:
188 code.append([int(x) for x in c])
188 code.append([int(x) for x in c])
189 op = voltage1.addOperation(name='Decoder', optype='other')
189 op = voltage1.addOperation(name='Decoder', optype='other')
190 op.addParameter(name='code', value=code)
190 op.addParameter(name='code', value=code)
191 op.addParameter(name='nCode', value=len(code), format='int')
191 op.addParameter(name='nCode', value=len(code), format='int')
192 op.addParameter(name='nBaud', value=len(code[0]), format='int')
192 op.addParameter(name='nBaud', value=len(code[0]), format='int')
193 else:
193 else:
194 code = ['0']
194 code = ['0']
195
195
196 op = voltage1.addOperation(name='CohInt', optype='other') #Minimo integrar 2 perfiles por ser codigo complementario
196 op = voltage1.addOperation(name='CohInt', optype='other') #Minimo integrar 2 perfiles por ser codigo complementario
197 op.addParameter(name='n', value=2, format='int')
197 op.addParameter(name='n', value=2, format='int')
198
198
199 if args.range > 0:
199 if args.range > 0:
200 op = voltage1.addOperation(name='selectHeights')
200 op = voltage1.addOperation(name='selectHeights')
201 op.addParameter(name='minIndex', value='0', format='int')
201 op.addParameter(name='minIndex', value='0', format='int')
202 op.addParameter(name='maxIndex', value=max_index(RMIX, sample_rate, ipp), format='int')
202 op.addParameter(name='maxIndex', value=max_index(RMIX, sample_rate, ipp), format='int')
203
203
204 op = voltage1.addOperation(name='setH0')
204 op = voltage1.addOperation(name='setH0')
205 op.addParameter(name='h0', value=H0, format='float')
205 op.addParameter(name='h0', value=H0, format='float')
206
206
207 op = voltage1.addOperation(name='PulsePair_vRF', optype='other')
207 op = voltage1.addOperation(name='PulsePair_vRF', optype='other')
208 op.addParameter(name='n', value=int(conf['usrp_tx']['repetitions_1'])/2, format='int')
208 op.addParameter(name='n', value=int(conf['usrp_tx']['repetitions_1'])/2, format='int')
209 #op.addParameter(name='removeDC', value=1, format='int')
209 #op.addParameter(name='removeDC', value=1, format='int')
210
210
211
211
212 proc1 = project.addProcUnit(datatype='ParametersProc', inputId=voltage1.getId())
212 proc1 = project.addProcUnit(datatype='ParametersProc', inputId=voltage1.getId())
213 proc1.addParameter(name='runNextUnit', value=True)
213 proc1.addParameter(name='runNextUnit', value=True)
214
214
215 opObj10 = proc1.addOperation(name="WeatherRadar")
215 opObj10 = proc1.addOperation(name="WeatherRadar")
216 opObj10.addParameter(name='tauW',value=(1e-6/sample_rate)*len(code[0]))
216 opObj10.addParameter(name='tauW',value=(1e-6/sample_rate)*len(code[0]))
217 opObj10.addParameter(name='Pt',value=((1e-6/sample_rate)*len(code[0])/ipp)*200)
217 opObj10.addParameter(name='Pt',value=200)
218
218
219 op = proc1.addOperation(name='PedestalInformation')
219 op = proc1.addOperation(name='PedestalInformation')
220 op.addParameter(name='path', value=path_ped, format='str')
220 op.addParameter(name='path', value=path_ped, format='str')
221 op.addParameter(name='interval', value='0.04')
221 op.addParameter(name='interval', value='0.04')
222 op.addParameter(name='time_offset', value=time_offset)
222 op.addParameter(name='time_offset', value=time_offset)
223 op.addParameter(name='mode', value='PPI')
223 op.addParameter(name='mode', value='PPI')
224
224
225 op = proc1.addOperation(name='Block360')
225 op = proc1.addOperation(name='Block360')
226 op.addParameter(name='attr_data', value='data_param')
226 op.addParameter(name='attr_data', value='data_param')
227 op.addParameter(name='runNextOp', value=True)
227 op.addParameter(name='runNextOp', value=True)
228
228
229
229
230 voltage2 = project.addProcUnit(datatype='VoltageProc', inputId=reader.getId())
230 voltage2 = project.addProcUnit(datatype='VoltageProc', inputId=reader.getId())
231
231
232 op = voltage2.addOperation(name='ProfileSelector')
232 op = voltage2.addOperation(name='ProfileSelector')
233 op.addParameter(name='profileRangeList', value='{},{}'.format(conf['usrp_tx']['repetitions_1'], conf['usrp_tx']['repetitions_1']+conf['usrp_tx']['repetitions_2']-1))
233 op.addParameter(name='profileRangeList', value='{},{}'.format(conf['usrp_tx']['repetitions_1'], conf['usrp_tx']['repetitions_1']+conf['usrp_tx']['repetitions_2']-1))
234
234
235 if conf['usrp_tx']['code_type_2']:
235 if conf['usrp_tx']['code_type_2']:
236 codes = [ c.strip() for c in conf['usrp_tx']['code_2'].split(',')]
236 codes = [ c.strip() for c in conf['usrp_tx']['code_2'].split(',')]
237 code = []
237 code = []
238 for c in codes:
238 for c in codes:
239 code.append([int(x) for x in c])
239 code.append([int(x) for x in c])
240 op = voltage2.addOperation(name='Decoder', optype='other')
240 op = voltage2.addOperation(name='Decoder', optype='other')
241 op.addParameter(name='code', value=code)
241 op.addParameter(name='code', value=code)
242 op.addParameter(name='nCode', value=len(code), format='int')
242 op.addParameter(name='nCode', value=len(code), format='int')
243 op.addParameter(name='nBaud', value=len(code[0]), format='int')
243 op.addParameter(name='nBaud', value=len(code[0]), format='int')
244
244
245 op = voltage2.addOperation(name='CohInt', optype='other') #Minimo integrar 2 perfiles por ser codigo complementario
245 op = voltage2.addOperation(name='CohInt', optype='other') #Minimo integrar 2 perfiles por ser codigo complementario
246 op.addParameter(name='n', value=len(code), format='int')
246 op.addParameter(name='n', value=len(code), format='int')
247 ncode = len(code)
247 ncode = len(code)
248 else:
248 else:
249 ncode = 1
249 ncode = 1
250
250
251 if args.range > 0:
251 if args.range > 0:
252 op = voltage2.addOperation(name='selectHeights')
252 op = voltage2.addOperation(name='selectHeights')
253 op.addParameter(name='minIndex', value=max_index(RMIX, sample_rate, ipp), format='int')
253 op.addParameter(name='minIndex', value=max_index(RMIX, sample_rate, ipp), format='int')
254 op.addParameter(name='maxIndex', value=max_index(args.range, sample_rate, ipp), format='int')
254 op.addParameter(name='maxIndex', value=max_index(args.range, sample_rate, ipp), format='int')
255
255
256 op = voltage2.addOperation(name='setH0')
256 op = voltage2.addOperation(name='setH0')
257 op.addParameter(name='h0', value=H0, format='float')
257 op.addParameter(name='h0', value=H0, format='float')
258
258
259 op = voltage2.addOperation(name='PulsePair_vRF', optype='other')
259 op = voltage2.addOperation(name='PulsePair_vRF', optype='other')
260 op.addParameter(name='n', value=int(conf['usrp_tx']['repetitions_2'])/ncode, format='int')
260 op.addParameter(name='n', value=int(conf['usrp_tx']['repetitions_2'])/ncode, format='int')
261 #op.addParameter(name='removeDC', value=1, format='int')
261 #op.addParameter(name='removeDC', value=1, format='int')
262
262
263
263
264 proc2 = project.addProcUnit(datatype='ParametersProc', inputId=voltage2.getId())
264 proc2 = project.addProcUnit(datatype='ParametersProc', inputId=voltage2.getId())
265 proc2.addParameter(name='runNextUnit', value=True)
265 proc2.addParameter(name='runNextUnit', value=True)
266
266
267 opObj10 = proc2.addOperation(name="WeatherRadar")
267 opObj10 = proc2.addOperation(name="WeatherRadar")
268 opObj10.addParameter(name='tauW',value=(1e-6/sample_rate)*len(code[0]))
268 opObj10.addParameter(name='tauW',value=(1e-6/sample_rate)*len(code[0]))
269 opObj10.addParameter(name='Pt',value=((1e-6/sample_rate)*len(code[0])/ipp)*200)
269 opObj10.addParameter(name='Pt',value=200)
270
270
271 op = proc2.addOperation(name='PedestalInformation')
271 op = proc2.addOperation(name='PedestalInformation')
272 op.addParameter(name='path', value=path_ped, format='str')
272 op.addParameter(name='path', value=path_ped, format='str')
273 op.addParameter(name='interval', value='0.04')
273 op.addParameter(name='interval', value='0.04')
274 op.addParameter(name='time_offset', value=time_offset)
274 op.addParameter(name='time_offset', value=time_offset)
275 op.addParameter(name='mode', value='PPI')
275 op.addParameter(name='mode', value='PPI')
276
276
277 op = proc2.addOperation(name='Block360')
277 op = proc2.addOperation(name='Block360')
278 op.addParameter(name='attr_data', value='data_param')
278 op.addParameter(name='attr_data', value='data_param')
279 op.addParameter(name='runNextOp', value=True)
279 op.addParameter(name='runNextOp', value=True)
280
280
281 merge = project.addProcUnit(datatype='MergeProc', inputId=[proc1.getId(), proc2.getId()])
281 merge = project.addProcUnit(datatype='MergeProc', inputId=[proc1.getId(), proc2.getId()])
282 merge.addParameter(name='attr_data', value='data_param')
282 merge.addParameter(name='attr_data', value='data_param')
283 merge.addParameter(name='mode', value='7') #RM
283 merge.addParameter(name='mode', value='7') #RM
284
284
285
285
286 for param in parameters:
286 for param in parameters:
287
287
288 if args.plot:
288 if args.plot:
289 op= merge.addOperation(name='WeatherParamsPlot')
289 op= merge.addOperation(name='WeatherParamsPlot')
290 if args.save:
290 if args.save:
291 op.addParameter(name='save', value=path_plots, format='str')
291 op.addParameter(name='save', value=path_plots, format='str')
292 op.addParameter(name='save_period', value=-1)
292 op.addParameter(name='save_period', value=-1)
293 op.addParameter(name='show', value=args.show)
293 op.addParameter(name='show', value=args.show)
294 op.addParameter(name='channels', value='0,')
294 op.addParameter(name='channels', value='0,')
295 op.addParameter(name='zmin', value=PARAM[param]['zmin'], format='int')
295 op.addParameter(name='zmin', value=PARAM[param]['zmin'], format='int')
296 op.addParameter(name='zmax', value=PARAM[param]['zmax'], format='int')
296 op.addParameter(name='zmax', value=PARAM[param]['zmax'], format='int')
297 op.addParameter(name='attr_data', value=param, format='str')
297 op.addParameter(name='attr_data', value=param, format='str')
298 op.addParameter(name='labels', value=[PARAM[param]['label']])
298 op.addParameter(name='labels', value=[PARAM[param]['label']])
299 op.addParameter(name='save_code', value=param)
299 op.addParameter(name='save_code', value=param)
300 op.addParameter(name='cb_label', value=PARAM[param]['cb_label'])
300 op.addParameter(name='cb_label', value=PARAM[param]['cb_label'])
301 op.addParameter(name='colormap', value=PARAM[param]['colormap'])
301 op.addParameter(name='colormap', value=PARAM[param]['colormap'])
302 op.addParameter(name='bgcolor', value='black')
302 op.addParameter(name='bgcolor', value='black')
303 if MASK: op.addParameter(name='mask', value=MASK, format='float')
303 if MASK: op.addParameter(name='mask', value=MASK, format='float')
304 if args.server:
304 if args.server:
305 op.addParameter(name='server', value='0.0.0.0:4444')
305 op.addParameter(name='server', value='0.0.0.0:4444')
306 op.addParameter(name='exp_code', value='400')
306 op.addParameter(name='exp_code', value='400')
307
307
308 desc = {
308 desc = {
309 'Data': {
309 'Data': {
310 'data_param': {PARAM[param]['wrname']: ['H', 'V']},
310 'data_param': {PARAM[param]['wrname']: ['H', 'V']},
311 'utctime': 'time'
311 'utctime': 'time'
312 },
312 },
313 'Metadata': {
313 'Metadata': {
314 'heightList': 'range',
314 'heightList': 'range',
315 'data_azi': 'azimuth',
315 'data_azi': 'azimuth',
316 'data_ele': 'elevation',
316 'data_ele': 'elevation',
317 'mode_op': 'scan_type',
317 'mode_op': 'scan_type',
318 'h0': 'range_correction',
318 'h0': 'range_correction',
319 }
319 }
320 }
320 }
321
321
322 if args.save:
322 if args.save:
323 writer = merge.addOperation(name='HDFWriter')
323 writer = merge.addOperation(name='HDFWriter')
324 writer.addParameter(name='path', value=path_save, format='str')
324 writer.addParameter(name='path', value=path_save, format='str')
325 writer.addParameter(name='Reset', value=True)
325 writer.addParameter(name='Reset', value=True)
326 writer.addParameter(name='setType', value='weather')
326 writer.addParameter(name='setType', value='weather')
327 writer.addParameter(name='description', value=json.dumps(desc))
327 writer.addParameter(name='description', value=json.dumps(desc))
328 writer.addParameter(name='blocksPerFile', value='1',format='int')
328 writer.addParameter(name='blocksPerFile', value='1',format='int')
329 writer.addParameter(name='metadataList', value='heightList,data_azi,data_ele,mode_op,latitude,longitude,altitude,heading,radar_name,institution,contact,h0,range_unit')
329 writer.addParameter(name='metadataList', value='heightList,data_azi,data_ele,mode_op,latitude,longitude,altitude,heading,radar_name,institution,contact,h0,range_unit')
330 writer.addParameter(name='dataList', value='data_param,utctime')
330 writer.addParameter(name='dataList', value='data_param,utctime')
331 writer.addParameter(name='weather_var', value=param)
331 writer.addParameter(name='weather_var', value=param)
332 writer.addParameter(name='mask', value=MASK, format='float')
332 writer.addParameter(name='mask', value=MASK, format='float')
333 # meta
333 # meta
334 writer.addParameter(name='latitude', value='-12.040436')
334 writer.addParameter(name='latitude', value='-12.040436')
335 writer.addParameter(name='longitude', value='-75.295893')
335 writer.addParameter(name='longitude', value='-75.295893')
336 writer.addParameter(name='altitude', value='3379.2147')
336 writer.addParameter(name='altitude', value='3379.2147')
337 writer.addParameter(name='heading', value='0')
337 writer.addParameter(name='heading', value='0')
338 writer.addParameter(name='radar_name', value='SOPHy')
338 writer.addParameter(name='radar_name', value='SOPHy')
339 writer.addParameter(name='institution', value='IGP')
339 writer.addParameter(name='institution', value='IGP')
340 writer.addParameter(name='contact', value='dscipion@igp.gob.pe')
340 writer.addParameter(name='contact', value='dscipion@igp.gob.pe')
341 writer.addParameter(name='created_by', value='Signal Chain (https://pypi.org/project/schainpy/)')
341 writer.addParameter(name='created_by', value='Signal Chain (https://pypi.org/project/schainpy/)')
342 writer.addParameter(name='range_unit', value='km')
342 writer.addParameter(name='range_unit', value='km')
343
343
344 project.start()
344 project.start()
345
345
346 if __name__ == '__main__':
346 if __name__ == '__main__':
347
347
348 parser = argparse.ArgumentParser(description='Script to process SOPHy data.')
348 parser = argparse.ArgumentParser(description='Script to process SOPHy data.')
349 parser.add_argument('experiment',
349 parser.add_argument('experiment',
350 help='Experiment name')
350 help='Experiment name')
351 parser.add_argument('--parameters', nargs='*', default=['S'],
351 parser.add_argument('--parameters', nargs='*', default=['S'],
352 help='Variables to process: P, Z, V')
352 help='Variables to process: P, Z, V')
353 parser.add_argument('--time_offset', default=0,
353 parser.add_argument('--time_offset', default=0,
354 help='Fix time offset')
354 help='Fix time offset')
355 parser.add_argument('--range', default=0, type=float,
355 parser.add_argument('--range', default=0, type=float,
356 help='Max range to plot')
356 help='Max range to plot')
357 parser.add_argument('--save', action='store_true',
357 parser.add_argument('--save', action='store_true',
358 help='Create output files')
358 help='Create output files')
359 parser.add_argument('--plot', action='store_true',
359 parser.add_argument('--plot', action='store_true',
360 help='Create plot files')
360 help='Create plot files')
361 parser.add_argument('--show', action='store_true',
361 parser.add_argument('--show', action='store_true',
362 help='Show matplotlib plot.')
362 help='Show matplotlib plot.')
363 parser.add_argument('--online', action='store_true',
363 parser.add_argument('--online', action='store_true',
364 help='Set online mode.')
364 help='Set online mode.')
365 parser.add_argument('--server', action='store_true',
365 parser.add_argument('--server', action='store_true',
366 help='Send to realtime')
366 help='Send to realtime')
367 parser.add_argument('--start_time', default='',
367 parser.add_argument('--start_time', default='',
368 help='Set start time.')
368 help='Set start time.')
369
369
370
370
371 args = parser.parse_args()
371 args = parser.parse_args()
372
372
373 main(args)
373 main(args)
374
374
375 # python sophy_proc.py HYO_PM@2022-06-09T15-05-12 --parameters V --plot --save --show --range 36S
375 # python sophy_proc.py HYO_PM@2022-06-09T15-05-12 --parameters V --plot --save --show --range 36S
General Comments 0
You need to be logged in to leave comments. Login now